41 #include "bj_big_number.h"    44 #include "top_exception.h"    45 #include "ch_string.h"    46 #include "print_macros.h"    48 #define NUM_BYTES_IN_KBYTE  1024    52 typedef integer         row_index;
    53 typedef char            comparison;
    55 #define CMP_FN_T(nm_fun) comparison (*nm_fun)(obj_t const & obj1, obj_t const & obj2)    57 #define as_bool(prm)    ((prm) != 0)    67 #ifndef k_num_bits_byte    68 #define k_num_bits_byte     8    71 #define TOOLS_CK(prm)       DBG_CK(prm)    72 #define TOOLS_CK_2(prm, comm)       DBG_CK_2(prm, comm)    74 #define MIN_TYPE(type)      (((type)1) << (sizeof(type) * k_num_bits_byte - 1))    75 #define MAX_TYPE(type)      (- (MIN_TYPE(type) + 1))    77 #define MIN_INTEGER     MIN_TYPE(integer)    80 #define MIN_INDEX       MIN_TYPE(row_index)    83 #define SUB_SET_OPS     4       // each loop counts as this num ops    85 #define indent_fmt      "%-*d"      87 #define SELEC_SORT_LIM      10    90 #define INVALID_IDX     -1    93 #ifndef INVALID_NATURAL    94 #define INVALID_NATURAL     -1   101 #ifndef FILL_FULL_CAP   102 #define FILL_FULL_CAP   -100   106 #define START_CAP       16  // avoid mem problems (due to mem alloc, re-alloc failures)   109 #define SZ_ATTRIB_T(the_type)   row_data<the_type>::sz   110 #define CAP_ATTRIB_T(the_type)  row_data<the_type>::cap   112 #define SZ_ATTRIB       row_data<obj_t>::sz   113 #define CAP_ATTRIB      row_data<obj_t>::cap   115 #define lo_hex_as_int(the_byte) (((the_byte) >> 4) & 0xF)   116 #define hi_hex_as_int(the_byte) ((the_byte) & 0x0F)   124     rwx_bad_call_set_cap,
   129 class row_exception : 
