Doxygen Generated Documentation of Ben-Jose Trainable SAT Solver Library
tools.h
1 
2 
3 /*************************************************************
4 
5 This file is part of ben-jose.
6 
7 ben-jose is free software: you can redistribute it and/or modify
8 it under the terms of the version 3 of the GNU General Public
9 License as published by the Free Software Foundation.
10 
11 ben-jose is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with ben-jose. If not, see <http://www.gnu.org/licenses/>.
18 
19 ------------------------------------------------------------
20 
21 Copyright (C) 2007-2012, 2014-2016. QUIROGA BELTRAN, Jose Luis.
22 Id (cedula): 79523732 de Bogota - Colombia.
23 See https://github.com/joseluisquiroga/ben-jose
24 
25 ben-jose is free software thanks to The Glory of Our Lord
26  Yashua Melej Hamashiaj.
27 Our Resurrected and Living, both in Body and Spirit,
28  Prince of Peace.
29 
30 ------------------------------------------------------------
31 
32 tools.h
33 
34 Some usefult abstract template classes and others.
35 
36 --------------------------------------------------------------*/
37 
38 #ifndef TOOLS_H
39 #define TOOLS_H
40 
41 #include "bj_big_number.h"
42 #include "bit_row.h"
43 #include "bj_time.h"
44 #include "top_exception.h"
45 #include "ch_string.h"
46 #include "print_macros.h"
47 
48 #define NUM_BYTES_IN_KBYTE 1024
49 
50 // 'integer' must be of a signed type
51 typedef long integer;
52 typedef integer row_index;
53 typedef char comparison;
54 
55 #define CMP_FN_T(nm_fun) comparison (*nm_fun)(obj_t const & obj1, obj_t const & obj2)
56 
57 #define as_bool(prm) ((prm) != 0)
58 
59 enum cmp_is_sub {
60  k_lft_is_sub = -1,
61  k_no_is_sub = 0,
62  k_rgt_is_sub = 1
63 };
64 
65 // size_t
66 
67 #ifndef k_num_bits_byte
68 #define k_num_bits_byte 8
69 #endif
70 
71 #define TOOLS_CK(prm) DBG_CK(prm)
72 #define TOOLS_CK_2(prm, comm) DBG_CK_2(prm, comm)
73 
74 #define MIN_TYPE(type) (((type)1) << (sizeof(type) * k_num_bits_byte - 1))
75 #define MAX_TYPE(type) (- (MIN_TYPE(type) + 1))
76 
77 #define MIN_INTEGER MIN_TYPE(integer)
78 //define MAX_INTEGER MAX_TYPE(integer)
79 
80 #define MIN_INDEX MIN_TYPE(row_index)
81 //define MAX_INDEX MAX_TYPE(row_index)
82 
83 #define SUB_SET_OPS 4 // each loop counts as this num ops
84 
85 #define indent_fmt "%-*d"
86 
87 #define SELEC_SORT_LIM 10
88 
89 #ifndef INVALID_IDX
90 #define INVALID_IDX -1
91 #endif
92 
93 #ifndef INVALID_NATURAL
94 #define INVALID_NATURAL -1
95 #endif
96 
97 #ifndef INVALID_SZ
98 #define INVALID_SZ -1
99 #endif
100 
101 #ifndef FILL_FULL_CAP
102 #define FILL_FULL_CAP -100
103 #endif
104 
105 #ifndef START_CAP
106 #define START_CAP 16 // avoid mem problems (due to mem alloc, re-alloc failures)
107 #endif
108 
109 #define SZ_ATTRIB_T(the_type) row_data<the_type>::sz
110 #define CAP_ATTRIB_T(the_type) row_data<the_type>::cap
111 
112 #define SZ_ATTRIB row_data<obj_t>::sz
113 #define CAP_ATTRIB row_data<obj_t>::cap
114 
115 #define lo_hex_as_int(the_byte) (((the_byte) >> 4) & 0xF)
116 #define hi_hex_as_int(the_byte) ((the_byte) & 0x0F)
117 
118 
119 //======================================================================
120 // row_exception
121 
122 typedef enum {
123  rwx_bad_pt,
124  rwx_bad_call_set_cap,
125  rwx_bad_call_clear,
126  rwx_bad_call_pos
127 } rw_ex_cod_t;
128 
129 class row_exception : public top_exception {
130 public:
131  row_exception(long the_id = 0) : top_exception(the_id)
132  {}
133 };
134 
135 //======================================================================
136 // number funcs
137 
138 inline
139 long
140 log2(long val){
141  long ln_v = 0;
142  while(val > 1){
143  ln_v++;
144  val >>= 1;
145  }
146  return ln_v;
147 }
148 
149 inline
150 long
151 abs_long(long val){
152  if(val < 0){
153  val = -val;
154  }
155  TOOLS_CK(val >= 0);
156  return val;
157 }
158 
159 inline
160 long
161 get_var(long lit){
162  return abs_long(lit);
163 }
164 
165 inline
166 comparison
167 cmp_string(ch_string const & n1, ch_string const & n2){
168  if(n1 == n2){ return 0; }
169  if(n1 < n2){ return -1; }
170  return 1;
171 }
172 
173 inline
174 comparison
175 cmp_long(long const & n1, long const & n2){
176  if(n1 == n2){ return 0; }
177  if(n1 < n2){ return -1; }
178  return 1;
179 }
180 
181 inline
182 comparison
183 cmp_char(char const & c1, char const & c2){
184  if(c1 == c2){ return 0; }
185  if(c1 < c2){ return -1; }
186  return 1;
187 }
188 
189 inline
190 comparison
191 cmp_double(double const & n1, double const & n2){
192  if(n1 == n2){ return 0; }
193  if(n1 < n2){ return -1; }
194  return 1;
195 }
196 
197 inline
198 comparison
199 cmp_abs_long(long const & nn1, long const & nn2){
200  long n1 = abs_long(nn1);
201  long n2 = abs_long(nn2);
202  TOOLS_CK(n1 >= 0);
203  TOOLS_CK(n2 >= 0);
204  return cmp_long(n1, n2);
205 }
206 
207 inline
208 comparison
209 cmp_integer(integer const & i1, integer const & i2){
210  if(i1 == i2){ return 0; }
211  if(i1 < i2){ return -1; }
212  return 1;
213 }
214 
215 inline
216 comparison
217 cmp_big_floating(bj_big_float_t const & bn1, bj_big_float_t const & bn2){
218  if(bn1 < bn2){ return -1; }
219  if(bn1 > bn2){ return 1; }
220  return 0;
221 }
222 
223 //======================================================================
224 // Base types and funcs
225 
226 typedef char trinary;
227 
228 template<class obj_t> static inline obj_t
229 min_val(obj_t x, obj_t y) {
230  return (x < y) ? x : y;
231 }
232 
233 template<class obj_t> static inline obj_t
234 max_val(obj_t x, obj_t y) {
235  return (x > y) ? x : y;
236 }
237 
238 WIN32_COD(
239 inline
240 bj_ostream& operator << (bj_ostream& os, __int64 ii ){
241  char buf[30];
242  sprintf(buf,"%I64d", ii );
243  os << buf;
244  return os;
245 }
246 )
247 
248 
249 template<class obj_t>
250 static inline row_index
251 get_idx_of_pt(obj_t* data, obj_t* pt_obj, row_index the_size){
252  row_index pt_idx = INVALID_IDX;
253  if(data != NULL_PT){
254  long pt1 = (long)data;
255  long pt2 = pt1 + (sizeof(obj_t) * the_size);
256  long pt3 = (long)pt_obj;
257  bool in_range = (pt1 <= pt3) && (pt3 < pt2);
258  bool in_place = (((pt3 - pt1) % sizeof(obj_t)) == 0);
259  if(in_range && in_place){
260  pt_idx = ((pt3 - pt1) / sizeof(obj_t));
261  }
262  }
263  return pt_idx;
264 }
265 
266 //======================================================================
267 // flags
268 
269 #define k_flag0 ((char)0x01)
270 #define k_flag1 ((char)0x02)
271 #define k_flag2 ((char)0x04)
272 #define k_flag3 ((char)0x08)
273 #define k_flag4 ((char)0x10)
274 #define k_flag5 ((char)0x20)
275 #define k_flag6 ((char)0x40)
276 #define k_flag7 ((char)0x80)
277 
278 static inline
279 char set_flag(char& flags, char bit_flag){
280  flags = (char)(flags | bit_flag);
281  return flags;
282 }
283 
284 static inline
285 char reset_flag(char& flags, char bit_flag){
286  flags = (char)(flags & ~bit_flag);
287  return flags;
288 }
289 
290 static inline
291 bool get_flag(char flags, char bit_flag){
292  char resp = (char)(flags & bit_flag);
293  return (resp != 0);
294 }
295 
296 //======================================================================
297 // bit array
298 
299 inline
300 long div8l(long val){
301  return ((val)>>3);
302 }
303 
304 inline
305 long mod8l(long val){
306  return ((val)&7);
307 }
308 
309 inline
310 bool bit_get(t_1byte* the_bits, long bit_idx){
311  return (bool)((the_bits[div8l(bit_idx)] >> mod8l(bit_idx)) & 1);
312 }
313 
314 inline
315 void bit_set(t_1byte* the_bits, long bit_idx){
316  the_bits[div8l(bit_idx)] |= (1 << mod8l(bit_idx));
317 }
318 
319 inline
320 void bit_reset(t_1byte* the_bits, long bit_idx){
321  the_bits[div8l(bit_idx)] &= ~(1 << mod8l(bit_idx));
322 }
323 
324 inline
325 void bit_toggle(t_1byte* the_bits, long bit_idx){
326  the_bits[div8l(bit_idx)] ^= (1 << mod8l(bit_idx));
327 }
328 
329 inline
330 long as_num_bytes(long num_bits){
331  return (div8l(num_bits) + (mod8l(num_bits) > 0));
332 }
333 
334 inline
335 long as_num_bits(long num_bytes){
336  return (num_bytes * 8);
337 }
338 
339 //======================================================================
340 // row_data
341 
342 
343 // NOTE. ONLY for types that can be used with 're-alloc'
344 
345 
346 template<class obj_t>
347 class row_data {
348 
349 protected:
350  row_index sz;
351  row_index cap;
352 
353 public:
354  typedef bj_ostream& (*print_func_t)(bj_ostream& os, obj_t& obj);
355  typedef comparison (*cmp_func_t)(obj_t const & obj1, obj_t const & obj2);
356 
357  row_index get_cap(){
358  return cap;
359  }
360 
361  virtual bool ck_valid_pt(obj_t* pt_obj){
362  throw row_exception(rwx_bad_pt);
363  }
364 
365  virtual void set_cap(row_index min_cap){
366  throw row_exception(rwx_bad_call_set_cap);
367  }
368 
369  virtual void clear(bool destroy = false, bool dealloc = false, row_index from = 0){
370  throw row_exception(rwx_bad_call_clear);
371  }
372 
373  virtual obj_t& pos(row_index idx){
374  throw row_exception(rwx_bad_call_pos);
375  //return *((obj_t*)NULL_PT);
376  }
377 
378  row_index sz_in_bytes(){
379  return (sz * sizeof(obj_t));
380  }
381 
382  bool is_empty(){
383  return (sz == 0);
384  }
385 
386  // constructors
387  row_data(): sz(0), cap(0) {}
388 
389  /*virtual ~row_data(){
390  abort_func(0, "func: 'row_data::~row_data'");
391  }*/
392 
393  // Size operations:
394  void grow(row_index min_cap){
395  if(min_cap <= cap){ return; }
396  row_index nxt_cap = cap;
397 
398  if(nxt_cap == 0){
399  nxt_cap = START_CAP;
400  }
401 
402  do{
403  nxt_cap = nxt_cap * 2;
404  } while(nxt_cap < min_cap);
405 
406  TOOLS_CK(nxt_cap > 1);
407  set_cap(nxt_cap);
408  }
409 
410  //virtual if kk_queue
411  row_index size() const {
412  return sz;
413  }
414 
415  row_index last_idx(){
416  return (size() - 1);
417  }
418 
419  //virtual if kk_queue
420  bool is_full() {
421  return (sz == cap);
422  }
423 
424  // Stack interface:
425  void push(const obj_t elem){
426  if(is_full()){
427  grow(sz + 2);
428  }
429  new (&pos(sz)) obj_t(elem);
430  sz++;
431  }
432 
433  obj_t& inc_sz(){
434  if(is_full()){
435  grow(sz + 2);
436  }
437  new (&pos(sz)) obj_t();
438  sz++;
439  return last();
440  }
441 
442  void minc_sz(long num_incs){
443  for(long aa = 0; aa < num_incs; aa++){
444  inc_sz();
445  }
446  }
447 
448  void dec_sz(){
449  TOOLS_CK(sz > 0);
450  sz--;
451  pos(sz).~obj_t();
452  }
453 
454  obj_t pop(){
455  TOOLS_CK(sz > 0);
456  sz--;
457  obj_t tmp1 = pos(sz);
458  pos(sz).~obj_t();
459  return tmp1;
460  }
461 
462  obj_t& first(){
463  TOOLS_CK(sz > 0);
464  return pos(0);
465  }
466 
467  obj_t& last(){
468  TOOLS_CK(sz > 0);
469  return pos(sz - 1);
470  }
471 
472  void swap(row_index idx1, row_index idx2){
473  TOOLS_CK(is_valid_idx(idx1));
474  TOOLS_CK(is_valid_idx(idx2));
475 
476  obj_t tmp1 = pos(idx1);
477  pos(idx1) = pos(idx2);
478  pos(idx2) = tmp1;
479  }
480 
481  void call_swap_with(row_index idx1, row_index idx2){
482  TOOLS_CK(is_valid_idx(idx1));
483  TOOLS_CK(is_valid_idx(idx2));
484 
485  obj_t& tmp1 = pos(idx1);
486  obj_t& tmp2 = pos(idx2);
487  tmp1.swap_with(tmp2);
488  }
489 
490  /*
491  row_index
492  random_swap_last(){
493  TOOLS_CK(sz > 0);
494  row_index idx1 = sz - 1;
495  row_index idx2 = gen_random_num(0, sz);
496  if(idx1 != idx2){
497  swap(idx1, idx2);
498  }
499  return idx2;
500  }*/
501 
502  obj_t swap_pop(row_index idx){
503  TOOLS_CK(is_valid_idx(idx));
504 
505  obj_t tmp1 = pos(idx);
506  sz--;
507  pos(idx) = pos(sz);
508  pos(sz).~obj_t();
509  return tmp1;
510  }
511 
512  void swapop(row_index idx){
513  TOOLS_CK(is_valid_idx(idx));
514 
515  sz--;
516  pos(idx) = pos(sz);
517  pos(sz).~obj_t();
518  }
519 
520  // Vector interface:
521 
522  void fill(const obj_t elem, row_index num_fill = INVALID_IDX,
523  row_index from_idx = 0)
524  {
525  if(from_idx == INVALID_IDX){
526  from_idx = sz;
527  }
528 
529  if(num_fill == INVALID_IDX){
530  num_fill = sz;
531  } else
532  if(num_fill == FILL_FULL_CAP){
533  num_fill = cap;
534  } else {
535  num_fill += from_idx;
536  }
537  set_cap(num_fill);
538  row_index ii = from_idx;
539  for(ii = from_idx; ((ii < sz) && (ii < num_fill)); ii++){
540  pos(ii) = elem;
541  }
542  for(; ii < num_fill; ii++){
543  push(elem);
544  }
545  }
546 
547  void fill_new(row_index num_fill = INVALID_IDX){
548  clear(true, true);
549  if(num_fill == INVALID_IDX){
550  num_fill = sz;
551  }
552  if(num_fill == FILL_FULL_CAP){
553  num_fill = cap;
554  }
555  set_cap(num_fill);
556  for(row_index ii = 0; ii < num_fill; ii++){
557  inc_sz();
558  }
559  }
560 
561  bool is_valid_idx(row_index idx){
562  return ((idx >= 0) && (idx < sz));
563  }
564 
565  obj_t& operator [] (row_index idx) {
566  TOOLS_CK(is_valid_idx(idx));
567  return pos(idx);
568  }
569 
570  // Don't allow copying (error prone):
571  // force use of referenced rows
572 
573  row_data<obj_t>& operator = (row_data<obj_t>& other) {
574  OBJECT_COPY_ERROR;
575  }
576 
577  row_data(row_data<obj_t>& other){
578  OBJECT_COPY_ERROR;
579  }
580 
581  // Duplication (preferred instead):
582  void copy_to(row_data<obj_t>& dest,
583  row_index first_ii = 0, row_index last_ii = -1,
584  bool inv = false)
585  {
586  TOOLS_CK(&dest != this);
587  dest.clear(true, true);
588  append_to(dest, first_ii, last_ii, inv);
589  }
590 
591  void append_to(row_data<obj_t>& dest,
592  row_index first_ii = 0, row_index last_ii = -1,
593  bool inv = false)
594  {
595  if((last_ii < 0) || (last_ii > sz)){
596  last_ii = sz;
597  }
598  if((first_ii < 0) || (first_ii > last_ii)){
599  first_ii = 0;
600  }
601  dest.set_cap(dest.sz + (last_ii - first_ii));
602  row_index ii = INVALID_IDX;
603  if(inv){
604  for(ii = last_ii - 1; ii >= first_ii; ii--){
605  TOOLS_CK(is_valid_idx(ii));
606  obj_t ob = pos(ii);
607  dest.push(ob);
608  }
609  } else {
610  for(ii = first_ii; ii < last_ii; ii++){
611  TOOLS_CK(is_valid_idx(ii));
612  obj_t ob = pos(ii);
613  dest.push(ob);
614  }
615  }
616  }
617 
618  // io funcs
619 
620  bj_ostream& print_row_data(
621  bj_ostream& os,
622  bool with_lims = true,
623  const char* sep = " ",
624  row_index low = INVALID_IDX,
625  row_index hi = INVALID_IDX,
626  bool pointers = false,
627  row_index grp_sz = -1,
628  const char* grp_sep = "\n",
629  row_index from_idx = 0,
630  print_func_t prt_fn = NULL_PT
631  )
632  {
633  if(from_idx == INVALID_IDX){
634  from_idx = sz;
635  }
636 
637  row_index num_elem = 1;
638  if(with_lims){ os << "["; }
639  for(row_index ii = from_idx; ii < sz; ii++){
640  if(ii == low){ os << ">"; }
641  if(prt_fn != NULL_PT){
642  (*prt_fn)(os, pos(ii));
643  } else {
644  os << pos(ii);
645  /*
646  if(! pointers){
647  os << pos(ii);
648  } else {
649  os << &(pos(ii));
650  }
651  */
652  }
653  if(ii == hi){ os << "<"; }
654  os << sep;
655  os.flush();
656  if((grp_sz > 1) && ((num_elem % grp_sz) == 0)){
657  os << grp_sep;
658  }
659  num_elem++;
660  }
661  if(with_lims){ os << "] "; }
662  os.flush();
663  return os;
664  }
665 
666  // sort & selec funcs
667 
668  void selec_sort(cmp_func_t cmp_fn){
669  row_index ii, jj, best_ii;
670  obj_t tmp;
671  for (ii = 0; ii < (sz - 1); ii++){
672  best_ii = ii;
673  for (jj = ii+1; jj < sz; jj++){
674  if((*cmp_fn)(pos(jj), pos(best_ii)) < 0){
675  best_ii = jj;
676  }
677  }
678  tmp = pos(ii);
679  pos(ii) = pos(best_ii);
680  pos(best_ii) = tmp;
681  }
682  }
683 
684  bool is_sorted(cmp_func_t cmp_fn){
685  if(sz == 0){ return true; }
686  obj_t* lst = &(pos(0));
687  for(row_index ii = 1; ii < sz; ii++){
688  if((*cmp_fn)(*lst, pos(ii)) > 0){
689  return false;
690  }
691  lst = &(pos(ii));
692  }
693  return true;
694  }
695 
696  bool equal_to(row_data<obj_t>& rw2, row_index first_ii = 0, row_index last_ii = -1){
697  if((sz == 0) && (rw2.size() == 0)){
698  return true;
699  }
700  if((last_ii < 0) && (sz != rw2.size())){
701  return false;
702  }
703  if((last_ii < 0) || (last_ii > sz)){
704  last_ii = sz;
705  }
706  if((first_ii < 0) || (first_ii > last_ii)){
707  first_ii = 0;
708  }
709 
710  if(! is_valid_idx(first_ii)){ return false; }
711  if(! is_valid_idx(last_ii - 1)){ return false; }
712  if(! rw2.is_valid_idx(first_ii)){ return false; }
713  if(! rw2.is_valid_idx(last_ii - 1)){ return false; }
714 
715  for (row_index ii = first_ii; ii < last_ii; ii++){
716  if(pos(ii) != rw2.pos(ii)){
717  return false;
718  }
719  }
720  return true;
721  }
722 
723  long equal_to_diff(cmp_func_t cmp_fn,
724  row_data<obj_t>& rw2, row_data<obj_t>* diff = NULL_PT,
725  row_index first_ii = 0, row_index last_ii = -1)
726  {
727  if((sz == 0) && (rw2.size() == 0)){
728  return INVALID_IDX;
729  }
730  if((last_ii < 0) || (last_ii > sz)){
731  last_ii = sz;
732  }
733  if((first_ii < 0) || (first_ii > last_ii)){
734  first_ii = 0;
735  }
736 
737  if(diff != NULL_PT){
738  diff->fill_new(last_ii);
739  }
740 
741  long df_pos = INVALID_IDX;
742  row_index ii = INVALID_IDX;
743  for (ii = first_ii; ii < last_ii; ii++){
744  if(! is_valid_idx(ii)){ break; }
745  if(! rw2.is_valid_idx(ii)){ break; }
746 
747  //if(pos(ii) != rw2.pos(ii)){
748  if((*cmp_fn)(pos(ii), rw2.pos(ii)) != 0){
749  if(diff != NULL_PT){
750  //diff[ii] = pos(ii);
751  diff->pos(ii) = pos(ii);
752  }
753  if(df_pos == INVALID_IDX){
754  df_pos = ii;
755  }
756  }
757  }
758  if((ii >= 0) && (ii != last_ii)){
759  df_pos = ii;
760  }
761  return df_pos;
762  }
763 };
764 
765 template<class obj_t>
766 inline
767 bj_ostream& operator << (bj_ostream& os, row_data<obj_t>& rr){
768  rr.print_row_data(os, true, " ");
769  return os;
770 }
771 
772 template<class obj_t>
773 inline
774 bj_ostream& operator << (bj_ostream& os, row_data<obj_t>* rr){
775  if(rr == NULL_PT){
776  os << "NULL_ROW";
777  } else {
778  rr->print_row_data(os, true, " ");
779  }
780  return os;
781 }
782 
783 template<class obj_t>
784 inline
785 row_data<obj_t>& operator << (row_data<obj_t>& rr, const obj_t elem){
786  rr.push(elem);
787  return rr;
788 }
789 
790 template<class obj_t>
791 inline
792 row_data<obj_t>& operator >> (row_data<obj_t>& rr, obj_t& elem){
793  elem = rr.pop();
794  return rr;
795 }
796 
797 
798 //================================================================
799 // row_iter
800 
801 template<class obj_t>
802 class row_iter {
803 public:
804  row_data<obj_t>& the_row;
805  row_index the_ref;
806 
807  row_iter(row_data<obj_t>& d_row) : the_row(d_row){
808  the_ref = INVALID_IDX;
809  }
810  row_iter(row_iter& row_it): the_row(row_it.the_row){
811  the_ref = INVALID_IDX;
812  }
813  ~row_iter(){
814  }
815 
816  long size(){
817  return the_row.size();
818  }
819 
820  void go_first_ref(){
821  if(size() > 0){
822  the_ref = 0;
823  } else {
824  the_ref = INVALID_IDX;
825  }
826  }
827 
828  void go_last_ref(){
829  if(size() > 0){
830  the_ref = the_row.last_idx();
831  } else {
832  the_ref = INVALID_IDX;
833  }
834  }
835 
836  obj_t& get_obj(){
837  return the_row[the_ref];
838  }
839 
840  bool in_null(){
841  return ((the_ref < 0) || (the_ref >= size()));
842  }
843 
844  void go_next(){
845  the_ref++;
846  }
847 
848  void go_prev(){
849  the_ref--;
850  }
851 
852  long get_ref(){
853  return the_ref;
854  }
855 
856  void operator ++ (){
857  go_next();
858  }
859 
860  void operator -- (){
861  go_prev();
862  }
863 
864  void operator ++ (int) { ++(*this); }
865 
866  void operator -- (int) { --(*this); }
867 };
868 
869 //======================================================================
870 // row
871 
872 #define DATA_ATTRIB_T(the_type) row<the_type>::data
873 
874 #define DATA_ATTRIB row<obj_t>::data
875 
876 template<class obj_t>
877 class row: public row_data<obj_t> {
878 protected:
879  obj_t* data;
880 
881 public:
882  typedef comparison (*cmp_func_t)(obj_t const & obj1, obj_t const & obj2);
883  typedef void (*in_both_func_t)(obj_t const & obj1);
884 
885  // Don't allow copying (error prone):
886  // force use of referenced rows
887 
888  row<obj_t>& operator = (row<obj_t>& other) {
889  OBJECT_COPY_ERROR;
890  }
891 
892  row(row<obj_t>& other){
893  OBJECT_COPY_ERROR;
894  }
895 
896  const t_1byte* get_data(){
897  return ((t_1byte*)data);
898  }
899 
900  long get_data_sz(){
901  return (SZ_ATTRIB * sizeof(obj_t));
902  }
903 
904  void as_hex_txt(row<char>& hex_str){
905  char hexval[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
906  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
907  const t_1byte* by_arr = get_data();
908  long sz_arr = get_data_sz();
909  long hex_sz = sz_arr * 2;
910 
911  hex_str.clear();
912  hex_str.fill('0', hex_sz);
913 
914  for(long aa = 0; aa < sz_arr; aa++){
915  hex_str[aa * 2] = hexval[lo_hex_as_int(by_arr[aa])];
916  hex_str[(aa * 2) + 1] = hexval[hi_hex_as_int(by_arr[aa])];
917  }
918  }
919 
920  ch_string as_hex_str(){
921  row<char> hex_txt;
922  as_hex_txt(hex_txt);
923  hex_txt.push(0);
924  ch_string out_str = hex_txt.get_c_array();
925  return out_str;
926  }
927 
928  const obj_t* get_c_array(){
929  return data;
930  }
931 
932  long get_c_array_sz(){
933  return SZ_ATTRIB;
934  }
935 
936 #ifdef BIT_ROW_H
937  void init_s_bit_row(s_bit_row& rr){
938  rr.init_data(((t_1byte*)data), get_data_sz());
939  }
940 #endif
941 
942  virtual bool ck_valid_pt(obj_t* pt_obj){
943  row_index pt_idx = get_idx_of_pt<obj_t>(data, pt_obj, SZ_ATTRIB);
944  return (pt_idx != INVALID_IDX);
945  }
946 
947  virtual void set_cap(row_index min_cap){
948  if(min_cap <= CAP_ATTRIB){ return; }
949  row_index old_cap = CAP_ATTRIB;
950  TOOLS_CK(old_cap >= 0);
951  //CAP_ATTRIB = min_cap + CAP_MARGIN;
952  CAP_ATTRIB = min_cap;
953  obj_t* n_dat = tpl_realloc(data, old_cap, CAP_ATTRIB);
954  data = n_dat;
955  }
956 
957  virtual
958  void set_size(row_index n_sz){
959  set_cap(n_sz);
960  SZ_ATTRIB = n_sz;
961  }
962 
963  void clear_each(row_index from = 0){
964  for(row_index ii = from; ii < SZ_ATTRIB; ii++){
965  pos(ii).clear();
966  }
967  }
968 
969  virtual void clear(bool destroy = false, bool dealloc = false, row_index from = 0){
970  if(data != NULL_PT){
971  if(from != 0){
972  dealloc = false;
973  }
974  if(destroy){
975  for(row_index ii = from; ii < SZ_ATTRIB; ii++){
976  pos(ii).~obj_t();
977  }
978  }
979  SZ_ATTRIB = from;
980  if(dealloc){
981  tpl_free(data, CAP_ATTRIB);
982  data = NULL_PT;
983  CAP_ATTRIB = 0;
984  }
985  }
986  }
987 
988  virtual
989  obj_t& pos(row_index idx){
990  return data[idx];
991  }
992 
993  virtual
994  void move_to(row<obj_t>& dest, bool just_init = false){
995  if(!just_init){
996  dest.clear(true, true);
997  }
998  dest.data = data;
999  dest.sz = SZ_ATTRIB;
1000  dest.cap = CAP_ATTRIB;
1001  data = NULL_PT;
1002  SZ_ATTRIB = 0;
1003  CAP_ATTRIB = 0;
1004  }
1005 
1006  virtual
1007  void swap_with(row<obj_t>& other){
1008  obj_t* tmp_data = other.data;
1009  row_index tmp_sz = other.sz;
1010  row_index tmp_cap = other.cap;
1011 
1012  other.data = data;
1013  other.sz = SZ_ATTRIB;
1014  other.cap = CAP_ATTRIB;
1015 
1016  data = tmp_data;
1017  SZ_ATTRIB = tmp_sz;
1018  CAP_ATTRIB = tmp_cap;
1019  }
1020 
1021  virtual
1022  bool copy_to_c(long c_arr_sz, obj_t* c_arr){
1023  TOOLS_CK(c_arr != data);
1024  if(c_arr_sz != SZ_ATTRIB){
1025  return false;
1026  }
1027  bj_memcpy(c_arr, data, row_data<obj_t>::sz_in_bytes());
1028  return true;
1029  }
1030 
1031  void mem_copy_to(row<obj_t>& r_cpy){
1032  TOOLS_CK(&r_cpy != this);
1033  r_cpy.set_cap(SZ_ATTRIB);
1034  bj_memcpy(r_cpy.data, data, row_data<obj_t>::sz_in_bytes());
1035  r_cpy.sz = SZ_ATTRIB;
1036  }
1037 
1038  // constructors
1039  row(row_index pm_cap = 0): row_data<obj_t>(), data(NULL_PT){
1040  if(pm_cap > 0){ row<obj_t>::set_cap(pm_cap); }
1041  }
1042 
1043  ~row(){
1044  clear(true, true);
1045  }
1046 
1047  void mix_sort(cmp_func_t cmp_fn);
1048 
1049  // adhere asummes:
1050  // - 'shared' of 'this' with 'set' is empty (no intersec)
1051  // - 'this' & 'set' are sorted by cmp_fn (min to max)
1052  // - each elem in 'this' & 'set' is unique
1053  void sorted_set_adhere(row<obj_t>& set, cmp_func_t cmp_fn);
1054 
1055  // reduce asummes:
1056  // - 'set' is subset of 'this' (intersec is set)
1057  // - 'this' & 'set' are sorted by cmp_fn (min to max)
1058  // - each elem in 'this' & 'set' is unique
1059  void sorted_set_reduce(row<obj_t>& set, cmp_func_t cmp_fn);
1060 
1061  // shared assummes:
1062  // - 'this' & 'set' are sorted by cmp_fn (min to max)
1063  // - each elem in 'this' & 'set' is unique
1064  // - 'shared' output is NOT sorted
1065  void sorted_set_shared(row<obj_t>& shared,
1066  row<obj_t>& set, cmp_func_t cmp_fn);
1067 
1068  cmp_is_sub sorted_set_is_subset(row<obj_t>& set,
1069  cmp_func_t cmp_fn, bool& are_eq, in_both_func_t both_fn = NULL_PT);
1070 
1071  long shuffle(row_index from = 0, bool init_random = true);
1072 
1073 };
1074 
1075 typedef row<long> row_long_t;
1076 typedef row<row_long_t> row_row_long_t;
1077 
1078 template<class obj_t>
1079 inline
1080 comparison cmp_with(row<obj_t>& set1, row<obj_t>& set2, CMP_FN_T(cmp_fn)){
1081  //row<obj_t> const& set1 = *this;
1082  if(set1.size() < set2.size()){
1083  return -1;
1084  }
1085  if(set1.size() > set2.size()){
1086  return 1;
1087  }
1088  TOOLS_CK(set1.size() == set2.size());
1089  for(row_index ii = 0; ii < set1.size(); ii++){
1090  comparison cmp_resp = (*cmp_fn)(set1.pos(ii), set2.pos(ii));
1091  if(cmp_resp != 0){
1092  return cmp_resp;
1093  }
1094  }
1095  return 0;
1096 }
1097 
1098 //======================================================================
1099 // s_row
1100 
1101 // careful: cannot free the given data while using the
1102 // s_row object because it is a pointer to the given data.
1103 
1104 template<class obj_t>
1105 class s_row : public row<obj_t> {
1106 private:
1107  virtual
1108  void grow(row_index bits_cap){ MARK_USED(bits_cap); }
1109  virtual
1110  void set_cap(row_index bits_cap){ MARK_USED(bits_cap); }
1111  virtual
1112  void set_size(row_index bits_sz){ MARK_USED(bits_sz); }
1113  virtual
1114  void push(const bool elem){ MARK_USED(elem); }
1115  virtual
1116  void inc_sz(){}
1117  virtual
1118  void dec_sz(){}
1119  virtual
1120  bool pop(){ return false; }
1121  virtual
1122  bool swap_pop(row_index idx){ MARK_USED(idx); return false; }
1123  virtual
1124  void swapop(row_index idx){ MARK_USED(idx); }
1125 
1126 public:
1127  s_row(t_1byte* dat = NULL_PT, long dat_num_bytes = 0){
1128  init_data(dat, dat_num_bytes);
1129  }
1130 
1131  ~s_row(){
1132  clear(true, true);
1133  }
1134 
1135  virtual
1136  void clear(bool reset_them = false, bool dealloc = false, row_index from = 0){
1137  MARK_USED(reset_them);
1138  MARK_USED(dealloc);
1139  MARK_USED(from);
1140  SZ_ATTRIB = 0;
1141  CAP_ATTRIB = 0;
1142  DATA_ATTRIB = NULL_PT;
1143  }
1144 
1145  long to_objs(long num_bytes){
1146  return (num_bytes / sizeof(obj_t));
1147  }
1148 
1149  void init_obj_data(const obj_t* dat, long num_obj){
1150  SZ_ATTRIB = num_obj;
1151  CAP_ATTRIB = num_obj;
1152  if(CAP_ATTRIB > 0){
1153  DATA_ATTRIB = (obj_t*)dat;
1154  } else {
1155  DATA_ATTRIB = NULL_PT;
1156  }
1157  }
1158 
1159  void init_data(t_1byte* dat, long dat_num_bytes){
1160  SZ_ATTRIB = to_objs(dat_num_bytes);
1161  CAP_ATTRIB = to_objs(dat_num_bytes);
1162  if(CAP_ATTRIB > 0){
1163  DATA_ATTRIB = (obj_t*)dat;
1164  } else {
1165  DATA_ATTRIB = NULL_PT;
1166  }
1167  }
1168 
1169 #ifdef BIT_ROW_H
1170  void init_data_with_s_bit_row(s_bit_row& rr){
1171  SZ_ATTRIB = to_objs(rr.get_bytes_cap());
1172  CAP_ATTRIB = to_objs(rr.get_bytes_cap());
1173  if(CAP_ATTRIB > 0){
1174  DATA_ATTRIB = (obj_t*)(rr.data);
1175  } else {
1176  DATA_ATTRIB = NULL_PT;
1177  }
1178  }
1179 #endif
1180 
1181  void erase_data(){
1182  if(DATA_ATTRIB == NULL_PT){
1183  return;
1184  }
1185  bj_memset(DATA_ATTRIB, 0, (SZ_ATTRIB * sizeof(obj_t)));
1186  }
1187 };
1188 
1189 //======================================================================
1190 // k_row
1191 
1192 template<class obj_t>
1193 class k_row : public row_data<obj_t> {
1194 protected:
1195  obj_t** pt_data;
1196  row_index first_exp;
1197  row_index first_cap;
1198 public:
1199  row_index cap2i(row_index& nxt_cap, row_index& rest){
1200  if(first_exp == 0){
1201  rest = 0;
1202  row_index cc = 1;
1203  while(cc < nxt_cap){ cc <<= 1; first_exp++; }
1204  if(first_exp != 0){
1205  nxt_cap = cc;
1206  first_cap = i2c(0);
1207  TOOLS_CK(first_cap == cc);
1208  return 0;
1209  }
1210  return -1;
1211  }
1212  TOOLS_CK(first_cap > 0);
1213  row_index ii = 0;
1214  row_index cc = first_cap;
1215  row_index n_cap = first_cap;
1216  rest = 0;
1217  while(n_cap < nxt_cap){
1218  cc <<= 1;
1219  n_cap += cc;
1220  ii++;
1221  }
1222  rest = nxt_cap - (n_cap - cc);
1223  //nxt_cap = n_cap;
1224  return ii;
1225  }
1226 
1227  row_index i2e(row_index ii){
1228  return (ii + first_exp);
1229  }
1230 
1231  row_index i2c(row_index ii){
1232  row_index ee = i2e(ii);
1233  return (1 << ee);
1234  }
1235 
1236  virtual void set_cap(row_index nxt_cap){
1237  if(nxt_cap <= CAP_ATTRIB){ return; }
1238  if(nxt_cap <= START_CAP){ nxt_cap = START_CAP; }
1239 
1240  row_index rest = INVALID_IDX;
1241  row_index old_cap = CAP_ATTRIB;
1242  row_index old_i = cap2i(old_cap, rest);
1243  row_index old_dt_sz = old_i + 1;
1244  TOOLS_CK(old_cap == CAP_ATTRIB);
1245 
1246  row_index new_i = cap2i(nxt_cap, rest);
1247  row_index new_dt_sz = new_i + 1;
1248 
1249  CAP_ATTRIB = nxt_cap;
1250  TOOLS_CK(first_cap == i2c(0));
1251 
1252  obj_t** n_pt_dat = tpl_realloc(pt_data, old_dt_sz, new_dt_sz);
1253  pt_data = n_pt_dat;
1254 
1255  for(row_index ii = old_dt_sz; ii < new_dt_sz; ii++){
1256  pt_data[ii] = NULL_PT;
1257  pt_data[ii] = tpl_malloc<obj_t>(i2c(ii));
1258  }
1259  }
1260 
1261  virtual void clear(bool destroy = false, bool dealloc = false, row_index from = 0){
1262  if(pt_data != NULL_PT){
1263  if(from != 0){
1264  dealloc = false;
1265  }
1266  if(destroy){
1267  for(row_index ii = from; ii < SZ_ATTRIB; ii++){
1268  pos(ii).~obj_t();
1269  }
1270  }
1271  SZ_ATTRIB = from;
1272  if(dealloc){
1273  TOOLS_CK(first_exp > 0);
1274  row_index rest = INVALID_IDX;
1275  row_index dt_sz = cap2i(CAP_ATTRIB, rest) + 1;
1276 
1277 
1278 
1279  for(row_index jj = 0; jj < dt_sz; jj++){
1280  //if(pt_data[jj] != NULL_PT)
1281  tpl_free(pt_data[jj], i2c(jj));
1282  pt_data[jj] = NULL_PT;
1283  }
1284  tpl_free(pt_data, dt_sz);
1285  pt_data = NULL_PT;
1286  CAP_ATTRIB = 0;
1287  first_exp = 0;
1288  first_cap = 0;
1289  }
1290  }
1291  }
1292 
1293  void get_coordinates(row_index idx,
1294  row_index& coor1, row_index& coor2)
1295  {
1296  if(idx < first_cap){
1297  coor1 = 0;
1298  coor2 = idx;
1299  return;
1300  }
1301 
1302  row_index sub_ii = INVALID_IDX;
1303  row_index ii = idx + 1;
1304  row_index dt_ii = cap2i(ii, sub_ii);
1305 
1306  coor1 = dt_ii;
1307  coor2 = sub_ii - 1;
1308  }
1309 
1310  virtual obj_t& pos(row_index idx){
1311  row_index coor1 = INVALID_IDX;
1312  row_index coor2 = INVALID_IDX;
1313  get_coordinates(idx, coor1, coor2);
1314  TOOLS_CK(coor1 != INVALID_IDX);
1315  TOOLS_CK(coor2 != INVALID_IDX);
1316  return pt_data[coor1][coor2];
1317  }
1318 
1319  virtual bool ck_valid_pt(obj_t* pt_obj){
1320  bool ck_valid = false;
1321  if(pt_data != NULL_PT){
1322  TOOLS_CK(first_exp > 0);
1323  row_index rest = INVALID_IDX;
1324  row_index dt_sz = cap2i(CAP_ATTRIB, rest) + 1;
1325  for(row_index jj = 0; jj < dt_sz; jj++){
1326  TOOLS_CK(pt_data[jj] != NULL_PT);
1327  row_index pt_idx = get_idx_of_pt<obj_t>(pt_data[jj],
1328  pt_obj, i2c(jj));
1329  if(pt_idx != INVALID_IDX){
1330  row_index coor1_last = INVALID_IDX;
1331  row_index coor2_last = INVALID_IDX;
1332  get_coordinates(SZ_ATTRIB - 1, coor1_last, coor2_last);
1333  if( (jj < coor1_last) ||
1334  ((jj == coor1_last) && (pt_idx <= coor2_last)))
1335  {
1336  TOOLS_CK(&(pt_data[jj][pt_idx]) == pt_obj);
1337  ck_valid = true;
1338  }
1339  break;
1340  }
1341  }
1342  }
1343  return ck_valid;
1344  }
1345 
1346  // Constructors:
1347  k_row(row_index pm_cap = 0):
1348  row_data<obj_t>(),
1349  pt_data(NULL_PT),
1350  first_exp(0),
1351  first_cap(0)
1352  {
1353  if(pm_cap > 0){ k_row<obj_t>::set_cap(pm_cap); }
1354  }
1355 
1356  ~k_row(){
1357  clear(true, true);
1358  }
1359 
1360 };
1361 
1362 //=============================================================================
1363 // queue
1364 
1365 template <class obj_t>
1366 class queue : public row<obj_t> {
1367  long first;
1368 
1369 public:
1370  queue(void) : first(0) { }
1371 
1372  obj_t head() {
1373  return row<obj_t>::pos(first);
1374  }
1375  obj_t pick() {
1376  return row<obj_t>::pos(first++);
1377  }
1378 
1379  virtual void clear(bool destroy = false, bool dealloc = false){
1380  first = 0;
1381  row<obj_t>::clear(destroy, dealloc);
1382  }
1383  virtual long size() const {
1384  return SZ_ATTRIB - first;
1385  }
1386 };
1387 
1388 
1389 //======================================================================
1390 // heap
1391 
1392 template<class obj_t>
1393 class heap : public row<obj_t> {
1394  row_index parent(row_index idx){ return ((idx+1)>>1) - 1; }
1395  row_index left(row_index idx){ return ((idx+1)<<1) - 1; }
1396  row_index right(row_index idx){ return ((idx+1)<<1); }
1397 
1398  row_index heapify(row_index idx);
1399 
1400  void update_idx(row_index idx){
1401  if(func_idx == NULL_PT){ return; }
1402  (*func_idx)(row<obj_t>::pos(idx)) = idx;
1403  }
1404  void ck_idx(row_index idx){
1405  if(func_idx == NULL_PT){ return; }
1406  TOOLS_CK(idx == (*func_idx)(row<obj_t>::pos(idx)));
1407  }
1408 
1409 public:
1410  typedef comparison (*cmp_func_t)(obj_t const & obj1, obj_t const & obj2);
1411  typedef row_index& (*func_idx_t)(obj_t&);
1412 
1413  cmp_func_t cmp_func;
1414  func_idx_t func_idx;
1415 
1416  comparison cmp(row_index idx1, row_index idx2){
1417  return (*cmp_func)(row<obj_t>::pos(idx1), row<obj_t>::pos(idx2));
1418  }
1419 
1420  comparison cmp_obj(row_index idx1, obj_t& obj){
1421  return (*cmp_func)(row<obj_t>::pos(idx1), obj);
1422  }
1423 
1424  heap(cmp_func_t f_key, func_idx_t f_idx = NULL_PT, row_index pm_cap = 0)
1425  : row<obj_t>(pm_cap)
1426  {
1427  cmp_func = f_key;
1428  func_idx = f_idx;
1429  }
1430 
1431  heap(row<obj_t>& arr, cmp_func_t f_key, func_idx_t f_idx = NULL_PT)
1432  {
1433  cmp_func = f_key;
1434  func_idx = f_idx;
1435 
1436  arr.move_to(*this, true);
1437  build();
1438  }
1439 
1440  ~heap(){
1441  row<obj_t>::clear(true, true);
1442  }
1443 
1444  void build();
1445  row_index insert(obj_t obj);
1446  row_index changed_key(row_index idx);
1447 
1448  obj_t remove(row_index idx);
1449  obj_t pop_top();
1450 
1451  obj_t top(){
1452  if(SZ_ATTRIB > 0){ return row<obj_t>::pos(0); }
1453  return obj_t();
1454  }
1455  void n_top_to(row_index nn, row<obj_t>& top_ob){
1456  if(SZ_ATTRIB == 0){ return; }
1457  for(row_index ii = 0;
1458  ( (ii < SZ_ATTRIB) &&
1459  (top_ob.size() < nn) &&
1460  (cmp(0, ii) == 0));
1461  ii++)
1462  {
1463  top_ob.push(row<obj_t>::pos(ii));
1464  }
1465 
1466  }
1467 
1468  bool dbg_is_heap_ok(row_index idx = 0);
1469 
1470  bj_ostream& print_heap(bj_ostream& os, row_index idx);
1471 
1472  void hsort(){
1473  row_index orig_sz = SZ_ATTRIB;
1474  for(row_index ii = orig_sz - 1; ii >= 0; ii--){
1475  row_data<obj_t>::swap(0, ii);
1476  (SZ_ATTRIB)--;
1477  heapify(0);
1478  }
1479  row<obj_t>::clear(true, false, orig_sz);
1480  }
1481 
1482 };
1483 
1484 template<class obj_t>
1485 inline
1486 bj_ostream& operator << (bj_ostream& os, heap<obj_t>& he){
1487  return he.print_heap(os, 0);
1488 }
1489 
1490 
1491 //======================================================================
1492 // set comparison
1493 
1494 inline
1495 ch_string subset_cmp_str(cmp_is_sub val){
1496  ch_string str = "k_invalid !!!";
1497  switch(val){
1498  case k_lft_is_sub:
1499  str = "k_lft_is_sub"; break;
1500  case k_no_is_sub:
1501  str = "k_no_is_sub"; break;
1502  case k_rgt_is_sub:
1503  str = "k_rgt_is_sub"; break;
1504  }
1505  return str;
1506 }
1507 
1508 #define decl_cmp_fn(o_t, nam) comparison (*nam)(o_t const & obj1, o_t const & obj2)
1509 #define decl_both_fn(o_t, nam) void (*nam)(o_t const & obj1)
1510 
1511 template<class obj_t, class iter_t>
1512 cmp_is_sub
1513 is_subset_cmp(iter_t& iter1, iter_t& iter2,
1514  decl_cmp_fn(obj_t, cmp_fn), bool& are_eq,
1515  decl_both_fn(obj_t, both_fn) = NULL_PT)
1516 {
1517  are_eq = false;
1518 
1519  long sz1 = iter1.size();
1520  long sz2 = iter2.size();
1521  bool empt1 = (sz1 == 0);
1522  bool empt2 = (sz2 == 0);
1523  if(empt1 && empt2){
1524  are_eq = true;
1525  }
1526  if(empt1){
1527  return k_lft_is_sub;
1528  }
1529  if(empt2){
1530  return k_rgt_is_sub;
1531  }
1532 
1533  iter_t* sub_iter = &iter1;
1534  iter_t* set_iter = &iter2;
1535  cmp_is_sub is_sub_val = k_lft_is_sub;
1536 
1537  if(sz1 > sz2){
1538  sub_iter = &iter2;
1539  set_iter = &iter1;
1540  is_sub_val = k_rgt_is_sub;
1541  }
1542 
1543  iter_t& hi_sub = *(sub_iter);
1544 
1545  iter_t lo_sub(hi_sub);
1546 
1547  iter_t& hi_set = *(set_iter);
1548  iter_t lo_set(hi_set);
1549 
1550  long hi_sub_to_ck = sub_iter->size() - 1;
1551  long lo_sub_to_ck = 0;
1552 
1553  long hi_set_to_ck = set_iter->size() - 1;
1554  long lo_set_to_ck = 0;
1555 
1556  lo_sub.go_first_ref();
1557  hi_sub.go_last_ref();
1558 
1559  lo_set.go_first_ref();
1560  hi_set.go_last_ref();
1561 
1562  cmp_is_sub final_cmp = k_no_is_sub;
1563 
1564  bool is_sub = false;
1565  MARK_USED(is_sub);
1566 
1567  comparison cmp_lo = -3, cmp_hi = -3;
1568 
1569  TOOLS_CK((is_sub_val == k_lft_is_sub) || (is_sub_val == k_rgt_is_sub));
1570 
1571  while(true){
1572  //TOOLS_CK(lo_sub_to_ck == lo_sub.get_ref());
1573  //TOOLS_CK(hi_sub_to_ck == hi_sub.get_ref());
1574  //TOOLS_CK(lo_set_to_ck == lo_set.get_ref());
1575  //TOOLS_CK(hi_set_to_ck == hi_set.get_ref());
1576 
1577  long sub_to_ck = (hi_sub_to_ck - lo_sub_to_ck);
1578  long set_to_ck = (hi_set_to_ck - lo_set_to_ck);
1579 
1580  if(sub_to_ck < 0){
1581  break;
1582  }
1583  if(set_to_ck < 0){
1584  TOOLS_CK(final_cmp == k_no_is_sub);
1585  return final_cmp;
1586  }
1587 
1588  obj_t& lo_sub_obj = lo_sub.get_obj();
1589  obj_t& hi_sub_obj = hi_sub.get_obj();
1590  obj_t& lo_set_obj = lo_set.get_obj();
1591  obj_t& hi_set_obj = hi_set.get_obj();
1592 
1593  cmp_lo = (*cmp_fn)(lo_sub_obj, lo_set_obj);
1594  cmp_hi = (*cmp_fn)(hi_sub_obj, hi_set_obj);
1595 
1596  if(both_fn != NULL_PT){
1597  if(cmp_lo == 0){
1598  (*both_fn)(lo_sub_obj);
1599  (*both_fn)(lo_set_obj);
1600  }
1601  if(cmp_hi == 0){
1602  (*both_fn)(hi_sub_obj);
1603  (*both_fn)(hi_set_obj);
1604  }
1605  }
1606 
1607  if((sub_to_ck == 0) && ((cmp_lo == 0) || (cmp_hi == 0))){
1608  are_eq = (sz1 == sz2);
1609  TOOLS_CK(! are_eq || (set_to_ck <= 0));
1610  final_cmp = is_sub_val;
1611  TOOLS_CK(final_cmp != k_no_is_sub);
1612  return final_cmp;
1613  }
1614 
1615  if( (sub_to_ck > set_to_ck) ||
1616  (cmp_lo < 0) ||
1617  (cmp_hi > 0) )
1618  {
1619  TOOLS_CK(final_cmp == k_no_is_sub);
1620  return final_cmp;
1621  }
1622 
1623  if(cmp_lo > 0){ lo_set++; lo_set_to_ck++; }
1624  if(cmp_lo == 0){ lo_sub++; lo_set++; lo_sub_to_ck++; lo_set_to_ck++; }
1625  if(cmp_hi == 0){ hi_sub--; hi_set--; hi_sub_to_ck--; hi_set_to_ck--; }
1626  if(cmp_hi < 0){ hi_set--; hi_set_to_ck--;}
1627  }
1628 
1629  TOOLS_CK(final_cmp == k_no_is_sub);
1630  if((cmp_lo == 0) && (cmp_hi == 0)){
1631  are_eq = (sz1 == sz2);
1632  //TOOLS_CK(! are_eq || ((sub_to_ck <= 0) && (set_to_ck <= 0)));
1633  final_cmp = is_sub_val;
1634  TOOLS_CK(final_cmp != k_no_is_sub);
1635  }
1636  return final_cmp;
1637 }
1638 
1639 template<class obj_t>
1640 cmp_is_sub
1641 cmp_sorted_rows(row_data<obj_t>& r1, row_data<obj_t>& r2,
1642  decl_cmp_fn(obj_t, cmp_fn), bool& are_eq,
1643  decl_both_fn(obj_t, both_fn) = NULL_PT)
1644 {
1645  row_iter<obj_t> iter1(r1);
1646  row_iter<obj_t> iter2(r2);
1647 
1648  return is_subset_cmp<obj_t, row_iter<obj_t> >(iter1,
1649  iter2, cmp_fn, are_eq, both_fn);
1650 }
1651 
1652 #define decl_cmp_sm_fn(o_t, nam) cmp_subsume_t (*nam)(o_t const & obj1, o_t const & obj2)
1653 
1654 //======================================================================
1655 // FUNCTIONS
1656 
1657 template<class obj_t>
1658 static inline
1659 row_index
1660 get_last_eq_obj_pos(row_index from_pos,
1661  row<obj_t>& rr1, row<obj_t>& rr2){
1662  if(rr1.is_empty()){
1663  return -1;
1664  }
1665  if(rr2.is_empty()){
1666  return -1;
1667  }
1668  if(from_pos < 0){
1669  from_pos = 0;
1670  }
1671  TOOLS_CK(from_pos >= 0);
1672  int sz1 = rr1.size();
1673  int sz2 = rr2.size();
1674  int min_sz = (sz1 < sz2)?(sz1):(sz2);
1675  TOOLS_CK_2(from_pos < min_sz,
1676  os << "from_pos=" << from_pos << bj_eol;
1677  os << "min_sz=" << min_sz << bj_eol;
1678  os << "sz1=" << sz1 << bj_eol;
1679  os << "sz2=" << sz2 << bj_eol;
1680  );
1681 
1682  row_index ii = -1;
1683  for(ii = from_pos; ii < min_sz; ii++){
1684  TOOLS_CK(rr1.is_valid_idx(ii));
1685  TOOLS_CK(rr2.is_valid_idx(ii));
1686  obj_t vv1 = rr1[ii];
1687  obj_t vv2 = rr2[ii];
1688  if(vv1 != vv2){
1689  break;
1690  }
1691  }
1692  row_index lst_pos = ii - 1;
1693  if((lst_pos >= from_pos) && (lst_pos < min_sz)){
1694  TOOLS_CK_2(rr1[lst_pos] == rr2[lst_pos],
1695  os << "from_pos=" << from_pos << bj_eol;
1696  os << "min_sz=" << min_sz << bj_eol;
1697  os << "sz1=" << sz1 << bj_eol;
1698  os << "sz2=" << sz2 << bj_eol;
1699  os << "lst_pos=" << lst_pos << bj_eol;
1700  os << "rr1=" << rr1 << bj_eol;
1701  os << "rr2=" << rr2 << bj_eol;
1702  );
1703  return lst_pos;
1704  }
1705  return -1;
1706 }
1707 
1708 template<class obj_t>
1709 cmp_is_sub
1710 row<obj_t>::sorted_set_is_subset(row<obj_t>& set,
1711  cmp_func_t cmp_fn, bool& are_eq, in_both_func_t both_fn)
1712 {
1713  return cmp_sorted_rows(*this, set, cmp_fn, are_eq, both_fn);
1714 }
1715 
1716 template<class obj_t>
1717 void
1718 row<obj_t>::sorted_set_shared(row<obj_t>& shared,
1719  row<obj_t>& rr2, cmp_func_t cmp_fn)
1720 {
1721  row_index lo_idx1 = 0;
1722  row_index hi_idx1 = row<obj_t>::last_idx();
1723  row_index lo_idx2 = 0;
1724  row_index hi_idx2 = rr2.last_idx();
1725 
1726  shared.clear(true, true);
1727 
1728  while(true){
1729  if(hi_idx1 < lo_idx1){
1730  break;
1731  }
1732  if(hi_idx2 < lo_idx2){
1733  break;
1734  }
1735 
1736  obj_t& lo_a1 = row<obj_t>::pos(lo_idx1);
1737  obj_t& hi_a1 = row<obj_t>::pos(hi_idx1);
1738  obj_t& lo_a2 = rr2[lo_idx2];
1739  obj_t& hi_a2 = rr2[hi_idx2];
1740 
1741  comparison cmp_a1 = (*cmp_fn)(lo_a1, hi_a1);
1742  comparison cmp_a2 = (*cmp_fn)(lo_a2, hi_a2);
1743  comparison cmp_hi1_lo2 = (*cmp_fn)(hi_a1, lo_a2);
1744  comparison cmp_hi2_lo1 = (*cmp_fn)(hi_a2, lo_a1);
1745  comparison cmp_lo1_lo2 = (*cmp_fn)(lo_a1, lo_a2);
1746  comparison cmp_hi1_hi2 = (*cmp_fn)(hi_a1, hi_a2);
1747 
1748  MARK_USED(cmp_a2);
1749  TOOLS_CK(cmp_a1 <= 0);
1750  TOOLS_CK(cmp_a2 <= 0);
1751 
1752  if(cmp_hi1_lo2 < 0){
1753  break;
1754  }
1755  if(cmp_hi2_lo1 < 0){
1756  break;
1757  }
1758 
1759  if(cmp_lo1_lo2 < 0){ lo_idx1++; }
1760  if(cmp_lo1_lo2 > 0){ lo_idx2++; }
1761  if(cmp_lo1_lo2 == 0){
1762  TOOLS_CK(lo_a1 == lo_a2);
1763  shared << lo_a1;
1764  lo_idx1++; lo_idx2++;
1765  }
1766  if((cmp_a1 != 0) && (cmp_hi1_hi2 == 0)){
1767  TOOLS_CK(hi_a1 == hi_a2);
1768  shared << hi_a1;
1769  hi_idx1--; hi_idx2--;
1770  }
1771  if(cmp_hi1_hi2 < 0){ hi_idx2--; }
1772  if(cmp_hi1_hi2 > 0){ hi_idx1--; }
1773  }
1774 }
1775 
1776 template<class obj_t>
1777 void
1778 row<obj_t>::sorted_set_adhere(row<obj_t>& set, cmp_func_t cmp_fn){
1779  if(set.is_empty()){
1780  return;
1781  }
1782  if(row<obj_t>::is_empty()){
1783  set.copy_to(*this);
1784  return;
1785  }
1786 
1787  DBG(bool is_sted = row<obj_t>::is_sorted(cmp_fn));
1788  TOOLS_CK(is_sted);
1789  DBG(bool is_sted_set = set.is_sorted(cmp_fn));
1790  TOOLS_CK(is_sted_set);
1791 
1792 
1793  row_index s_idx = set.last_idx();
1794  row<obj_t>::set_cap(row<obj_t>::size() + set.size());
1795 
1796  row_index m_idx = row<obj_t>::last_idx();
1797  minc_sz(set.size());
1798  row_index a_idx = row<obj_t>::last_idx();
1799 
1800  while(s_idx >= 0){
1801  obj_t& s_obj = set[s_idx];
1802  s_idx--;
1803  TOOLS_CK((s_idx < 0) || (cmp_fn(set[s_idx], s_obj) < 0));
1804  comparison cmp_val = 1;
1805  while((m_idx >= 0) &&
1806  ((cmp_val = cmp_fn(s_obj, row<obj_t>::pos(m_idx))) < 0))
1807  {
1808  row<obj_t>::swap(m_idx, a_idx);
1809  m_idx--;
1810  a_idx--;
1811  }
1812  TOOLS_CK((m_idx < 0) || (cmp_val > 0));
1813  row<obj_t>::pos(a_idx) = s_obj;
1814  a_idx--;
1815  }
1816 
1817  DBG(is_sted = row<obj_t>::is_sorted(cmp_fn));
1818  TOOLS_CK(is_sted);
1819 }
1820 
1821 template<class obj_t>
1822 void
1823 row<obj_t>::sorted_set_reduce(row<obj_t>& set, cmp_func_t cmp_fn){
1824  if(set.is_empty()){
1825  return;
1826  }
1827  DBG(bool is_sted = row<obj_t>::is_sorted(cmp_fn));
1828  TOOLS_CK(is_sted);
1829  DBG(bool is_sted_set = set.is_sorted(cmp_fn));
1830  TOOLS_CK(is_sted_set);
1831 
1832  row_index s_idx = 0;
1833  row_index d_idx = 0;
1834  long num_reds = 0;
1835 
1836  while(s_idx < set.size()){
1837  TOOLS_CK(d_idx < row<obj_t>::size());
1838  comparison cmp_val;
1839  while((cmp_val = cmp_fn(set[s_idx], row<obj_t>::pos(d_idx))) > 0){
1840  if(num_reds > 0){
1841  row<obj_t>::pos(d_idx - num_reds) = row<obj_t>::pos(d_idx);
1842  }
1843  d_idx++;
1844  TOOLS_CK(d_idx < row<obj_t>::size());
1845  }
1846  TOOLS_CK(cmp_val == 0);
1847  num_reds++;
1848  d_idx++;
1849  s_idx++;
1850  }
1851  while(d_idx < row<obj_t>::size()){
1852  TOOLS_CK(num_reds > 0);
1853  row<obj_t>::pos(d_idx - num_reds) = row<obj_t>::pos(d_idx);
1854  d_idx++;
1855  }
1856  row<obj_t>::clear(true, false, d_idx - num_reds);
1857 
1858  DBG(is_sted = row<obj_t>::is_sorted(cmp_fn));
1859  TOOLS_CK(is_sted);
1860 }
1861 
1862 /*
1863 template<class obj_t>
1864 long
1865 row<obj_t>::shuffle(row_index from, bool init_random){
1866 
1867  row<obj_t> tmp_bag;
1868 
1869  long old_sz = row<obj_t>::size();
1870 
1871  row<obj_t>::copy_to(tmp_bag, from);
1872  row<obj_t>::clear(true, false, from);
1873 
1874  long seed = 0;
1875  if(init_random){
1876  seed = init_random_nums();
1877  }
1878  while(tmp_bag.size() > 0){
1879  long idx_pop = gen_random_num(0, tmp_bag.size());
1880  TOOLS_CK(idx_pop >= 0);
1881  TOOLS_CK(idx_pop < tmp_bag.size());
1882  obj_t var = tmp_bag.swap_pop(idx_pop);
1883  row<obj_t>::push(var);
1884  }
1885 
1886  TOOLS_CK(row<obj_t>::size() == old_sz);
1887 
1888  return seed;
1889 }*/
1890 
1891 template<class obj_t>
1892 void
1893 row<obj_t>::mix_sort(cmp_func_t cmp_fn){
1894  if(SZ_ATTRIB < SELEC_SORT_LIM){
1895  row_data<obj_t>::selec_sort(cmp_fn);
1896  } else {
1897  heap<obj_t> he1(*this, cmp_fn);
1898  he1.hsort();
1899  he1.move_to(*this);
1900  }
1901 }
1902 
1903 template<class obj_t>
1904 void
1905 heap<obj_t>::build(){
1906  for(row_index ii = (SZ_ATTRIB)/2; ii >= 0; ii--){ heapify(ii); }
1907 }
1908 
1909 template<class obj_t>
1910 row_index
1911 heap<obj_t>::heapify(row_index idx){
1912  bool go_on = true;
1913  do{
1914  go_on = false;
1915  row_index lft = left(idx);
1916  row_index rgt = right(idx);
1917  row_index maxx = idx;
1918  if((lft < SZ_ATTRIB) && (cmp(lft, maxx) > 0)){ maxx = lft; }
1919  if((rgt < SZ_ATTRIB) && (cmp(rgt, maxx) > 0)){ maxx = rgt; }
1920  if(maxx != idx){
1921  row_data<obj_t>::swap(idx, maxx); // r_f
1922  update_idx(idx);
1923  update_idx(maxx);
1924 
1925  idx = maxx;
1926  go_on = true;
1927  }
1928  }while(go_on);
1929  return idx;
1930 };
1931 
1932 template<class obj_t>
1933 row_index
1934 heap<obj_t>::changed_key(row_index idx){
1935  row_index ii = idx, pp = parent(idx);
1936  obj_t the_obj = row<obj_t>::pos(idx);
1937  ck_idx(idx);
1938  for(; (ii > 0) && (pp >= 0) && (cmp_obj(pp, the_obj) < 0); ii = pp, pp = parent(ii)){
1939  row<obj_t>::pos(ii) = row<obj_t>::pos(pp); // r_f
1940  update_idx(ii);
1941  }
1942  row<obj_t>::pos(ii) = the_obj; // r_f
1943  update_idx(ii);
1944  idx = heapify(ii);
1945  return idx;
1946 };
1947 
1948 template<class obj_t>
1949 row_index
1950 heap<obj_t>::insert(obj_t n_obj){
1951  row_data<obj_t>::inc_sz();
1952  TOOLS_CK((func_idx == NULL_PT) || ((*func_idx)(n_obj) == INVALID_IDX));
1953  row<obj_t>::pos(SZ_ATTRIB - 1) = n_obj; // r_f
1954  update_idx(SZ_ATTRIB - 1);
1955  return changed_key(SZ_ATTRIB - 1);
1956 };
1957 
1958 template<class obj_t>
1959 obj_t
1960 heap<obj_t>::pop_top(){
1961  obj_t resp = obj_t();
1962  if(SZ_ATTRIB == 0){ return resp; }
1963  resp = row<obj_t>::pos(0);
1964  if(func_idx != NULL_PT){ (*func_idx)(resp) = INVALID_IDX; }
1965 
1966  row<obj_t>::pos(0) = row<obj_t>::pos(SZ_ATTRIB - 1); // r_f
1967  update_idx(0);
1968  (SZ_ATTRIB)--;
1969  heapify(0);
1970  return resp;
1971 };
1972 
1973 template<class obj_t>
1974 obj_t
1975 heap<obj_t>::remove(row_index idx){
1976  if(SZ_ATTRIB == 0){ return obj_t(); }
1977  obj_t obj = row_data<obj_t>::swap_pop(idx); // r_f
1978  if(func_idx != NULL_PT){ (*func_idx)(obj) = INVALID_IDX; }
1979 
1980  update_idx(idx);
1981  changed_key(idx);
1982  return obj;
1983 };
1984 
1985 template<class obj_t>
1986 bj_ostream&
1987 heap<obj_t>::print_heap(bj_ostream& os, row_index idx){
1988  row_index lin = 1;
1989  for(row_index ii = 0; ii < SZ_ATTRIB; ii++){
1990  if(ii == lin){
1991  os << "\n";
1992  lin = left(lin);
1993  }
1994  os << row<obj_t>::pos(ii);
1995  if(func_idx != NULL_PT){ os << "@" << (*func_idx)(row<obj_t>::pos(ii)); }
1996  os << " ";
1997  }
1998  os << "\nEOT\n";
1999  return os;
2000 }
2001 
2002 template<class obj_t>
2003 bool
2004 heap<obj_t>::dbg_is_heap_ok(row_index idx){
2005  row_index lft = left(idx);
2006  row_index rgt = right(idx);
2007  row_index maxx = idx;
2008  if((lft < SZ_ATTRIB) && (cmp(lft, maxx) > 0)){ maxx = lft; }
2009  if((rgt < SZ_ATTRIB) && (cmp(rgt, maxx) > 0)){ maxx = rgt; }
2010  if(maxx != idx){ return false; }
2011  if((func_idx != NULL_PT) && (idx != (*func_idx)(row<obj_t>::pos(idx)))){
2012  return false;
2013  }
2014  if((lft < SZ_ATTRIB) && !dbg_is_heap_ok(lft)){ return false; }
2015  if((rgt < SZ_ATTRIB) && !dbg_is_heap_ok(rgt)){ return false; }
2016  return true;
2017 }
2018 
2019 //=================================================================
2020 // row based types
2021 
2022 typedef row<ch_string> row_str_t;
2023 
2024 //=================================================================
2025 // average
2026 
2027 class average {
2028 public:
2029  bj_big_float_t avg;
2030  bj_big_int_t sz; // the number of avg numbers
2031 
2032  average(){
2033  init_average();
2034  }
2035 
2036  void init_average(bj_big_float_t the_avg = 0, bj_big_int_t the_sz = 0){
2037  avg = the_avg;
2038  sz = the_sz;
2039  }
2040 
2041  void add_val(bj_big_float_t val){
2042  if(sz == 0){ sz = 1; avg = val; return; }
2043  avg = (avg * ((bj_big_float_t)sz / (sz + 1))) + (val / (sz + 1));
2044  sz++;
2045  }
2046 
2047  void remove_val(bj_big_float_t val){
2048  if(sz == 1){ sz = 0; avg = 0; return; }
2049  avg = (avg * ((bj_big_float_t)sz / (sz - 1))) - (val / (sz - 1));
2050  sz--;
2051  }
2052 
2053  bj_ostream& print_average(bj_ostream& os){
2054  os << "avg:" << avg << " sz:" << sz << " ";
2055  os.flush();
2056  return os;
2057  }
2058 
2059 };
2060 
2061 inline
2062 bj_ostream& operator << (bj_ostream& os, average& obj){
2063  return obj.print_average(os);
2064 }
2065 
2066 //=================================================================
2067 // avg_stat
2068 
2069 class avg_stat : public average {
2070 public:
2071  bj_big_float_t vs_tot_val;
2072  bj_big_float_t vs_max_val;
2073  ch_string vs_nam;
2074 
2075  avg_stat(ch_string nam = "avg?") {
2076  vs_tot_val = 0.0;
2077  vs_max_val = 0.0;
2078  vs_nam = nam;
2079  }
2080 
2081  void add_val(bj_big_float_t val){
2082  vs_tot_val += val;
2083  average::add_val(val);
2084  if(val > vs_max_val){ vs_max_val = val; }
2085  }
2086 
2087  void remove_val(bj_big_float_t val){
2088  vs_tot_val -= val;
2089  average::remove_val(val);
2090  }
2091 
2092  bj_ostream& print_avg_stat(bj_ostream& os);
2093 
2094 };
2095 
2096 inline
2097 bj_ostream&
2098 avg_stat::print_avg_stat(bj_ostream& os){
2099  bj_big_float_t avg_perc = 0.0;
2100  if(vs_max_val > 0.0){
2101  avg_perc = ((avg / vs_max_val) * 100.0);
2102  }
2103 
2104  os << bj_fixed;
2105  os.precision(2);
2106 
2107  os << vs_nam;
2108  os << " tot=" << vs_tot_val;
2109  os << " avg=" << avg;
2110  os << " max=" << vs_max_val;
2111  os << " (avg/max)=" << avg_perc << "%";
2112  os << bj_eol;
2113  os.flush();
2114  return os;
2115 }
2116 
2117 inline
2118 bj_ostream& operator << (bj_ostream& os, avg_stat& obj){
2119  return obj.print_avg_stat(os);
2120 }
2121 
2122 
2123 //======================================================================
2124 // timeout_exception
2125 
2126 class timeout_exception : public top_exception {
2127 public:
2128  timeout_exception(long the_id = 0) : top_exception(the_id)
2129  {}
2130 };
2131 
2132 //=================================================================
2133 // timer
2134 
2135 #define MIN_TIMER_PERIOD 0.0
2136 #define MIN_TIMER_TIMEOUT 0.0
2137 
2138 inline
2139 double run_time(){
2140  return cpu_time();
2141 }
2142 
2143 typedef void (*tmr_func_t)(void* pm, double curr_secs);
2144 
2145 class timer {
2146 public:
2147  bool tmr_reporting;
2148  double tmr_start_secs;
2149  double tmr_last_secs;
2150  double tmr_desired_secs;
2151  double tmr_desired_timeout;
2152 
2153  double tmr_cycles;
2154  double tmr_current_cycle;
2155 
2156  bool tmr_force_check;
2157 
2158  bool tmr_first_cycle;
2159 
2160  bool tmr_is_periodic;
2161  bool tmr_has_timeout;
2162 
2163  timer(double period = 4.0, double tm_out = 0.0){
2164  init_timer(period, tm_out);
2165  }
2166 
2167  void init_timer(double period = 4.0, double tm_out = 0.0){
2168  tmr_reporting = false;
2169  tmr_start_secs = 0.0;
2170  tmr_last_secs = 0.0;
2171  tmr_desired_secs = period;
2172  tmr_desired_timeout = tm_out;
2173 
2174  tmr_cycles = 1;
2175  tmr_current_cycle = 0;
2176 
2177  tmr_force_check = false;
2178 
2179  tmr_first_cycle = true;
2180 
2181  tmr_is_periodic = (tmr_desired_secs > MIN_TIMER_PERIOD);
2182  tmr_has_timeout = (tmr_desired_timeout > MIN_TIMER_TIMEOUT);
2183  }
2184 
2185  double elapsed_time(double current_secs = 0.0){
2186  if(current_secs == 0.0){
2187  current_secs = run_time();
2188  }
2189  double s_time = (current_secs - tmr_start_secs);
2190  return s_time;
2191  }
2192 
2193  double period_time(double current_secs = 0.0){
2194  if(current_secs == 0.0){
2195  current_secs = run_time();
2196  }
2197  double p_time = (current_secs - tmr_last_secs);
2198  return p_time;
2199  }
2200 
2201  bool check_period(tmr_func_t fn = NULL_PT, void* pm = NULL_PT);
2202 };
2203 
2204 inline
2205 bool
2206 timer::check_period(tmr_func_t tmr_fn, void* pm_fn){
2207  if(! tmr_has_timeout && ! tmr_is_periodic){
2208  return false;
2209  }
2210 
2211  tmr_current_cycle++;
2212 
2213  bool is_over = false;
2214  bool is_period = (tmr_current_cycle >= tmr_cycles);
2215 
2216  if(is_period || tmr_force_check){
2217  tmr_force_check = false;
2218  double tmr_current_secs = run_time();
2219  if(tmr_first_cycle){
2220  tmr_first_cycle = false;
2221  TOOLS_CK(tmr_start_secs == 0.0);
2222  tmr_start_secs = tmr_current_secs;
2223  tmr_last_secs = tmr_current_secs;
2224  }
2225  TOOLS_CK(tmr_current_secs >= tmr_start_secs);
2226 
2227  tmr_current_cycle = 0;
2228  double real_period = (tmr_current_secs - tmr_last_secs);
2229  tmr_last_secs = tmr_current_secs;
2230 
2231  if(real_period < tmr_desired_secs){
2232  tmr_cycles *= 2;
2233  } else if(tmr_cycles > 2.0){
2234  tmr_cycles /= 2;
2235  }
2236  TOOLS_CK(tmr_cycles >= 1.0);
2237 
2238  double elpsd_tm = elapsed_time(tmr_current_secs);
2239  if(! tmr_reporting &&
2240  (elpsd_tm > tmr_desired_secs))
2241  {
2242  tmr_reporting = true;
2243  }
2244 
2245  if(tmr_has_timeout){
2246  is_over = (elpsd_tm > tmr_desired_timeout);
2247  }
2248 
2249  bool report_prd = tmr_reporting && ! is_over &&
2250  tmr_is_periodic &&
2251  ( ! tmr_force_check ||
2252  (real_period >= tmr_desired_secs));
2253 
2254  if(report_prd && (tmr_fn != NULL_PT)){
2255  (*tmr_fn)(pm_fn, tmr_current_secs);
2256  }
2257  }
2258  return is_over;
2259 }
2260 
2261 
2262 #endif // TOOLS_H
2263