public top_exception {
   131     row_exception(
long the_id = 0) : top_exception(the_id)
   162     return abs_long(lit);
   167 cmp_string(ch_string 
const & n1, ch_string 
const & n2){ 
   168     if(n1 == n2){ 
return 0; }
   169     if(n1 < n2){ 
return -1; }
   175 cmp_long(
long const & n1, 
long const & n2){ 
   176     if(n1 == n2){ 
return 0; }
   177     if(n1 < n2){ 
return -1; }
   183 cmp_char(
char const & c1, 
char const & c2){ 
   184     if(c1 == c2){ 
return 0; }
   185     if(c1 < c2){ 
return -1; }
   191 cmp_double(
double const & n1, 
double const & n2){ 
   192     if(n1 == n2){ 
return 0; }
   193     if(n1 < n2){ 
return -1; }
   199 cmp_abs_long(
long const & nn1, 
long const & nn2){
   200     long n1 = abs_long(nn1); 
   201     long n2 = abs_long(nn2); 
   204     return cmp_long(n1, n2);
   209 cmp_integer(integer 
const & i1, integer 
const & i2){ 
   210     if(i1 == i2){ 
return 0; }
   211     if(i1 < i2){ 
return -1; }
   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; }
   226 typedef char    trinary;
   228 template<
class obj_t> 
static inline obj_t 
   229 min_val(obj_t x, obj_t y) { 
   230     return (x < y) ? x : y; 
   233 template<
class obj_t> 
static inline obj_t 
   234 max_val(obj_t x, obj_t y) { 
   235     return (x > y) ? x : y; 
   240 bj_ostream& 
operator << (bj_ostream& os, __int64 ii ){
   242     sprintf(buf,
"%I64d", ii );
   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;
   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));
   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)   279 char    set_flag(
char& flags, 
char bit_flag){
   280     flags = (char)(flags | bit_flag);
   285 char    reset_flag(
char& flags, 
char bit_flag){
   286     flags = (char)(flags & ~bit_flag);
   291 bool    get_flag(
char flags, 
char bit_flag){
   292     char  resp  = (char)(flags & bit_flag);
   300 long    div8l(
long val){
   305 long    mod8l(
long val){
   310 bool    bit_get(t_1byte* the_bits, 
long bit_idx){
   311     return (
bool)((the_bits[div8l(bit_idx)] >> mod8l(bit_idx)) & 1);
   315 void    bit_set(t_1byte* the_bits, 
long bit_idx){
   316     the_bits[div8l(bit_idx)] |= (1 << mod8l(bit_idx));
   320 void    bit_reset(t_1byte* the_bits, 
long bit_idx){
   321     the_bits[div8l(bit_idx)] &= ~(1 << mod8l(bit_idx));
   325 void    bit_toggle(t_1byte* the_bits, 
long bit_idx){
   326     the_bits[div8l(bit_idx)] ^= (1 << mod8l(bit_idx));
   330 long    as_num_bytes(
long num_bits){
   331     return (div8l(num_bits) + (mod8l(num_bits) > 0));
   335 long    as_num_bits(
long num_bytes){
   336     return (num_bytes * 8);
   346 template<
class obj_t>
   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);
   361     virtual bool    ck_valid_pt(obj_t* pt_obj){ 
   362         throw row_exception(rwx_bad_pt);
   365     virtual void    set_cap(row_index min_cap){ 
   366         throw row_exception(rwx_bad_call_set_cap);
   369     virtual void    clear(
bool destroy = 
false, 
bool dealloc = 
false, row_index from = 0){ 
   370         throw row_exception(rwx_bad_call_clear);
   373     virtual obj_t&      pos(row_index idx){ 
   374         throw row_exception(rwx_bad_call_pos);
   378     row_index   sz_in_bytes(){
   379         return (sz * 
sizeof(obj_t));
   387     row_data(): sz(0), cap(0) {}
   394     void    grow(row_index min_cap){
   395         if(min_cap <= cap){ 
return; }
   396         row_index nxt_cap = cap;
   403             nxt_cap = nxt_cap * 2; 
   404         } 
while(nxt_cap < min_cap);
   406         TOOLS_CK(nxt_cap > 1);
   411     row_index   size()
 const { 
   415     row_index   last_idx(){
   425     void    push(
const obj_t elem){ 
   429         new (&pos(sz)) obj_t(elem); 
   437         new (&pos(sz)) obj_t();
   442     void    minc_sz(
long num_incs){
   443         for(
long aa = 0; aa < num_incs; aa++){
   457         obj_t tmp1 = pos(sz);
   472     void    swap(row_index idx1, row_index idx2){ 
   473         TOOLS_CK(is_valid_idx(idx1));
   474         TOOLS_CK(is_valid_idx(idx2));
   476         obj_t tmp1 = pos(idx1);
   477         pos(idx1) = pos(idx2);
   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));
   485         obj_t& tmp1 = pos(idx1);
   486         obj_t& tmp2 = pos(idx2);
   487         tmp1.swap_with(tmp2);
   502     obj_t   swap_pop(row_index idx){
   503         TOOLS_CK(is_valid_idx(idx));
   505         obj_t tmp1 = pos(idx);
   512     void    swapop(row_index idx){ 
   513         TOOLS_CK(is_valid_idx(idx));
   522     void    fill(
const obj_t elem, row_index num_fill = INVALID_IDX,
   523                     row_index from_idx = 0)
   525         if(from_idx == INVALID_IDX){
   529         if(num_fill == INVALID_IDX){
   532         if(num_fill == FILL_FULL_CAP){
   535             num_fill += from_idx;
   538         row_index ii = from_idx;
   539         for(ii = from_idx; ((ii < sz) && (ii < num_fill)); ii++){
   542         for(; ii < num_fill; ii++){
   547     void    fill_new(row_index num_fill = INVALID_IDX){ 
   549         if(num_fill == INVALID_IDX){
   552         if(num_fill == FILL_FULL_CAP){
   556         for(row_index ii = 0; ii < num_fill; ii++){
   561     bool    is_valid_idx(row_index idx){
   562         return ((idx >= 0) && (idx < sz));
   565     obj_t&       operator [] (row_index idx)        { 
   566         TOOLS_CK(is_valid_idx(idx));
   573     row_data<obj_t>&  operator = (row_data<obj_t>& other) { 
   577     row_data(row_data<obj_t>& other){ 
   582     void copy_to(row_data<obj_t>& dest, 
   583             row_index first_ii = 0, row_index last_ii = -1,
   586         TOOLS_CK(&dest != 
this);
   587         dest.clear(
true, 
true); 
   588         append_to(dest, first_ii, last_ii, inv);
   591     void append_to(row_data<obj_t>& dest, 
   592             row_index first_ii = 0, row_index last_ii = -1,
   595         if((last_ii < 0) || (last_ii > sz)){
   598         if((first_ii < 0) || (first_ii > last_ii)){
   601         dest.set_cap(dest.sz + (last_ii - first_ii)); 
   602         row_index ii = INVALID_IDX;
   604             for(ii = last_ii - 1; ii >= first_ii; ii--){
   605                 TOOLS_CK(is_valid_idx(ii));
   610             for(ii = first_ii; ii < last_ii; ii++){
   611                 TOOLS_CK(is_valid_idx(ii));
   620     bj_ostream& print_row_data(
   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
   633         if(from_idx == INVALID_IDX){
   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));
   653             if(ii == hi){ os << 
"<"; }
   656             if((grp_sz > 1) && ((num_elem % grp_sz) == 0)){
   661         if(with_lims){ os << 
"] "; }
   668     void    selec_sort(cmp_func_t cmp_fn){
   669         row_index   ii, jj, best_ii;
   671         for (ii = 0; ii < (sz - 1); ii++){
   673             for (jj = ii+1; jj < sz; jj++){
   674                 if((*cmp_fn)(pos(jj), pos(best_ii)) < 0){
   679             pos(ii) = pos(best_ii); 
   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){
   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)){
   700         if((last_ii < 0) && (sz != rw2.size())){
   703         if((last_ii < 0) || (last_ii > sz)){
   706         if((first_ii < 0) || (first_ii > last_ii)){
   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; }
   715         for (row_index ii = first_ii; ii < last_ii; ii++){
   716             if(pos(ii) != rw2.pos(ii)){
   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)
   727         if((sz == 0) && (rw2.size() == 0)){
   730         if((last_ii < 0) || (last_ii > sz)){
   733         if((first_ii < 0) || (first_ii > last_ii)){
   738             diff->fill_new(last_ii);
   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; }
   748             if((*cmp_fn)(pos(ii), rw2.pos(ii)) != 0){
   751                     diff->pos(ii) = pos(ii);
   753                 if(df_pos == INVALID_IDX){
   758         if((ii >= 0) && (ii != last_ii)){
   765 template<
class obj_t>
   767 bj_ostream& operator << (bj_ostream& os, row_data<obj_t>& rr){
   768     rr.print_row_data(os, 
true, 
" ");
   772 template<
class obj_t>
   774 bj_ostream& operator << (bj_ostream& os, row_data<obj_t>* rr){
   778         rr->print_row_data(os, 
true, 
" ");
   783 template<
class obj_t>
   785 row_data<obj_t>&    operator << (row_data<obj_t>& rr, 
const obj_t elem){
   790 template<
class obj_t>
   792 row_data<obj_t>&    operator >> (row_data<obj_t>& rr, obj_t& elem){
   801 template<
class obj_t>
   804     row_data<obj_t>&    the_row;
   807     row_iter(row_data<obj_t>& d_row) : the_row(d_row){
   808         the_ref = INVALID_IDX;
   810     row_iter(row_iter& row_it): the_row(row_it.the_row){
   811         the_ref = INVALID_IDX;
   817         return the_row.size();
   824             the_ref = INVALID_IDX;
   830             the_ref = the_row.last_idx();
   832             the_ref = INVALID_IDX;
   837         return the_row[the_ref]; 
   841         return ((the_ref < 0) || (the_ref >= size()));
   864     void    operator ++ (
int) { ++(*this); }
   866     void    operator -- (
int) { --(*this); }
   872 #define DATA_ATTRIB_T(the_type) row<the_type>::data   874 #define DATA_ATTRIB row<obj_t>::data   876 template<
class obj_t>
   877 class row: 
public row_data<obj_t> {
   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);
   888     row<obj_t>&  operator = (row<obj_t>& other) { 
   892     row(row<obj_t>& other){ 
   896     const t_1byte*  get_data(){
   897         return ((t_1byte*)data);
   901         return (SZ_ATTRIB * 
sizeof(obj_t));
   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;
   912         hex_str.fill(
'0', hex_sz);
   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])];
   920     ch_string   as_hex_str(){
   924         ch_string out_str = hex_txt.get_c_array();
   928     const obj_t*    get_c_array(){
   932     long        get_c_array_sz(){
   937     void        init_s_bit_row(s_bit_row& rr){
   938         rr.init_data(((t_1byte*)data), get_data_sz());
   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);
   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);
   952         CAP_ATTRIB = min_cap;
   953         obj_t* n_dat = tpl_realloc(data, old_cap, CAP_ATTRIB);
   958     void    set_size(row_index n_sz){ 
   963     void    clear_each(row_index from = 0){ 
   964         for(row_index ii = from; ii < SZ_ATTRIB; ii++){ 
   969     virtual void    clear(
bool destroy = 
false, 
bool dealloc = 
false, row_index from = 0){ 
   975                 for(row_index ii = from; ii < SZ_ATTRIB; ii++){ 
   981                 tpl_free(data, CAP_ATTRIB);
   989     obj_t&      pos(row_index idx){ 
   994     void move_to(row<obj_t>& dest, 
bool just_init = 
false){ 
   996             dest.clear(
true, 
true); 
  1000         dest.cap = CAP_ATTRIB; 
  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;
  1013         other.sz = SZ_ATTRIB;
  1014         other.cap = CAP_ATTRIB;
  1018         CAP_ATTRIB = tmp_cap;
  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){
  1027         bj_memcpy(c_arr, data, row_data<obj_t>::sz_in_bytes());
  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;
  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); }
  1047     void    mix_sort(cmp_func_t cmp_fn);
  1053     void    sorted_set_adhere(row<obj_t>& 
set, cmp_func_t cmp_fn);
  1059     void    sorted_set_reduce(row<obj_t>& 
set, cmp_func_t cmp_fn);
  1065     void    sorted_set_shared(row<obj_t>& shared, 
  1066                 row<obj_t>& 
set, cmp_func_t cmp_fn);
  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);
  1071     long    shuffle(row_index from = 0, 
bool init_random = 
true);
  1075 typedef row<long>       row_long_t;
  1076 typedef row<row_long_t>     row_row_long_t;
  1078 template<
class obj_t>
  1080 comparison      cmp_with(row<obj_t>& set1, row<obj_t>& set2, CMP_FN_T(cmp_fn)){
  1082     if(set1.size() < set2.size()){
  1085     if(set1.size() > set2.size()){
  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));
  1104 template<
class obj_t>
  1105 class s_row : 
public row<obj_t> {
  1108     void    grow(row_index bits_cap){ MARK_USED(bits_cap); }
  1110     void    set_cap(row_index bits_cap){ MARK_USED(bits_cap); }
  1112     void    set_size(row_index bits_sz){ MARK_USED(bits_sz); }
  1114     void    push(
const bool elem){ MARK_USED(elem); }
  1120     bool    pop(){ 
return false; }
  1122     bool    swap_pop(row_index idx){ MARK_USED(idx); 
return false; }
  1124     void    swapop(row_index idx){ MARK_USED(idx); }
  1127     s_row(t_1byte* dat = NULL_PT, 
long dat_num_bytes = 0){
  1128         init_data(dat, dat_num_bytes);
  1136     void    clear(
bool reset_them = 
false, 
bool dealloc = 
false, row_index from = 0){
  1137         MARK_USED(reset_them);
  1142         DATA_ATTRIB = NULL_PT;
  1145     long to_objs(
long num_bytes){
  1146         return (num_bytes / 
sizeof(obj_t));
  1149     void init_obj_data(
const obj_t* dat, 
long num_obj){
  1150         SZ_ATTRIB = num_obj;
  1151         CAP_ATTRIB = num_obj;
  1153             DATA_ATTRIB = (obj_t*)dat;
  1155             DATA_ATTRIB = NULL_PT;
  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);
  1163             DATA_ATTRIB = (obj_t*)dat;
  1165             DATA_ATTRIB = NULL_PT;
  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());
  1174             DATA_ATTRIB = (obj_t*)(rr.data);
  1176             DATA_ATTRIB = NULL_PT;
  1182         if(DATA_ATTRIB == NULL_PT){
  1185         bj_memset(DATA_ATTRIB, 0, (SZ_ATTRIB * 
sizeof(obj_t)));
  1192 template<
class obj_t>
  1193 class k_row : 
public row_data<obj_t> {
  1196     row_index   first_exp;
  1197     row_index   first_cap;
  1199     row_index       cap2i(row_index& nxt_cap, row_index& rest){
  1203             while(cc < nxt_cap){ cc <<= 1; first_exp++; }
  1207                 TOOLS_CK(first_cap == cc);
  1212         TOOLS_CK(first_cap > 0);
  1214         row_index cc = first_cap;
  1215         row_index n_cap = first_cap;
  1217         while(n_cap < nxt_cap){
  1222         rest = nxt_cap - (n_cap - cc);
  1227     row_index       i2e(row_index ii){
  1228         return (ii + first_exp);
  1231     row_index       i2c(row_index ii){
  1232         row_index ee = i2e(ii);
  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; }
  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);
  1246         row_index new_i = cap2i(nxt_cap, rest);
  1247         row_index new_dt_sz = new_i + 1;
  1249         CAP_ATTRIB = nxt_cap;
  1250         TOOLS_CK(first_cap == i2c(0));
  1252         obj_t** n_pt_dat = tpl_realloc(pt_data, old_dt_sz, new_dt_sz);
  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));
  1261     virtual void    clear(
bool destroy = 
false, 
bool dealloc = 
false, row_index from = 0){ 
  1262         if(pt_data != NULL_PT){
  1267                 for(row_index ii = from; ii < SZ_ATTRIB; ii++){ 
  1273                 TOOLS_CK(first_exp > 0);
  1274                 row_index rest = INVALID_IDX;
  1275                 row_index dt_sz = cap2i(CAP_ATTRIB, rest) + 1;
  1279                 for(row_index jj = 0; jj < dt_sz; jj++){
  1281                     tpl_free(pt_data[jj], i2c(jj));
  1282                     pt_data[jj] = NULL_PT;
  1284                 tpl_free(pt_data, dt_sz);
  1293     void    get_coordinates(row_index idx, 
  1294         row_index& coor1, row_index& coor2)
  1296         if(idx < first_cap){
  1302         row_index sub_ii = INVALID_IDX;
  1303         row_index ii = idx + 1;
  1304         row_index dt_ii = cap2i(ii, sub_ii);
  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];
  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], 
  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)))
  1336                         TOOLS_CK(&(pt_data[jj][pt_idx]) == pt_obj);
  1347     k_row(row_index pm_cap = 0):
  1353         if(pm_cap > 0){ k_row<obj_t>::set_cap(pm_cap); }
  1365 template <
class obj_t>
  1366 class queue : 
public row<obj_t> {
  1370     queue(
void) : first(0) { }
  1373         return row<obj_t>::pos(first); 
  1376         return row<obj_t>::pos(first++); 
  1379     virtual void    clear(
bool destroy = 
false, 
bool dealloc = 
false){ 
  1381         row<obj_t>::clear(destroy, dealloc); 
  1383     virtual long        size()
 const { 
  1384         return SZ_ATTRIB - first; 
  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); }
  1398     row_index   heapify(row_index idx);
  1400     void        update_idx(row_index idx){ 
  1401         if(func_idx == NULL_PT){ 
return; }
  1402         (*func_idx)(row<obj_t>::pos(idx)) = idx; 
  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)));
  1410     typedef comparison (*cmp_func_t)(obj_t 
const & obj1, obj_t 
const & obj2);
  1411     typedef row_index&  (*func_idx_t)(obj_t&);
  1413     cmp_func_t  cmp_func;
  1414     func_idx_t  func_idx;
  1416     comparison          cmp(row_index idx1, row_index idx2){
  1417         return (*cmp_func)(row<obj_t>::pos(idx1), row<obj_t>::pos(idx2));
  1420     comparison          cmp_obj(row_index idx1, obj_t& obj){
  1421         return (*cmp_func)(row<obj_t>::pos(idx1), obj);
  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)
  1431     heap(row<obj_t>& arr, cmp_func_t f_key, func_idx_t f_idx = NULL_PT)
  1436         arr.move_to(*
this, 
true);
  1441         row<obj_t>::clear(
true, 
true);
  1445     row_index       insert(obj_t obj);
  1446     row_index       changed_key(row_index idx);
  1448     obj_t       
remove(row_index idx);
  1452         if(SZ_ATTRIB > 0){ 
return row<obj_t>::pos(0); }
  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) && 
  1463             top_ob.push(row<obj_t>::pos(ii));
  1468     bool        dbg_is_heap_ok(row_index idx = 0);
  1470     bj_ostream& print_heap(bj_ostream& os, row_index idx);
  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);
  1479         row<obj_t>::clear(
true, 
false, orig_sz);
  1484 template<
class obj_t>
  1486 bj_ostream& operator << (bj_ostream& os, heap<obj_t>& he){
  1487     return he.print_heap(os, 0);
  1495 ch_string   subset_cmp_str(cmp_is_sub val){
  1496     ch_string str = 
"k_invalid !!!";
  1499         str = 
"k_lft_is_sub"; 
break;
  1501         str = 
"k_no_is_sub"; 
break;
  1503         str = 
"k_rgt_is_sub"; 
break;
  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)  1511 template<
class obj_t, 
class iter_t>
  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)
  1519     long sz1 = iter1.size(); 
  1520     long sz2 = iter2.size();
  1521     bool empt1 = (sz1 == 0);
  1522     bool empt2 = (sz2 == 0);
  1527         return k_lft_is_sub;
  1530         return k_rgt_is_sub;
  1533     iter_t*     sub_iter = &iter1;
  1534     iter_t*     set_iter = &iter2;
  1535     cmp_is_sub  is_sub_val = k_lft_is_sub;
  1540         is_sub_val = k_rgt_is_sub;
  1543     iter_t& hi_sub = *(sub_iter);
  1545     iter_t  lo_sub(hi_sub);
  1547     iter_t& hi_set = *(set_iter);
  1548     iter_t  lo_set(hi_set);
  1550     long hi_sub_to_ck = sub_iter->size() - 1; 
  1551     long lo_sub_to_ck = 0;
  1553     long hi_set_to_ck = set_iter->size() - 1;
  1554     long lo_set_to_ck = 0;
  1556     lo_sub.go_first_ref();
  1557     hi_sub.go_last_ref();
  1559     lo_set.go_first_ref();
  1560     hi_set.go_last_ref();
  1562     cmp_is_sub  final_cmp = k_no_is_sub;
  1564     bool        is_sub = 
false; 
  1567     comparison  cmp_lo = -3, cmp_hi = -3;
  1569     TOOLS_CK((is_sub_val == k_lft_is_sub) || (is_sub_val == k_rgt_is_sub));
  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);
  1584             TOOLS_CK(final_cmp == k_no_is_sub);
  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();
  1593         cmp_lo = (*cmp_fn)(lo_sub_obj, lo_set_obj);
  1594         cmp_hi = (*cmp_fn)(hi_sub_obj, hi_set_obj);
  1596         if(both_fn != NULL_PT){
  1598                 (*both_fn)(lo_sub_obj);
  1599                 (*both_fn)(lo_set_obj);
  1602                 (*both_fn)(hi_sub_obj);
  1603                 (*both_fn)(hi_set_obj);
  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);
  1615         if( (sub_to_ck > set_to_ck) ||
  1619             TOOLS_CK(final_cmp == k_no_is_sub);
  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--;}
  1629     TOOLS_CK(final_cmp == k_no_is_sub);
  1630     if((cmp_lo == 0) && (cmp_hi == 0)){
  1631         are_eq = (sz1 == sz2); 
  1633         final_cmp = is_sub_val; 
  1634         TOOLS_CK(final_cmp != k_no_is_sub);
  1639 template<
class obj_t>
  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)
  1645     row_iter<obj_t> iter1(r1);
  1646     row_iter<obj_t> iter2(r2);
  1648     return is_subset_cmp<obj_t, row_iter<obj_t> >(iter1, 
  1649         iter2, cmp_fn, are_eq, both_fn); 
  1652 #define decl_cmp_sm_fn(o_t, nam) cmp_subsume_t (*nam)(o_t const & obj1, o_t const & obj2)  1657 template<
class obj_t>
  1660 get_last_eq_obj_pos(row_index from_pos, 
  1661                 row<obj_t>& rr1, row<obj_t>& rr2){
  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;
  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];
  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;
  1708 template<
class obj_t>
  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)
  1713     return cmp_sorted_rows(*
this, 
set, cmp_fn, are_eq, both_fn);
  1716 template<
class obj_t>
  1718 row<obj_t>::sorted_set_shared(row<obj_t>& shared, 
  1719             row<obj_t>& rr2, cmp_func_t cmp_fn)
  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();
  1726     shared.clear(
true, 
true);
  1729         if(hi_idx1 < lo_idx1){
  1732         if(hi_idx2 < lo_idx2){
  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];
  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);
  1749         TOOLS_CK(cmp_a1 <= 0);
  1750         TOOLS_CK(cmp_a2 <= 0);
  1752         if(cmp_hi1_lo2 < 0){
  1755         if(cmp_hi2_lo1 < 0){
  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);
  1764             lo_idx1++; lo_idx2++; 
  1766         if((cmp_a1 != 0) && (cmp_hi1_hi2 == 0)){ 
  1767             TOOLS_CK(hi_a1 == hi_a2);
  1769             hi_idx1--; hi_idx2--; 
  1771         if(cmp_hi1_hi2 < 0){ hi_idx2--; }
  1772         if(cmp_hi1_hi2 > 0){ hi_idx1--; }
  1776 template<
class obj_t>
  1778 row<obj_t>::sorted_set_adhere(row<obj_t>& 
set, cmp_func_t cmp_fn){
  1782     if(row<obj_t>::is_empty()){
  1787     DBG(
bool is_sted = row<obj_t>::is_sorted(cmp_fn));
  1789     DBG(
bool is_sted_set = 
set.is_sorted(cmp_fn));
  1790     TOOLS_CK(is_sted_set);
  1793     row_index s_idx = 
set.last_idx();
  1794     row<obj_t>::set_cap(row<obj_t>::size() + 
set.size());
  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();
  1801         obj_t& s_obj = 
set[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))
  1808             row<obj_t>::swap(m_idx, a_idx);
  1812         TOOLS_CK((m_idx < 0) || (cmp_val > 0));
  1813         row<obj_t>::pos(a_idx) = s_obj;
  1817     DBG(is_sted = row<obj_t>::is_sorted(cmp_fn));
  1821 template<
class obj_t>
  1823 row<obj_t>::sorted_set_reduce(row<obj_t>& 
set, cmp_func_t cmp_fn){
  1827     DBG(
bool is_sted = row<obj_t>::is_sorted(cmp_fn));
  1829     DBG(
bool is_sted_set = 
set.is_sorted(cmp_fn));
  1830     TOOLS_CK(is_sted_set);
  1832     row_index s_idx = 0;
  1833     row_index d_idx = 0;
  1836     while(s_idx < 
set.size()){
  1837         TOOLS_CK(d_idx < row<obj_t>::size());
  1839         while((cmp_val = cmp_fn(
set[s_idx], row<obj_t>::pos(d_idx))) > 0){
  1841                 row<obj_t>::pos(d_idx - num_reds) = row<obj_t>::pos(d_idx);
  1844             TOOLS_CK(d_idx < row<obj_t>::size());
  1846         TOOLS_CK(cmp_val == 0);
  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);
  1856     row<obj_t>::clear(
true, 
false, d_idx - num_reds);
  1858     DBG(is_sted = row<obj_t>::is_sorted(cmp_fn));
  1891 template<
class obj_t>
  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);
  1897         heap<obj_t> he1(*
this, cmp_fn);
  1903 template<
class obj_t>
  1905 heap<obj_t>::build(){
  1906     for(row_index ii = (SZ_ATTRIB)/2; ii >= 0; ii--){ heapify(ii);  }
  1909 template<
class obj_t>
  1911 heap<obj_t>::heapify(row_index idx){
  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; }
  1921             row_data<obj_t>::swap(idx, maxx); 
  1932 template<
class obj_t>
  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);
  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);  
  1942     row<obj_t>::pos(ii) = the_obj;  
  1948 template<
class obj_t>
  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;  
  1954     update_idx(SZ_ATTRIB - 1);
  1955     return changed_key(SZ_ATTRIB - 1);
  1958 template<
class 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; }
  1966     row<obj_t>::pos(0) = row<obj_t>::pos(SZ_ATTRIB - 1);  
  1973 template<
class 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);  
  1978     if(func_idx != NULL_PT){ (*func_idx)(obj) = INVALID_IDX; }
  1985 template<
class obj_t>
  1987 heap<obj_t>::print_heap(bj_ostream& os, row_index idx){
  1989     for(row_index ii = 0; ii < SZ_ATTRIB; ii++){
  1994         os << row<obj_t>::pos(ii);
  1995         if(func_idx != NULL_PT){ os << 
"@" << (*func_idx)(row<obj_t>::pos(ii)); } 
  2002 template<
class obj_t>
  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)))){    
  2014     if((lft < SZ_ATTRIB) && !dbg_is_heap_ok(lft)){ 
return false; }
  2015     if((rgt < SZ_ATTRIB) && !dbg_is_heap_ok(rgt)){ 
return false; }
  2022 typedef row<ch_string>  row_str_t;
  2036     void    init_average(bj_big_float_t the_avg = 0, bj_big_int_t the_sz = 0){
  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));
  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));
  2053     bj_ostream& print_average(bj_ostream& os){
  2054         os << 
"avg:" << avg << 
" sz:" << sz << 
" ";
  2062 bj_ostream& operator << (bj_ostream& os, average& obj){
  2063     return obj.print_average(os);
  2069 class avg_stat : 
public average {
  2071     bj_big_float_t  vs_tot_val;
  2072     bj_big_float_t  vs_max_val;
  2075     avg_stat(ch_string nam = 
"avg?") {
  2081     void    add_val(bj_big_float_t val){
  2083         average::add_val(val);
  2084         if(val > vs_max_val){ vs_max_val = val; }
  2087     void    remove_val(bj_big_float_t val){
  2089         average::remove_val(val);
  2092     bj_ostream& print_avg_stat(bj_ostream& os);
  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);
  2108     os << 
" tot=" << vs_tot_val;
  2109     os << 
" avg=" << avg;
  2110     os << 
" max=" << vs_max_val;
  2111     os << 
" (avg/max)=" << avg_perc << 
"%";
  2118 bj_ostream& operator << (bj_ostream& os, avg_stat& obj){
  2119     return obj.print_avg_stat(os);
  2126 class timeout_exception : 
public top_exception {
  2128     timeout_exception(
long the_id = 0) : top_exception(the_id)
  2135 #define MIN_TIMER_PERIOD    0.0  2136 #define MIN_TIMER_TIMEOUT   0.0  2143 typedef void (*tmr_func_t)(
void* pm, 
double curr_secs);
  2148     double          tmr_start_secs;
  2149     double          tmr_last_secs;
  2150     double          tmr_desired_secs;
  2151     double          tmr_desired_timeout;
  2154     double          tmr_current_cycle;
  2156     bool            tmr_force_check;
  2158     bool            tmr_first_cycle;
  2160     bool            tmr_is_periodic;
  2161     bool            tmr_has_timeout;
  2163     timer(
double period = 4.0, 
double tm_out = 0.0){
  2164         init_timer(period, tm_out);
  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;
  2175         tmr_current_cycle = 0;
  2177         tmr_force_check = 
false;
  2179         tmr_first_cycle = 
true;
  2181         tmr_is_periodic = (tmr_desired_secs > MIN_TIMER_PERIOD);
  2182         tmr_has_timeout = (tmr_desired_timeout > MIN_TIMER_TIMEOUT);
  2185     double  elapsed_time(
double current_secs = 0.0){
  2186         if(current_secs == 0.0){
  2187             current_secs = run_time();
  2189         double s_time = (current_secs - tmr_start_secs);
  2193     double  period_time(
double current_secs = 0.0){
  2194         if(current_secs == 0.0){
  2195             current_secs = run_time();
  2197         double p_time = (current_secs - tmr_last_secs);
  2201     bool    check_period(tmr_func_t fn = NULL_PT, 
void* pm = NULL_PT);
  2206 timer::check_period(tmr_func_t tmr_fn, 
void* pm_fn){
  2207     if(! tmr_has_timeout && ! tmr_is_periodic){
  2211     tmr_current_cycle++;
  2213     bool is_over = 
false;
  2214     bool is_period = (tmr_current_cycle >= tmr_cycles);
  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;
  2225         TOOLS_CK(tmr_current_secs >= tmr_start_secs);
  2227         tmr_current_cycle = 0;
  2228         double real_period = (tmr_current_secs - tmr_last_secs);
  2229         tmr_last_secs = tmr_current_secs;
  2231         if(real_period < tmr_desired_secs){
  2233         } 
else if(tmr_cycles > 2.0){
  2236         TOOLS_CK(tmr_cycles >= 1.0);
  2238         double elpsd_tm = elapsed_time(tmr_current_secs);
  2239         if(! tmr_reporting && 
  2240             (elpsd_tm > tmr_desired_secs))
  2242             tmr_reporting = 
true;
  2245         if(tmr_has_timeout){
  2246             is_over = (elpsd_tm > tmr_desired_timeout);
  2249         bool report_prd = tmr_reporting && ! is_over && 
  2251             (   ! tmr_force_check || 
  2252                 (real_period >= tmr_desired_secs));
  2254         if(report_prd && (tmr_fn != NULL_PT)){
  2255             (*tmr_fn)(pm_fn, tmr_current_secs);