├── .gitignore ├── .htaccess ├── .old ├── b-array.cc ├── cdf-model.h ├── model.h ├── nelder-mead-min.h ├── t-cdf-model.cc ├── t-group_mean.cc ├── t-model.cc └── t-round.cc ├── 3rd └── fixed.h ├── LICENSE ├── Makefile ├── README.txt ├── a-pow.cc ├── array.h ├── b-array.h ├── b-cmp.cc ├── b-cmp.h ├── b-lower_bound.cc ├── b-sum.cc ├── b-sum.h ├── benchmark.h ├── bithacks ├── bithacks-test.c └── bithacks.h ├── blitz-promote-old.h ├── bug.cc ├── cache_arch.h ├── check.h ├── csv.h ├── defer.h ├── doc ├── .htaccess ├── Makefile ├── array │ ├── .gitignore │ ├── Makefile │ ├── array-2.pdf │ ├── index.txt │ └── summary.txt ├── e-check.cc ├── e-print-any.cc ├── e-timer.cc ├── index.txt ├── meta │ └── index.txt └── summary.txt ├── float.h ├── include.m4 ├── include.mk ├── int2float-to-add.cc ├── last_n.h ├── lvv.h ├── make_unique.h ├── math.h ├── memoize.h ├── meta.h ├── mmap.h ├── png.h ├── spool.h ├── sse.h ├── t-abs.cc ├── t-array-opt.cc ├── t-array.cc ├── t-check.cc ├── t-csv.cc ├── t-equal.cc ├── t-float-exception.cc ├── t-fpe-signal.cc ├── t-memoize.cc ├── t-mmap.cc ├── t-png.cc ├── t-progress_dots.cc ├── t-s_pool.cc ├── t-timer-c11.cc ├── t-timer.cc ├── t-type-descriptor.cc ├── timer.h ├── token.h ├── u-array-small.cc ├── u-array.cc ├── u-float.cc ├── u-last_n.cc ├── u-math.cc ├── u-meta.cc ├── u-powi.cc └── u-token.cc /.gitignore: -------------------------------------------------------------------------------- 1 | log 2 | .old 3 | *.html 4 | t-* 5 | u-* 6 | !t-*.* 7 | !u-*.* 8 | -------------------------------------------------------------------------------- /.htaccess: -------------------------------------------------------------------------------- 1 | Redirect permanent /project/lvvlib/array.html http://volnitsky.com/project/lvvlib/array/ 2 | -------------------------------------------------------------------------------- /.old/b-array.cc: -------------------------------------------------------------------------------- 1 | 2 | /////////////////// CONFIG 3 | //#define I16 4 | #define F32 5 | #define REPEAT 7 6 | 7 | 8 | #ifndef INCLUDE 9 | //#define INCLUDE "b-lower_bound.h" 10 | #define INCLUDE "b-cmp.h" 11 | //#define INCLUDE "b-sum.h" 12 | #endif 13 | 14 | #ifdef F32 15 | #define TYPE float 16 | //#define CANUSE_OMP 17 | #define CANUSE_SSE 18 | #define CANUSE_SSE2 19 | //#define CANUSE_SSE3 20 | //#define CANUSE_SSE4 21 | // _mm_minpos_epu16 22 | 23 | #define SSE_SIZE 4 24 | #define MM_ADD_OP _mm_add_ps 25 | #define MM_CMP_OP _mm_max_ps 26 | #define CMP_OP > 27 | #define REG_T __m128 28 | #define MK_REG mk_m128 29 | 30 | #define DO_PLAIN 31 | #define DO_SIMD 32 | #define DO_OMP 33 | #endif 34 | 35 | #ifdef I16 36 | #define TYPE int16_t 37 | #define CANUSE_SSE 38 | #define CANUSE_SSE2 39 | #define CANUSE_SSE3 40 | #define CANUSE_OMP 41 | 42 | #define SSE_SIZE 8 43 | #define MM_CMP_OP _mm_max_epi16 44 | #define CMP_OP > 45 | #define REG_T __m128i 46 | #define MK_REG mk_m128i 47 | #define DO_PLAIN 48 | #define DO_SIMD 49 | //#define DO_OMP 50 | #endif 51 | 52 | #ifndef TYPE 53 | #error "type (F32/I16/...) not defined" 54 | #endif 55 | 56 | 57 | #define dID 1 58 | 59 | /////////////////////////////////// 60 | #include 61 | using namespace std; 62 | 63 | #include 64 | using lvv::array; 65 | using lvv::sse; 66 | using lvv::sse2; 67 | using lvv::plain; 68 | using lvv::mk_array; 69 | 70 | #include 71 | using lvv::Timer; 72 | 73 | #include 74 | #include 75 | 76 | #include 77 | 78 | 79 | int main(int argc, char *argv[]) { 80 | 81 | /////////////////////////////////// ID 82 | cout << ID //<< " << " 83 | #ifdef CANUSE_MMX 84 | << " mmx " 85 | #endif 86 | #ifdef CANUSE_SSE 87 | << " sse " 88 | #endif 89 | #ifdef CANUSE_SSE2 90 | << " sse2 " 91 | #endif 92 | #ifdef CANUSE_OMP 93 | << " omp " 94 | #endif 95 | << ">>" << endl; 96 | 97 | /////////////////////////////////// 98 | 99 | 100 | Timer t(true); 101 | float sec, ticks; 102 | 103 | cout << "\nValue\tSeconds\t\tTick/Cycle ... Min-Tick/Cycle \t Method\n" << setprecision(4); 104 | 105 | array tick; 106 | 107 | // one-test -> one-line print 108 | // called multile time from test-cycle (cycle var: r) 109 | // print EXPR value (on r==0), individual times, minumal time, test name 110 | #define PRINT(NAME,EXPR) \ 111 | tick[r] = ticks = t.interval_ticks() / float (N); sec = t.interval_cpu(); \ 112 | if (r==0) cout << setprecision(6) << setw(11) << (EXPR) << " " << setprecision(3) << setw(8) << sec <<"\t";\ 113 | /* any r */ cout << "\t" << ticks; \ 114 | if (r==(REPEAT-1)) cout << "\t\t" << tick.min() << " \t" << NAME << endl;\ 115 | t.interval_ticks(); 116 | 117 | // include tests 118 | #include INCLUDE 119 | cerr << endl; 120 | } 121 | -------------------------------------------------------------------------------- /.old/cdf-model.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LVVMODEL_H 3 | #define LVVMODEL_H 4 | 5 | #include 6 | #include 7 | using std::fixed; 8 | using std::showpos; 9 | 10 | #include 11 | #include 12 | #include 13 | using lvv::powi; 14 | 15 | #include "multimin.h" 16 | using lvv::f_minimizer; 17 | 18 | #include 19 | using std::max; 20 | using std::min; 21 | 22 | #include 23 | using lvv::array; 24 | 25 | namespace lvv { 26 | 27 | //int const poly_order = 4; 28 | 29 | double cdf_model_eval (int M, const double x, double *C) { 30 | double poly = C[0] ; 31 | double pow_x = 1.0 ; // x[0,0]^0 32 | 33 | for (int i=1; i(gsl_vector_const_ptr(gv_param,0)); 45 | double *X = (double *) (((void **) var) [0]); 46 | double *Y = (double *) (((void **) var) [1]); 47 | int N = *(int *) (((void **) var) [2]); 48 | 49 | double sum = 0.0; 50 | for (int i=0; i < N; i++) { 51 | sum += pow2 ( Y[i] - cdf_model_eval(N, X[i], C) ); 52 | //FMT("\t X[i]=%f \t Y[i]=%f \t cdf_model_eval()=%f\n") %X[i] %Y[i] %cdf_model_eval(N, X[i], C); 53 | } 54 | 55 | //int static cnt = 0; 56 | //FMT("sse: call=%d sse=%d \t C[]: ") % cnt++ %sum << *(array*)C << endl; 57 | //copy(X, X+N, ostream_iterator(cout, " ")); 58 | return sum; 59 | } 60 | 61 | template 62 | class Model { public: ///////////////////////////////////////////////////////////// Model Data - μ² polinom fitting 63 | 64 | Model () : n(0), X(NULL), Y(NULL) {} 65 | 66 | Model (double X[], double Y[], int n ) : n(n), X(X), Y(Y) { //////////////////////////////// CTOR 67 | 68 | // N - data points [0..N) ( 5 for NF ) 69 | // M - number of model parameters [0..M) 70 | // if polynomial used in model: 71 | // M-1 - poly order C[0]..C[m-1] 72 | 73 | //assert(n >= 3 && "not implemented"); 74 | assert (n >= M); 75 | 76 | array C0 = {{ -1.73996, 0.349906, -0.0125859, 0.00720428 }}; 77 | array C_step; 78 | C_step.assign(0.1); C_step[0]= 0.5; C_step[1]=0.2; 79 | 80 | C = C0; 81 | 82 | // fit model paramS 83 | void *var[] = {X, Y, &n}; 84 | f_minimizer fm(M, sse, (double *)&C, (double *) &C_step, var); 85 | fm.find_min(2e-4, 200); 86 | //if (!fm.found) cerr << "# error model::fitting: minimum not found\n"; 87 | C = *(array*)fm.xmin; 88 | //cout << "xmin: " << *(array*) fm.xmin << endl; 89 | //cout << "C: " << C << endl; 90 | }; 91 | 92 | ~Model() { ////////////////////////////////////////////////////////////////// DTOR 93 | }; 94 | 95 | 96 | double estimate (const double x) const { 97 | if (x> 7) return 1; 98 | if (x<-1) return 0; 99 | 100 | double poly = C[0] ; 101 | double pow_x = 1.0 ; // x[0,0]^0 102 | 103 | for (int i=1; i -25); 129 | assert(r_guess < 30); 130 | cdf_guess = estimate(r_guess); 131 | if (r_step > 0 && cdf_guess < cdf) goto LOOP; 132 | if (r_step < 0 && cdf_guess > cdf) goto LOOP; 133 | 134 | 135 | 136 | ////// binary(?) search 137 | double r_low = min(r_guess, r_last); 138 | double r_high = max(r_guess, r_last); 139 | 140 | int const max_cnt = 200; 141 | double const precision = 0.0001; 142 | 143 | for (int cnt=0; cnt < max_cnt; cnt++) { 144 | double r_middle = (r_high + r_low)/2; 145 | double cdf_middle = estimate(r_middle); 146 | 147 | if (cdf_middle > cdf) r_high = r_middle; 148 | else r_low = r_middle; 149 | 150 | //PR4(cdf, cdf_middle, r_low, r_high) 151 | if ( (r_high-r_low) < precision ) 152 | break; 153 | } 154 | return (r_high+r_low)/2.; 155 | 156 | }; 157 | 158 | 159 | void print (string title="") const { 160 | cout << "# :gnuplot: set key bottom; set ytics 0,0.5; set yrange [-0.1:1.1]; set xrange [-2:7]; set grid; set pointsize 1.5;" 161 | << (title.length()>0 ? "set title \" " + title + "\";" : "") << 162 | 163 | "plot " 164 | " \"pipe\" using 1:3 title \"model\" with lines 5, " 165 | " \"pipe\" using 4:2 title \"inv x(y)\" with point 4," 166 | " \"pipe\" using 1:2 title \"data\" with points 11 " 167 | ";\n"; 168 | 169 | format table(" % 9f %20t % 9f %40t % 9f %60t % 9f\n"); 170 | string _("\" \""); 171 | cout << table % "# X" % " Y" % "Y-mod" % "X-mod-inv" ; 172 | 173 | for (int i=0; i C; 185 | array C_step; 186 | public: 187 | }; 188 | 189 | } // namespace lvv 190 | #endif // LVVMODEL_H 191 | -------------------------------------------------------------------------------- /.old/model.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LVVMODEL_H 3 | #define LVVMODEL_H 4 | 5 | #include 6 | #include 7 | using std::fixed; 8 | using std::showpos; 9 | 10 | #include 11 | #include 12 | #include 13 | #include "lvv.h" 14 | #include "math.h" 15 | using lvv::powi; 16 | 17 | 18 | namespace lvv { 19 | 20 | int const poly_order = 4; 21 | 22 | // template 23 | class Model { public: ///////////////////////////////////////////////////////////// Model Data - μ² polinom fitting 24 | 25 | 26 | Model () : n(0), m(0), x(NULL), y(NULL), X(NULL), cov(NULL), c(NULL) {} 27 | 28 | Model (double _x[], double _y[], int _n, int _m=-1) : n(_n), m(_m), x(_x), y(_y) { //////////////////////////////// CTOR 29 | 30 | // N - data points [0..N) ( 5 for NF ) 31 | // M - number of model parameters [0..M) 32 | // if polynomial used in model: 33 | // M-1 - poly order C[0]..C[m-1] 34 | 35 | assert(_n >= 3 && "not implemented"); 36 | if (_m == -1) { // then need autodetect 37 | if (n < 6 ) m = n-2; 38 | else if (n < 10) m = n-3; 39 | else if (n < 20) m = n-4; 40 | } 41 | 42 | assert(n >= m); 43 | 44 | X = gsl_matrix_alloc (n, m) ; assert(X); 45 | c = gsl_vector_alloc (m ) ; assert(c); 46 | cov = gsl_matrix_alloc (m, m) ; assert(cov); 47 | 48 | xv = gsl_vector_view_array (_x, n); 49 | yv = gsl_vector_view_array (_y, n); 50 | 51 | ///// INIT - PREP MATRIX for POLIFIT 52 | for (i = 0; idata; 85 | 86 | if (m>2) { 87 | 88 | double c0_save = C[0]; 89 | C[0] = c0_save-yy; 90 | 91 | struct { double real; double imag; } z[poly_order-1]; 92 | 93 | int order = poly_order; 94 | //if ( abs(C[poly_order-1]) < 0.000001 ) // reduce polinomial order of last elem == 0 95 | if ( C[poly_order-1] == 0 ) // reduce polinomial order of last elem == 0 96 | order = poly_order-1; 97 | assert (C[poly_order-1] != 0); // hope we don't need to do it twice 98 | 99 | // solve 100 | gsl_poly_complex_workspace * w = gsl_poly_complex_workspace_alloc (order); 101 | gsl_poly_complex_solve (gsl_vector_ptr(c,0), order, w, (double *)z); 102 | gsl_poly_complex_workspace_free (w); 103 | 104 | // select real root from list of complex roots 105 | double oorr_distance = numeric_limits::max(); // out_of_range root distance to normal interval 106 | bool got_root = false; 107 | bool got_out_of_range_root = false; 108 | double out_of_range_root = -100; 109 | double real_root = -100000; 110 | 111 | //double x_step = x[1]-x[0]; // with step p-rmse go from 0.9904215 to 0.9907456 112 | double x_lower_bound = x[0] /* -x_step/2.0 */ ; 113 | double x_upper_bound = x[n-1] /* +x_step/2.0 */ ; 114 | 115 | for (int i = 0; i < order-1; i++) { // for all roots 116 | //cerr << " \t("< 0.00000001) continue; 118 | 119 | if ( x_lower_bound <= z[i].real && z[i].real <= x_upper_bound) { // in x valid range 120 | real_root = z[i].real; 121 | got_root = true; 122 | //cerr << " rr=" << real_root; 123 | break; // found it 124 | } 125 | 126 | double below_lower_distance = x_lower_bound - z[i].real; 127 | if ( below_lower_distance > 0 ) { 128 | if (( got_out_of_range_root && below_lower_distance < oorr_distance ) || ! got_out_of_range_root) { 129 | oorr_distance = below_lower_distance; // new shortest oorr distance 130 | got_out_of_range_root = true; 131 | out_of_range_root = x_lower_bound; 132 | //cerr << " oor=" << out_of_range_root ; 133 | continue; 134 | } 135 | } 136 | 137 | double above_upper_distance = z[i].real - x_upper_bound ; 138 | if ( above_upper_distance > 0 ) { 139 | if (( got_out_of_range_root && above_upper_distance < oorr_distance ) || ! got_out_of_range_root) { 140 | oorr_distance = above_upper_distance; 141 | got_out_of_range_root = true; 142 | out_of_range_root = x_upper_bound; 143 | //cerr << " oor=" << out_of_range_root ; 144 | continue; 145 | } 146 | } 147 | 148 | }; 149 | 150 | 151 | if (got_root) xx = real_root; 152 | else if (got_out_of_range_root) xx = out_of_range_root; 153 | else { xx=3.66; cerr << "#model::inverse_estimate(): root not found\n"; ; } 154 | //cerr << " ROOT=" << xx << endl; 155 | 156 | gsl_vector_set(c, 0, c0_save); 157 | 158 | /* 159 | double c0 = gsl_vector_get(c,0); 160 | double c1 = gsl_vector_get(c,1); 161 | double c2 = gsl_vector_get(c,2); 162 | double c3 = gsl_vector_get(c,3); 163 | if ( 0 > (27*pow2(c3)*pow2(yy)+(-54*c0*pow2(c3)+18*c1*c2*c3-4*pow3(c2))*yy+27*pow2(c0)*pow2(c3)+(4*pow3(c1)-18*c0*c1*c2)*c3+4*c0*pow3(c2)-pow2(c1)*pow2(c2))) { 164 | cout << "inverse_estimate-4-1: cannot solve: c0-2" << c0 << " " << c1 << " " << c2 << " " << c3 << " y: " << yy << endl; 165 | return 3.6; 166 | } 167 | if ( 0 > 27*pow2(c3)*pow2(yy)+(-54*c0*pow2(c3)+18*c1*c2*c3-4*pow3(c2))*yy+27*pow2(c0)*pow2(c3)+(4*pow3(c1)-18*c0*c1*c2)*c3+4*c0*pow3(c2)-pow2(c1)*pow2(c2)) { 168 | cout << "inverse_estimate-4-2: cannot solve: c0-2" << c0 << " " << c1 << " " << c2 << " " << c3 << " y: " << yy << endl; 169 | return 3.6; 170 | } 171 | xx = cbrt((sqrt(27*pow2(c3)*pow2(yy)+(-54*c0*pow2(c3)+18*c1*c2*c3-4*pow3(c2))*yy+27*pow2(c0)*pow2(c3)+(4*pow3(c1)-18*c0*c1*c2)*c3+4*c0*pow3(c2)-pow2(c1)*pow2(c2))/(6*sqrt(3)*pow2(c3))-(-27*pow2(c3)*yy+27*c0*pow2(c3)-9*c1*c2*c3+2*pow3(c2))/(54*pow3(c3))))-cbrt((3*c1*c3-pow2(c2))/(9*pow2(c3)*(sqrt(27*pow2(c3)*pow2(yy)+(-54*c0*pow2(c3)+18*c1*c2*c3-4*pow3(c2))*yy+27*pow2(c0)*pow2(c3)+(4*pow3(c1)-18*c0*c1*c2)*c3+4*c0*pow3(c2)-pow2(c1)*pow2(c2))/(6*sqrt(3)*pow2(c3))-(-27*pow2(c3)*yy+27*c0*pow2(c3)-9*c1*c2*c3+2*pow3(c2))/(54*pow3(c3)))))-c2/(3*c3); 172 | 173 | } else if (m==3){ 174 | double c0 = gsl_vector_get(c,0); 175 | double c1 = gsl_vector_get(c,1); 176 | double c2 = gsl_vector_get(c,2); 177 | 178 | if(4*c2*yy-4*c0*c2+pow2(c1) < 0) { 179 | cout << "inverse_estimate-3: cannot solve: c0-2" << c0 << " " << c1 << " " << c2 << " y: " << yy << endl; 180 | return 3.6; 181 | } 182 | 183 | xx = (sqrt(4*c2*yy-4*c0*c2+pow2(c1))-c1)/(2*c2); 184 | //xx = -(sqrt(4*c2*yy-4*c0*c2+pow2(c1))+c1)/(2*c2); 185 | 186 | */ 187 | } else if (m==2){ 188 | double c0 = gsl_vector_get(c,0); 189 | double c1 = gsl_vector_get(c,1); 190 | xx = (yy-c0)/c1; 191 | } else { 192 | assert(false); 193 | } 194 | 195 | return xx; 196 | }; 197 | 198 | 199 | void print (string title="") const { 200 | cout << "# :gnuplot: set key bottom; set ytics 0,0.5; set yrange [-0.1:1.1]; set xrange [0:6]; set grid; set pointsize 1.5;" 201 | << (title.length()>0 ? "set title \" " + title + "\";" : "") << 202 | 203 | "plot " 204 | " \"pipe\" using 1:3 title \"model\" with lines 5, " 205 | " \"pipe\" using 4:2 title \"inv x(y)\" with point 4," 206 | " \"pipe\" using 1:2 title \"data\" with points 11 " 207 | ";\n"; 208 | 209 | format table(" % 9f %20t % 9f %40t % 9f %60t % 9f\n"); 210 | string _("\" \""); 211 | cout << table % "# X" % " Y" % "Y-mod" % "X-mod-inv" ; 212 | 213 | for (int i=0; i 6 | #include 7 | using std::cerr; 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace lvv { 15 | 16 | 17 | class f_minimizer { public: 18 | 19 | f_minimizer (const int N, double F(const gsl_vector*, void *), double *xa, double *ssa, void *var, bool _trace=false) 20 | : T (gsl_multimin_fminimizer_nmsimplex), trace(_trace), found(false), fmin(999999) 21 | { 22 | minex_func.n = N; 23 | minex_func.f = F; 24 | minex_func.params = var; 25 | 26 | mk_gsl_vector x (xa,N);// this is auto on stack(temp), will be copied in minimizer, // so we are fine when it will go out of scope 27 | mk_gsl_vector ss(ssa, N); 28 | //gv_x = gsl_vector_alloc(N); for (int i=0; ix->data; 36 | if (trace) cout << "# minimizer: " << gsl_multimin_fminimizer_name (minimizer) << endl; 37 | }; 38 | 39 | 40 | ~f_minimizer () { gsl_multimin_fminimizer_free(minimizer); /* gsl_vector_free(gv_x); gsl_vector_free(gv_ss) ;*/ }; 41 | 42 | 43 | void find_min (double characteristic_size, int max_iter) { 44 | int test_status=GSL_CONTINUE; // test_status: GSL_SUCCESS==0; GSL_CONTINUE==-2; 45 | 46 | if (trace) FMT("# Itr %10t Y %20t Step %30t X[0..]\n"); 47 | 48 | for ( iter=0; iterfval; 63 | if (trace ) cout << "converged to minimum at\n"; 64 | } 65 | 66 | if (trace) { 67 | FMT("%5d %10.5d %10.5d") %iter %(minimizer->fval) %size; 68 | for (unsigned i=0; i < minimizer->x->size; ++i) FMT("%10.5d") %gsl_vector_get(minimizer->x, i); 69 | cout << endl; 70 | } 71 | 72 | } 73 | } 74 | 75 | const gsl_multimin_fminimizer_type *T; 76 | gsl_multimin_fminimizer *minimizer; 77 | gsl_multimin_function minex_func; 78 | bool trace; 79 | bool found; 80 | double *xmin; 81 | double fmin; 82 | gsl_vector *gv_x; 83 | gsl_vector *gv_ss; 84 | int iter; 85 | }; 86 | } // namespace 87 | 88 | #endif // LVV_MULTIMIN_H 89 | -------------------------------------------------------------------------------- /.old/t-cdf-model.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using lvv::array; 5 | 6 | using namespace std; 7 | 8 | #include "cdf-model.h" 9 | using namespace lvv; 10 | 11 | int main (int argc, char **argv) { 12 | //////////////////////////////////////////////// 5 13 | //double X[] = {1 , 2 , 3 , 4 , 5} ; 14 | //double Y[] = { +0.0259, 0.0693, 0.1966, 0.4537, 0.8006 }; 15 | 16 | //double Y[] = { 0.0645 , 0.1649, 0.2814, 0.4427, 0.7616} ; 17 | //double Y[] = {+0.0662 , 0.2824, 0.6288, 0.8986, 0.9861} ; 18 | //double Y[] = {0 , 0 , 0 , 0.2 , 0.9} ; 19 | //double Y[] = {0.1 , 0.3 , 0.4 , 0.7 , 0.9} ; 20 | 21 | //////////////////////////////////////////////// 5+2 22 | double X[] = {-1 , 1 , 2 , 3 , 4 , 5 , 7 } ; 23 | double Y[] = { -0.01 , +0.1259, 0.43, 0.5, 0.53, 0.7006, 1.01 }; 24 | //double Y[] = { -0.01, +0.0259, 0.0693, 0.1966, 0.4537, 0.8006, 1.01 }; 25 | 26 | //double Y[] = { 0 , 0.0645 , 0.1649, 0.2814, 0.4427, 0.7616, 1} ; 27 | //double Y[] = {0 , +0.0662, 0.2824, 0.6288, 0.8986, 0.9861, 1 } ; 28 | //double Y[] = {0 , 0 , 0 , 0 , 0.2 , 0.9 , 1} ; 29 | //double Y[] = {0 , 0.1 , 0.3 , 0.4 , 0.7 , 0.9 , 1} ; 30 | 31 | int n = sizeof(X)/(sizeof(*X)); 32 | Model<6> m(X, Y, n); 33 | Model<4> m_empty; // to test default dtor/ctor 34 | 35 | m.print("t-model.cc"); 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /.old/t-group_mean.cc: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | using namespace std; 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | using lvv::group_mean; 10 | 11 | 12 | int main() { 13 | 14 | double sample_value = 1.; 15 | double samples= 20 ; 16 | double global_value = 10.; 17 | double K = 5.; 18 | 19 | for (int i=1; i < 20; i++) 20 | FMT("sv=%f sN=%f gv=%f K=%f === GM=%f\n") %sample_value %i %global_value %K %group_mean(sample_value, i, global_value, K); 21 | } 22 | -------------------------------------------------------------------------------- /.old/t-model.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | #include "model.h" 6 | using namespace lvv; 7 | 8 | int main (int argc, char **argv) { 9 | 10 | double X[] = { 1 , 2 , 3 , 4 , 5 } ; 11 | double Y[] = { +0.0259 , 0.0693, 0.1966, 0.4537, 0.8006 }; 12 | //double Y[] = { 0.0645 , 0.1649, 0.2814, 0.4427, 0.7616} ; 13 | //double Y[] = { +0.0662, 0.2824, 0.6288, 0.8986, 0.9861 }; 14 | //double Y[] = { 0 , 0 , 0 , 0.2 , 0.9} ; 15 | //double Y[] = {0.1 , 0.3 , 0.4 , 0.7 , 0.9} ; 16 | 17 | int n = sizeof(X)/(sizeof(*X)); 18 | Model m(X, Y, n); 19 | //Model<4> m_empty; // to test default dtor/ctor 20 | 21 | m.print("t-model.cc"); 22 | 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /.old/t-round.cc: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "../lvv/lvv.h" 4 | #include "../lvv/lvvmath.h" 5 | 6 | 7 | template I round(F x) { return I(x+0.5); } 8 | 9 | /////////////////////////////////////////////////////////////////// 10 | int 11 | main() { 12 | 13 | cout << "\n\n *** Test equal() ***\n"; 14 | cout << std::boolalpha; 15 | float pi=3.1415; 16 | float f9=9.999; 17 | cout << round(pi) << endl; 18 | cout << round(f9) << endl; 19 | } 20 | 21 | 22 | -------------------------------------------------------------------------------- /3rd/fixed.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008 3 | * Evan Teran 4 | * 5 | * Permission to use, copy, modify, and distribute this software and its 6 | * documentation for any purpose and without fee is hereby granted, provided 7 | * that the above copyright notice appears in all copies and that both the 8 | * copyright notice and this permission notice appear in supporting 9 | * documentation, and that the same name not be used in advertising or 10 | * publicity pertaining to distribution of the software without specific, 11 | * written prior permission. We make no representations about the 12 | * suitability this software for any purpose. It is provided "as is" 13 | * without express or implied warranty. 14 | */ 15 | 16 | #ifndef FIXED_20060211_H_ 17 | #define FIXED_20060211_H_ 18 | 19 | 20 | #include 21 | #include 22 | #include // for std::size_t 23 | #include // for CHAR_BIT 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | namespace numeric { 31 | 32 | template 33 | class Fixed; 34 | 35 | namespace detail { 36 | template 37 | struct bit_size { 38 | static const std::size_t size = sizeof(T) * CHAR_BIT; 39 | }; 40 | 41 | // helper templates to make magic with types :) 42 | // these allow us to determine resonable types from 43 | // a desired size, they also let us infer the next largest type 44 | // from a type which is nice for the division op 45 | template 46 | struct type_from_size { 47 | static const bool is_specialized = false; 48 | typedef void value_type; 49 | }; 50 | 51 | template <> 52 | struct type_from_size<64> { 53 | static const bool is_specialized = true; 54 | static const std::size_t size = 64; 55 | typedef int64_t value_type; 56 | typedef type_from_size<128> next_size; 57 | }; 58 | 59 | template <> 60 | struct type_from_size<32> { 61 | static const bool is_specialized = true; 62 | static const std::size_t size = 32; 63 | typedef int32_t value_type; 64 | typedef type_from_size<64> next_size; 65 | }; 66 | 67 | template <> 68 | struct type_from_size<16> { 69 | static const bool is_specialized = true; 70 | static const std::size_t size = 16; 71 | typedef int16_t value_type; 72 | typedef type_from_size<32> next_size; 73 | }; 74 | 75 | template <> 76 | struct type_from_size<8> { 77 | static const bool is_specialized = true; 78 | static const std::size_t size = 8; 79 | typedef int8_t value_type; 80 | typedef type_from_size<16> next_size; 81 | }; 82 | 83 | // this is to assist in adding support for non-native base 84 | // types (for adding big-int support), this should be fine 85 | // unless your bit-int class doesn't nicely support casting 86 | template 87 | B next_to_base(const N& rhs) { 88 | return static_cast(rhs); 89 | } 90 | 91 | struct divide_by_zero : std::exception { 92 | }; 93 | 94 | template 95 | void divide(const Fixed &numerator, const Fixed &denominator, Fixed "ient, Fixed &remainder, typename boost::enable_if_c::next_size::is_specialized>::type* = 0) { 96 | 97 | BOOST_STATIC_ASSERT(detail::type_from_size::next_size::is_specialized); 98 | 99 | typedef typename Fixed::next_type next_type; 100 | typedef typename Fixed::base_type base_type; 101 | static const std::size_t fractional_bits = Fixed::fractional_bits; 102 | 103 | next_type t(numerator.to_raw()); 104 | t <<= fractional_bits; 105 | 106 | quotient = Fixed::from_base(detail::next_to_base(t / denominator.to_raw())); 107 | remainder = Fixed::from_base(detail::next_to_base(t % denominator.to_raw())); 108 | } 109 | 110 | template 111 | void divide(Fixed numerator, Fixed denominator, Fixed "ient, Fixed &remainder, typename boost::disable_if_c::next_size::is_specialized>::type* = 0) { 112 | 113 | // NOTE: division is broken for large types :-( 114 | // especially when dealing with negative quantities 115 | 116 | typedef typename Fixed::base_type base_type; 117 | static const int bits = Fixed::total_bits; 118 | 119 | if(denominator == 0) { 120 | throw divide_by_zero(); 121 | quotient = 0; 122 | remainder = 0; 123 | } else { 124 | 125 | int sign = 0; 126 | 127 | if(numerator < 0) { 128 | sign ^= 1; 129 | numerator = -numerator; 130 | } 131 | 132 | if(denominator < 0) { 133 | sign ^= 1; 134 | denominator = -denominator; 135 | } 136 | 137 | base_type n = numerator.to_raw(); 138 | base_type d = denominator.to_raw(); 139 | base_type x = 1; 140 | base_type answer = 0; 141 | 142 | 143 | while((n >= d) && (((d >> (bits - 1)) & 1) == 0)) { 144 | x <<= 1; 145 | d <<= 1; 146 | } 147 | 148 | while(x != 0) { 149 | if(n >= d) { 150 | n -= d; 151 | answer |= x; 152 | } 153 | 154 | x >>= 1; 155 | d >>= 1; 156 | } 157 | 158 | quotient = answer; 159 | remainder = n; 160 | 161 | if(sign) { 162 | quotient = -quotient; 163 | } 164 | } 165 | } 166 | 167 | // this is the usual implementation of multiplication 168 | template 169 | void multiply(const Fixed &lhs, const Fixed &rhs, Fixed &result, typename boost::enable_if_c::next_size::is_specialized>::type* = 0) { 170 | 171 | BOOST_STATIC_ASSERT(detail::type_from_size::next_size::is_specialized); 172 | 173 | typedef typename Fixed::next_type next_type; 174 | typedef typename Fixed::base_type base_type; 175 | 176 | static const std::size_t fractional_bits = Fixed::fractional_bits; 177 | 178 | next_type t(static_cast(lhs.to_raw()) * static_cast(rhs.to_raw())); 179 | t >>= fractional_bits; 180 | result = Fixed::from_base(next_to_base(t)); 181 | } 182 | 183 | // this is the fall back version we use when we don't have a next size 184 | // it is slightly slower, but is more robust since it doesn't 185 | // require and upgraded type 186 | template 187 | void multiply(const Fixed &lhs, const Fixed &rhs, Fixed &result, typename boost::disable_if_c::next_size::is_specialized>::type* = 0) { 188 | 189 | typedef typename Fixed::base_type base_type; 190 | 191 | static const std::size_t fractional_bits = Fixed::fractional_bits; 192 | static const std::size_t integer_mask = Fixed::integer_mask; 193 | static const std::size_t fractional_mask = Fixed::fractional_mask; 194 | 195 | // more costly but doesn't need a larger type 196 | const base_type a_hi = (lhs.to_raw() & integer_mask) >> fractional_bits; 197 | const base_type b_hi = (rhs.to_raw() & integer_mask) >> fractional_bits; 198 | const base_type a_lo = (lhs.to_raw() & fractional_mask); 199 | const base_type b_lo = (rhs.to_raw() & fractional_mask); 200 | 201 | const base_type x1 = a_hi * b_hi; 202 | const base_type x2 = a_hi * b_lo; 203 | const base_type x3 = a_lo * b_hi; 204 | const base_type x4 = a_lo * b_lo; 205 | 206 | result = Fixed::from_base((x1 << fractional_bits) + (x3 + x2) + (x4 >> fractional_bits)); 207 | 208 | } 209 | } 210 | 211 | 212 | // lets us do things like "typedef numeric::fixed_from_type::fixed_type fixed"; 213 | // NOTE: that we will use a type of equivalent size, not neccessarily the type 214 | // specified. Should make little to no difference to the user 215 | template 216 | struct fixed_from_type { 217 | typedef Fixed::size / 2, detail::bit_size::size / 2> fixed_type; 218 | }; 219 | 220 | 221 | /* 222 | * inheriting from boost::operators enables us to be a drop in replacement for base types 223 | * without having to specify all the different versions of operators manually 224 | */ 225 | template 226 | class Fixed : boost::operators >, boost::shiftable > { 227 | BOOST_STATIC_ASSERT(detail::type_from_size::is_specialized); 228 | 229 | public: 230 | static const std::size_t fractional_bits = F; 231 | static const std::size_t integer_bits = I; 232 | static const std::size_t total_bits = I + F; 233 | 234 | typedef detail::type_from_size base_type_info; 235 | 236 | typedef typename base_type_info::value_type base_type; 237 | typedef typename base_type_info::next_size::value_type next_type; 238 | 239 | private: 240 | static const std::size_t base_size = base_type_info::size; 241 | static const base_type fractional_mask = ~((~base_type(0)) << fractional_bits); 242 | static const base_type integer_mask = ~fractional_mask; 243 | 244 | public: 245 | static const base_type one = base_type(1) << fractional_bits; 246 | 247 | public: // constructors 248 | Fixed() : data_(0) { 249 | } 250 | 251 | Fixed(long n) : data_(base_type(n) << fractional_bits) { 252 | // TODO: assert in range! 253 | } 254 | 255 | Fixed(unsigned long n) : data_(base_type(n) << fractional_bits) { 256 | // TODO: assert in range! 257 | } 258 | 259 | Fixed(int n) : data_(base_type(n) << fractional_bits) { 260 | // TODO: assert in range! 261 | } 262 | 263 | Fixed(unsigned int n) : data_(base_type(n) << fractional_bits) { 264 | // TODO: assert in range! 265 | } 266 | 267 | Fixed(float n) : data_(static_cast(n * one)) { 268 | // TODO: assert in range! 269 | } 270 | 271 | Fixed(double n) : data_(static_cast(n * one)) { 272 | // TODO: assert in range! 273 | } 274 | 275 | Fixed(const Fixed &o) : data_(o.data_) { 276 | } 277 | 278 | Fixed& operator=(const Fixed &o) { 279 | data_ = o.data_; 280 | return *this; 281 | } 282 | 283 | private: 284 | // this makes it simpler to create a fixed point object from 285 | // a native type without scaling 286 | // use "Fixed::from_base" in order to perform this. 287 | struct no_scale {}; 288 | 289 | Fixed(base_type n, const no_scale &) : data_(n) { 290 | } 291 | 292 | public: 293 | static Fixed from_base(base_type n) { 294 | return Fixed(n, no_scale()); 295 | } 296 | 297 | public: // comparison operators 298 | bool operator==(const Fixed &o) const { 299 | return data_ == o.data_; 300 | } 301 | 302 | bool operator<(const Fixed &o) const { 303 | return data_ < o.data_; 304 | } 305 | 306 | public: // unary operators 307 | bool operator!() const { 308 | return !data_; 309 | } 310 | 311 | Fixed operator~() const { 312 | Fixed t(*this); 313 | t.data_ = ~t.data_; 314 | return t; 315 | } 316 | 317 | Fixed operator-() const { 318 | Fixed t(*this); 319 | t.data_ = -t.data_; 320 | return t; 321 | } 322 | 323 | Fixed& operator++() { 324 | data_ += one; 325 | return *this; 326 | } 327 | 328 | Fixed& operator--() { 329 | data_ -= one; 330 | return *this; 331 | } 332 | 333 | public: // basic math operators 334 | Fixed& operator+=(const Fixed &n) { 335 | data_ += n.data_; 336 | return *this; 337 | } 338 | 339 | Fixed& operator-=(const Fixed &n) { 340 | data_ -= n.data_; 341 | return *this; 342 | } 343 | 344 | Fixed& operator&=(const Fixed &n) { 345 | data_ &= n.data_; 346 | return *this; 347 | } 348 | 349 | Fixed& operator|=(const Fixed &n) { 350 | data_ |= n.data_; 351 | return *this; 352 | } 353 | 354 | Fixed& operator^=(const Fixed &n) { 355 | data_ ^= n.data_; 356 | return *this; 357 | } 358 | 359 | Fixed& operator*=(const Fixed &n) { 360 | detail::multiply(*this, n, *this); 361 | return *this; 362 | } 363 | 364 | Fixed& operator/=(const Fixed &n) { 365 | Fixed temp; 366 | detail::divide(*this, n, *this, temp); 367 | return *this; 368 | } 369 | 370 | Fixed& operator>>=(const Fixed &n) { 371 | data_ >>= n.to_int(); 372 | return *this; 373 | } 374 | 375 | Fixed& operator<<=(const Fixed &n) { 376 | data_ <<= n.to_int(); 377 | return *this; 378 | } 379 | 380 | public: // conversion to basic types 381 | int to_int() const { 382 | return (data_ & integer_mask) >> fractional_bits; 383 | } 384 | 385 | unsigned int to_uint() const { 386 | return (data_ & integer_mask) >> fractional_bits; 387 | } 388 | 389 | float to_float() const { 390 | return static_cast(data_) / Fixed::one; 391 | } 392 | 393 | double to_double() const { 394 | return static_cast(data_) / Fixed::one; 395 | } 396 | 397 | base_type to_raw() const { 398 | return data_; 399 | } 400 | 401 | public: 402 | void swap(Fixed &rhs) { 403 | std::swap(data_, rhs.data_); 404 | } 405 | 406 | public: 407 | base_type data_; 408 | }; 409 | 410 | template 411 | std::ostream &operator<<(std::ostream &os, const Fixed &f) { 412 | os << f.to_double(); 413 | return os; 414 | } 415 | } 416 | #endif 417 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Leonid Volnitsky 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | .DEFAULT_GOAL := u-array-r 3 | 4 | include include.mk 5 | 6 | 7 | u-* : CXXFLAGS += 8 | #t-* u-* : *.h 9 | 10 | #CXXFLAGS += -D ASMLIB -I .. -I /usr/local/include 11 | #LDFLAGS += -L /usr/local/lib/ -l:alibelf64o.a -lgsl 12 | 13 | id: 14 | @echo "****COMP_ID " $(COMP_ID) |cat -A 15 | @echo "****_cc " $(_cc) |cat -A 16 | @echo "****_rev " $(_rev) |cat -A 17 | @echo "****_date " $(_date) |cat -A 18 | @echo "****_cpu " $(_cpu) |cat -A 19 | @echo "****_mhz " $(_mhz) |cat -A 20 | 21 | test: u-array u-powi 22 | ./u-array 23 | ./u-powi 24 | 25 | testall: u-array u-powi 26 | ./u-array 27 | ./u-powi 28 | 29 | t-png: CXXFLAGS += -I.. -O3 -Wall -march=native -DNDEBUG -I /home/lvv/p/ -std=c++0x -lpng 30 | 31 | t-lin-r: t-lin 32 | echo -e "aaaa\n1 2 3\nA: 11 22 33 44" | ./t-lin 33 | 34 | 35 | b-array-m: b-array 36 | g++ -DCOMP_ID='"."' b-array.cc -o b-array -Wall -std=c++0x -I /home/lvv/p/ -I /usr/include/boost-1_41/ -DNDEBUG -DNOCHECK -I /usr/local/include -Wstrict-aliasing=2 -pipe -Wno-reorder -Wno-sign-compare -O3 -fwhole-program --combine -fopenmp -fomit-frame-pointer -funsafe-loop-optimizations -march=opteron -static 37 | -O3 38 | 39 | t-timer: t-timer.cc 40 | $(CXX) $(CXXFLAGS) $< $(LDFLAGS) -o $@ 41 | 42 | 43 | allt: t-timer t-equal t-gzstream t-gzip 44 | 45 | 46 | 47 | install: 48 | rm -rf /usr/local/include/{lvv,lvvlib}/ 49 | mkdir -p /usr/local/include/lvv/ 50 | cp *.h /usr/local/include/lvv/ 51 | ln -sf /usr/local/include/lvv/ /usr/local/include/lvvlib 52 | 53 | debug_install: 54 | rm -rf /usr/local/include/{lvv,lvvlib}/ 55 | mkdir -p /usr/local/include/lvv/ 56 | cd /; ln -vs $(PWD)/*.h /usr/local/include/lvv/ 57 | ln -sf /usr/local/include/lvv/ /usr/local/include/lvvlib 58 | 59 | clean: 60 | rm -f *.html 61 | find -type f -executable -exec rm {} \; 62 | git clean -df 63 | 64 | t-s_pool-r: 65 | bash -c 'for i in {1..222}; do echo ===== $$i ======== ; done | ./t-s_pool' 66 | 67 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | == LvvLib - C++ utility library 2 | 3 | // HTML rendered version of this file is at: http://volnitsky.com/project/lvvlib 4 | 5 | :gh-ll: http://github.com/lvv/lvvlib/tree/master/ 6 | 7 | Private library of headers that I use in my projects. 'LVV' are my initials (Leonid V. Volnitsky). 8 | Needs some cleanup, dependency pruning and documentation. Not ready for prime 9 | time, parts of it probably bit-rotten from neglect. 10 | Files: u-* — unit tests; t-* — simple test; b-* — benchmarks 11 | 12 | === http://github.com/lvv/lvvlib/tree/master/array.h[array.h] 13 | 14 | Enhanced version of http://www.boost.org/doc/libs/1_37_0/doc/html/array.html[`boost::array`] 15 | which is plain C array wrapped in class to make it STL compatible 16 | container. If you look in such array in debugger its looks exactly like C 17 | arrays (which means you can freely cast to and from C array). 18 | There are no mallocs, no extra pointers, no extraneous class members. 19 | Because it doesn't have constructor, it is an agrigate type, meaning that it can be initialised like C arrays, 20 | some vector operation are supported. Sample use: 21 | 22 | --------------------------------- 23 | using lvv:array; 24 | array A = {{1., 2., 3.}}; 25 | array B; 26 | B = 1.; 27 | A += B; 28 | cout << "vector A: " << A << endl; 29 | cout << "vector B: " << B << endl; 30 | cout << "dot product: " << dot_prod(A,B) << endl; 31 | ------------------------------ 32 | 33 | Second set of curly braces needed because this is an array inside a class. 34 | All `B` elements are assigned scalar `1.f`, then vector `B` added to `A`, you can 35 | send `lvv::array` to `iostream`. 36 | GCC 4.4 promoted `boost::array` to `tr1::array`. 37 | 38 | .lvv::array have following added capabilities: 39 | - Vector operation 40 | - Optimized template specialization for specific combination of CPU capabilities, array size and type. 41 | * explicit SSE vectorization (gcc not very good yet in auto-vectorization). 42 | * parallelization with OpenMP 43 | * out-of order execution optimization 44 | - Index of first element defaults to 0, but can be any number. 45 | - Index value tested if it is in valid range when `NDEBUG` macro is not defined (not optimized compile). 46 | - basic linear algebra functions: `norm2(A)`, `distance_norm2(A1,A2)`, `dot_product(A1,A2)`, etc 47 | 48 | ==== Specialization 49 | Template specialization is technique which allow with zero overhead to select 50 | most appropriate implementation. Zero overhead means no run-time 51 | implementation-selection code, everything done in compile time. This is similar 52 | to run time CPU dispatch, but it is done in compile time. Selection logic is based on data-type, performed 53 | operation, target cpu, array size. Below is benchmark of specialised 54 | operations. Benchmarks are done on Core2 Duo, 2.2Ghz, with GCC-4.4. Benchmark 55 | source is at `b-*.h` files. 56 | 57 | .Sum of 100,000,000 float-s with values {1, 2, 1, 2, 1, 2 ...} 58 | [cols="3,^2,^2, 16",frame="topbot",options="header"] 59 | |============================================================================================ 60 | | *Method* | *Ticks per cycle* | *Computed Value* | *Source* 61 | | lvv::array member fn | 1.74 | 1.5e+08 | `float sum = A.sum();` // same as `sum()` 62 | | lvv::array, explicit OpenMP | 1.67 | 1.5e+08 | `float sum = A.sum();` 63 | | plain for-loop, double | 3.14 | 1.5e+08 | `double sum=0; for (int i=0; i() | 3.06 | 3.35e+07 | `float sum = accumulate(A.begin(), A.end(), 0.f));` 66 | |============================================================================================ 67 | Note that two last lines have big rounding error. Benchmark source is at b-array.cc. 68 | Further optimizatin is difficult as it is obviously memory bound. 69 | 70 | .Maximum of 100,000,000 float-s 71 | [cols="2,^1,11",frame="topbot",options="header"] 72 | |======================================================================================================================= 73 | | *Method* | *Ticks per cycle* | * *Source* 74 | | lvv::array member fn | 1.63 | `float max = A.max()` 75 | | plain for-loop | 5.81 | `float max=0; for (size_t i=0; i max) max = A[i];` 76 | | OpenMP | 1.88 | `(source same as above, 2xCPU, no check for race)` 77 | | std::max_element() | 5.81 | `float max = *std::max_element (A.begin(), A.end());` 78 | | SSE intrinsics | 1.67 | `__m128 m = mk_m128(A[0]); for (size_t i=4; i::epsilon()`). This is only possible way to make it 119 | invariant to type used. That is error expressed in ULP is about the same when 120 | we change type (needed for generic programming). 121 | 122 | The longer chain of calculation is the bigger accumulated error is. 123 | In `eq` acceptable error specified as integer ULP 124 | multiplier (3th template argument). Default is 100. 125 | 126 | For integers: If one of arguments is `unsigned` then other argument converted to unsigned type too (to avoid overflows). 127 | It is assumed that if comparison is with `unsigned` then it is guaranted that other value is positive (TODO: add assert check) 128 | 129 | 130 | === check.h 131 | 132 | Very basic unit testing. I had to write my own unit testing because gcc44 can not 133 | compile BOOST_CHECK. Implemented mostly in macros. See examples in any ++u-*.cc++ file. 134 | 135 | === Other 136 | 137 | [width="80%",cols="3,3,6",frame="none",options="header"] 138 | |========================== 139 | | Header | Sample Use | Description 140 | | {gh-ll}timer.h[timer.h]| {gh-ll}t-timer.cc[t-timer.cc] | timer of interval/total for cpu/wall/tick time (depricated by +++C++11+++) 141 | | {gh-ll}meta.h[meta.h] | {gh-ll}u-meta.cc[u-meta.cc] | meta programming 142 | | {gh-ll}float.h[float.h] | {gh-ll}u-float.cc[u-float.cc]| floating point traits and bit-twiddling 143 | | {gh-ll}mmap.h[mmap.h] | {gh-ll}t-mmap.cc[t-mmap.cc] | wrapper to simplify mmap ops. 144 | | {gh-ll}csv.h[float.h] | {gh-ll}t-csv.cc[u-float.cc] | CSV reader 145 | |========================== 146 | 147 | == Refrence 148 | http://www.ddj.com/cpp/184401967?pgno=1[Dr. Dobb's Journal: Optimizing C/C++ with Inline Assembly Programming. June 01, 2005 ] 149 | 150 | // vim:ft=asciidoc: 151 | -------------------------------------------------------------------------------- /a-pow.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | template 4 | struct S { 5 | //volatile float f=1.00001f; 6 | T eval(T x) { 7 | //volatile unsigned n = 11; 8 | //return std::pow(x,N); 9 | return ((x*x)*(x*x))*((x*x)*(x*x))*((x*x)*(x*x))*(x*x)/N + x/N; 10 | } 11 | }; 12 | 13 | int main() { 14 | 15 | volatile float vf = 1.00001f; 16 | float f = vf; 17 | //S s; 18 | //std::cout << s.eval(f); 19 | std::cout << (f*f)*(f*f); 20 | } 21 | -------------------------------------------------------------------------------- /b-array.h: -------------------------------------------------------------------------------- 1 | 2 | /////////////////// CONFIG 3 | //#define I16 4 | #define F32 5 | 6 | #ifdef F32 7 | #define TYPE float 8 | //#define CANUSE_OMP 9 | #define CANUSE_SSE 10 | #define CANUSE_SSE2 11 | //#define CANUSE_SSE3 12 | //#define CANUSE_SSE4 13 | // _mm_minpos_epu16 14 | 15 | #define SSE_SIZE 4 16 | #define MM_ADD_OP _mm_add_ps 17 | #define MM_CMP_OP _mm_max_ps 18 | #define CMP_OP > 19 | #define REG_T __m128 20 | #define MK_REG mk_m128 21 | 22 | #define DO_PLAIN 23 | #define DO_SIMD 24 | #define DO_OMP 25 | #endif 26 | 27 | #ifdef I16 28 | #define TYPE int16_t 29 | #define CANUSE_SSE 30 | #define CANUSE_SSE2 31 | #define CANUSE_SSE3 32 | #define CANUSE_OMP 33 | 34 | #define SSE_SIZE 8 35 | #define MM_CMP_OP _mm_max_epi16 36 | #define CMP_OP > 37 | #define REG_T __m128i 38 | #define MK_REG mk_m128i 39 | #define DO_PLAIN 40 | #define DO_SIMD 41 | //#define DO_OMP 42 | #endif 43 | 44 | #ifndef TYPE 45 | #error "type (F32/I16/...) not defined" 46 | #endif 47 | 48 | 49 | #define dID 1 50 | -------------------------------------------------------------------------------- /b-cmp.cc: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | 5 | using lvv::sse; 6 | using lvv::sse2; 7 | using lvv::plain; 8 | using lvv::mk_array; 9 | #include 10 | 11 | 12 | /////////////////// CONFIG 13 | //#define I16 14 | #define F32 15 | 16 | #ifdef F32 17 | #define TYPE float 18 | //#define CANUSE_OMP 19 | #define CANUSE_SSE 20 | #define CANUSE_SSE2 21 | //#define CANUSE_SSE3 22 | //#define CANUSE_SSE4 23 | // _mm_minpos_epu16 24 | 25 | #define SSE_SIZE 4 26 | #define MM_ADD_OP _mm_add_ps 27 | #define MM_CMP_OP _mm_max_ps 28 | #define CMP_OP > 29 | #define REG_T __m128 30 | #define MK_REG mk_m128 31 | 32 | #define DO_PLAIN 33 | #define DO_SIMD 34 | #define DO_OMP 35 | #endif 36 | 37 | #ifdef I16 38 | #define TYPE int16_t 39 | #define CANUSE_SSE 40 | #define CANUSE_SSE2 41 | #define CANUSE_SSE3 42 | #define CANUSE_OMP 43 | 44 | #define SSE_SIZE 8 45 | #define MM_CMP_OP _mm_max_epi16 46 | #define CMP_OP > 47 | #define REG_T __m128i 48 | #define MK_REG mk_m128i 49 | #define DO_PLAIN 50 | #define DO_SIMD 51 | //#define DO_OMP 52 | #endif 53 | 54 | #ifndef TYPE 55 | #error "type (F32/I16/...) not defined" 56 | #endif 57 | 58 | 59 | #define dID 1 60 | 61 | int main() { 62 | 63 | /////////////////////////////////// CID 64 | cout << CID //<< " << " 65 | #ifdef CANUSE_MMX 66 | << " mmx " 67 | #endif 68 | #ifdef CANUSE_SSE 69 | << " sse " 70 | #endif 71 | #ifdef CANUSE_SSE2 72 | << " sse2 " 73 | #endif 74 | #ifdef CANUSE_OMP 75 | << " omp " 76 | #endif 77 | << ">>" << endl; 78 | 79 | /////////////////////////////////// 80 | 81 | timer_t t(true); 82 | float sec, ticks; 83 | cout << "\nValue\tSeconds\t\tTick/Cycle ... Min-Tick/Cycle \t Method\n" << setprecision(4); 84 | 85 | // include tests 86 | #include "b-cmp.h" 87 | 88 | 89 | cerr << endl; 90 | } 91 | -------------------------------------------------------------------------------- /b-lower_bound.cc: -------------------------------------------------------------------------------- 1 | 2 | /////////////////////////////////// BENCHMARK CONFIG 3 | #define TYPE float 4 | #define REPEAT 4 5 | const static unsigned long N = 10000; 6 | const float test_step = 0.2f; 7 | 8 | ////////////////////////////////// 9 | 10 | #include 11 | #include 12 | 13 | int main() { 14 | 15 | 16 | BENCHMARK_HEADER 17 | 18 | 19 | array A; for (size_t i=A.ibg; i 0) { 42 | half = len >> 1; 43 | middle = first + half; 44 | if (*middle < val) { 45 | first = middle; 46 | ++first; 47 | len = len - half - 1; 48 | } 49 | else 50 | len = half; 51 | } 52 | 53 | s += *first; // found result 54 | } 55 | PRINT("loop ", s ); 56 | } 57 | 58 | for (int r=0; r= A.ibg); 64 | assert(val <= A.ien+1); 65 | dx= val - A.front(); 66 | int im = dx / step; 67 | s += A[A.ibg + im +1]; 68 | //PR2(val, A[A.ibg+im+1]); 69 | } 70 | PRINT("math ", s ); 71 | } 72 | 73 | 74 | /* 75 | while (__len > 0) { 76 | __half = __len >> 1; 77 | __middle = __first; 78 | std::advance(__middle, __half); 79 | if (*__middle < __val) 80 | { 81 | __first = __middle; 82 | ++__first; 83 | __len = __len - __half - 1; 84 | } 85 | else 86 | __len = __half; 87 | } 88 | return __first; 89 | */ 90 | 91 | //for (size_t r=0; r:", A.max() ); } 92 | 93 | 94 | cerr << endl; 95 | } 96 | -------------------------------------------------------------------------------- /benchmark.h: -------------------------------------------------------------------------------- 1 | // Benchmarks 2 | // Part of lvvlib - https://github.com/lvv/lvvlib 3 | // Copyright (c) 2000-2013 4 | // Leonid Volnitsky (Leonid@Volnitsky.com) 5 | #ifndef LVV_BENCHMARK_H 6 | #define LVV_BENCHMARK_H 7 | 8 | #ifndef REPEAT 9 | #define REPEAT 7 10 | #endif 11 | 12 | 13 | /////////////////////////////////// 14 | #include 15 | #include 16 | using namespace std; 17 | 18 | #include 19 | using lvv::array; 20 | using lvv::mk_array; 21 | 22 | #include 23 | using lvv::timer_t; 24 | 25 | 26 | 27 | 28 | ///////////////////////////////////////////////////////////////////////////////////////////// STATIC VARS 29 | array tick; 30 | timer_t t(true); 31 | float sec, ticks; 32 | 33 | 34 | 35 | ///////////////////////////////////////////////////////////////////////////////////////////// ONE-TEST -> ONE-LINE PRINT 36 | // called multile time from test-cycle (cycle var: r) 37 | // print EXPR value (on r==0), individual times, minumal time, test name 38 | #define PRINT(NAME,EXPR) \ 39 | tick[r] = ticks = t.interval_ticks() / float (N); sec = t.interval_cpu(); \ 40 | if (r==0) cerr << setprecision(6) << setw(11) << (EXPR) << " " << setprecision(3) << setw(8) << sec <<"\t";\ 41 | /* any r */ cerr << "\t" << std::fixed << ticks; \ 42 | if (r==(REPEAT-1)) cerr << "\t\t" << tick.min() << " \t" << NAME << endl;\ 43 | t.interval_ticks(); 44 | 45 | ///////////////////////////////////////////////////////////////////////////////////////////// ONLY TICKS 46 | // called multile time from test-cycle (cycle var: r) 47 | #define PRINT1 \ 48 | tick[r] = ticks = t.interval_ticks() / float (N); sec = t.interval_cpu(); \ 49 | if (r==(REPEAT-1)) cerr << setprecision(3) << setw(8) << tick.min() ;\ 50 | t.interval_ticks(); 51 | 52 | //////////////////////////////////////////////////////////////////////////////////////////// PRINT CONFIG 53 | #define BENCHMARK_HEADER cerr /*<< "*** TYPE: " << LVV_STR(TYPE) << endl*/ \ 54 | << "*** REPEAT:" << REPEAT << endl\ 55 | << "*** CID: " << "" CID << endl; \ 56 | cerr << "\nValue\tSeconds\t\tTick/Cycle ... Min-Tick/Cycle \t Method\n" << setprecision(4); 57 | 58 | #endif // LVV_BENCHMARK_H 59 | -------------------------------------------------------------------------------- /bithacks/bithacks-test.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** bithacks-test.c - tests for bithacks.h 3 | ** 4 | ** Peteris Krumins (peter@catonmat.net) 5 | ** http://www.catonmat.net -- good coders code, great reuse 6 | ** 7 | ** This file is explained in the following articles: 8 | ** http://www.catonmat.net/blog/bit-hacks-header-file 9 | ** http://www.catonmat.net/blog/low-level-bit-hacks-you-absolutely-must-know 10 | ** 11 | ** Released under the MIT license. 12 | */ 13 | 14 | #include 15 | #include 16 | 17 | #include "bithacks.h" 18 | 19 | int error_count; 20 | 21 | #define TEST_OK(exp, what) do { \ 22 | if ((exp)!=(what)) { \ 23 | error_count++; \ 24 | printf("Test '%s' at line %d failed.\n", #exp, __LINE__); \ 25 | } } while(0) 26 | 27 | #define TEST_END do { \ 28 | if (error_count) { \ 29 | printf("Testing failed: %d failed tests.\n", error_count); \ 30 | } else { \ 31 | printf("All tests OK.\n"); \ 32 | } } while (0) 33 | 34 | void test_B8() 35 | { 36 | /* test B8 */ 37 | TEST_OK(B8(0), 0); 38 | TEST_OK(B8(1), 1); 39 | TEST_OK(B8(11), 3); 40 | TEST_OK(B8(111), 7); 41 | TEST_OK(B8(1111), 15); 42 | TEST_OK(B8(11111), 31); 43 | TEST_OK(B8(111111), 63); 44 | TEST_OK(B8(1111111), 127); 45 | TEST_OK(B8(00000000), 0); 46 | TEST_OK(B8(11111111), 255); 47 | TEST_OK(B8(1010), 10); 48 | TEST_OK(B8(10101010), 170); 49 | TEST_OK(B8(01010101), 85); 50 | } 51 | 52 | void test_B_EVEN() 53 | { 54 | /* test B_EVEN */ 55 | TEST_OK(B_EVEN(B8(0)), 1); 56 | TEST_OK(B_EVEN(B8(00000000)), 1); 57 | TEST_OK(B_EVEN(B8(1)), 0); 58 | TEST_OK(B_EVEN(B8(11111111)), 0); 59 | TEST_OK(B_EVEN(B8(10101010)), 1); 60 | TEST_OK(B_EVEN(B8(01010101)), 0); 61 | TEST_OK(B_EVEN(44), 1); 62 | TEST_OK(B_EVEN(131), 0); 63 | } 64 | 65 | void test_B_ODD() 66 | { 67 | /* test B_ODD */ 68 | TEST_OK(B_ODD(B8(0)), 0); 69 | TEST_OK(B_ODD(B8(00000000)), 0); 70 | TEST_OK(B_ODD(B8(1)), 1); 71 | TEST_OK(B_ODD(B8(11111111)), 1); 72 | TEST_OK(B_ODD(B8(10101010)), 0); 73 | TEST_OK(B_ODD(B8(01010101)), 1); 74 | TEST_OK(B_ODD(44), 0); 75 | TEST_OK(B_ODD(131), 1); 76 | } 77 | 78 | void test_B_IS_SET() 79 | { 80 | /* test B_IS_SET */ 81 | TEST_OK(B_IS_SET(B8(0), 0), 0); 82 | TEST_OK(B_IS_SET(B8(00000000), 0), 0); 83 | TEST_OK(B_IS_SET(B8(1), 0), 1); 84 | TEST_OK(B_IS_SET(B8(11111111), 0), 1); 85 | TEST_OK(B_IS_SET(B8(11111111), 1), 1); 86 | TEST_OK(B_IS_SET(B8(11111111), 2), 1); 87 | TEST_OK(B_IS_SET(B8(11111111), 3), 1); 88 | TEST_OK(B_IS_SET(B8(11111111), 4), 1); 89 | TEST_OK(B_IS_SET(B8(11111111), 5), 1); 90 | TEST_OK(B_IS_SET(B8(11111111), 6), 1); 91 | TEST_OK(B_IS_SET(B8(11111111), 7), 1); 92 | TEST_OK(B_IS_SET(B8(11110000), 0), 0); 93 | TEST_OK(B_IS_SET(B8(11110000), 1), 0); 94 | TEST_OK(B_IS_SET(B8(11110000), 2), 0); 95 | TEST_OK(B_IS_SET(B8(11110000), 3), 0); 96 | TEST_OK(B_IS_SET(B8(11110000), 4), 1); 97 | TEST_OK(B_IS_SET(B8(11110000), 5), 1); 98 | TEST_OK(B_IS_SET(B8(11110000), 6), 1); 99 | TEST_OK(B_IS_SET(B8(11110000), 7), 1); 100 | TEST_OK(B_IS_SET(B8(00001111), 0), 1); 101 | TEST_OK(B_IS_SET(B8(00001111), 1), 1); 102 | TEST_OK(B_IS_SET(B8(00001111), 2), 1); 103 | TEST_OK(B_IS_SET(B8(00001111), 3), 1); 104 | TEST_OK(B_IS_SET(B8(00001111), 4), 0); 105 | TEST_OK(B_IS_SET(B8(00001111), 5), 0); 106 | TEST_OK(B_IS_SET(B8(00001111), 6), 0); 107 | TEST_OK(B_IS_SET(B8(00001111), 7), 0); 108 | TEST_OK(B_IS_SET(B8(10101010), 0), 0); 109 | TEST_OK(B_IS_SET(B8(10101010), 1), 1); 110 | TEST_OK(B_IS_SET(B8(10101010), 2), 0); 111 | TEST_OK(B_IS_SET(B8(10101010), 3), 1); 112 | TEST_OK(B_IS_SET(B8(10101010), 4), 0); 113 | TEST_OK(B_IS_SET(B8(10101010), 5), 1); 114 | TEST_OK(B_IS_SET(B8(10101010), 6), 0); 115 | TEST_OK(B_IS_SET(B8(10101010), 7), 1); 116 | TEST_OK(B_IS_SET(B8(01010101), 0), 1); 117 | TEST_OK(B_IS_SET(B8(01010101), 1), 0); 118 | TEST_OK(B_IS_SET(B8(01010101), 2), 1); 119 | TEST_OK(B_IS_SET(B8(01010101), 3), 0); 120 | TEST_OK(B_IS_SET(B8(01010101), 4), 1); 121 | TEST_OK(B_IS_SET(B8(01010101), 5), 0); 122 | TEST_OK(B_IS_SET(B8(01010101), 6), 1); 123 | TEST_OK(B_IS_SET(B8(01010101), 7), 0); 124 | } 125 | 126 | void test_B_SET() 127 | { 128 | /* test B_SET */ 129 | unsigned char x; 130 | 131 | x = B8(00000000); 132 | TEST_OK(B_SET(x, 0), B8(00000001)); 133 | TEST_OK(B_SET(x, 1), B8(00000011)); 134 | TEST_OK(B_SET(x, 2), B8(00000111)); 135 | TEST_OK(B_SET(x, 3), B8(00001111)); 136 | TEST_OK(B_SET(x, 4), B8(00011111)); 137 | TEST_OK(B_SET(x, 5), B8(00111111)); 138 | TEST_OK(B_SET(x, 6), B8(01111111)); 139 | TEST_OK(B_SET(x, 7), B8(11111111)); 140 | 141 | x = B8(11111111); 142 | TEST_OK(B_SET(x, 0), B8(11111111)); 143 | TEST_OK(B_SET(x, 1), B8(11111111)); 144 | TEST_OK(B_SET(x, 2), B8(11111111)); 145 | TEST_OK(B_SET(x, 3), B8(11111111)); 146 | TEST_OK(B_SET(x, 4), B8(11111111)); 147 | TEST_OK(B_SET(x, 5), B8(11111111)); 148 | TEST_OK(B_SET(x, 6), B8(11111111)); 149 | TEST_OK(B_SET(x, 7), B8(11111111)); 150 | } 151 | 152 | void test_B_UNSET() 153 | { 154 | unsigned char x; 155 | 156 | x = B8(11111111); 157 | TEST_OK(B_UNSET(x, 0), B8(11111110)); 158 | TEST_OK(B_UNSET(x, 1), B8(11111100)); 159 | TEST_OK(B_UNSET(x, 2), B8(11111000)); 160 | TEST_OK(B_UNSET(x, 3), B8(11110000)); 161 | TEST_OK(B_UNSET(x, 4), B8(11100000)); 162 | TEST_OK(B_UNSET(x, 5), B8(11000000)); 163 | TEST_OK(B_UNSET(x, 6), B8(10000000)); 164 | TEST_OK(B_UNSET(x, 7), B8(00000000)); 165 | 166 | x = B8(00000000); 167 | TEST_OK(B_UNSET(x, 0), B8(00000000)); 168 | TEST_OK(B_UNSET(x, 1), B8(00000000)); 169 | TEST_OK(B_UNSET(x, 2), B8(00000000)); 170 | TEST_OK(B_UNSET(x, 3), B8(00000000)); 171 | TEST_OK(B_UNSET(x, 4), B8(00000000)); 172 | TEST_OK(B_UNSET(x, 5), B8(00000000)); 173 | TEST_OK(B_UNSET(x, 6), B8(00000000)); 174 | TEST_OK(B_UNSET(x, 7), B8(00000000)); 175 | } 176 | 177 | void test_B_TOGGLE() 178 | { 179 | unsigned char x = B8(11111111); 180 | TEST_OK(B_TOGGLE(x, 0), B8(11111110)); 181 | TEST_OK(B_TOGGLE(x, 0), B8(11111111)); 182 | TEST_OK(B_TOGGLE(x, 1), B8(11111101)); 183 | TEST_OK(B_TOGGLE(x, 1), B8(11111111)); 184 | TEST_OK(B_TOGGLE(x, 2), B8(11111011)); 185 | TEST_OK(B_TOGGLE(x, 2), B8(11111111)); 186 | TEST_OK(B_TOGGLE(x, 3), B8(11110111)); 187 | TEST_OK(B_TOGGLE(x, 3), B8(11111111)); 188 | TEST_OK(B_TOGGLE(x, 4), B8(11101111)); 189 | TEST_OK(B_TOGGLE(x, 4), B8(11111111)); 190 | TEST_OK(B_TOGGLE(x, 5), B8(11011111)); 191 | TEST_OK(B_TOGGLE(x, 5), B8(11111111)); 192 | TEST_OK(B_TOGGLE(x, 6), B8(10111111)); 193 | TEST_OK(B_TOGGLE(x, 6), B8(11111111)); 194 | TEST_OK(B_TOGGLE(x, 7), B8(01111111)); 195 | TEST_OK(B_TOGGLE(x, 7), B8(11111111)); 196 | } 197 | 198 | void test_B_TURNOFF_1() 199 | { 200 | unsigned char x; 201 | 202 | x = B8(11111111); 203 | TEST_OK(B_TURNOFF_1(x), B8(11111110)); 204 | TEST_OK(B_TURNOFF_1(x), B8(11111100)); 205 | TEST_OK(B_TURNOFF_1(x), B8(11111000)); 206 | TEST_OK(B_TURNOFF_1(x), B8(11110000)); 207 | TEST_OK(B_TURNOFF_1(x), B8(11100000)); 208 | TEST_OK(B_TURNOFF_1(x), B8(11000000)); 209 | TEST_OK(B_TURNOFF_1(x), B8(10000000)); 210 | TEST_OK(B_TURNOFF_1(x), B8(00000000)); 211 | TEST_OK(B_TURNOFF_1(x), B8(00000000)); 212 | 213 | x = B8(10101010); 214 | TEST_OK(B_TURNOFF_1(x), B8(10101000)); 215 | TEST_OK(B_TURNOFF_1(x), B8(10100000)); 216 | TEST_OK(B_TURNOFF_1(x), B8(10000000)); 217 | TEST_OK(B_TURNOFF_1(x), B8(00000000)); 218 | TEST_OK(B_TURNOFF_1(x), B8(00000000)); 219 | 220 | x = B8(01010101); 221 | TEST_OK(B_TURNOFF_1(x), B8(01010100)); 222 | TEST_OK(B_TURNOFF_1(x), B8(01010000)); 223 | TEST_OK(B_TURNOFF_1(x), B8(01000000)); 224 | TEST_OK(B_TURNOFF_1(x), B8(00000000)); 225 | TEST_OK(B_TURNOFF_1(x), B8(00000000)); 226 | } 227 | 228 | void test_B_ISOLATE_1() 229 | { 230 | unsigned char x; 231 | 232 | x = B8(11111111); 233 | TEST_OK(B_ISOLATE_1(x), B8(00000001)); 234 | TEST_OK(B_ISOLATE_1(x), B8(00000001)); 235 | 236 | x = B8(11111110); 237 | TEST_OK(B_ISOLATE_1(x), B8(00000010)); 238 | TEST_OK(B_ISOLATE_1(x), B8(00000010)); 239 | 240 | x = B8(11111100); 241 | TEST_OK(B_ISOLATE_1(x), B8(00000100)); 242 | TEST_OK(B_ISOLATE_1(x), B8(00000100)); 243 | 244 | x = B8(11111000); 245 | TEST_OK(B_ISOLATE_1(x), B8(00001000)); 246 | TEST_OK(B_ISOLATE_1(x), B8(00001000)); 247 | 248 | x = B8(11110000); 249 | TEST_OK(B_ISOLATE_1(x), B8(00010000)); 250 | TEST_OK(B_ISOLATE_1(x), B8(00010000)); 251 | 252 | x = B8(11100000); 253 | TEST_OK(B_ISOLATE_1(x), B8(00100000)); 254 | TEST_OK(B_ISOLATE_1(x), B8(00100000)); 255 | 256 | x = B8(11000000); 257 | TEST_OK(B_ISOLATE_1(x), B8(01000000)); 258 | TEST_OK(B_ISOLATE_1(x), B8(01000000)); 259 | 260 | x = B8(10000000); 261 | TEST_OK(B_ISOLATE_1(x), B8(10000000)); 262 | TEST_OK(B_ISOLATE_1(x), B8(10000000)); 263 | 264 | x = B8(00000000); 265 | TEST_OK(B_ISOLATE_1(x), B8(00000000)); 266 | 267 | x = B8(10000000); 268 | TEST_OK(B_ISOLATE_1(x), B8(10000000)); 269 | 270 | x = B8(10001001); 271 | TEST_OK(B_ISOLATE_1(x), B8(00000001)); 272 | 273 | x = B8(10001000); 274 | TEST_OK(B_ISOLATE_1(x), B8(00001000)); 275 | } 276 | 277 | void test_B_PROPAGATE_1() 278 | { 279 | unsigned char x; 280 | 281 | x = B8(00000000); 282 | TEST_OK(B_PROPAGATE_1(x), B8(11111111)); 283 | TEST_OK(B_PROPAGATE_1(x), B8(11111111)); 284 | 285 | x = B8(10000000); 286 | TEST_OK(B_PROPAGATE_1(x), B8(11111111)); 287 | 288 | x = B8(11000000); 289 | TEST_OK(B_PROPAGATE_1(x), B8(11111111)); 290 | 291 | x = B8(11100000); 292 | TEST_OK(B_PROPAGATE_1(x), B8(11111111)); 293 | 294 | x = B8(11110000); 295 | TEST_OK(B_PROPAGATE_1(x), B8(11111111)); 296 | 297 | x = B8(11111000); 298 | TEST_OK(B_PROPAGATE_1(x), B8(11111111)); 299 | 300 | x = B8(11111100); 301 | TEST_OK(B_PROPAGATE_1(x), B8(11111111)); 302 | 303 | x = B8(11111110); 304 | TEST_OK(B_PROPAGATE_1(x), B8(11111111)); 305 | 306 | x = B8(11111111); 307 | TEST_OK(B_PROPAGATE_1(x), B8(11111111)); 308 | 309 | x = B8(00100000); 310 | TEST_OK(B_PROPAGATE_1(x), B8(00111111)); 311 | TEST_OK(B_PROPAGATE_1(x), B8(00111111)); 312 | 313 | x = B8(10101000); 314 | TEST_OK(B_PROPAGATE_1(x), B8(10101111)); 315 | TEST_OK(B_PROPAGATE_1(x), B8(10101111)); 316 | 317 | x = B8(10101010); 318 | TEST_OK(B_PROPAGATE_1(x), B8(10101011)); 319 | TEST_OK(B_PROPAGATE_1(x), B8(10101011)); 320 | 321 | x = B8(10101010); 322 | TEST_OK(B_PROPAGATE_1(x), B8(10101011)); 323 | TEST_OK(B_PROPAGATE_1(x), B8(10101011)); 324 | } 325 | 326 | void test_B_ISOLATE_0() 327 | { 328 | unsigned char x; 329 | 330 | x = B8(00000000); 331 | TEST_OK(B_ISOLATE_0(x), B8(00000001)); 332 | TEST_OK(B_ISOLATE_0(x), B8(00000010)); 333 | TEST_OK(B_ISOLATE_0(x), B8(00000001)); 334 | 335 | x = B8(00000011); 336 | TEST_OK(B_ISOLATE_0(x), B8(00000100)); 337 | TEST_OK(B_ISOLATE_0(x), B8(00000001)); 338 | 339 | x = B8(00000111); 340 | TEST_OK(B_ISOLATE_0(x), B8(00001000)); 341 | TEST_OK(B_ISOLATE_0(x), B8(00000001)); 342 | 343 | x = B8(00001111); 344 | TEST_OK(B_ISOLATE_0(x), B8(00010000)); 345 | TEST_OK(B_ISOLATE_0(x), B8(00000001)); 346 | 347 | x = B8(00011111); 348 | TEST_OK(B_ISOLATE_0(x), B8(00100000)); 349 | TEST_OK(B_ISOLATE_0(x), B8(00000001)); 350 | 351 | x = B8(00111111); 352 | TEST_OK(B_ISOLATE_0(x), B8(01000000)); 353 | TEST_OK(B_ISOLATE_0(x), B8(00000001)); 354 | 355 | x = B8(01111111); 356 | TEST_OK(B_ISOLATE_0(x), B8(10000000)); 357 | TEST_OK(B_ISOLATE_0(x), B8(00000001)); 358 | 359 | x = B8(11111111); 360 | TEST_OK(B_ISOLATE_0(x), B8(00000000)); 361 | 362 | x = B8(01010101); 363 | TEST_OK(B_ISOLATE_0(x), B8(00000010)); 364 | 365 | x = B8(01010111); 366 | TEST_OK(B_ISOLATE_0(x), B8(00001000)); 367 | 368 | x = B8(01011111); 369 | TEST_OK(B_ISOLATE_0(x), B8(00100000)); 370 | 371 | x = B8(01111111); 372 | TEST_OK(B_ISOLATE_0(x), B8(10000000)); 373 | } 374 | 375 | void test_B_TURNON_0() 376 | { 377 | unsigned char x; 378 | 379 | x = B8(00000000); 380 | TEST_OK(B_TURNON_0(x), B8(00000001)); 381 | TEST_OK(B_TURNON_0(x), B8(00000011)); 382 | TEST_OK(B_TURNON_0(x), B8(00000111)); 383 | TEST_OK(B_TURNON_0(x), B8(00001111)); 384 | TEST_OK(B_TURNON_0(x), B8(00011111)); 385 | TEST_OK(B_TURNON_0(x), B8(00111111)); 386 | TEST_OK(B_TURNON_0(x), B8(01111111)); 387 | TEST_OK(B_TURNON_0(x), B8(11111111)); 388 | TEST_OK(B_TURNON_0(x), B8(11111111)); 389 | 390 | x = B8(10101010); 391 | TEST_OK(B_TURNON_0(x), B8(10101011)); 392 | TEST_OK(B_TURNON_0(x), B8(10101111)); 393 | TEST_OK(B_TURNON_0(x), B8(10111111)); 394 | TEST_OK(B_TURNON_0(x), B8(11111111)); 395 | 396 | x = B8(10000000); 397 | TEST_OK(B_TURNON_0(x), B8(10000001)); 398 | TEST_OK(B_TURNON_0(x), B8(10000011)); 399 | TEST_OK(B_TURNON_0(x), B8(10000111)); 400 | TEST_OK(B_TURNON_0(x), B8(10001111)); 401 | TEST_OK(B_TURNON_0(x), B8(10011111)); 402 | TEST_OK(B_TURNON_0(x), B8(10111111)); 403 | TEST_OK(B_TURNON_0(x), B8(11111111)); 404 | } 405 | 406 | int main() 407 | { 408 | test_B8(); 409 | test_B_EVEN(); 410 | test_B_ODD(); 411 | test_B_IS_SET(); 412 | test_B_SET(); 413 | test_B_UNSET(); 414 | test_B_TOGGLE(); 415 | test_B_TURNOFF_1(); 416 | test_B_ISOLATE_1(); 417 | test_B_PROPAGATE_1(); 418 | test_B_ISOLATE_0(); 419 | test_B_TURNON_0(); 420 | 421 | TEST_END; 422 | 423 | return error_count ? EXIT_FAILURE : EXIT_SUCCESS; 424 | } 425 | 426 | -------------------------------------------------------------------------------- /bithacks/bithacks.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** bithacks.h - bit hacks macros. v1.0 3 | ** 4 | ** Peteris Krumins (peter@catonmat.net) 5 | ** http://www.catonmat.net -- good coders code, great reuse 6 | ** 7 | ** This file is explained in the following article: 8 | ** http://www.catonmat.net/blog/bit-hacks-header-file 9 | ** 10 | ** Released under the MIT license. 11 | */ 12 | 13 | #ifndef BITHACKS_H 14 | #define BITHACKS_H 15 | 16 | #define HEXIFY(X) 0x##X##LU 17 | 18 | #define B8IFY(Y) (((Y&0x0000000FLU)?1:0) + \ 19 | ((Y&0x000000F0LU)?2:0) + \ 20 | ((Y&0x00000F00LU)?4:0) + \ 21 | ((Y&0x0000F000LU)?8:0) + \ 22 | ((Y&0x000F0000LU)?16:0) + \ 23 | ((Y&0x00F00000LU)?32:0) + \ 24 | ((Y&0x0F000000LU)?64:0) + \ 25 | ((Y&0xF0000000LU)?128:0)) 26 | 27 | #define B8(Z) ((unsigned char)B8IFY(HEXIFY(Z))) 28 | 29 | /* 30 | ** Bit hack routines. See the following article for explanation: 31 | ** http://www.catonmat.net/blog/low-level-bit-hacks-you-absolutely-must-know 32 | ** 33 | */ 34 | 35 | /* test if x is even */ 36 | #define B_EVEN(x) (((x)&1)==0) 37 | 38 | /* test if x is odd */ 39 | #define B_ODD(x) (!B_EVEN((x))) 40 | 41 | /* test if n-th bit in x is set */ 42 | #define B_IS_SET(x, n) (((x) & (1<<(n)))?1:0) 43 | 44 | /* set n-th bit in x */ 45 | #define B_SET(x, n) ((x) |= (1<<(n))) 46 | 47 | /* unset n-th bit in x */ 48 | #define B_UNSET(x, n) ((x) &= ~(1<<(n))) 49 | 50 | /* toggle n-th bit in x */ 51 | #define B_TOGGLE(x, n) ((x) ^= (1<<(n))) 52 | 53 | /* turn off right-most 1-bit in x */ 54 | #define B_TURNOFF_1(x) ((x) &= ((x)-1)) 55 | 56 | /* isolate right-most 1-bit in x */ 57 | #define B_ISOLATE_1(x) ((x) &= (-(x))) 58 | 59 | /* right-propagate right-most 1-bit in x */ 60 | #define B_PROPAGATE_1(x) ((x) |= ((x)-1)) 61 | 62 | /* isolate right-most 0-bit in x */ 63 | #define B_ISOLATE_0(x) ((x) = ~(x) & ((x)+1)) 64 | 65 | /* turn on right-most 0-bit in x */ 66 | #define B_TURNON_0(x) ((x) |= ((x)+1)) 67 | 68 | /* 69 | ** more bit hacks coming as soon as I post an article on advanced bit hacks 70 | */ 71 | 72 | #endif 73 | 74 | -------------------------------------------------------------------------------- /bug.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char *argv[]) { 6 | 7 | int16_t A[2000]; for (int i=0; i<(2000-2); i+=2) { A[i]=1; A[i+1]=2; }; A[333] = 3; 8 | 9 | #define mk_m128i(x) *(__m128i*)&(x) 10 | __m128i m1 = mk_m128i(A[0]); 11 | __m128i m2 = mk_m128i(A[8]); 12 | 13 | for (int i= 16; i < 2000-16; i+=16) { // SSE 14 | m1 = _mm_max_epi16(m1, mk_m128i(A[i]) ); 15 | m2 = _mm_max_epi16(m2, mk_m128i(A[i+8]) ); 16 | } 17 | 18 | m1 = _mm_max_epi16(m1, m2); 19 | 20 | int16_t* ip = (int16_t*)&m1; 21 | printf("%hi %hi %hi %hi %hi %hi %hi %hi \n", *ip++, *ip++, *ip++, *ip++, *ip++, *ip++, *ip++, *ip); 22 | 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /cache_arch.h: -------------------------------------------------------------------------------- 1 | /* 2 | Core 2 Extreme QX6700: L1D: 32 KByte 8-way; L1I: 32 KByte; 2x4 MByte 16-way 3 | 4 | Core 2 : L1D: 32 KByte 8-way; L1I: 32 KByte; 4/2 MByte 16-way 5 | 6 | Athlon 64 X2 / FX-62: L1D: 64 KByte 2-way; L1I: 64 KByte; 2x 512 KByte / 2x 1 MByte (FX-62) 16-way 7 | 8 | Pentium 4: L1D: 16 KByte 8-way; L1I: 12 Kuops (equivalent 8 till 16 KByte); 1 MByte 8-way 9 | 10 | 11 | AMD PREFETCH and PREFETCHW 12 | • K6-2: 13 | • Small performance improvement – share FSB, low priority 14 | • Don’t add overhead through useless prefetching 15 | • K6-3: 16 | • Separate backside bus 17 | • Up to 20% improvements 18 | Hagen Paul Pfeifer 19 | 3 | 19 20 | • 64 bytes per prefetch 21 | • AMD tip: prefetch 192 (3*64) bytes ahead or three cachelines (Prefetch 22 | Distance) 23 | • BTW: FSB and AMD is a separate topic (keyword HyperTransport, 24 | Memory controller, Direct Connect Architecture ) 25 | 26 | 27 | ------------------- 28 | Pentium 3 has a 32-byte cacheline size, while a Core 2 has a 64-byte cacheline. 29 | 30 | 31 | */ 32 | -------------------------------------------------------------------------------- /check.h: -------------------------------------------------------------------------------- 1 | // Simple unit test. 2 | // Part of lvvlib - https://github.com/lvv/lvvlib 3 | // Copyright (c) 2000-2013 4 | // Leonid Volnitsky (Leonid@Volnitsky.com) 5 | 6 | #ifndef LVV_CHECK_H 7 | #define LVV_CHECK_H 8 | #include 9 | using std::cout; 10 | using std::endl; 11 | //#include 12 | 13 | namespace check { 14 | 15 | ///////////////////////////////////////////////////////////////////////////////////// TEST MACROS 16 | static __attribute__((unused)) bool all_pass=true; 17 | static bool result=false; 18 | #define PASS " pass " 19 | #define FAIL ">>> FAIL <<<" 20 | #define RESULT std::cout << (check::result ? PASS : FAIL) << " " << __LINE__ << "\t\t"; 21 | 22 | 23 | #define CHECK(e) check::result=(e); check::all_pass = check::all_pass && check::result; RESULT; std::cout << "check: \t" #e << std::endl; 24 | 25 | /* 26 | #define CHECK_ARE_FP_EQUAL(e1,e2) result=(eq((e1),(e2))); all_pass = (all_pass && result); RESULT; \ 27 | if (result) std::cout << "are equal: \t" << #e1 "\t == " #e2 << std::endl; \ 28 | else std::cout << "are equal: \t" << #e1 "\t == " #e2 << " (values: " << (e1) << ", " << (e2) << ")" << std::endl; 29 | */ 30 | 31 | #define CHECK_TYPES_ARE_SAME(T,U) check::result=std::is_same::value; check::all_pass = (check::all_pass && check::result); RESULT; \ 32 | if (check::result) std::cout << "same: \t" << #T "\t == " #U << std::endl; \ 33 | else std::cout << "same: \t" << #T "\t == " #U << " (values: " << type2name() << ", " << type2name() << ")" << std::endl; 34 | 35 | #define CHECK_ARE_EQUAL(e1,e2) check::result=((e1)==(e2)); check::all_pass = (check::all_pass && check::result); RESULT; \ 36 | if (check::result) std::cout << "are equal: \t" << #e1 "\t == " #e2 << std::endl; \ 37 | else std::cout << "are equal: \t" << #e1 "\t == " #e2 << " (values: " << (e1) << ", " << (e2) << ")" << std::endl; 38 | 39 | #define CHECK_NOT_EQUAL(e1,e2) check::result=((e1)!=(e2)); check::all_pass = (check::all_pass && check::result); RESULT; \ 40 | if (check::result) std::cout << "are not equal: \t" << #e1 "\t != " #e2 << std::endl; \ 41 | else std::cout << "are not equal: \t" << #e1 "\t != " #e2 << " values: " << (e1) << ", " << (e2) << std::endl; 42 | 43 | 44 | #define CHECK_EXIT \ 45 | std::cout << (check::all_pass ? "\n------------ all pass ------------\n" : "\n!!!!!!!!! SOME FAILED !!!!!!!!\n"); \ 46 | exit(check::all_pass ? 0 : 1); 47 | 48 | // aliases 49 | #define CHECKeq CHECK_ARE_EQUAL 50 | #define CHECKneq CHECK_NOT_EQUAL 51 | 52 | }; // namespace check 53 | #endif // LVV_CHECK_H 54 | -------------------------------------------------------------------------------- /csv.h: -------------------------------------------------------------------------------- 1 | // CVS reader 2 | // Part of lvvlib - https://github.com/lvv/lvvlib 3 | // Copyright (c) 2000-2013 4 | // Leonid Volnitsky (Leonid@Volnitsky.com) 5 | 6 | #ifndef LVV_CSV_H 7 | #define LVV_CSV_H 8 | 9 | // from http://www.daniweb.com/code/snippet217438.html 10 | // 11 | // TOFIX: If the last input line isn't terminated by right recordDelim character last returned record doesn't contain last value. 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | /// loads a CSV record from the stream is 18 | /// 19 | /// * leading and trailing white space is removed outside of 20 | // quoted sections when trimWhiteSpace is true 21 | /// * line breaks are preserved in quoted sections 22 | /// * quote literals consist of two adjacent quote characters 23 | /// * quote literals must be in quoted sections 24 | /// 25 | /// input stream for CSV records 26 | /// trims white space on unquoted fields 27 | /// field delimiter. defaults to ',' for CSV 28 | /// record delimiter. defaults to '\n' for CSV 29 | /// delimiter for quoted fields. defaults to '"' 30 | /// a list of fields in the record 31 | 32 | namespace lvv { 33 | 34 | std::vector 35 | csv_get_line( std::istream & is, bool trimWhiteSpace = true, const char fieldDelim = ',', const char recordDelim = '\n', const char quote = '"') { 36 | using namespace std; 37 | 38 | vector < string > record; // result record list. default empty 39 | string field; // temporary field construction zone 40 | int start = -1, // start of a quoted section for trimming 41 | end = -1; // end of a quoted section for trimming 42 | char ch; 43 | 44 | while (is.get(ch)) { 45 | if (ch == fieldDelim || ch == recordDelim) 46 | // fieldDelim and recordDelim mark the end of a 47 | // field. save the field, reset for the next field, 48 | // and break if there are no more fields 49 | { 50 | if (trimWhiteSpace) 51 | // trim all external white space 52 | // exclude chars between start and end 53 | { 54 | const string wsList = " \t\n\f\v\r"; 55 | int ePos, sPos; 56 | 57 | // order dependency: right trim before let trim 58 | // left trim will invalidate end's index value 59 | if ((ePos = field.find_last_not_of(wsList)) != string::npos) { 60 | // ePos+1 because find_last_not_of stops on white space 61 | field.erase((end > ePos) ? end : ePos + 1); 62 | } 63 | 64 | if ((sPos = field.find_first_not_of(wsList)) != string::npos) { 65 | field.erase(0, (start != -1 && start < sPos) ? start : sPos); 66 | } 67 | // reset the quoted section 68 | start = end = -1; 69 | } 70 | // save the new field and reset the temporary 71 | record.push_back(field); 72 | field.clear(); 73 | 74 | // exit case 1: !is, managed by loop condition 75 | // exit case 2: recordDelim, managed here 76 | if (ch == recordDelim) 77 | break; 78 | } else if (ch == quote) { 79 | // save the start of the quoted section 80 | start = field.length(); 81 | 82 | while (is.get(ch)) { 83 | if (ch == '"') { 84 | // consecutive quotes are an escaped quote literal 85 | // only applies in quoted fields 86 | // 'a""b""c' becomes 'abc' 87 | // 'a"""b"""c' becomes 'a"b"c' 88 | // '"a""b""c"' becomes 'a"b"c' 89 | if (is.peek() != '"') { 90 | // save the end of the quoted section 91 | end = field.length(); 92 | break; 93 | } else 94 | field.push_back(is.get()); 95 | } else 96 | field.push_back(ch); 97 | } 98 | } else 99 | field.push_back(ch); 100 | } 101 | 102 | return record; 103 | } 104 | 105 | 106 | }; // namespace lvv 107 | #endif // LVV_CSV_H 108 | -------------------------------------------------------------------------------- /defer.h: -------------------------------------------------------------------------------- 1 | http://blog.korfuri.fr/post/go-defer-in-cpp/ 2 | -------------------------------------------------------------------------------- /doc/.htaccess: -------------------------------------------------------------------------------- 1 | Redirect permanent /project/lvvlib/array.html http://volnitsky.com/project/lvvlib/array/ 2 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | HOMEDIR ?= /home/lvv/p/volnitsky.com/ 2 | include $(HOMEDIR)/include.mk 3 | COPY_LIST = .htaccess 4 | 5 | -------------------------------------------------------------------------------- /doc/array/.gitignore: -------------------------------------------------------------------------------- 1 | *.png 2 | -------------------------------------------------------------------------------- /doc/array/Makefile: -------------------------------------------------------------------------------- 1 | HOMEDIR ?= /home/lvv/p/volnitsky.com/ 2 | include $(HOMEDIR)/include.mk 3 | 4 | #index.html: force-remake 5 | -------------------------------------------------------------------------------- /doc/array/array-2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lvv/lvvlib/b610a089103853e7cf970efde2ce4bed9f505090/doc/array/array-2.pdf -------------------------------------------------------------------------------- /doc/array/index.txt: -------------------------------------------------------------------------------- 1 | 2 | LVV::ARRAY 3 | ========== 4 | 5 | // HTML rendered version of this file is at: http://volnitsky.com/project/lvvlib/array 6 | 7 | :gh-lvvlib: httpx://github.com/lvv/lvvlib/tree/master/ 8 | 9 | include::summary.txt[] 10 | 11 | lvv::array is plain C-array wrapped in class. Wrapping adds zero memory and speed overhead. 12 | As C-arrays the lvv::array is static-sized, meaning "known at compile time size". 13 | 14 | Quick Start 15 | ----------- 16 | 17 | ----------------------------------------------- 18 | using lvv::array; 19 | 20 | // These are plain C++, not a C++0x constructors. 21 | // Second set of curly braces is optional, but 22 | // some compilers issues warning if single set of braces is used. 23 | array A = {{1., 2., 3.}}; 24 | array B; 25 | array C = {{10., 20., 30.}}; 26 | array RES; 27 | 28 | B = 1.0; // all elements are assigned `1.0f` 29 | RES = A+C; // vector op 30 | RES += B; // vector op 31 | 32 | // you can send an array to iostream 33 | cout << "vector A : " << A << endl; 34 | cout << "vector B : " << B << endl; 35 | cout << "vector C : " << C << endl; 36 | cout << "vector RES : " << RES << endl; 37 | cout << "dot product: " << dot(A,B) << endl; 38 | ------------------------------------ 39 | 40 | Output: 41 | ------------------------------------ 42 | vector A : 1 2 3 43 | vector B : 1 1 1 44 | vector C : 10 20 30 45 | vector RES : 12 23 34 46 | dot product: 6 47 | ------------------------------------- 48 | 49 | 50 | Speed 51 | ----- 52 | 53 | Some operation were substantially accelerated (explicitly specialized) using meta-programing, 54 | explicit vectorisation (with SSE), parallel programming (with OpenMP), out of order optimization, and some inline assembly. 55 | Below are some {gh-lvvlib}b-array.cc[benchmarks] on two-core, 2200Mhz Core2 Duo CPU: 56 | 57 | === array::sum() 58 | 59 | ["mpl", "speed-sum.png"] 60 | ----------------------------------------- 61 | title('SUM - benchmark lvv::array.sum()') 62 | xlabel('CPU ticks per array element') 63 | benchmark(c[0], c[1]) 64 | _________________________________________ 65 | 'plain for-loop, double ', 3.14 66 | 'plain for-loop, float ', 3.06 67 | 'std::accumulate() ', 3.06 68 | 'lvv::array.sum() ', 1.74 69 | ----------------------------------------- 70 | 71 | //'lvv::array.sum() ', 1.67 72 | 73 | Tick refer to CPU tick and is about 0.45 nano seconds. 74 | Sum was done for 100,000,000 float-s with values {1.f, 2.f, 1.f, 2.f, 1.f, 2.f ...}. Same benchmark is in below table: 75 | 76 | [cols="3s,^2,^2, 16",frame="topbot",options="header"] 77 | |============================================================================================ 78 | ^.^| *Method* | *Ticks per element* | *Computed Value* ^.^| *Source* 79 | | plain for-loop, double | 3.14 | 1.5e+08 | `double sum=0; for (int i=0; i() | 3.06 | 3.35e+07 | `float sum = accumulate(A.begin(), A.end(), 0.f));` 82 | | lvv::array | 1.74 | 1.5e+08 | `float sum = A.sum();` 83 | |============================================================================================ 84 | //| lvv::array, explicit OpenMP | 1.67 | 1.5e+08 | `float sum = A.sum();` 85 | 86 | SSE method is selected (through meta-programming) if no summation method explicitly specified (if CPU supports SSE). 87 | Note that float plain-for-loop and std::accumulate methods have incorrect computed values due to rounding error. 88 | 89 | 90 | === array::max() 91 | 92 | // Now benchmark for .max() method: 93 | 94 | ["mpl", "speed-max.png"] 95 | ----------------------------------------- 96 | title('MAX -- lvv::array.max() benchmark') 97 | xlabel('CPU ticks per array element') 98 | benchmark(c[0], c[1]) 99 | _________________________________________ 100 | 'plain for-loop ', 5.81 101 | 'std::max_element() ', 5.81 102 | 'lvv::array.sum() ', 1.63 103 | ----------------------------------------- 104 | //'SSE intrinsics ', 1.67 105 | // RETEST: 'OpenMP ', 1.88 106 | 107 | Maximum search was done on 100,000,000 float-s 108 | 109 | [cols="2,^1,11",frame="topbot",options="header"] 110 | |======================================================================================================================= 111 | ^.^| *Method* | *Ticks per element* ^.^| *Source* 112 | | plain for-loop | 5.81 | `float max=0; for (size_t i=0; i max) max = A[i];` 113 | | std::max_element() | 5.81 | `float max = *std::max_element (A.begin(), A.end());` 114 | | lvv::array | 1.63 | `float max = A.max()` 115 | |======================================================================================================================== 116 | //| SSE intrinsics | 1.67 | `__m128 m = mk_m128(A[0]); for (size_t i=4; i 2 | using namespace lvv; 3 | 4 | int main() { 5 | // Check basic math 6 | CHECK(1+2 == 3); // eval expression; 7 | CHECK(2*2 == 4); // prints pass/fail, line-number and expression 8 | CHECK(1/2 == 0.5); 9 | CHECK(4-2 == 2); 10 | 11 | CHECK_EXIT; // prints failure if any test fails, success otherwise 12 | } 13 | -------------------------------------------------------------------------------- /doc/e-print-any.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | 5 | vector V = {0, 1, 2, 3, 4, 5, 6}; 6 | cout << V << endl; 7 | 8 | list L = {0, 1, 2, 3, 4, 5, 6}; 9 | cout << L << endl; 10 | 11 | set S = {6,3,4,1,2,0,5}; 12 | cout << S << endl; 13 | 14 | map M = { {"A",1}, {"B",2}, {"C",3} }; 15 | cout << M << endl; 16 | 17 | cout << make_pair("abcd", 123) << endl; 18 | } 19 | -------------------------------------------------------------------------------- /doc/e-timer.cc: -------------------------------------------------------------------------------- 1 | #include 2 | using lvv::Timer; 3 | using lvv::read_tick; 4 | 5 | int main() { 6 | Timer tm; // CTOR inits total counters and interval counters 7 | // any timer read, resets conresponding interval counter 8 | // reset() - resets all intervals timers 9 | 10 | cout << "\n usleep(30000) ... \n"; usleep(useconds_t(30000)); 11 | 12 | cout << "\n interval_ticks(): " << tm.interval_ticks(); 13 | cout << "\n interval_wall(): " << tm.interval_wall(); 14 | cout << "\n interval_cpu(): " << tm.interval_cpu(); 15 | 16 | cout << "\n\n usleep(20000) ... \n"; usleep(useconds_t(20000)); 17 | 18 | cout << "\n total_ticks(): " << tm.total_ticks(); 19 | cout << "\n total_wall(): " << tm.total_wall(); 20 | cout << "\n total_cpu(): " << tm.total_cpu(); 21 | 22 | cout << "\n\n Raw CPU tick reader: " << read_tick() << endl; 23 | } 24 | -------------------------------------------------------------------------------- /doc/index.txt: -------------------------------------------------------------------------------- 1 | LvvLib - C++ utility library 2 | ============================ 3 | 4 | 5 | // HTML rendered version of this file is at: http://volnitsky.com/project/lvvlib 6 | 7 | MMAP.H 8 | ------- 9 | 10 | Wraps and simplifies use of mmap(2) and munmap(2) functions. 11 | 12 | Example of how to save an object of type T: 13 | 14 | #define path "t.mmap" 15 | T a; 16 | mmap_write(path,out); // saves object a 17 | T& b = mmap_read(path); // restore object a in object b 18 | 19 | 20 | Same, but now we save an array: 21 | T a[n]; 22 | mmap_write(path,a); 23 | 24 | size_t n; // array size 25 | T *b = mmap_read(path,n); // restore it, size in n 26 | for (size_t i=0; i::epsilon()`. 64 | 65 | // FIXME add example 66 | 67 | Error in floating point expression is proportional to absolute value of 68 | compared values. Error will be bigger for `10000` than for `0.00001` and 69 | bigger for `float` than for `double`. This absolute value here is called 70 | _characteristic value_. Usually characteristic value is equal to value that we 71 | want to compare, and that is what `eq` defaults to: average of absolutes of 72 | compared values (1st and 2nd argument). But in chain of calculations 73 | characteristic value can be different and this is why we might need to 74 | explicitly specify it. For example in: `x=1000.1; y=x-1000.` characteristic 75 | value of `y` is `1000` even though it is approximately equal to `0.1`. 76 | 77 | For integer types exact comparison will be used and ULPs and characteristic value are ignored. 78 | Also if one of arguments is `unsigned` then other argument converted to unsigned type too (to avoid overflows). 79 | It is assumed that if comparison is with `unsigned` then it is guaranted that other value is positive (TODO: add assert check) 80 | //////////////////////////// 81 | 82 | 83 | 84 | CHECK.H 85 | ------- 86 | Very basic unit testing. 87 | 88 | Example use: 89 | --------------------------------- 90 | include::e-check.cc[] 91 | ---------------------------------- 92 | 93 | 94 | Output: 95 | --------------------- 96 | pass 6 check: 1+2 == 3 97 | pass 7 check: 2*2 == 4 98 | >>> FAIL <<< 8 check: 1/2 == 0.5 99 | 100 | !!!!!!!!! SOME FAILED !!!!!!!! 101 | 102 | --------------------- 103 | 104 | See also any ++u-*.cc++ file. 105 | 106 | 107 | SIMPLE.H 108 | -------- 109 | Used for something like Google CodeJam. Includes most common STL headers; can print 110 | any STL containers simply by `cout << C`; simplified line-oriented input (for CodeJam). 111 | 112 | 113 | Example use: 114 | --------------------------------- 115 | include::e-print-any.cc[] 116 | ---------------------------------- 117 | 118 | Output: 119 | ----------------------- 120 | 0, 1, 2, 3, 4, 5, 6 size:7 121 | 0, 1, 2, 3, 4, 5, 6 size:7 122 | 0, 1, 2, 3, 4, 5, 6 size:7 123 | , , size:3 124 | 125 | ----------------------- 126 | 127 | TIMER.H 128 | ------- 129 | Various timer funcion: interval/total for cpu/wall/tick time. Extensivly used 130 | for benchmarking. 131 | 132 | Example use: 133 | --------------------------------- 134 | include::e-timer.cc[] 135 | ---------------------------------- 136 | 137 | 138 | 139 | Other 140 | ----- 141 | [width="80%",cols="3,3,6",frame="none",options="header"] 142 | |========================== 143 | | Header | Sample Use | Description 144 | | mmap.h | t-mmap.cc | simplified mmap files ops. 145 | | meta.h | u-meta.cc | meta programming 146 | | float.h | u-float.cc | floating point traits and bit-twiddling 147 | | sse.h | u-array.cc | sse 148 | |========================== 149 | 150 | include::~/p/volnitsky.com/project/howto-submit-patch.txt[] 151 | 152 | // TR http://stackoverflow.com/questions/199333/best-way-to-detect-integer-overflow-in-c-c 153 | 154 | 155 | // vim:ft=asciidoc: 156 | -------------------------------------------------------------------------------- /doc/meta/index.txt: -------------------------------------------------------------------------------- 1 | = Template Metaprograming - META.H 2 | 3 | See list of avalable functions and sample use in meta.h unit test output: 4 | 5 | ----------------------------------------------------------------------------- 6 | #@make u-meta.cc 7 | make[1]: Leaving directory `/home/lvv/p/lvvlib' 8 | ./u-meta 9 | ********* PROMOTE<> ********** 10 | --(26)-- (type_descriptor::type >() ) = int32_t 11 | --(27)-- (type_descriptor::type >() ) = double 12 | --(29)-- (type_descriptor::promote_type >() ) = double 13 | --(30)-- (type_descriptor::promote_type >() ) = int32_t 14 | --(31)-- (type_descriptor::promote_type >() ) = float 15 | --(32)-- (type_descriptor::promote_type >() ) = float 16 | --(33)-- (type_descriptor::promote_type >() ) = float 17 | --(34)-- (type_descriptor::promote_type >() ) = int32_t 18 | --(35)-- (type_descriptor::promote_type >() ) = uint32_t 19 | --(36)-- (type_descriptor::promote_type >() ) = long double 20 | 21 | 22 | *** Test is_integral *** 23 | --(39)-- std::tr1::is_integral::value = 1 24 | --(40)-- std::tr1::is_integral::value = 0 25 | --(41)-- std::tr1::is_integral::value = 0 26 | ********* RATIO_<> ********** 27 | pass 45 are equal: (ratio_<2>::denominator) == 1 28 | pass 46 are equal: (ratio_<2,3>::denominator) == 3 29 | pass 47 are equal: (ratio_<2,3>::numerator) == 2 30 | pass 48 are equal: (ratio_<2,3>::convert()) == float(2./3.) 31 | pass 49 are equal: (ratio_<2,3>::convert()) == 0 32 | pass 50 are equal: (ratio_<1,2>::convert()) == 1./2. 33 | pass 51 are equal: (ratio_<0,3>::convert()) == float(0.) 34 | pass 52 are equal: (ratio_<-2,3>::convert()) == float(2./-3.) 35 | pass 53 are equal: (ratio_<1,1000>::convert()) == float(0.001) 36 | ********* FP<> ********** 37 | pass 58 are equal: (fp::value) == float(0.2) 38 | pass 59 are equal: (fp::value) == 2 39 | pass 60 are equal: (fp::value) == 20 40 | ********* INT_<> ********** 41 | pass 64 are equal: (int_<3>::value) == 3 42 | pass 65 are equal: (int_<-3>::value) == -3 43 | pass 66 are equal: (int_<3>::numerator) == 3 44 | pass 67 are equal: (int_<3>::denominator) == 1 45 | pass 68 are equal: (int_<3>::convert()) == 3. 46 | ********* PLUS<> and MINUS<> ********** 47 | pass 71 are equal: (lvv::plus < ratio_<1,3>, ratio_<1,3> >::type::convert()) == 2./3. 48 | pass 72 are equal: (lvv::plus < ratio_<1,3>, int_<2> >::type::convert()) == 2.+1./3. 49 | pass 73 are equal: (lvv::minus< ratio_<1,3>, int_<2> >::type::convert()) == 1./3.-2. 50 | pass 74 are equal: (lvv::minus< int_<2>, ratio_<1,3> >::type::convert()) == 2.-1./3. 51 | ***** IPOW ******* 52 | pass 80 are equal: (lvv::ipow<3,0>::value) == 1 53 | pass 81 are equal: (lvv::ipow<3,1>::value) == 3 54 | pass 82 are equal: (lvv::ipow<3,2>::value) == 9 55 | ***** ILOG2 ******* 56 | pass 85 are equal: (lvv::ilog2<1>::value) == 0 57 | pass 86 are equal: (lvv::ilog2<2>::value) == 1 58 | pass 87 are equal: (lvv::ilog2<4>::value) == 2 59 | pass 88 are equal: (lvv::ilog2<256>::value) == 8 60 | 61 | ------------ all pass ------------ 62 | ------------------------------------------------------------------------- 63 | 64 | -------------------------------------------------------------------------------- /doc/summary.txt: -------------------------------------------------------------------------------- 1 | Initially collection of C++ headers that I used in my projects. 'LVV' are my initials (Leonid V. Volnitsky). 2 | Needs some cleanup, dependency pruning and documentation. 3 | -------------------------------------------------------------------------------- /float.h: -------------------------------------------------------------------------------- 1 | // Floating point numers utilities 2 | // Part of lvvlib - https://github.com/lvv/lvvlib 3 | // Copyright (c) 2000-2013 4 | // Leonid Volnitsky (Leonid@Volnitsky.com) 5 | #ifndef LVV_FLOAT_H 6 | #define LVV_FLOAT_H 7 | namespace lvv { 8 | 9 | // TR floating point utils: http://www.codeproject.com/KB/cpp/floatutils.aspx 10 | // TR http://stackoverflow.com/questions/17333/most-effective-way-for-float-and-double-comparison/3423299#3423299 11 | 12 | ////////////////////////////////////////////////////////////////////////////////////////////// IEEE FLOATING POINT 13 | template struct fp { 14 | T const static value = M * (E > 0 ? ipow<10,E>::value : ( E < 0 ? T(1)/T(ipow<10,-E>::value) : 1) ); 15 | }; 16 | 17 | template<> struct fp { 18 | enum { 19 | mantissa_size = 23, 20 | mantissa_mask = 0x7FFFFF, 21 | //const long evoreal::FLT_EXP_BITS = 0x7F800000L; 22 | //const long evoreal::DBL_EXP_BITS = 0x7FF00000UL; 23 | exponent_size = 8, 24 | sign_mask = 0x80000000 25 | }; 26 | typedef uint32_t uint_t; 27 | float static const one_ulp_magic = 0x1.0p23f; 28 | float static const floor_one_ulp_magic = 0x1.0p23f*1.5f+1; 29 | }; 30 | 31 | template<> struct fp { 32 | enum { 33 | mantissa_size = 52, 34 | exponent_size = -1 35 | }; 36 | typedef uint64_t uint_t; 37 | uint64_t static const mantissa_mask = (~(~1L<<52)); 38 | uint64_t static const sign_mask = 0x8000000000000000; 39 | float static const one_ulp_magic = 6755399441055744.0; //2^52 * 1.5 40 | }; 41 | 42 | //////////////////////////////////////////////////////////////////////////////////// TODO ABS 43 | /* make x = abs(x) */ 44 | // TO TRY: *(((int *) &x) + 1) &= 0x7fffffff; 45 | //------------------------------------------------------------ 46 | // TO TRY 47 | // bool is_negative(float x) { 48 | // unsigned int *ui = (unsigned int *)&x; 49 | // return (*ui & 0x80000000 != 0); 50 | // } 51 | 52 | // bool is_negative(float x) { 53 | // union { 54 | // unsigned int ui; 55 | // float d; 56 | // } my_union; 57 | // my_union.d = x; 58 | // return (my_union.ui & 0x80000000 != 0); 59 | // } 60 | //////////////////////////////////////////////////////////////////////////////////// TODO COMPARE 61 | // FROM http://aggregate.org/MAGIC/#Absolute%20Value%20of%20a%20Float 62 | // #define FasI(f) (*((int *) &(f))) 63 | // #define FasUI(f) (*((unsigned int *) &(f))) 64 | // 65 | // #define lt0(f) (FasUI(f) > 0x80000000U) 66 | // #define le0(f) (FasI(f) <= 0) 67 | // #define gt0(f) (FasI(f) > 0) 68 | // #define ge0(f) (FasUI(f) <= 0x80000000U) 69 | // 70 | 71 | //////////////////////////////////////////////////////////////////////////////////// TODO RECIPROCAL 72 | // This is about 2.12 times faster than using 1.0f / n 73 | // 74 | // r = 1/p 75 | /* 76 | #define FP_INV(r,p) { \ 77 | int _i = 2 * 0x3F800000 - *(int *)&(p); \ 78 | (r) = *(float *)&_i; \ 79 | (r) = (r) * (2.0f - (p) * (r)); \ 80 | } 81 | */ 82 | 83 | //////////////////////////////////////////////////////////////////////////////////// FLOOR 84 | 85 | // floor(float) 86 | const static float fm = 0x1.0p23f*1.5f+1; // 2^52 * 1.5, uses limited precisicion to floor 87 | const static float fmd = 1.5e-8; // .5f + 1e^(number of exp bit) 88 | const static float fme = .5f-fmd; // .5f - 1e^(number of exp bit) 89 | 90 | float static inline floor(float x) { return x - fme + fm - fm; } 91 | float static inline ceil (float x) { return x - fme + fm - fm + 1; } 92 | float static inline BROKEN_trunc(float x) { return x + 0x1.0p23f - 0x1.0p23f; } 93 | 94 | // floor(double) 95 | const static double dm = 6755399441055744.0; //2^52 * 1.5, uses limited precisicion to floor 96 | const static double dmd = 1.5e-8; //almost .5f = .5f + 1e^(number of exp bit) 97 | const static double dme = .5f-dmd; //almost .5f = .5f - 1e^(number of exp bit) 98 | 99 | double static inline floor(double x) { return x - dme + dm - dm; } 100 | double static inline ceil (double x) { return x - dme + dm - dm + 1; } 101 | 102 | //////////////////////////////////////////////////////////////////////////////////// INTEGER --> FP 103 | 104 | /* 105 | const double _double2fixmagic = 68719476736.0*1.5; //2^36 * 1.5, (52-_shiftamt=36) uses limited precisicion to floor 106 | //const int32 _shiftamt = 16; //16.16 fixed point representation, 107 | 108 | #if BigEndian_ 109 | #define iexp_ 0 110 | #define iman_ 1 111 | #else 112 | #define iexp_ 1 113 | #define iman_ 0 114 | #endif 115 | 116 | inline int32 double2int(double val) { 117 | val = val + _double2fixmagic; 118 | return ((int32*)&val)[iman_] >> _shiftamt; 119 | } 120 | 121 | inline int32 float2int(double val) { return (float) doulbe2int(val); } 122 | */ 123 | 124 | /*------------------------------------------------ 125 | one (stable) way is to use bit fiddling magic, so converting i in [0..2^32-1] to f in [0..1): 126 | 127 | int_as_float(0x3F800000 | (i>>9)) - 1.0f 128 | 129 | (maps an integer into the float mantissa by rescaling (>>9), then 130 | setting the exponent to 1.0f (0x3F800000), then subtracting to map it from 131 | [1..2) to [0..1) (- 1.0f)) */ 132 | } 133 | #endif // LVV_MATH_H 134 | -------------------------------------------------------------------------------- /include.m4: -------------------------------------------------------------------------------- 1 | changequote(«,»)dnl 2 | changecom(«//») 3 | undefine(«format») 4 | 5 | 6 | define(«ADD», « 7 | pushdef(«tmp», eval($1+$2)) 8 | undefine($1) 9 | define(«$1»,tmp) 10 | popdef(«tmp») 11 | »)dnl 12 | 13 | define(«INCR», «define(«$1»,incr($1))»)dnl 14 | 15 | 16 | -------------------------------------------------------------------------------- /include.mk: -------------------------------------------------------------------------------- 1 | 2 | # TODO add options from http://www.antoarts.com/the-most-useful-gcc-options-and-extensions/ 3 | # 4 | ############################################################################ CONFIG 5 | 6 | # to set speed run as: make s=o 7 | CXX ?= g++ 8 | FC = gfortran 9 | 10 | TMPDIR ?=/v 11 | 12 | ################################################################################ COMP_ID 13 | _cc := $(CXX)-$(shell $(CXX) -v 2>&1 | sed -n 's/^.*ersion *\(4[^ ]*\) .*/\1/p') 14 | #_date := $(shell date +'%y%m%d_%H%M%S') 15 | _rev :=$(shell test -d .git && git rev-parse HEAD|sed -n 's/^\(........\).*/\1/p' ) 16 | #_cpu=$(shell uname -m -p |sed 's/Intel(R)//;s/(TM)//;s/@//;s/CPU//;s/ \+/-/g') 17 | _cpu :=$(shell sed -n '/^model name/!d; s/.*: //; s/(tm) Processor//; s/Intel(R)//; s/(TM)//; s/@//; s/^ //; s/ \+/-/g;p;q' /proc/cpuinfo ) 18 | _cores := $(shell awk '/^processor/{cores=$$3+1}; END{print cores}' /proc/cpuinfo) 19 | _mhz := $(shell awk '/^cpu MHz/{mhz=$$4}; END{print mhz}' /proc/cpuinfo |sed 's/\.[0-9]\+//') 20 | COMP_ID := $(shell echo "$(_rev)-$(_cc)-$(SPEED:DEBUG=g)-$(_cpu)-x$(_cores)@$(_mhz)" | tr -d ' ') 21 | 22 | ######################################################################################## 23 | #SPEED := $(s:o=OPTIMZE) 24 | SPEED := $(s:d=DEBUG) 25 | #SPEED := $(s:d=CHECK) 26 | #SPEED = $($($(s:d=DEBUG):c=CHECK):o=OPTIMIZE) 27 | SPEED ?= DEBUG 28 | 29 | 30 | 31 | ####################################################################################### GCC 32 | 33 | g++FLAGS :=-Wno-reorder -Wno-sign-compare # -fstrict-aliasing # -Wmissing-braces 34 | #g++FLAGS+= -march=native -I /usr/local/include -l:/opt/intel/Compiler/11.0/074/lib/intel64/libimf.so -Wstrict-aliasing=2 35 | g++FLAGS+= -pipe -Wstrict-aliasing=2 36 | 37 | g++FLAGS_OPTIMIZE := -O3 -march=native -fno-stack-protector -D_FORTIFY_SOURCE=0 38 | #g++FLAGS_OPTIMIZE += -fomit-frame-pointer -funsafe-loop-optimizations 39 | g++FLAGS_OPTIMIZE += -fwhole-program 40 | #g++FLAGS_OPTIMIZE += -fopenmp -D_GLIBCXX_PARALLEL 41 | #g++FLAGS_OPTIMIZE := -ffast-math -fassociative-math -mfpmath=sse,387 -fno-builtin -fargument-noalias-anything 42 | 43 | 44 | g++FLAGS_PROFILE := -pg -g -O2 -march=native -fno-omit-frame-pointer -fno-inline-functions -fno-inline-functions-called-once -fno-optimize-sibling-calls -fno-default-inline -fno-inline 45 | 46 | # CHECK+DEBUG 47 | g++FLAGS_DEBUG := -g -O0 -D_GLIBCXX_DEBUG 48 | g++FLAGS_CHECK := $(g++FLAGS_DEBUG) -fdelete-null-pointer-checks -fstack-protector -ftrapv -fbounds-check -fsignaling-nans 49 | #g++FLAGS_CHECK := -fmudflap -lmudflap 50 | 51 | #g++FLAGS_CHECK := -O0 -p -Wpacked -fsignaling-nans -fdelete-null-pointer-checks -fstack-protector -ftrapv -fbounds-check -D_GLIBCXX_DEBUG -DGSL_RANGE_CHECK 52 | #g++FLAGS_DEBUG := -O0 -ggdb3 -p -Wpacked -fsignaling-nans 53 | #g++FLAGS_DEBUG += -Wfloat-equal -Weffc++ 54 | #g++FLAGS_DEBUG += -fmudflap 55 | 56 | ########3################################################################################## ICC 57 | 58 | iccFLAGS := -vec-report0 -Wformat -openmp-report0 -wd1418 -wd981 -wd424 -wd810 -wd383 -wd82 -wd1572 -wd2259 -wd11001 -wd11005 59 | #-gxx-name=/usr/libexec/gcc/x86_64-pc-linux-gnu/4.2.4/ 60 | iccFLAGS_OPTIMIZE := -O3 -ipo -march=core2 -openmp -xT -openmp-lib compat 61 | #iccFLAGS_OPTIMIZE := -ipo -march=core2 -fomit-frame-pointer -parallel 62 | #iccFLAGS_OPTIMIZE := -ipo -msse3 -march=core2 -fomit-frame-pointer -parallel 63 | iccFLAGS_DEBUG := -debug all 64 | iccFLAGS_CHECK := -check-uninit -fmudflap -fstack-security-check -ftrapuv -Wcheck 65 | #for icc PATH=/usr/x86_64-pc-linux-gnu/gcc-bin/4.2.4:$(PATH) 66 | 67 | 68 | ####################################################################################### NON-COMPILER SPECIFIC 69 | CXXFLAGS += -Wall -std=c++0x -UCOMP_ID -DCOMP_ID='"$(COMP_ID)"' -I /home/lvv/p/ 70 | CXXFLAGS_OPTIMIZE := -DNDEBUG -DGSL_RANGE_CHECK_OFF -DNOCHECK 71 | CXXFLAGS_DEBUG := -DDEBUG -DNOCHECK -DNOSTATS -DGSL_RANGE_CHECK_ON 72 | CXXFLAGS_CHECK := -DDEBUG -DDOCHECK -DDOSTATS -D_GLIBCXX_DEBUG 73 | 74 | ####################################################################################### BUILD CXXFLAGS 75 | CXXFLAGS += $(CXXFLAGS_$(SPEED)) $($(CXX)FLAGS) $($(CXX)FLAGS_$(SPEED)) $(CF) $(CFLAGS) 76 | 77 | 78 | .SUFFIXES: .cc -r -c -g 79 | .PHONY: %-r %-g %-c 80 | 81 | b-% u-% : MAKEFLAGS += -B 82 | 83 | 84 | %-r %-c: % 85 | @tput sgr0; tput setaf 2 86 | $< 87 | @tput sgr0 88 | 89 | #%-c: % 90 | # @tput sgr0; tput setaf 2 91 | # $< 92 | # @tput sgr0 93 | 94 | %-g: % 95 | echo -e "br main\nr" > /tmp/t 96 | gdb -q -x /tmp/t $< 97 | 98 | 99 | 100 | #%-d %-r: % 101 | # ./$< 102 | 103 | 104 | %-r : SPEED = OPTIMIZE 105 | %-c : SPEED = CHECK 106 | %-g : SPEED = DEBUG 107 | 108 | a-% : CXXFLAGS += -O3 -save-temps 109 | u-% : CXXFLAGS += -Wno-unused-variable 110 | 111 | # vim:noexpandtab ft=make: 112 | -------------------------------------------------------------------------------- /int2float-to-add.cc: -------------------------------------------------------------------------------- 1 | Nice trick :) Here is a generalized implementation: 2 | 3 | First some supporting code. 4 | 5 | Code: Select all 6 | template< 7 | uint taNumber> 8 | struct NumberOfSignificantBits; 9 | 10 | template<> 11 | struct NumberOfSignificantBits<0> 12 | { 13 | enum { VALUE = 0 }; 14 | }; 15 | 16 | template< 17 | uint taNumber> 18 | struct NumberOfSignificantBits 19 | { 20 | enum { VALUE = 1 + NumberOfSignificantBits<(taNumber >> 1)>::VALUE }; 21 | }; 22 | 23 | template< 24 | uint taNumber> 25 | struct FloatConvertShift 26 | { 27 | enum 28 | { 29 | SHIFT_LEFT = NumberOfSignificantBits::VALUE < 23, 30 | SHIFT_AMOUNT = SHIFT_LEFT ? 31 | 23 - NumberOfSignificantBits::VALUE : 32 | NumberOfSignificantBits::VALUE - 23 33 | }; 34 | }; 35 | 36 | 37 | 38 | And then the actual function: 39 | 40 | Code: Select all 41 | template< 42 | uint taMaxValue> 43 | float convertToFloat01( 44 | const uint aValue) 45 | { 46 | union { int i; float f; }; 47 | 48 | // this branch will be optimized away by the compiler 49 | if(FloatConvertShift::SHIFT_LEFT) 50 | { 51 | i = 0x3F800000 | (aValue << FloatConvertShift::SHIFT_AMOUNT); 52 | } 53 | else 54 | { 55 | i = 0x3F800000 | (aValue >> FloatConvertShift::SHIFT_AMOUNT); 56 | } 57 | 58 | return f - 1.0f; 59 | } 60 | 61 | 62 | 63 | You just throw it the number and the maximum value your integer could get: 64 | 65 | Code: Select all 66 | convertToFloat01<15>(8); // returns 0.5 67 | convertToFloat01<255>(8); // returns 0.03125 68 | convertToFloat01(10000); // returns 0.305176 69 | 70 | 71 | 72 | With a bit more work (e.g. traits for the size of the mantissa) you could generalize it to work with any common floating point type (float, double, long double). 73 | ----------------------------------------------------------------------------- 74 | 75 | 76 | * Reply with quote 77 | 78 | Re: gdb and C give different numerical results.... 79 | 80 | Postby tbp on 27 Nov 2008, 06:36 81 | Err, except your generalization is leaking bits everywhere and that defeats the purpose; if you insist about obfuscating generalizing then something to the tune of 82 | 83 | Code: Select all 84 | typedef unsigned int uint32_t; 85 | typedef unsigned long long uint64_t; 86 | 87 | template struct fp_details; 88 | template<> struct fp_details { enum { w = 32, mnt_w = 23, exp_w = 8, sgn_w = 1 }; typedef uint32_t base_type; }; 89 | template<> struct fp_details { enum { w = 64, mnt_w = 53, exp_w = 11, sgn_w = 1 }; typedef uint64_t base_type; }; 90 | 91 | template struct twiddler : fp_details { 92 | typedef typename fp_details::base_type base_type; 93 | typedef T fp_type; 94 | enum { exp_bias = (1 << (exp_w - 1)) - 1, mnt_fix = w - mnt_w }; 95 | template static fp_type construct(base_type bits) { 96 | union { base_type u; fp_type f; } num = { 97 | (base_type(sgn) << (w - sgn_w)) | 98 | (((base_type(exp_bias+exp) << (w - exp_w)) >> sgn_w)) | 99 | (bits >> mnt_fix) 100 | }; 101 | return num.f; 102 | } 103 | // [2^exp_scale, 2^exp_scale+1) + sgn_offset*2^exp_offset 104 | template static fp_type ranged(base_type bits) { 105 | return construct<0, exp_scale>(bits) + construct(0); 106 | } 107 | // [2^exp_scale, 2^exp_scale+1) + sgn_offset*1.5*2^exp_offset 108 | template static fp_type centered(base_type bits) { 109 | return construct<0, exp_scale>(bits) + construct(1 << (mnt_w+mnt_fix-1)); 110 | } 111 | }; 112 | 113 | int main(int argc, char *argv[]) { 114 | float foo = twiddler::ranged<+0, +0, 1>(rand()); // [2^0, 2^1) - 2^+0 -> [0, 1) 115 | double bar = twiddler::centered<+1, +1, 1>(rand()); // [2^1, 2^2) - 1.5*2^1 -> [-1, +1) 116 | return 0; 117 | } 118 | 119 | 120 | -------------------------------------------------------------------------------- /last_n.h: -------------------------------------------------------------------------------- 1 | // last_n - circular buffer class 2 | // Part of lvvlib - https://github.com/lvv/lvvlib 3 | // Copyright (c) 2000-2013 4 | // Leonid Volnitsky (Leonid@Volnitsky.com) 5 | 6 | #ifndef LVV_LAST_N_H 7 | #define LVV_LAST_N_H 8 | 9 | #include 10 | template 11 | struct last_n { 12 | size_t oldest=0; 13 | T ring[N]={0}; 14 | void push_back(T x) { ring[oldest++] = x; oldest %= N; }; 15 | T prev(size_t i) { return ring[(oldest-1-i+N)%N];}; 16 | }; 17 | #endif 18 | -------------------------------------------------------------------------------- /lvv.h: -------------------------------------------------------------------------------- 1 | // General/Misc utilities 2 | // Part of lvvlib - https://github.com/lvv/lvvlib 3 | // Copyright (c) 2000-2013 4 | // Leonid Volnitsky (Leonid@Volnitsky.com) 5 | 6 | 7 | #ifndef LVV_H 8 | #define LVV_H 9 | 10 | #include 11 | #include 12 | 13 | 14 | #if defined(NDEBUG) && defined(DEBUG) 15 | #undef DEBUG 16 | #endif 17 | 18 | #if ! defined(NDEBUG) && ! defined(DEBUG) 19 | #define NDEBUG 20 | #endif 21 | 22 | 23 | /////////////////////////////////////////////////////////////////////////// MAP SELECTION 24 | 25 | #ifdef UNORDERED_MAP 26 | #include 27 | #define MAP tr1::unordered_map 28 | #endif 29 | 30 | #ifdef BT 31 | #include 32 | #define MAP map 33 | #endif 34 | 35 | // FIXME add || http://developer.apple.com/documentation/DeveloperTools/gcc-4.0.1/cpp/Defined.html#Defined 36 | 37 | #ifdef GOOGLE_SPARSE 38 | #include 39 | #ifndef MAP 40 | //SPARSE HASH (default) 41 | #define MAP google::sparse_hash_map 42 | #endif 43 | #ifndef SET 44 | #include 45 | #define SET google::sparse_hash_set 46 | #endif 47 | #endif 48 | 49 | #ifndef MAP 50 | #define MAP std::map 51 | #endif 52 | 53 | #ifndef SET 54 | #define SET std::set 55 | #endif 56 | 57 | 58 | 59 | using std::flush; 60 | using std::string; 61 | using std::cout; 62 | using std::cerr; 63 | using std::endl; 64 | using std::setw; 65 | using std::ostream; 66 | using std::setprecision; 67 | 68 | namespace lvv { 69 | 70 | // from linux kernel 71 | #define likely(x) __builtin_expect((x),1) 72 | #define unlikely(x) __builtin_expect((x),0) 73 | 74 | /////////////////////////////////////////////////////////////////////////////////// 75 | 76 | 77 | #define LVV_STR(x) __LVV_STR__(x) 78 | #define __LVV_STR__(x) #x 79 | 80 | // TODO reimplement with __VA_ARGS__ 81 | // #define A_(a, ...) << a A(__VA_ARGS__) 82 | // #define A (...) cout A_(__VA_ARGS__) ; 83 | 84 | 85 | #define _STR(x) (string(" " #x "=")+lexical_cast(x)) 86 | #undef __PRETTY_FUNCTION__ 87 | 88 | #ifdef NOPR 89 | #define PR(x) 90 | #define PR1(x1) 91 | #define PR2(x1,x2) 92 | #define PR3(x1,x2,x3) 93 | #define PR4(x1,x2,x3,x4) 94 | #define PR5(x1,x2,x3,x4,x5) 95 | #define PR6(x1,x2,x3,x4,x5,x6) 96 | #define PR7(x1,x2,x3,x4,x5,x6,x7) 97 | #define PR8(x1,x2,x3,x4,x5,x6,x7,x8) 98 | #define PR9(x1,x2,x3,x4,x5,x6,x7,x8,x9) 99 | #else 100 | #define PR(x) std::cerr << " " #x " = " << (x) << " "<< flush; 101 | 102 | #define PR1(x1) std::cerr << "--("<<__LINE__<< ")-- "; PR(x1) ; std::cerr < 7 | #include 8 | #include 9 | 10 | template 11 | std::unique_ptr make_unique_helper(std::false_type, Args&&... args) { 12 | return std::unique_ptr(new T(std::forward(args)...)); 13 | } 14 | 15 | template 16 | std::unique_ptr make_unique_helper(std::true_type, Args&&... args) { 17 | static_assert(std::extent::value == 0, 18 | "make_unique() is forbidden, please use make_unique()."); 19 | 20 | typedef typename std::remove_extent::type U; 21 | return std::unique_ptr(new U[sizeof...(Args)]{std::forward(args)...}); 22 | } 23 | 24 | template 25 | std::unique_ptr make_unique(Args&&... args) { 26 | return make_unique_helper(std::is_array(), std::forward(args)...); 27 | } 28 | -------------------------------------------------------------------------------- /math.h: -------------------------------------------------------------------------------- 1 | // math.h 2 | // Part of lvvlib - https://github.com/lvv/lvvlib 3 | // Copyright (c) 2000-2013 4 | // Leonid Volnitsky (Leonid@Volnitsky.com) 5 | 6 | #ifndef LVV_MATH_H 7 | #define LVV_MATH_H 8 | 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | using std::numeric_limits; 15 | 16 | #include 17 | 18 | //#include 19 | #include 20 | #include 21 | 22 | #include 23 | using std::string; 24 | 25 | #include 26 | #include 27 | using std::cout; 28 | using std::cerr; 29 | using std::flush; 30 | using std::endl; 31 | using std::setw; 32 | using std::boolalpha; 33 | using std::ostream; 34 | using std::setprecision; 35 | 36 | 37 | #include 38 | 39 | namespace lvv { 40 | 41 | //////////////////////////////////////////////////////////////////////////////////////// Average 42 | 43 | template 44 | class Average { public: 45 | Average(string _lable=0): count(0), sum(0), lable(_lable) {}; 46 | double average() const { /* div by 0 posible */ return double(sum)/count; } 47 | void sample(T x) { sum += x; ++count; } 48 | 49 | template friend ostream& operator<< (ostream& os, Average s); 50 | private: 51 | long count; 52 | //typename Type::SuperiorType sum; 53 | //typename std::tr1::promote::type sum; 54 | //__gnu_cxx::__promote::__type sum; 55 | typename LVV_PROMOTE1(T) sum; 56 | string lable; 57 | }; 58 | 59 | template ostream& 60 | operator<< (ostream& os, Average s) { 61 | if ( !s.lable.empty() ) 62 | os << s.lable << " avg: "; 63 | 64 | if (s.count > 0 ) 65 | cout << s.average(); 66 | else 67 | cout << "n/a" ; 68 | return os; 69 | }; 70 | 71 | //////////////////////////////////////////////////////////////////////////////////////////////////// POWI() 72 | // Depricated, use any of: 73 | // __gnu_cxx::power 74 | // http://www.sgi.com/tech/stl/power.html 75 | // http://www.boost.org/doc/libs/1_36_0/libs/math/doc/sf_and_dist/html/math_toolkit/special/powers/ct_pow.html 76 | // glibc pow vs std::pow - https://twiki.cern.ch/twiki/bin/view/Atlas/CalculatingIntegerPowers 77 | // TODO: type specialization 78 | // TODO: add asserts 79 | // TODO: fast pow with lookup table: http://www.hxa7241.org/articles/content/fast-pow-adjustable_hxa7241_2007.html 80 | template inline static 81 | T powi (T x, int n) { // simplified http://dslinux.gits.kiev.ua/trunk/lib/libm/powi.c 82 | T y; 83 | if ( n & 1 ) y = x; 84 | else y = 1.0; 85 | 86 | T w = x; 87 | n >>= 1; 88 | while( n ) { 89 | w = w * w; 90 | 91 | if ( n & 1 ) y *= w; 92 | n >>= 1; 93 | } 94 | return y; 95 | }; 96 | 97 | 98 | template T static inline pow2(T x) { return x*x; }; 99 | template T static inline pow3(T x) { return x*x*x; }; 100 | template T static inline pow4(T x) { return (x*x)*(x*x); }; 101 | template T static inline pow5(T x) { return (x*x)*(x*x)*x; }; 102 | 103 | 104 | //////////////////////////////////////////////////////////////////////////////////////////////////// ABS() 105 | // TODO add specialisation for FP 106 | // 107 | // We can take the absolute value by setting the sign bit to zero: 108 | // float f; 109 | // *(int*)&f &= 0x7FFFFFFF; // set sign bit to zero 110 | 111 | template T static inline abs(T x){ return x > 0 ? x : -x; }; 112 | template T static inline max(T x, T y){ 113 | return x > y ? x : y; 114 | }; 115 | template T static inline min(T x, T y){ 116 | return x < y ? x : y; 117 | }; 118 | /* 119 | #ifdef x__SSE__ 120 | // fit to range 121 | asm( 122 | " maxss %[Z_front], %[z];" 123 | " minss %[Z_back], %[z];" 124 | :[z] "=&x"(z) 125 | :"0"(z), [Z_front] "m"(rZ.front()), [Z_back] "m"(rZ.back()) 126 | ); 127 | */ 128 | 129 | 130 | 131 | ///////////////////////////////////////////////////////////////////////////////////////////////////// EQ (int/FP) 132 | typedef unsigned long long int ulp_t; 133 | 134 | ///type_trait overloded 135 | template bool static inline eq_impl (T1 n1, T2 n2, std::tr1::true_type integral_flag, ulp_t ulps, T characteristic_value) { // integral 136 | return (T)n1==(T)n2; 137 | }; 138 | 139 | template bool static inline eq_impl (T1 n1, T2 n2, std::tr1::false_type integral_flag, ulp_t ulps, T characteristic_value) { // floating point 140 | // algorithm taken from: http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm 141 | if (n1==n2) return true; 142 | T abs_diff = n1-n2 > 0 ? n1-n2 : n2-n1; // |n1-n2| 143 | if ( characteristic_value == 0 ) 144 | characteristic_value = (lvv::abs(n1)+ lvv::abs(n2)) * 0.5; // (|n1| + |n2|) /2 145 | T max_error = std::numeric_limits::epsilon() * ulps * characteristic_value ; 146 | //PR(diff/divider); PR(max_error); 147 | return abs_diff < max_error; 148 | } 149 | 150 | 151 | template static inline 152 | bool eq (T1 n1,T2 n2, ulp_t ulps=100, typename LVV_PROMOTE2(T1,T2) characteristic_value=0) { 153 | typedef typename LVV_PROMOTE2(T1,T2) T; 154 | typename std::tr1::is_integral::type integral_flag; 155 | return eq_impl(n1, n2, integral_flag, ulps, characteristic_value); 156 | } 157 | 158 | 159 | ////////////////////////////////////////////////////////////////////////////////////// SIMON_MEAN 160 | static inline 161 | double group_mean ( 162 | double sample_value, 163 | double samples, 164 | double gloable_value, 165 | double eq_N // K 166 | ) { 167 | // So intead of : mean = sum(ratings)/count(ratings) 168 | // He uses: bettermean = [K*global_mean + sum(ratings)] / [K+count(ratings)] and he uses K=25 169 | // http://en.wikipedia.org/wiki/Bayesian_average 170 | //assert (group_weight > 0); 171 | return (eq_N*gloable_value + sample_value*samples ) / ( eq_N + samples ); 172 | } 173 | 174 | 175 | ////////////////////////////////////////////////////////////////////////////////////// FP Exceptions 176 | 177 | // from http://publib.boulder.ibm.com/infocenter/systems/index.jsp?topic=/com.ibm.aix.basetechref/doc/basetrf1/nextafterf.htm 178 | // An application wishing to check for error situations should set the errno 179 | // global variable to zero and call feclearexcept(FE_ALL_EXCEPT) before calling 180 | // these subroutines. Upon return, if errno is nonzero or 181 | // fetestexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW) is 182 | // nonzero, an error has occurred. 183 | // 184 | // rounding 185 | // FE_TONEAREST = 0, 186 | // FE_DOWNWARD = 0x400, 187 | // FE_UPWARD = 0x800, 188 | // FE_TOWARDZERO = 0xc00 189 | // int fegetround(void) 190 | // void fesetround(int) 191 | 192 | jmp_buf setjmp_environment; 193 | 194 | void fpe_signal_handler (int signum, siginfo_t *info, void *context) { 195 | 196 | cerr << "FP error: "; 197 | switch (info->si_code) { // FIXME there might be several exception at the same time 198 | case FPE_INTDIV: cerr << "Integer divide by zero " ; break ; 199 | case FPE_INTOVF: cerr << "Integer overflow " ; break ; 200 | case FPE_FLTDIV: cerr << "Floating point divide by zero " ; break ; 201 | case FPE_FLTOVF: cerr << "Floating point overflow " ; break ; 202 | case FPE_FLTUND: cerr << "Floating point underflow " ; break ; 203 | case FPE_FLTRES: cerr << "Floating point inexact result " ; break ; 204 | case FPE_FLTINV: cerr << "Floating point invalid operation " ; break ; 205 | case FPE_FLTSUB: cerr << "Subscript out of range " ; break ; 206 | default: cerr << "unknown. si_code: " << info->si_code ; 207 | } 208 | cerr << endl; 209 | longjmp(setjmp_environment, 1); 210 | } 211 | 212 | void setup_fpe () { 213 | //feenableexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW); // do not enable all 214 | feenableexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW ); // do not enable all 215 | struct sigaction fpe_sigaction; 216 | memset(&fpe_sigaction, 0, sizeof(fpe_sigaction)); 217 | fpe_sigaction.sa_sigaction = &fpe_signal_handler; 218 | fpe_sigaction.sa_flags = SA_RESETHAND | SA_SIGINFO; 219 | sigaction(SIGFPE, &fpe_sigaction, 0); 220 | 221 | if (setjmp(setjmp_environment)) 222 | exit(111); // after exception control comes here 223 | } 224 | 225 | template 226 | double polynomial_eval (const double x, ARRAY_t C) { 227 | 228 | double poly = *C.begin() ; 229 | double pow_x = 1.0; // x[0,0]^0 230 | for ( int i=C.ibegin()+1; i < C.iend(); ++i ) { 231 | pow_x *= x; 232 | poly += C[i]*pow_x; 233 | } 234 | 235 | return poly; 236 | }; 237 | 238 | // x = a + b*x + c*x^2 239 | // dx = 0 + b + 2c*x 240 | template 241 | double polynomial_derivative_eval (const double x, ARRAY_t C) { 242 | 243 | double sum = *(C.begin()+1) ; // 1st nonomial == 0, this is second 244 | double pow_x = 1.0; // x[0,0]^0 245 | for ( int i = C.ibegin()+2; i < C.iend(); ++i ) { 246 | pow_x *= x; 247 | sum += i*C[i]*pow_x; 248 | } 249 | 250 | return sum; 251 | }; 252 | 253 | // template 254 | //int ilog2 (T n) { 255 | // int ilog = 0; 256 | // if (!n) return 0; 257 | //// while (n >>= 1) { ilog++; } 258 | // return ilog; 259 | //} 260 | 261 | 262 | ////////////////////////////////////////////////////////////////////////////////// END 263 | } 264 | #endif // LVV_MATH_H 265 | 266 | -------------------------------------------------------------------------------- /memoize.h: -------------------------------------------------------------------------------- 1 | // memoize - add chashing to pure function 2 | // Part of lvvlib - https://github.com/lvv/lvvlib 3 | // Copyright (c) 2000-2013 4 | // Leonid Volnitsky (Leonid@Volnitsky.com) 5 | 6 | // from http://slackito.com/2011/03/17/automatic-memoization-in-cplusplus0x/ 7 | 8 | #ifndef LVV_MEMOIZE_H 9 | #define LVV_MEMOIZE_H 10 | 11 | #include 12 | #include 13 | namespace lvv { 14 | 15 | 16 | template 17 | std::function 18 | memoize (std::function func) { 19 | 20 | std::map, ReturnType> cache; 21 | 22 | return ([=](Args... args) mutable { 23 | std::tuple t(args...); 24 | if (cache.find(t) == cache.end()) 25 | cache[t] = func(args...); 26 | return cache[t]; 27 | }); 28 | } 29 | 30 | 31 | }; // namespace lvv 32 | #endif // LVV_MOMOIZE_H 33 | 34 | -------------------------------------------------------------------------------- /meta.h: -------------------------------------------------------------------------------- 1 | // meta.h - template metaprogramming and convenience macros (obsolete) 2 | // Part of lvvlib - https://github.com/lvv/lvvlib 3 | // Copyright (c) 2000-2013 4 | // Leonid Volnitsky (Leonid@Volnitsky.com) 5 | 6 | 7 | #ifndef LVV_META_H 8 | #define LVV_META_H 9 | 10 | #ifdef __GXX_EXPERIMENTAL_CXX0X__ 11 | #include 12 | #endif 13 | #include 14 | 15 | 16 | //#include 17 | //#include 18 | #define LVV_TRUE_TYPE std::tr1::true_type 19 | #define LVV_FALSE_TYPE std::tr1::false_type 20 | // what is std::__false_type ? 21 | 22 | #include 23 | // for type_descriptor 24 | 25 | #ifdef OLD_PRE_TR1_FIX 26 | #include 27 | #define LVV_PROMOTE1(T) boost::promote::type 28 | #define LVV_IS_INTEGRAL(T) boost::is_integral::value 29 | 30 | #include 31 | #define LVV_PROMOTE2(T1,T2) boost::numeric::ublas::promote_traits::promote_type 32 | #endif 33 | //------------------------------------------------------------------------------------------ SELECT BOOST OR TR1 34 | #include 35 | #define LVV_PROMOTE2(T1,T2) boost::numeric::ublas::promote_traits::promote_type 36 | 37 | #include 38 | #define LVV_PROMOTE1(T) boost::promote::type 39 | #define LVV_IS_INTEGRAL(T) std::tr1::is_integral::value 40 | 41 | /* for promotion: 42 | for single arg only: 43 | #include 44 | boost::promote 45 | 46 | for 2 args 47 | #include 48 | boost::numeric:ublas 49 | 50 | old blitz promte: 51 | //#include 52 | 53 | gcc builtin doesn't works with T from template? 54 | __gnu_cxx::__promote_2 55 | 56 | my own, depricated: 57 | 58 | DEPRICATED 59 | // this is promote_trait class to provide summator type 60 | // use: 61 | // typename Type::SuperiorType sum; 62 | // if T if float then sum will be double 63 | // if T if int then sum will be long 64 | template struct Type { typedef long SuperiorType; }; 65 | template <> struct Type< signed char> { typedef signed long SuperiorType; }; 66 | template <> struct Type { typedef unsigned long SuperiorType; }; 67 | template <> struct Type { typedef unsigned long SuperiorType; }; 68 | template <> struct Type { typedef unsigned long SuperiorType; }; 69 | template <> struct Type { typedef unsigned long SuperiorType; }; 70 | template <> struct Type { typedef double SuperiorType; }; 71 | template <> struct Type { typedef double SuperiorType; }; 72 | */ 73 | 74 | 75 | #ifdef __GNUC__ 76 | #define PURE __attribute__((const)) 77 | #else 78 | #define PURE 79 | #endif 80 | 81 | namespace lvv { 82 | 83 | //////////////////////////////////////////////////////////////////////////////////////////// TRAIT 84 | 85 | typedef int64_t int_longest_t; 86 | typedef uint64_t uint_longest_t; 87 | typedef long double float_longest_t; 88 | 89 | 90 | //------------------------------------------------------------------------------------------ TODO: FLOAT DEMOTION 91 | // see after #else at /usr/include/boost-1_37/boost/type_traits/floating_point_promotion.hpp 92 | 93 | //------------------------------------------------------------------------------------------ TYPE_DESCRIPTOR 94 | // by Ariel Badichi, Irfan Zaidi and Leonid Volnitsky 95 | // usage: cout << type_descriptor; 96 | 97 | template struct type_descriptor; 98 | 99 | template struct type_descriptor {std::ostream & print(std::ostream & out) const{return out << type_descriptor() << " *"; }}; 100 | template struct type_descriptor {std::ostream & print(std::ostream & out) const{return out << type_descriptor() << " &"; }}; 101 | template struct type_descriptor{std::ostream & print(std::ostream & out) const{return out << type_descriptor() << " [" << N << "]";}}; 102 | template struct type_descriptor {std::ostream & print(std::ostream & out) const{return out << type_descriptor() << " const"; }}; 103 | template struct type_descriptor {std::ostream & print(std::ostream & out) const{return out << type_descriptor() << " volatile"; }}; 104 | template struct type_descriptor {std::ostream & print(std::ostream& out) const {out << "const volatile " << type_descriptor(); return out; } }; 105 | template struct type_descriptor {std::ostream & print(std::ostream& out) const {out << type_descriptor() << "* const"; return out; } }; 106 | 107 | 108 | template<> struct type_descriptor {std::ostream & print(std::ostream & out) const{return out << "char"; }}; // without this compile error 109 | template<> struct type_descriptor {std::ostream & print(std::ostream & out) const{return out << "int8_t"; }}; 110 | template<> struct type_descriptor {std::ostream & print(std::ostream & out) const{return out << "uint8_t"; }}; 111 | template<> struct type_descriptor {std::ostream & print(std::ostream & out) const{return out << "int16_t"; }}; 112 | template<> struct type_descriptor {std::ostream & print(std::ostream & out) const{return out << "uint16_t"; }}; 113 | template<> struct type_descriptor {std::ostream & print(std::ostream & out) const{return out << "int32_t"; }}; 114 | template<> struct type_descriptor {std::ostream & print(std::ostream & out) const{return out << "uint32_t"; }}; 115 | template<> struct type_descriptor {std::ostream & print(std::ostream & out) const{return out << "int64_t"; }}; 116 | template<> struct type_descriptor {std::ostream & print(std::ostream & out) const{return out << "uint64_t"; }}; 117 | template<> struct type_descriptor {std::ostream & print(std::ostream & out) const{return out << "float"; }}; 118 | template<> struct type_descriptor {std::ostream & print(std::ostream & out) const{return out << "double"; }}; 119 | template<> struct type_descriptor{std::ostream & print(std::ostream & out) const{return out << "long double";}}; 120 | 121 | template std::ostream & operator<< (std::ostream & out, const type_descriptor & desc) { return desc.print(out); } 122 | 123 | 124 | //////////////////////////////////////////////////////////////////////////////////////////// CONTROL STRUCTURE 125 | 126 | //------------------------------------------------------------------------------------------ META IF 127 | 128 | // also in /usr/include/boost/detail/select_type.hpp 129 | template struct IF { typedef THEN type; }; 130 | 131 | template struct IF { typedef ELSE type; }; 132 | 133 | // USE like this: 134 | // if sizeof(int) < sizeof(long) then use long else use int 135 | // IF< sizeof(int)::type i; 136 | 137 | 138 | 139 | //////////////////////////////////////////////////////////////////////////////////////////// META MATH 140 | 141 | 142 | //------------------------------------------------------------------------------------------ RATIO 143 | template 144 | struct ratio_ { 145 | long const static numerator = N; 146 | long const static denominator = D; 147 | long const static value = N/D; 148 | typedef ratio_ type; 149 | template TO static convert() {return TO(N)/D; } 150 | }; 151 | 152 | template struct int_ : ratio_ { long const static value=N; }; 153 | 154 | //------------------------------------------------------------------------------------------ PLUS, MINUS 155 | template 156 | struct plus { typedef ratio_ type; }; 157 | 158 | template 159 | struct minus { typedef ratio_ type; }; 160 | 161 | 162 | 163 | //------------------------------------------------------------------------------------------ TODO IS_POW_OF_TWO 164 | 165 | /* 166 | template struct ipower { enum { value = x * ipower::value }; }; 167 | template struct ipower { enum { value = 1 }; }; 168 | template struct ipower<0, y> { enum { value = 0 }; }; 169 | template<> struct ipower<0, 0> {}; 170 | */ 171 | 172 | //------------------------------------------------------------------------------------------ IPOW 173 | template struct ipow { enum { value = ipow::value * ipow::value }; }; 174 | template struct ipow { enum { value = 1 }; }; 175 | template struct ipow { enum { value = X }; }; 176 | 177 | 178 | //template struct fpow { float const static value = fpow::value * fpow::value }; }; 179 | //template struct fpow { float const static value = 1; }; 180 | //template struct fpow { float const static value = X; }; 181 | 182 | //------------------------------------------------------------------------------------------ ILOG2 183 | template struct ilog2 { 184 | #ifdef __GXX_EXPERIMENTAL_CXX0X__ 185 | static_assert(N%2==0, "ilot2: N must be even number"); 186 | #endif 187 | enum { value = 1 + ilog2::value}; 188 | }; 189 | 190 | template<> struct ilog2<1> { enum { value = 0 }; }; 191 | template<> struct ilog2<2> { enum { value = 1 }; }; 192 | 193 | //------------------------------------------------------------------------------------------ BINARY 194 | 195 | // useage: const uint32_t mask=binary<101010>::value; 196 | template struct binary { static uint32_t const value = binary::value <<1 | N%10; }; 197 | template <> struct binary<0> { static uint32_t const value = 0; }; 198 | 199 | // useage: cout << to_binary(0x1f); 200 | template inline 201 | const char* to_binary(T n) { 202 | static char s[500]; 203 | int ni; 204 | size_t si; 205 | for (ni=8*sizeof(T)-1, si=0; ni>=0; ni--, si++) { 206 | int bit = ((n >> ni) & 1); 207 | if (bit) s[si] = '1'; 208 | else s[si] = '0'; 209 | if (ni%4==0 && si) { 210 | if (ni%8==0 && si) { s[++si]=' '; s[++si]=' '; } 211 | else s[++si]=','; 212 | } 213 | } 214 | s[si] = '\0'; 215 | return s; 216 | }; 217 | 218 | // hex 219 | // 220 | //for (int i=2*sizeof(int) - 1; i>=0; i--) { 221 | // cout << "0123456789ABCDEF"[((n >> i*4) & 0xF)]; 222 | //} 223 | 224 | 225 | 226 | 227 | //------------------------------------------------------------------------------------------ TODO FIXED NUMBERS 228 | // TR http://msdn.microsoft.com/en-us/library/ms972705.aspx 229 | //------------------------------------------------------------------------------------------ TODO UNION_CAST 230 | /* 231 | template 232 | union Union_Cast { 233 | From m_from; 234 | To m_to; 235 | Union_Cast (const From& from_) : m_from (from_) {} 236 | }; 237 | 238 | 239 | float f = Union_Cast (my_int).m_to; 240 | 241 | and you can even add some static assert to verify that sizeof(From) == sizeof (To) if you want. 242 | ------------------- 243 | template 244 | union union_cast { 245 | From from; 246 | To to; 247 | 248 | union_cast(From from) 249 | :from(from) { } 250 | 251 | To getTo() const { return to; } 252 | }; 253 | 254 | */ 255 | 256 | // TO test http://cocoawithlove.com/2008/04/using-pointers-to-recast-in-c-is-bad.html) 257 | /* #define UNION_CAST(x, destType) \ 258 | (((union {__typeof__(x) a; destType b;})x).b) 259 | */ 260 | 261 | } 262 | #endif // LVV_META_H 263 | 264 | -------------------------------------------------------------------------------- /mmap.h: -------------------------------------------------------------------------------- 1 | // mmap(2) wrapper 2 | // Part of lvvlib - https://github.com/lvv/lvvlib, 3 | // Copyright (c) 2000-2013 4 | // Leonid Volnitsky (Leonid@Volnitsky.com) 5 | // 6 | // Usage docs at doc/index.txt, see also t-mmap.cc 7 | 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | using std::cerr; 21 | namespace lvv { 22 | 23 | struct no_file: std::exception {}; 24 | struct no_free_space: std::exception {}; 25 | struct open_error: std::exception {}; 26 | struct io_error: std::exception {}; 27 | 28 | // this function is not used directly 29 | template 30 | void * mmap_read_ptr (const char *path, size_t& n) { 31 | 32 | int src_fd = open(path, O_RDWR); 33 | 34 | if (src_fd < 0) { 35 | cerr << "mmap_read error: couldn't open \"" << path << "\" file\n"; 36 | throw no_file(); 37 | } 38 | 39 | struct stat sb; 40 | 41 | // get file size 42 | if (fstat(src_fd, &sb) < 0) { 43 | cerr << "mmap_read error: couldn't stat \"" << path << "\" file\n"; 44 | close(src_fd); 45 | throw io_error(); 46 | } 47 | 48 | n = sb.st_size; 49 | 50 | void *p = mmap(NULL, n, PROT_READ | PROT_WRITE , SHARING, src_fd, 0); 51 | //void *p = mmap(NULL, sb.st_size , PROT_READ, SHARING, src_fd, 0); 52 | 53 | if ( p == MAP_FAILED ) { 54 | cerr << "mmap_read error: couldn't mmap \"" << path << "\" file\n"; 55 | close(src_fd); 56 | throw io_error(); 57 | } 58 | 59 | return p; 60 | } 61 | 62 | // read an object of MMAPTED_TYPE 63 | template 64 | MMAPED_TYPE& mmap_read(const char* path) { 65 | size_t unused; 66 | return *(MMAPED_TYPE*) mmap_read_ptr(path, unused); 67 | }; 68 | 69 | // read c-array of REC_T[] type 70 | template 71 | REC_T* mmap_read(const char* path, size_t& n) { 72 | size_t n_bytes; 73 | auto res = (REC_T*) mmap_read_ptr(path, n_bytes); 74 | n = n_bytes/sizeof(REC_T); 75 | return res; 76 | }; 77 | 78 | 79 | // write an oject of T type 80 | template void 81 | mmap_write(const char* path, T &obj) { 82 | 83 | size_t size=sizeof(T); 84 | unlink(path); 85 | 86 | int fd = open(path, O_CREAT | O_RDWR, S_IRWXU); 87 | if (fd < 0) { 88 | cerr << "mmap_write error: couldn't open \"" << path << "\" file\n"; 89 | //exit(2); 90 | throw open_error(); 91 | } 92 | 93 | if (ftruncate(fd, size) < 0) { 94 | cerr << "mmap_write error: couldn't allocate space for \"" << path << "\" file\n"; 95 | close(fd); 96 | //exit(4); 97 | throw no_free_space(); 98 | } 99 | 100 | 101 | void *p = mmap(NULL, size, PROT_WRITE, MAP_SHARED, fd, 0); 102 | if ( p == MAP_FAILED ) { 103 | cerr << "mmap_write error: couldn't mmap \"" << path << "\" file\n"; 104 | close(fd); 105 | //exit(6); 106 | throw io_error(); 107 | } 108 | 109 | /* MAP_FIXED 110 | Don’t interpret addr as a hint: place the mapping at exactly that address. addr must be a multiple of the page size. If the 111 | memory region specified by addr and len overlaps pages of any existing mapping(s), then the overlapped part of the existing map‐ 112 | ping(s) will be discarded. If the specified address cannot be used, mmap() will fail. Because requiring a fixed address for a 113 | mapping is less portable, the use of this option is discouraged. */ 114 | 115 | if (memcpy(p, &obj, size) < 0) { 116 | cerr << "mmap_write error: couldn't memcpy() for \"" << path << "\" file\n"; 117 | close(fd); 118 | //exit(8); 119 | throw std::exception(); 120 | } 121 | 122 | if (munmap(p, size) < 0) { 123 | cerr << "mmap_write error: couldn't munmap() for \"" << path << "\" file\n"; 124 | close(fd); 125 | //exit(10); 126 | throw std::exception(); 127 | } 128 | } 129 | 130 | // wirte c-array of REC_t[n] type 131 | template 132 | void mmap_write(const char* path, REC_T* rec, size_t n) { 133 | 134 | size_t size = n * sizeof(REC_T); 135 | 136 | unlink(path); 137 | 138 | int fd = open(path, O_CREAT | O_RDWR, S_IRWXU); 139 | if (fd < 0) { 140 | cerr << "mmap_write error: couldn't open \"" << path << "\" file\n"; 141 | throw open_error(); 142 | } 143 | 144 | if (ftruncate(fd, size) < 0) { 145 | cerr << "mmap_write error: couldn't allocate space for \"" << path << "\" file\n"; 146 | close(fd); 147 | throw no_free_space(); 148 | } 149 | 150 | 151 | void *p = mmap(NULL, size, PROT_WRITE, MAP_SHARED, fd, 0); 152 | if ( p == MAP_FAILED ) { 153 | cerr << "mmap_write error: couldn't mmap \"" << path << "\" file\n"; 154 | close(fd); 155 | //exit(6); 156 | throw io_error(); 157 | } 158 | 159 | if (memcpy(p, rec, size) < 0) { 160 | cerr << "mmap_write error: couldn't memcpy() for \"" << path << "\" file\n"; 161 | close(fd); 162 | //exit(8); 163 | throw std::exception(); 164 | } 165 | 166 | if (munmap(p, size) < 0) { 167 | cerr << "mmap_write error: couldn't munmap() for \"" << path << "\" file\n"; 168 | close(fd); 169 | //exit(10); 170 | throw std::exception(); 171 | } 172 | } 173 | 174 | } // namespace lvv 175 | -------------------------------------------------------------------------------- /png.h: -------------------------------------------------------------------------------- 1 | // PNG writer 2 | // Part of lvvlib - https://github.com/lvv/lvvlib 3 | // Copyright (c) 2000-2013 4 | // Leonid Volnitsky (Leonid@Volnitsky.com) 5 | #ifndef LVV_PNG_H 6 | #define LVV_PNG_H 7 | 8 | #include 9 | #include 10 | #include 11 | //#include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | #include 18 | using lvv::array; 19 | 20 | // possible tipes: 21 | // PNG_COLOR_TYPE_GRAY 22 | // PNG_COLOR_TYPE_PALETTE 23 | // PNG_COLOR_TYPE_RGB 24 | // PNG_COLOR_TYPE_RGB_ALPHA 25 | // PNG_COLOR_TYPE_GRAY_ALPHA 26 | 27 | 28 | namespace lvv { 29 | 30 | static void abort_(const char * s, ...) { 31 | va_list args; 32 | va_start(args, s); 33 | vfprintf(stderr, s, args); 34 | fprintf(stderr, "\n"); 35 | va_end(args); 36 | abort(); 37 | }; 38 | 39 | 40 | 41 | template static 42 | void array2png (const char* file_name, uint8_t* A) { 43 | 44 | png_byte color_type = PNG_TYPE; 45 | png_byte bit_depth = 8; 46 | 47 | png_structp png_ptr; 48 | png_infop info_ptr; 49 | 50 | /* create file */ 51 | FILE *fp = fopen(file_name, "wb"); 52 | if (!fp) abort_("[write_png_file] File %s could not be opened for writing", file_name); 53 | 54 | /* initialize stuff */ 55 | png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 56 | if (!png_ptr) abort_("[write_png_file] png_create_write_struct failed"); 57 | info_ptr = png_create_info_struct(png_ptr); 58 | if (!info_ptr) abort_("[write_png_file] png_create_info_struct failed"); 59 | if (setjmp(png_jmpbuf(png_ptr))) abort_("[write_png_file] Error during init_io"); 60 | png_init_io(png_ptr, fp); 61 | 62 | /* write header */ 63 | if (setjmp(png_jmpbuf(png_ptr))) abort_("[write_png_file] Error during writing header"); 64 | png_set_IHDR (png_ptr, info_ptr, width, height, bit_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); 65 | png_write_info(png_ptr, info_ptr); 66 | 67 | // fill AP 68 | png_bytep AP[height]; 69 | for (int r = 0; r static 85 | void array2png ( const char* file_name, array,W>,H>& A ) { array2png (file_name, &A[0][0][0]); } 86 | 87 | template static 88 | void array2png ( const char* file_name, array,W>,H>& A ) { array2png (file_name, &A[0][0][0]); } 89 | 90 | 91 | 92 | }; // namespace lvv 93 | #endif // LVV_H 94 | -------------------------------------------------------------------------------- /spool.h: -------------------------------------------------------------------------------- 1 | // spool.h 2 | // Part of lvvlib - https://github.com/lvv/lvvlib 3 | // Copyright (c) 2000-2013 4 | // Leonid Volnitsky (Leonid@Volnitsky.com) 5 | 6 | #ifndef LVV_SPOOL 7 | #define LVV_SPOOL 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace lvv { 15 | 16 | template 17 | struct buffer_t { 18 | OFFSET_t last; // offset to last string 19 | OFFSET_t buf_end; // offset to +1 past buffer end 20 | char pool [POOL_SIZE]; 21 | 22 | explicit buffer_t() : last(0) { pool[0] = '\0';}; 23 | }; 24 | 25 | 26 | template < 27 | typename BUF_INDEX_t, 28 | typename OFFSET_t 29 | > 30 | struct spool_ref_t { 31 | uint8_t buf; 32 | uint32_t offset; 33 | spool_ref_t (BUF_INDEX_t buf, OFFSET_t offset) : buf(buf), offset(offset) {}; 34 | spool_ref_t () : buf(0) , offset(0) {}; 35 | }; 36 | 37 | template < 38 | size_t STRING_MAX = 256, 39 | size_t POOL_SIZE = 100000000, // 100MB 40 | typename BUF_INDEX_t = uint8_t, 41 | typename OFFSET_t = uint32_t, 42 | BUF_INDEX_t BUF_LIST_MAX = 100 43 | > 44 | struct spool_t { 45 | typedef buffer_t buf_t; 46 | typedef spool_ref_t ref_t; 47 | //typedef spool_t type; 48 | buf_t * buf_list [BUF_LIST_MAX]; 49 | BUF_INDEX_t buf_list_last; 50 | 51 | static const size_t string_max = STRING_MAX; 52 | 53 | explicit spool_t () { buf_list[0] = new buf_t; buf_list_last=0; } 54 | 55 | char* get (const ref_t ref) { 56 | assert (ref.buf <= buf_list_last); 57 | buf_t* bp = buf_list[ref.buf]; assert (ref.offset <= bp->last); 58 | return bp->pool+ref.offset; 59 | }; 60 | 61 | char* get_new (ref_t& ref) { 62 | assert ( BUF_LIST_MAX < std::numeric_limits::max()); 63 | buf_t* bp = buf_list [buf_list_last]; 64 | size_t len = strlen(bp->pool+bp->last); 65 | OFFSET_t end = bp->last + len + 1; 66 | 67 | // new buf? 68 | if (end + STRING_MAX+1 > POOL_SIZE) { 69 | buf_list_last += 1; 70 | assert(buf_list_last < BUF_LIST_MAX); 71 | bp = buf_list[buf_list_last] = new buf_t(); 72 | end = 0; 73 | } else { 74 | bp->last = end; 75 | } 76 | 77 | ref.buf = buf_list_last; 78 | ref.offset = end; 79 | 80 | bp->pool[end] = '\0'; // in case string writing will fail 81 | return bp->pool + end; 82 | } ; 83 | }; 84 | }; // namespace lvv 85 | #endif 86 | -------------------------------------------------------------------------------- /sse.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef LVV_SSE_H 3 | #define LVV_SSE_H 4 | 5 | 6 | #include 7 | 8 | //#include // we can just include immitrin instead of all these test, but it is only in gcc44 9 | #ifdef __MMX__ 10 | #include 11 | #endif 12 | 13 | #ifdef __SSE__ 14 | #include 15 | #endif 16 | 17 | #ifdef __SSE2__ 18 | #include 19 | #endif 20 | 21 | #ifdef __SSE3__ 22 | #include 23 | #endif 24 | 25 | #ifdef __SSSE3__ 26 | #include 27 | #endif 28 | 29 | #include 30 | using boost::detail::if_true; 31 | 32 | namespace lvv { 33 | 34 | 35 | 36 | #ifdef __SSE__ 37 | #define mk_m128(x) *(__m128*)&(x) 38 | #define mk_m128i(x) *(__m128i*)&(x) 39 | template class array; 40 | //template array& mk_array(const __m128& V) { return *(array*)&(V); } // is there an overhead? 41 | //template const array& mk_array(const __m128& V) { return *(array*)&(V); } // is there an overhead? 42 | 43 | 44 | template 45 | union sse_vector{ 46 | __m128i m128i; 47 | array arr; 48 | }; 49 | 50 | //template const array& mk_array(const __m128i& V) { 51 | 52 | // template 53 | //const array& mk_array(const __m128i& V) { 54 | // sse_vector SV; 55 | // SV.m128i = V; 56 | // return SV.arr; 57 | //} 58 | // #endif // __SSE__ 59 | template 60 | const array& mk_array(const __m128i& V) { 61 | sse_vector SV; 62 | SV.m128i = V; 63 | return SV.arr; 64 | } 65 | #endif // __SSE__ 66 | 67 | 68 | // indicator what technology is available 69 | struct plain {}; // no OpenMP, no SSE 70 | struct ooo {}; // Out of Order Optimization 71 | struct nofpu {}; // FPU is not used (bit twiddle) 72 | 73 | struct mmx {}; 74 | struct sse {}; // SSE, no OpenMP 75 | struct sse2 {}; 76 | struct sse3 {}; 77 | struct ssse3 {}; 78 | 79 | struct openmp {}; // OpenMP + SSE 80 | const unsigned sse_threshould = 128; 81 | 82 | } // namespace lvv 83 | #endif // LVV_SSE_H 84 | -------------------------------------------------------------------------------- /t-abs.cc: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | using namespace lvv; 8 | /////////////////////////////////////////////////////////////////// 9 | int 10 | main() { 11 | setup_fpe(); 12 | cerr << setprecision(numeric_limits::digits10+4) << boolalpha; 13 | cout << setprecision(numeric_limits::digits10+4) << boolalpha; 14 | 15 | #include "../lvv/lvvcheck.h" 16 | 17 | cout << "\n\n *** Test equal() ***\n"; 18 | cout << std::boolalpha; 19 | CHECK(abs(1)==1); 20 | CHECK(abs(1u)==1); 21 | CHECK(abs((char)-1)==1); 22 | CHECK(abs(1UL)==1); 23 | CHECK(abs((long)-1)==1); 24 | CHECK(abs(9999)==9999); 25 | CHECK(abs(-31)==31); 26 | CHECK(abs(0)==0); 27 | 28 | CHECK(abs(1.0f)==1.f); 29 | CHECK(abs(-1.f)==1.f); 30 | CHECK(abs(-1.0)==1.); 31 | CHECK(abs(-1E10l)==1E10); 32 | CHECK(abs(9999)==9999); 33 | CHECK(abs(-31.f)==31.f); 34 | CHECK(abs(0.0f)==0.0); 35 | 36 | 37 | cout << (all_pass ? "\n------------ all pass ------------\n" : "\n!!!!!!!!! SOME FAILED !!!!!!!!\n"); 38 | exit(all_pass ? 0 : 1); 39 | } 40 | 41 | 42 | -------------------------------------------------------------------------------- /t-array-opt.cc: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | using namespace std; 4 | 5 | #include 6 | #include 7 | using lvv::array; 8 | 9 | 10 | int main() { 11 | 12 | typedef array a5_t; 13 | 14 | array a0 = {{0,1,2,3,4}}; // index starts from 0 15 | array a1 = {{1,2,3,4,5}}; // index starts from 1 16 | array const b1 = {{10,20,30,40,50}}; // index starts from 1 17 | array an = *new array ; // test new 18 | 19 | for (int i = a1.ibegin(); i < a1.iend(); ++i) { cout << "i=" << i << " a1[i]=" << a1[i] << endl; }; 20 | 21 | 22 | cout << "\n array op= array \n"; 23 | cout << "a1+=b1 " << (a1 += b1)<< endl; 24 | 25 | cout << "-a1 " << -a1 << endl; 26 | 27 | 28 | // vector ops 29 | array c1={{1,2}}; 30 | array c2={{2,2}}; 31 | cout << "dot prod: {1,2} x {2,2} = " << dot_prod(c1,c2) << endl; 32 | cout << "norm2: : |{2,2}| = " << norm2(c2) << endl; 33 | cout << "distance_norm2: : |{1,2}-{2,2}| = " << distance_norm2(c1,c2) << endl; 34 | 35 | cout << endl; 36 | } 37 | -------------------------------------------------------------------------------- /t-array.cc: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | using namespace std; 4 | 5 | //#include 6 | 7 | #include 8 | using boost::format; 9 | 10 | #include 11 | #include 12 | using lvv::array; 13 | 14 | 15 | int main() { 16 | 17 | typedef array a5_t; 18 | 19 | array a0 = {{0,1,2,3,4}}; // index starts from 0 20 | array a1 = {{1,2,3,4,5}}; // index starts from 1 21 | array const b1 = {{10,20,30,40,50}}; // index starts from 1 22 | array an = *new array ; // test new 23 | 24 | for (int i = a1.ibegin(); i < a1.iend(); ++i) { cout << format("i=%d a1[i]=%d") %i % (a1[i]) << endl; }; 25 | for (int i = an.ibegin(); i < an.iend(); ++i) { an[i]=i; cout << format("i=%d an[i]=%d") %i % (an[i]) << endl; }; 26 | 27 | cout << "a0: " << a0 << endl; 28 | cout << "a0 += 10: " << a0 << endl; 29 | 30 | cout << "a1: " << a1 << endl; 31 | cout << "an: " << an << endl; 32 | 33 | 34 | cout << "\n array op= scalar : an+10 " << (an += 10) << endl; 35 | 36 | cout << "\n array op= array \n"; 37 | cout << "a1+=b1 " << (a1 += b1)<< endl; 38 | 39 | //cout << "-a1 " << -a1 << endl; 40 | 41 | 42 | // vector ops 43 | array c1={{1,2}}; 44 | array c2={{2,2}}; 45 | cout << "dot prod: {1,2} x {2,2} = " << dot_prod(c1,c2) << endl; 46 | cout << "norm2: : |{2,2}| = " << norm2(c2) << endl; 47 | cout << "distance_norm2: : |{1,2}-{2,2}| = " << distance_norm2(c1,c2) << endl; 48 | 49 | 50 | //#define FOR_EACH(x,A) for(A::value_type& it=*A.begin(); .... 51 | //FOR_EACH(a,A) cout << a << endl; 52 | 53 | 54 | 55 | /* 56 | cout << "FOR_ARRAY "; 57 | typedef typeof(an) T; 58 | for( 59 | //array::iterator a=an.begin(); 60 | T::iterator a=an.begin(); 61 | a != an.end(); 62 | a++ 63 | ) 64 | cout << *a << " "; 65 | 66 | cout << endl; 67 | */ 68 | 69 | /* 70 | { 71 | cout << "\narray input test, type three whole number\n"; 72 | array A; 73 | cin >> A; 74 | cout << "got from input: " << A << endl; 75 | } 76 | */ 77 | } 78 | -------------------------------------------------------------------------------- /t-check.cc: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | using namespace lvv; 7 | 8 | 9 | template bool equal (T arg1, T arg2) { /*PR(arg1); PR(arg2);*/ return arg1 == arg2; }; 10 | template <> bool equal (int arg1, int arg2) { /*PR(arg1); PR(arg2);*/ return arg1 == arg2; }; 11 | 12 | int 13 | main() { 14 | 15 | int i0=0; 16 | int i1=1; 17 | int i2=2; 18 | 19 | float f0=0.0; 20 | float f1=1.0; 21 | float f2=2.0; 22 | 23 | cout << std::boolalpha; 24 | 25 | CHECK(1 == 1); 26 | CHECK(!equal(f1,f2)); 27 | CHECK( equal(f1,f1)); 28 | CHECK(!equal(f0,f1)); 29 | CHECK(!equal(f1,f0)); 30 | CHECK( equal(f0,f0)); 31 | 32 | CHECK(!equal(i1,i2)); 33 | CHECK( equal(i1,i1)); 34 | CHECK(!equal(i0,i1)); 35 | CHECK(!equal(i1,i0)); 36 | CHECK( equal(i0,i0)); 37 | 38 | CHECK(false); 39 | CHECK_ARE_EQUAL(1,2); 40 | CHECK_NOT_EQUAL(1,2); 41 | CHECK_ARE_EQUAL(1,1); 42 | 43 | CHECK_NOT_EQUAL(f1,f2); 44 | CHECK_ARE_EQUAL(f1,f1); 45 | CHECK_NOT_EQUAL(f0,f1); 46 | CHECK_NOT_EQUAL(f1,f0); 47 | CHECK_ARE_EQUAL(f0,f0); 48 | 49 | CHECK_NOT_EQUAL(i1,i2); 50 | CHECK_ARE_EQUAL(i1,i1); 51 | CHECK_NOT_EQUAL(i0,i1); 52 | CHECK_NOT_EQUAL(i1,i0); 53 | CHECK_ARE_EQUAL(i0,i0); 54 | 55 | cout << (all_pass ? "\n------------ all pass ------------\n" : "\n!!!!!!!!! SOME FAILED !!!!!!!!\n"); 56 | exit(all_pass ? 0 : 1); 57 | } 58 | -------------------------------------------------------------------------------- /t-csv.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | using namespace lvv; 8 | using namespace std; 9 | 10 | 11 | int main() { 12 | 13 | string csv = 14 | "a\"\"b\"\"c\n" 15 | "a\"\"\"b\"\"\"c\n" 16 | "\"a\"\"b\"\"c\"\n" 17 | ",\n" 18 | "a\n" 19 | ",a\n" 20 | "a,\n" 21 | "a,\" a\"a,b\"b \"\n" 22 | "aa,b\"b,c\"c, d ,,ee,ff, g\"g,h\"h \n" "aa, bb,cc ,\" dd\",\"ee \",\"f, g\n" ", h\",\"i,\"\"j,k\"\",l\"\n"; 23 | 24 | istringstream is(csv); 25 | 26 | while (true) { 27 | typedef vector rec_t; 28 | 29 | rec_t rec = csv_get_line(is); 30 | 31 | if (rec.size() == 0) break; 32 | 33 | for (rec_t::iterator x = rec.begin(); x != rec.end(); ++x) { 34 | cout << '>' << *x << "<\n"; 35 | } 36 | 37 | cout << string(20, '*') << '\n'; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /t-equal.cc: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | using namespace std; 8 | using namespace lvv; 9 | 10 | /////////////////////////////////////////////////////////////////// 11 | int 12 | main() { 13 | lvv::setup_fpe(); 14 | 15 | int const i0 = 0; 16 | int const i1 = 1; 17 | int const i2 = 2; 18 | 19 | float const f0 = 0.0; 20 | float const f1 = 1.0; 21 | float const f2 = 2.0; 22 | float const f3 = 3.0; 23 | double const d2= 2.0; 24 | float const f1_ulp = std::numeric_limits::epsilon(); 25 | float const d1_ulp = std::numeric_limits::epsilon(); 26 | 27 | cerr << setprecision(numeric_limits::digits10+4) << boolalpha; 28 | cout << setprecision(numeric_limits::digits10+4) << boolalpha; 29 | 30 | cout << "\n\n *** Test promote trait ***\n"; 31 | PR1(eq(i0,i1)) 32 | PR1(eq(i0,i0)) 33 | PR1(eq(i0,f0)) 34 | PR1(eq(f0,f0)) 35 | 36 | 37 | cout << "\n\n *** Test eq() ***\n"; 38 | cout << std::boolalpha; 39 | CHECK(!eq(1,2)); 40 | CHECK(!eq(1,2l)); 41 | CHECK( eq(1,1u)); 42 | CHECK( eq(0,0.0)); 43 | CHECK( eq(0.0,0.0)); 44 | CHECK( eq(1.0,1.0)); 45 | CHECK(!eq(i1,i2)); 46 | CHECK( eq(i1,i1)); 47 | CHECK(!eq(i0,i1)); 48 | CHECK(!eq(i1,i0)); 49 | CHECK( eq(i0,i0)); 50 | 51 | 52 | cout << "\n\n *** Test eq() ***\n"; 53 | // triv 54 | CHECK(!eq(f1,d2)); 55 | CHECK( eq(f1,f1)); 56 | CHECK(!eq(f0,f1)); 57 | CHECK(!eq(f1,f0)); 58 | CHECK( eq(f0,f0)); 59 | 60 | // compile time const evaluation 61 | CHECK( eq(1/3.0l,0.5l/1.5l)); 62 | CHECK( eq(1/7.0l,2.0l/14.0l)); 63 | 64 | CHECK( eq((f1*f2)/f3, 1/(f3/2))); 65 | CHECK(!eq(0.0f, 0.1*numeric_limits ::epsilon())); 66 | CHECK( eq(d2, d2+ numeric_limits::epsilon())); 67 | CHECK( eq(d2, d2+ 0.5*numeric_limits::epsilon())); 68 | CHECK( eq(d2, d2+ 2*numeric_limits::epsilon())); 69 | CHECK( eq(d2, d2+ 10*numeric_limits::epsilon())); 70 | CHECK( eq(d2, d2+ 20*numeric_limits::epsilon())); 71 | CHECK(!eq(d2, d2+ 500*numeric_limits::epsilon())); 72 | 73 | // big numbers 74 | float f=1e20; 75 | CHECK(!eq(f*0.0001 , f*(-0.0001) )); 76 | CHECK( eq(f*(f1*f2)/f3 , f*(1/(f3/2)) )); 77 | CHECK(!eq(f*0.0f , f*(0.1* f1_ulp) )); 78 | CHECK( eq(f*d2 , f*(d2+ numeric_limits::epsilon()) )); 79 | CHECK( eq(f*d2 , f*(d2+0.5* numeric_limits::epsilon()) )); 80 | CHECK( eq(f*d2 , f*(d2+ 2* numeric_limits::epsilon()) )); 81 | CHECK( eq(f*d2 , f*(d2+ 10*numeric_limits::epsilon()) )); 82 | CHECK( eq(f*d2 , f*(d2+ 20*numeric_limits::epsilon()) )); 83 | CHECK(!eq(f*d2 , f*(d2+ 500*numeric_limits::epsilon()) )); 84 | CHECK(!eq(f*0.0001 , f*((-0.0001)) )); 85 | 86 | // small 87 | f=-1e-20; 88 | CHECK(!eq(f*0.0001 , f*(-0.0001) )); 89 | CHECK( eq(f*(f1*f2)/f3 , f*(1/(f3/2)) )); CHECK(!eq(f*0.0f , f*(0.1*numeric_limits::epsilon()) )); 90 | CHECK( eq(f*d2 , f*(d2+ numeric_limits::epsilon()) )); 91 | CHECK( eq(f*d2 , f*(d2+ 0.5*numeric_limits::epsilon()) )); 92 | CHECK( eq(f*d2 , f*(d2+ 2*numeric_limits::epsilon()) )); 93 | CHECK( eq(f*d2 , f*(d2+ 10*numeric_limits::epsilon()) )); 94 | CHECK( eq(f*d2 , f*(d2+ 20*numeric_limits::epsilon()) )); 95 | CHECK(!eq(f*d2 , f*(d2+ 500*numeric_limits::epsilon()) )); 96 | CHECK(!eq(f*0.0001 , f*((-0.0001)) )); 97 | 98 | // near zero 99 | CHECK( eq(1.1E-20 , 0, 100, 1. )); 100 | 101 | 102 | cout << (all_pass ? "\n------------ all pass ------------\n" : "\n!!!!!!!!! SOME FAILED !!!!!!!!\n"); 103 | exit(all_pass ? 0 : 1); 104 | } 105 | -------------------------------------------------------------------------------- /t-float-exception.cc: -------------------------------------------------------------------------------- 1 | #include "lvv.h" 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | //extern "C" int feenableexcept (int excepts) 9 | 10 | int main () { 11 | 12 | float f999=999; 13 | float f1=1; 14 | float f0=0; 15 | char c1=1; 16 | int iMAX=numeric_limits::max(); 17 | unsigned ui0=0; 18 | 19 | PR1(iMAX+1000); 20 | PR1(c1+999.0); 21 | 22 | PR1(int(char(f999))); 23 | 24 | ui0=ui0-1; 25 | PR1(ui0); 26 | 27 | 28 | cout << " f1/f0 = " << flush << f1/ f0 << endl; 29 | cout << " f1/f0 = " << flush ; 30 | cout << f1/f0 << endl; 31 | //////////////////////////////////////////////////////////////////////////// 32 | feenableexcept (FE_ALL_EXCEPT); // see: man fenv 33 | cout << " enabled \n"; 34 | 35 | PR1(iMAX+1000); 36 | PR1(c1+999.0); 37 | 38 | PR1(int(char(f999))); 39 | 40 | ui0=ui0-1; 41 | PR1(ui0); 42 | 43 | cout << " f1/f0 = " << flush << f1/ f0 << endl; 44 | cout << " f1/f0 = " << flush ; 45 | cout << f1/f0 << endl; 46 | 47 | } 48 | -------------------------------------------------------------------------------- /t-fpe-signal.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | using namespace std; 7 | 8 | int main() { 9 | 10 | lvv::setup_fpe(); 11 | 12 | 13 | ////////////////////////////////////////////////////// INTS 14 | char c1=1; 15 | int iMAX=numeric_limits::max(); 16 | unsigned volatile int random; 17 | unsigned ui0=0; 18 | 19 | PR1(iMAX+1000); 20 | PR1(c1+999.0); 21 | 22 | PR1(int(char((float)999))); 23 | 24 | ui0=ui0-1; 25 | PR1(ui0); 26 | PR1(iMAX+1000); 27 | PR1(c1+999.0); 28 | ui0=ui0-1; 29 | PR1(ui0); 30 | 31 | /////////////////////////////////////////////////////// FLOAT 32 | float fMAX=numeric_limits::max(); 33 | float fMIN=numeric_limits::min(); 34 | float f999=999; 35 | float f1=1; 36 | float f0=0; 37 | 38 | cout << " UNDEFLOW? f999+r=fMIN = " << flush ; cout << f999+random+fMIN << endl; 39 | cout << " UNDEFLOW? - no 0/1 = " << flush ; cout << 0.0/1.0 << endl; 40 | cout << " UNDEFLOW? - no 0/1 = " << flush ; cout << 0.0/1.0 << endl; 41 | cout << " OVERFLOW: fMAX*fMAX = " << flush ; cout << fMAX*fMAX << endl; 42 | cout << " UNDEFLOW: fMIN/fMAX = " << flush ; cout << fMIN/fMAX << endl; 43 | cout << " DEV-BY-ZERO: f1/f0 = " << flush; cout << f1/f0 << endl; 44 | 45 | return 0; 46 | 47 | } // vim:nu noic: 48 | -------------------------------------------------------------------------------- /t-memoize.cc: -------------------------------------------------------------------------------- 1 | 2 | #include "memoize.h" 3 | 4 | #include 5 | using namespace std; 6 | 7 | int f (int i) { cout << "f(" << i << ")\n"; return i+1; }; 8 | int ff (int i, int j) { cout << "f(" << i << ", " << j << ")\n"; return i+j; }; 9 | 10 | 11 | int main() { 12 | auto f_cached = lvv::memoize ( std::function (f) ); 13 | f_cached(1); 14 | f_cached(2); 15 | f_cached(1); 16 | f_cached(2); 17 | f_cached(3); 18 | 19 | // output: 20 | // f(1) 21 | // f(2) 22 | // f(3) 23 | 24 | 25 | auto ff_cached = lvv::memoize ( std::function (ff) ); 26 | ff_cached(1,1); 27 | ff_cached(2,2); 28 | ff_cached(1,1); 29 | ff_cached(0,0); 30 | ff_cached(1,1); 31 | 32 | // output 33 | // f(1, 1) 34 | // f(2, 2) 35 | // f(0, 0) 36 | } 37 | -------------------------------------------------------------------------------- /t-mmap.cc: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | using namespace std; 4 | 5 | #include 6 | using lvv::array; 7 | 8 | #include 9 | using namespace lvv; 10 | using lvv::mmap_read; 11 | using lvv::mmap_write; 12 | 13 | 14 | int main(int argc, char *argv[]) { 15 | 16 | cout << "\n\n *** int write, read *** \n"; 17 | int i=1; 18 | size_t n; 19 | mmap_write ("/tmp/_i.mmap", i); 20 | int ii = *(int*)mmap_read_ptr ("/tmp/_i.mmap", n); // traditional void * 21 | int iii = mmap_read ("/tmp/_i.mmap"); // templated ref 22 | cout << "ii=" << ii << endl; 23 | cout << "iii=" << iii << endl; 24 | 25 | 26 | cout << "\n\n *** flat plain-array write, read *** \n"; 27 | float f[3]={1.11, 2.22, 3.33}; 28 | mmap_write("/tmp/_fa.mmap", f); 29 | 30 | 31 | float *F; 32 | F = mmap_read("/tmp/_fa.mmap",n); 33 | 34 | for (size_t i=0; i array_t; 44 | array_t d={{0.11, 0.22, 0.33}}; 45 | mmap_write ("/tmp/_da.mmap", d); // size is taken from array_t 46 | array_t& dd = mmap_read ("/tmp/_da.mmap"); 47 | cout << "array d =" << d << endl; 48 | cout << "array dd =" << dd << endl; 49 | 50 | ////////////////////////////////////////////////// PART OF VECTOR 51 | 52 | { 53 | cout << "\n\n *** vector char *** \n"; 54 | vector A={'a','b','c','d'}; 55 | mmap_write("/tmp/vector_char.mmap", A.data(),2); 56 | 57 | 58 | char *B; 59 | size_t B_size; 60 | B = mmap_read("/tmp/vector_char.mmap",B_size); 61 | 62 | for (size_t i=0; i *** \n"; 72 | vector A={1,2,3,4,5}; 73 | mmap_write("/tmp/vector_size.mmap", &A[0], 3); 74 | 75 | 76 | size_t *B; 77 | size_t B_size; 78 | B = mmap_read("/tmp/vector_size.mmap",B_size); 79 | 80 | for (size_t i=0; i B; B = 255; 25 | for (int r = 0; r ("t-b.png", &B[0]); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /t-progress_dots.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | int main () { 6 | 7 | for (int i = 100000; i <= 200000; ++i) 8 | lvv::progress_dots(i,100000,200000, "progress: "); 9 | } 10 | // vim:nu: 11 | -------------------------------------------------------------------------------- /t-s_pool.cc: -------------------------------------------------------------------------------- 1 | //#include 2 | 3 | #include "s_pool.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | int main() { 12 | 13 | typedef lvv::spool_t <20,50> SPOOL_t; 14 | typedef SPOOL_t::ref_t REF_t; 15 | SPOOL_t spool; 16 | deque s_list; 17 | REF_t ref; 18 | 19 | while (cin.getline (spool.get_new(ref), 1000)) { 20 | cout << "in: " << spool.get(ref) << " \t ref: " << int(ref.buf) << " / " << ref.offset << endl; 21 | s_list.push_back(ref); 22 | } 23 | 24 | for (auto it = s_list.rbegin(); it != s_list.rend(); it++) 25 | cout << "out: " << spool.get(*it) << endl; 26 | exit(0); 27 | } 28 | -------------------------------------------------------------------------------- /t-timer-c11.cc: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | using namespace std; 5 | //using namespace lvv; 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | //using lvv::timer_t; 12 | 13 | 14 | int main() { 15 | 16 | 17 | cout << lvv::read_tick() << " -- 1 \n"; 18 | cout << lvv::read_tick() << " -- 1 \n"; 19 | cout << lvv::read_tick() << " -- 1 \n"; 20 | cout << lvv::read_tick() << " -- 1 \n"; 21 | cout << lvv::read_tick() << " -- 1 \n"; 22 | cout << lvv::read_tick() << " -- 1 \n"; 23 | cout << lvv::read_tick() << " -- 1 \n"; 24 | cout << lvv::read_tick() << " -- 1 \n"; 25 | cout << lvv::read_tick() << " -- 1 \n"; 26 | cout << "timer_t CTOR\n"; 27 | lvv::timer_t verboze_t(true); 28 | lvv::timer_t t; 29 | auto start_t = std::chrono::system_clock::now(); 30 | t.print("timer.print() MSG test"); 31 | 32 | cout << "timer()=" << t() << endl; 33 | cout << "\n*** usleep 1000\n"; 34 | usleep(useconds_t(10000)); 35 | cout << "interval_ticks(): " << t.interval_ticks() << '\n'; 36 | t.print("2nd print()"); 37 | 38 | cout << "\n*** usleep 2000\n"; 39 | usleep(useconds_t(20000)); 40 | t.print("3rd print()"); 41 | cout << "stream << test " << t << endl; 42 | 43 | cout << "\n*** usleep 3000\n"; 44 | usleep(useconds_t(30000)); 45 | auto end_t = std::chrono::system_clock::now(); 46 | auto dur_t = end_t - start_t; 47 | auto dur_ms = std::chrono::duration_cast (dur_t); 48 | cout << "\nchrono timer: " << dur_ms.count() << " ms\n"; 49 | 50 | cout << "Last line will be from timer_t destructor \n"; 51 | } 52 | -------------------------------------------------------------------------------- /t-timer.cc: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | using namespace std; 5 | //using namespace lvv; 6 | 7 | #include 8 | #include 9 | using lvv::timer_t; 10 | 11 | 12 | int main() { 13 | 14 | 15 | cout << lvv::read_tick() << " -- 1 \n"; 16 | cout << lvv::read_tick() << " -- 1 \n"; 17 | cout << lvv::read_tick() << " -- 1 \n"; 18 | cout << lvv::read_tick() << " -- 1 \n"; 19 | cout << lvv::read_tick() << " -- 1 \n"; 20 | cout << lvv::read_tick() << " -- 1 \n"; 21 | cout << lvv::read_tick() << " -- 1 \n"; 22 | cout << lvv::read_tick() << " -- 1 \n"; 23 | cout << lvv::read_tick() << " -- 1 \n"; 24 | cout << "timer_t CTOR\n"; 25 | timer_t verboze_t(true); 26 | timer_t t; 27 | t.print("timer.print() MSG test"); 28 | 29 | cout << "timer()=" << t() << endl; 30 | cout << "\n*** usleep 1000\n"; 31 | usleep(useconds_t(10000)); 32 | cout << "interval_ticks(): " << t.interval_ticks() << '\n'; 33 | t.print("2nd print()"); 34 | 35 | cout << "\n*** usleep 2000\n"; 36 | usleep(useconds_t(20000)); 37 | t.print("3rd print()"); 38 | cout << "stream << test " << t << endl; 39 | 40 | cout << "\n*** usleep 3000\n"; 41 | usleep(useconds_t(30000)); 42 | 43 | cout << "Last line will be from timer_t destructor \n"; 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /t-type-descriptor.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using lvv::type_descriptor; 4 | 5 | int main() { 6 | std::cout 7 | << type_descriptor() << "\n" 8 | << type_descriptor() << "\n" 9 | << type_descriptor() << "\n" 10 | << type_descriptor() << "\n" 11 | << type_descriptor() << "\n" 12 | << type_descriptor() << "\n" 13 | << type_descriptor() << "\n" 14 | << type_descriptor() << "\n" 15 | << type_descriptor() << "\n" 16 | << type_descriptor() << std::endl; 17 | 18 | 19 | return 0; 20 | } 21 | 22 | -------------------------------------------------------------------------------- /timer.h: -------------------------------------------------------------------------------- 1 | // 2 | // TODO 3 | // http://bryanstamour.com/2012/05/13/timing-functions-with-chrono.html 4 | // http://solarianprogrammer.com/2012/10/14/cpp-11-timing-code-performance/ 5 | 6 | #ifndef LVV_TIMER_H 7 | #define LVV_TIMER_H 8 | 9 | // this is for uint64_t on gcc-4.4 10 | //#define _GLIBCXX_USE_C99_STDINT_TR1 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | using std::ostream; 20 | using std::endl; 21 | using std::cerr; 22 | using std::cout; 23 | using std::setprecision; 24 | #include 25 | 26 | 27 | namespace lvv { 28 | 29 | // TR http://www.viva64.com/en/b/0097/ 30 | 31 | /* OpenMP thread time? 32 | double omp_time = 0; 33 | double last_omp_time; 34 | last_omp_time = omp_time; 35 | omp_time = omp_get_wtime(); 36 | 37 | int static cnt = 0; 38 | MSG("(%d/%.1fs ? :%.1fs elapsed)%8t") % cnt++ %timer() %(omp_time-last_omp_time); 39 | -------------------------------- 40 | Timers: http://www.strchr.com/performance_measurements_with_rdtsc 41 | */ 42 | 43 | ///////////////////////////////////////////////////////////////////////////////////// READ_TICK 44 | 45 | // TODO: new stop start seq --- http://blog.regehr.org/archives/330 46 | #if defined(__x86_64) || defined (__i386) 47 | 48 | uint64_t static read_tick() { // tested with with x86_64 only. 49 | uint64_t now_tick; 50 | asm volatile ( "subl %%eax, %%eax;" 51 | "cpuid;" 52 | "rdtsc;" 53 | #if defined(__x86_64) 54 | "shlq $32, %%rdx;" 55 | "orq %%rdx, %%rax;" // combine into 64 bit register 56 | "movq %%rax, %[now_tick];" 57 | #endif 58 | #if defined(__i386) 59 | "movl %%eax, %[now_tick];" 60 | "lea %0, %%eax;" 61 | "movl %%edx, 4(%%eax);" 62 | #endif 63 | "cpuid;" 64 | :[now_tick] "=m"(now_tick) // output 65 | : 66 | #if defined(__x86_64) 67 | :"rax", "rdx", "rbx","rcx", "rdx" // clobbered register 68 | #else 69 | :"ebx","ecx", "edx" // clobbered register 70 | #endif 71 | ); 72 | return now_tick; 73 | } 74 | #endif 75 | 76 | class timer_t; 77 | static ostream& operator<< (ostream& os, timer_t& t) __attribute__((unused)) ; 78 | 79 | class timer_t { //=========================================== TIMER 80 | // TR http://www.viva64.com/en/b/0097/ 81 | // ------------- 82 | // article about hi-res timers: http://www.devx.com/cplus/Article/35375/0/page/2 83 | // see also OpenMP timer: http://gcc.gnu.org/onlinedocs/libgomp/omp_005fget_005fwtime.html#omp_005fget_005fwtime 84 | // --- 85 | // > how do you get the divide by 10? 86 | // 87 | // The TSC updates at the rate the bus clock ticks, and when it updates 88 | // it adds the (processor clock speed)/(bus clock speed) ratio, rather 89 | // than 1. Since my processor clock speed is 2.67 GHz and the bus clock 90 | // is 267 MHz, this ratio is 10 and so every TSC reading will be divisible 91 | // by 10. Just copy and paste some of your raw TSC measurements here 92 | // and the readers will be able to figure out your bus clock ratio. 93 | // When the ratio is 10, it is quite obvious because the last digit of 94 | // every measurement is zero, but for other ratios it might not be so 95 | // evident at a glance. 96 | // 97 | private: 98 | bool verbose_dtor; 99 | 100 | // Tick (cpu cycle) 101 | #if defined(__x86_64) || defined (__i386) 102 | uint64_t ctor_tick; 103 | uint64_t interval_start_tick; 104 | uint64_t now_tick; 105 | uint64_t overhead; 106 | #endif 107 | 108 | // TV - wall clock time 109 | timeval ctor_tv; 110 | timeval interval_start_tv; 111 | timeval now_tv; 112 | 113 | // RU - CPU time 114 | struct rusage ctor_ru; 115 | struct rusage interval_start_ru; 116 | struct rusage now_ru; 117 | 118 | double 119 | wall_time_at(timeval tv) { return tv.tv_sec + tv.tv_usec / 1000000.; }; 120 | 121 | double 122 | cpu_time_at(struct rusage ru) { 123 | return 124 | ru.ru_utime.tv_sec + ru.ru_utime.tv_usec / 1000000. + 125 | ru.ru_stime.tv_sec + ru.ru_stime.tv_usec / 1000000.; 126 | }; 127 | 128 | public: 129 | 130 | 131 | 132 | timer_t(bool verbose_dtor=false) : verbose_dtor(verbose_dtor) { 133 | #if defined(__x86_64) || defined (__i386) 134 | ctor_tick = interval_start_tick = read_tick(); 135 | overhead = interval_ticks(); 136 | #endif 137 | gettimeofday(&now_tv, NULL); ctor_tv = interval_start_tv = now_tv; 138 | getrusage(RUSAGE_SELF, &now_ru); ctor_ru = interval_start_ru = now_ru; 139 | }; 140 | 141 | ~timer_t() { 142 | if (verbose_dtor) { 143 | if (total_cpu() < 0.001) cerr << "(*) on exit: cpu time: " << std::fixed << total_cpu()/1000000 << " μs " << "wall time: " << total_wall()/1000000 << " μs " << endl; 144 | else cerr << "(*) on exit: cpu time: " << std::fixed << total_cpu() << " s " << "wall time: " << total_wall() << " s " << endl; 145 | } 146 | // memory report 147 | //system("egrep -r '^Vm(Peak|Size|RSS|Data|Stk|Exe|Lib)' /proc/$PPID/status |sed 's/^Vm//; s/ kB/k/; s/ *//'|tr ' \n' ' '"); 148 | // amount of unrequested memory - CommitLimit - Committed_AS 149 | }; 150 | 151 | void reset() { 152 | #if defined(__x86_64) || defined (__i386) 153 | interval_ticks(); 154 | #endif 155 | interval_cpu(); 156 | interval_wall(); 157 | } 158 | 159 | #if defined(__x86_64) || defined (__i386) 160 | uint64_t 161 | interval_ticks() { 162 | uint64_t now_tick = read_tick(); 163 | uint64_t ticks = now_tick - interval_start_tick; 164 | interval_start_tick = now_tick; 165 | return ticks; 166 | } 167 | #endif 168 | 169 | double 170 | interval_wall() { 171 | gettimeofday(&now_tv, NULL); 172 | double sec = wall_time_at(now_tv) - wall_time_at(interval_start_tv); 173 | interval_start_tv = now_tv; 174 | return sec; 175 | } 176 | double 177 | interval_cpu() { 178 | getrusage(RUSAGE_SELF, &now_ru); 179 | double sec = cpu_time_at(now_ru) - cpu_time_at(interval_start_ru); 180 | interval_start_ru = now_ru; 181 | return sec; 182 | } 183 | 184 | 185 | #if defined(__x86_64) || defined (__i386) 186 | uint64_t total_ticks () { return read_tick() - ctor_tick; } 187 | #endif 188 | double total_wall () { gettimeofday(&now_tv, NULL); return wall_time_at(now_tv) - wall_time_at(ctor_tv); } 189 | 190 | double total_cpu () { getrusage(RUSAGE_SELF, &now_ru); return cpu_time_at (now_ru) - cpu_time_at (ctor_ru); } 191 | 192 | double operator() () { return interval_wall(); } 193 | 194 | void 195 | print(std::string msg="") { 196 | 197 | if (msg=="") 198 | std::cerr << std::setw(13) << "(timer) " << std::flush; 199 | else { 200 | std::cerr <<" ⌛ " << msg << " " << std::flush; 201 | }; 202 | 203 | std::cerr << std::setprecision(4); 204 | #if defined(__x86_64) || defined (__i386) 205 | std::cerr << "overhead:" << overhead << "t " ; 206 | std::cerr << "interval:" << interval_ticks() << "t " ; 207 | std::cerr << "total: " << total_ticks( ) << "t " ; 208 | #endif 209 | std::cerr << "interval-wall:" << interval_wall() << "s " ; 210 | std::cerr << "interval-cpu: " << interval_cpu( ) << "s " ; 211 | std::cerr << "total-wall: " << total_wall( ) << "s " ; 212 | std::cerr << "total-cpu: " << total_cpu( ) << "s " ; 213 | std::cerr << std::endl; 214 | }; 215 | 216 | friend std::ostream& operator<< (std::ostream& os, timer_t& t); 217 | }; 218 | 219 | 220 | static ostream& 221 | operator<< (ostream& os, timer_t& t) { 222 | os << setprecision(5) << " " << t() << "s "; 223 | return os; 224 | } 225 | 226 | 227 | void static __attribute__((unused)) 228 | progress_dots(long var, long first, long last, std::string msg="" ) { //=============================================== progress_dots() 229 | 230 | static bool first_time = true; 231 | static int columns = 0; 232 | static int width; 233 | 234 | if (first_time) { 235 | 236 | first_time=false; 237 | char* columns_str=getenv("COLUMNS"); 238 | 239 | if (columns_str) 240 | columns=atoi(columns_str); 241 | 242 | width = columns - msg.length(); 243 | } 244 | 245 | if (!columns) return; 246 | if ( var==first) cerr << msg; 247 | int div=(last-first)/width; 248 | if ( (var-first) % (div+1) == 0 ) cerr << "." << std::flush; 249 | if ( var == last ) cerr << endl; 250 | } 251 | 252 | } // namespace lvv 253 | #endif // LVV_TIMER_H 254 | -------------------------------------------------------------------------------- /token.h: -------------------------------------------------------------------------------- 1 | // splits string into tokens 2 | // part of lvvlib - https://github.com/lvv/lvvlib 3 | 4 | //[u'\t', u'\n', u'\x0b', u'\x0c', u'\r', u'\x1c', u'\x1d', u'\x1e', u'\x1f', u' ', u'\x85', u'\xa0', u'\u1680', u'\u180e', u'\u2000', u'\u2001', u'\u2002', u'\u2003', u'\u2004', u'\u2005', u'\u2006', u'\u2007', u'\u2008', u'\u2009', u'\u200a', u'\u2028', u'\u2029', u'\u202f', u'\u205f', u'\u3000'] 5 | 6 | #include "unicode.h" 7 | 8 | #include 9 | using std::find_if; 10 | using std::find_if_not; 11 | 12 | #include 13 | namespace { 14 | 15 | typedef const char* pos_t; 16 | constexpr char token_separator = ' '; 17 | 18 | 19 | // names, token 20 | struct strref { 21 | strref () : b(nullptr), e(nullptr) {}; 22 | strref (pos_t b, pos_t e) : b(b), e(e) {}; 23 | strref (const char* cs) { b=cs; e=cs; while(*e) ++e; }; 24 | 25 | pos_t b, e; 26 | size_t size() const { return e-b; }; 27 | operator std::string () const { return std::string(b,e); }; 28 | bool operator==(const char* p) const { const char* pe=p; while(*pe) ++pe; return e-b == pe-p && std::equal(b,e, p); }; 29 | bool operator==(const std::string& s) const { return size_t(e-b) == s.size() && std::equal(b,e, s.begin()); }; 30 | }; 31 | 32 | __attribute__((unused)) 33 | std::ostream& operator<< (std::ostream& os, const strref& s) { 34 | return os << "(" << std::string(s.b,s.e) << ")"; 35 | }; 36 | 37 | 38 | struct is_t { 39 | is_t() { for (auto c: " \t\n\r-,.:'~`!@#$%^&*()_-+={}[]|\\|:;\"',<>./?") separator[(size_t)c]=1; } 40 | char separator[256]={0}; 41 | }; 42 | 43 | is_t is; 44 | 45 | 46 | 47 | ////pos_t get_tb(pos_t b, pos_t e) { return std::find_if_not (b,e, [](char c){ return c==' ' || c=='\t' || c=='\n' ; }); }; 48 | //pos_t get_tb(pos_t b, pos_t e) { assert(b<=e); return std::find_if (b,e, [](char c){ return !(c==' ' || c=='\t' || c=='\n'); }); }; 49 | //pos_t get_te(pos_t b, pos_t e) { assert(b<=e); return std::find_if (b,e, [](char c){ return c==' ' || c=='\t' || c=='\n' ; }); }; 50 | 51 | pos_t get_tb(pos_t b, pos_t e) { assert(b<=e); return std::find_if (b,e, [](char c){ return !is.separator[(size_t)c]; }); }; 52 | pos_t get_te(pos_t b, pos_t e) { assert(b<=e); return std::find_if (b,e, [](char c){ return is.separator[(size_t)c]; }); }; 53 | 54 | bool are_equal_token_chains (pos_t b1, pos_t e1, pos_t b2, pos_t e2) { 55 | 56 | pos_t tb1; 57 | pos_t te1 = b1; 58 | 59 | pos_t tb2; 60 | pos_t te2 = b2; 61 | 62 | while ( 63 | (tb1=get_tb(te1,e1)), 64 | (tb2=get_tb(te2,e2)), 65 | tb1!=e1 && tb2!=e2 66 | ) { 67 | te1=get_te(tb1,e1); 68 | te2=get_te(tb2,e2); 69 | if ( !((te1-tb1)==(te2-tb2) && std::equal (tb1,te1, tb2)) ) return false; 70 | } 71 | 72 | return tb1==e1 && tb2==e2; 73 | } 74 | 75 | 76 | bool is_head_of (pos_t b1, pos_t e1, pos_t b2, pos_t e2, pos_t& match_e) { 77 | // (b1,e1) - token chain; 78 | // (b2,e2) - string; 79 | // reuturns true if (b2,e2) starts with (b1,e1) and sets end of match in match_e 80 | pos_t tb1; 81 | pos_t te1 = b1; 82 | 83 | pos_t tb2; 84 | pos_t te2 = b2; 85 | 86 | while ( 87 | (tb1=get_tb(te1,e1)), 88 | (tb2=get_tb(te2,e2)), 89 | tb1!=e1 && tb2!=e2 90 | ) { 91 | te1=get_te(tb1,e1); 92 | te2=get_te(tb2,e2); 93 | if ( !((te1-tb1)==(te2-tb2) && std::equal (tb1,te1, tb2)) ) return false; 94 | } 95 | 96 | 97 | if ( tb1==e1) { // if 1st ended -> match 98 | match_e = te2; 99 | return true; 100 | } else { 101 | return false; 102 | } 103 | } 104 | 105 | bool are_equal_token_chains(strref n1, strref n2) { return are_equal_token_chains(n1.b, n1.e, n2.b, n2.e); } 106 | bool is_head_of(strref n1, strref n2, pos_t& match_e) { return is_head_of(n1.b, n1.e, n2.b, n2.e, match_e); } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /u-array-small.cc: -------------------------------------------------------------------------------- 1 | 2 | #define CANUSE_SSE 3 | #define CANUSE_SSE2 4 | #define CANUSE_SSE3 5 | //#include 6 | 7 | #include 8 | using lvv::eq; 9 | #include 10 | using lvv::array; 11 | using lvv::sse; 12 | using lvv::sse2; 13 | using lvv::plain; 14 | using lvv::openmp; 15 | using lvv::select_method; 16 | 17 | #include 18 | 19 | #include 20 | using namespace std; 21 | using namespace lvv; 22 | 23 | int 24 | main() { 25 | array h10 = {{1,2,3,4,5,6,7,8,9,10}}; 26 | //CHECKeq((h10.max_impl(sse2(),int16_t())),10); 27 | cout << h10[0] << endl; 28 | cout << h10 << endl; 29 | cout << h10[9] << endl; 30 | //cout << *(h10.sub_array(3)) << endl; 31 | 32 | CHECK_EXIT; 33 | } 34 | -------------------------------------------------------------------------------- /u-array.cc: -------------------------------------------------------------------------------- 1 | // don't touch this line, it is used for array input test 2 | 3 | #define CANUSE_SSE 4 | #define CANUSE_SSE2 5 | #define CANUSE_SSE3 6 | 7 | #include 8 | using std::cout; 9 | using std::endl; 10 | 11 | #include 12 | using std::is_sorted; 13 | 14 | #include 15 | using std::ifstream; 16 | 17 | 18 | #include 19 | using lvv::eq; 20 | #include 21 | using lvv::array; 22 | using lvv::sse; 23 | using lvv::sse2; 24 | using lvv::plain; 25 | using lvv::openmp; 26 | using lvv::select_method; 27 | 28 | #include 29 | 30 | #include 31 | //#include 32 | using namespace std; 33 | using namespace lvv; 34 | 35 | 36 | 37 | int 38 | main() { 39 | 40 | typedef array a5_t; 41 | 42 | cout << "\n ***** CTOR *******\n"; ////////////////////////////////////////////////////////////////////// 43 | array a0 = {{0,1,2,3,4}}; // index starts from 0 44 | CHECK(a0.ibegin()==0); 45 | CHECK( a0.iend()==5); 46 | CHECK( a0.size()==5); 47 | 48 | array a1 = {{1,2,3,4,5}}; // index starts from 1 49 | CHECK( a1.ibegin()==1); 50 | CHECK( a1.iend()==6); 51 | CHECK( a1.size()==5); 52 | array an = {{-2,-1,0,1,2}}; // index starts from -2 53 | CHECK( an.ibegin()==-2); 54 | CHECK( an.iend()==3); 55 | CHECK( an.size()==5); 56 | 57 | array const b1 = {{10,20,30,40,50}}; // index starts from 1 58 | array res; 59 | 60 | // cout << "a0: " << a0 << endl; 61 | 62 | { cout << "\n ***** VECTOR ASSIGNMENT *******\n"; /////////////////////////////////////////////// 63 | // = scalar 64 | array a0s; 65 | CHECK((a0s=0, a0s[0] == 0)); 66 | CHECK((a0s = 9, a0s.back() == 9)); 67 | 68 | 69 | // = diffrent dimentions 70 | array a0i = {{0,1,2}}; 71 | 72 | CHECK((a0s=a0i, a0s[0] == 0)); 73 | CHECK(( a0s.back() == 2)); 74 | 75 | 76 | // = diffrent type 77 | array b1f = {{1.f,2.f,3.f}}; 78 | array bm1d; 79 | bm1d = b1f; 80 | CHECKeq(bm1d.front(), 1.f); 81 | 82 | } 83 | cout << "\n ***** VECTOR OPS *******\n"; /////////////////////////////////////////////// 84 | an += 10; 85 | CHECK( *an.begin() == -2+10 ); 86 | CHECK( an[-1] == -1+10 ); 87 | CHECK( an[an.iend()-1] == 2+10 ); 88 | 89 | // array OP= array 90 | CHECK((res = a1, res+=b1, res[1] == 1+10)); 91 | CHECK((res = a1, res+=b1, res[5] == 5+50)); 92 | CHECK((res = a1, res*=b1, res[1] == 1*10)); 93 | CHECK((res = a1, res*=b1, res[5] == 5*50)); 94 | 95 | // array OP array 96 | CHECK((res = a1+b1, res[1] == 1+10)); 97 | CHECK((res = a1+b1, res[5] == 5+50)); 98 | 99 | // array OP scalar 100 | CHECK((res = a1+1, res[1] == 1+1)); 101 | CHECK((res = a1+1, res[5] == 5+1)); 102 | CHECK((res = a1*2, res[1] == 1*2)); 103 | CHECK((res = a1*2, res[5] == 5*2)); 104 | 105 | // scalar OP array 106 | CHECK((res = 1+a1, res[1] == 1+1)); 107 | CHECK((res = 1+a1, res[5] == 5+1)); 108 | CHECK((res = 2*a1, res[1] == 1*2)); 109 | CHECK((res = 2*a1, res[5] == 5*2)); 110 | 111 | 112 | /////////////////////////////////////////////////////////////////////////////////////////////////////////// 113 | 114 | cout << "\n ***** DOT PRODUCT *******\n"; /////////////////////////////////////////////// 115 | // vector ops 116 | array c1={{1,2}}; 117 | array c2={{2,2}}; 118 | array c201={}; 119 | 120 | // dot prod: vecot.vector {1,2} x {2,2} = " 121 | { 122 | array c1={{1,2}}; 123 | array c2={{2,2}}; 124 | CHECK( dot_prod(c1,c2) == 6 ); 125 | 126 | // dot prod: matrix.matrix 127 | //matrix A22={ {{1,2}}, {{3,4}} }; 128 | //matrix A23={ {{1,2}}, {{3,4}}, {{5,6}} }; 129 | ////CHECK( dot(A23, A23) == 6 ); 130 | //cout << "############################\n" << dot(A23, A23); 131 | } 132 | 133 | cout << "\n ***** NORM *******\n"; /////////////////////////////////////////////// 134 | // norm2: : |{2,2}| 135 | CHECK( eq(norm2(c2), 2.82843f) ); 136 | 137 | //distance_norm2: : |{1,2}-{2,2}| = 138 | array v1 = {{3., 0.}}; 139 | array v2 = {{0., 4.}}; 140 | CHECK( eq(distance_norm2(v1,v2), 5.)); 141 | 142 | #ifdef CONVERT_GSl_H 143 | cout << "\n ***** CONVERT_GSL *******\n"; /////////////////////////////////////////////// 144 | gsl_vector* gV; // 1st index == 0 145 | gV = gsl_vector_alloc(a0.size()); 146 | gV <<= a0; 147 | CHECK( gsl_vector_get(gV,0) == a0[0]); 148 | CHECK( gsl_vector_get(gV,2) == a0[2]); 149 | 150 | b0 <<= gV; 151 | CHECK( b0[2]== a0[2]); 152 | CHECK( b0 == a0); 153 | 154 | gV << a1; 155 | CHECK( gsl_vector_get(gV,0) == a1[1]); 156 | CHECK( gsl_vector_get(gV,2) == a1[3]); 157 | CHECK( gsl_vector_get(gV,4) == a1[5]); 158 | 159 | array b_m2; 160 | b_m2 << gV; 161 | CHECK( b_m2[-2]== a1[1]); 162 | CHECK( b_m2[2] == a1[5]); 163 | #endif 164 | 165 | 166 | 167 | cout << "\n ***** SSE ALIGNMENT *******\n"; /////////////////////////////////////////////// 168 | 169 | //#define CHK(var) cout << #var << " \t " << &var << " \t " << reinterpret_cast(&var) % 16 << endl; 170 | #define CHK(x) 171 | 172 | #define IS_ALIGN16(var) ((reinterpret_cast(&var) % 16) == 0) 173 | 174 | //cout << "SUM: " << c1.sum() << endl; 175 | //cout << "MAX: " << c1.max() << endl; 176 | //cout << "MAX: " << c1.max() << " \t " << &c1 << "\t addr % 16 = " << reinterpret_cast(&c1) % 16 << endl; 177 | //cout << "MAX: " << c2.max() << " \t " << &c2 << "\t addr % 16 = " << reinterpret_cast(&c2) % 16 << endl; 178 | //CHK(c2); 179 | 180 | CHK(c0); 181 | CHK(c1); 182 | CHK(b0); 183 | array f1; CHK(f1); 184 | array ch3; CHK(ch3); 185 | array f7; CHK(f7); 186 | array ch10; CHK(ch10); 187 | array ch11; CHK(ch11); 188 | array ch12; CHK(ch12); 189 | array ch13; CHK(ch13); 190 | array d1; CHK(d1); 191 | array ch14; CHK(ch14); 192 | array ch2; CHK(ch2); 193 | array f4; 194 | CHK(f4); 195 | CHK(f4[1]); 196 | CHK(f4[2]); 197 | CHK(f4[3]); 198 | 199 | CHK(c201); CHECK(IS_ALIGN16(c201)); 200 | 201 | typedef int i4_t[101]; // __attribute__((aligned(16))); 202 | i4_t i4; 203 | CHK(i4); CHECK(IS_ALIGN16(i4)); 204 | 205 | cout << "\n ***** SELECT_METHOD *******\n"; /////////////////////////////////////////////// 206 | CHECK(typeid(select_method::type ) == typeid(plain) ) ; 207 | CHECK(typeid(select_method::type) == typeid(plain) ) ; 208 | CHECK(typeid(select_method::type ) == typeid(plain) ) ; 209 | CHECK(typeid(select_method::type) == typeid(plain) ) ; 210 | CHECK(typeid(select_method::type ) == typeid(plain)); 211 | 212 | cout << "\n ##### SSE SPECIALISATION ##########################################\n"; /////////////////////////////////////////////// 213 | 214 | { cout << "\n ***** FLOAT-32 *******\n"; 215 | { array f6 = {{1,2,3,4,5,6}}; CHECK( f6.max() == 6 ); } 216 | 217 | CHECK(typeid(select_method::type ) == typeid(plain) ) ; 218 | CHECK(typeid(select_method::type) == typeid(sse) ) ; 219 | array f3 = {{1,2,3}}; 220 | array f4 = {{1,2,3,4}}; 221 | array f81 = {{1,2,3,4,5,6,7,8}}; 222 | array f10 = {{1,2,3,4,5,6,7,8,9,10}}; 223 | array f20 = {{1,2,3,4,5,6,7,8,9,10}}; 224 | 225 | #ifdef CANUSE_SSE 226 | // CHECKeq((f3.max()),3); should trigger static assert 227 | CHECKeq((f10.max()),10); 228 | CHECKeq((f10.max()),10); 229 | #endif 230 | CHECKeq(f20.max(),10); 231 | CHECKeq(f4.max(),4); 232 | CHECKeq(f81.max(),8); 233 | 234 | } 235 | 236 | { cout << "\n ***** INT-16 *******\n"; 237 | CHECK(typeid(select_method::type ) == typeid(plain) ) ; 238 | CHECK(typeid(select_method::type) == typeid(sse2) ) ; 239 | array h3 = {{1,2,3}}; CHECK(IS_ALIGN16(h3)); 240 | array h10 = {{1,2,3,4,5,6,7,8,9,10}}; CHECK(IS_ALIGN16(h10)); 241 | array h20 = {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20}}; CHECK(IS_ALIGN16(h10)); 242 | array h1000 = {{1,2,3,4,5,6,7,8,9,10}}; CHECK(IS_ALIGN16(h1000)); 243 | 244 | // CHECKeq((f3.max()),3); should trigger static assert 245 | CHECKeq((h10.max()),10); 246 | CHECKeq((h10.max()),10); 247 | CHECKeq((h20.max()),20); 248 | 249 | CHECKeq((h1000.max()),10); 250 | CHECKeq((h1000.max()),10); 251 | CHECKeq((h1000.max_impl(sse2(),int16_t())),10); 252 | CHECKeq((h1000.max()),10); 253 | 254 | } 255 | 256 | cout << "\n ##### CHAR[] ##########################################\n"; /////////////////////////////////////////////// 257 | 258 | { 259 | array s_dont = {{'/', '/', ' ', 'd', 'o', 'n', '\'', 't', '\0'}}; 260 | array s_in; 261 | array cstr = {"ABCDE"}; // zero terminated 262 | 263 | ifstream in("u-array.cc"); 264 | in >> s_in; 265 | CHECKeq(s_in,s_dont); 266 | //cout << s_in << endl; 267 | //cout << s_dont << endl; 268 | cout << cstr << endl; 269 | } 270 | 271 | cout << "\n ##### 0-size ##########################################\n"; /////////////////////////////////////////////// 272 | array i0; 273 | CHECKeq((i0.size()), 0); 274 | 275 | cout << "\n ##### STL COMPATIBLE ##########################################\n"; /////////////////////////////////////////////// 276 | { 277 | array A = {{1, 2, 3}}; 278 | CHECKeq((is_sorted(A.begin(), A.end())), true); 279 | } 280 | 281 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 282 | CHECK_EXIT; 283 | } 284 | -------------------------------------------------------------------------------- /u-float.cc: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | using lvv::eq; 4 | 5 | #include 6 | 7 | #include 8 | using namespace lvv; 9 | //#include 10 | using namespace std; 11 | 12 | #include 13 | int 14 | main() { 15 | 16 | 17 | { cout << " ***** FLOOR (DOUBLE) *******\n"; 18 | using lvv::fp; 19 | CHECKeq(fp::mantissa_size,23); 20 | CHECKeq(fp::exponent_size,8); 21 | } 22 | 23 | { cout << " ***** FLOOR (DOUBLE) *******\n"; 24 | using lvv::floor; 25 | double d; 26 | CHECK((d = 0.0, floor(d) == 0. )) ; 27 | CHECK((d = 0.2, floor(d) == 0. )) ; 28 | CHECK((d = 0.9, floor(d) == 0. )) ; 29 | CHECK((d = 1.0, floor(d) == 1. )) ; 30 | CHECK((d = 1.1, floor(d) == 1. )) ; 31 | CHECK((d = 1.9, floor(d) == 1. )) ; 32 | CHECK((d = 99999.2, floor(d) == 99999.f )) ; 33 | 34 | CHECK((d = -0.0, floor(d) == 0. )) ; 35 | CHECK((d = -0.2, floor(d) == -1. )) ; 36 | CHECK((d = -0.9, floor(d) == -1. )) ; 37 | CHECK((d = -1.0, floor(d) == -1. )) ; 38 | CHECK((d = -1.1, floor(d) == -2. )) ; 39 | CHECK((d = -1.9, floor(d) == -2. )) ; 40 | CHECK((d = -12345.2, floor(d) == -12346.f )) ; 41 | } 42 | 43 | { cout << " ***** FLOOR (FLOAT) *******\n"; 44 | using lvv::floor; 45 | float f; 46 | CHECK((f = 0.0, floor(f) == 0.f )) ; 47 | CHECK((f = 0.2, floor(f) == 0.f )) ; 48 | CHECK((f = 0.9, floor(f) == 0.f )) ; 49 | CHECK((f = 1.0, floor(f) == 1.f )) ; 50 | CHECK((f = 1.1, floor(f) == 1.f )) ; 51 | CHECK((f = 1.9, floor(f) == 1.f )) ; 52 | CHECK((f = 99999.2, floor(f) == 99999.f )) ; 53 | 54 | CHECK((f = -0.0, floor(f) == 0.f )) ; 55 | CHECK((f = -0.2, floor(f) == -1.f )) ; 56 | CHECK((f = -0.9, floor(f) == -1.f )) ; 57 | CHECK((f = -1.0, floor(f) == -1.f )) ; 58 | CHECK((f = -1.1, floor(f) == -2.f )) ; 59 | CHECK((f = -1.9, floor(f) == -2.f )) ; 60 | CHECK((f = -12345.2, floor(f) == -12346.f )) ; 61 | } 62 | 63 | { cout << " ***** TRUNC (FLOAT) ******* - STILL BROKEN\n"; 64 | using lvv::trunc; 65 | float f; 66 | CHECK((f = 0.0 , trunc(f) == 0.f ) ) ; 67 | CHECK((f = 0.2 , trunc(f) == 0.f ) ) ; 68 | CHECK((f = 0.9 , trunc(f) == 0.f ) ) ; 69 | CHECK((f = 1.0 , trunc(f) == 1.f ) ) ; 70 | CHECK((f = 1.1 , trunc(f) == 1.f ) ) ; 71 | CHECK((f = 1.9 , trunc(f) == 1.f ) ) ; 72 | CHECK((f = 99999.2 , trunc(f) == 99999.f ) ) ; 73 | CHECK((f = -0.0 , trunc(f) == 0.f ) ) ; 74 | CHECK((f = -0.2 , trunc(f) == -0.f ) ) ; 75 | CHECK((f = -0.9 , trunc(f) == -0.f ) ) ; 76 | CHECK((f = -1.0 , trunc(f) == -1.f ) ) ; 77 | CHECK((f = -1.1 , trunc(f) == -1.f ) ) ; 78 | CHECK((f = -1.9 , trunc(f) == -1.f ) ) ; 79 | CHECK((f = -12345.2, trunc(f) == -12345.f) ) ; 80 | } 81 | 82 | CHECK_EXIT; 83 | } 84 | /* 85 | #include 86 | using namespace std; 87 | using namespace lvv; 88 | 89 | int main () { 90 | 91 | float f; 92 | f = 0 ; cout << f << "->" << f - fme + fm -fm << endl; 93 | f = 0.2 ; cout << f << "->" << f - fme + fm -fm << endl; 94 | f = 0.9 ; cout << f << "->" << f - fme + fm -fm << endl; 95 | f = 1.8 ; cout << f << "->" << f - fme + fm -fm << endl; 96 | f = -0.2; cout << f << "->" << f - fme + fm -fm << endl; 97 | f = -1.2; cout << f << "->" << f - fme + fm -fm << endl; 98 | f = -1.9; cout << f << "->" << f - fme + fm -fm << endl; 99 | 100 | double d; 101 | d=0; cout << d << " -> " << d - dme + dm -dm << endl; 102 | d=0.2; cout << d << " -> " << d - dme + dm -dm << endl; 103 | d=0.9; cout << d << " -> " << d - dme + dm -dm << endl; 104 | d=1.8; cout << d << " -> " << d - dme + dm -dm << endl; 105 | d=-0.2; cout << d << " -> " << d - dme + dm -dm << endl; 106 | d=-1.2; cout << d << " -> " << d - dme + dm -dm << endl; 107 | d=-1.9; cout << d << " -> " << d - dme + dm -dm << endl; 108 | }*/ 109 | -------------------------------------------------------------------------------- /u-last_n.cc: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | int main() { 6 | 7 | last_n last; 8 | for (int i=1; i<5; ++i) { last.push_back(i); /*__ i, last.ring;*/ }; 9 | 10 | CHECK_ARE_EQUAL(last.prev(0), 4); 11 | CHECK_ARE_EQUAL(last.prev(1), 3); 12 | CHECK_ARE_EQUAL(last.prev(2), 2); 13 | 14 | CHECK_EXIT; 15 | } 16 | -------------------------------------------------------------------------------- /u-math.cc: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | #include 5 | //using namespace std; 6 | using namespace lvv; 7 | int 8 | main() { 9 | 10 | 11 | CHECK_EXIT; 12 | } 13 | -------------------------------------------------------------------------------- /u-meta.cc: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | // for typeid 8 | 9 | using namespace std; 10 | using namespace lvv; 11 | 12 | template 13 | struct fixed_user { 14 | 15 | fixed_user() { 16 | cout << R::template convert() << endl; 17 | }; 18 | }; 19 | 20 | 21 | int 22 | main() { 23 | 24 | cout << "********* PROMOTE<> **********\n"; 25 | 26 | PR1((type_descriptor() ) ) ; 27 | PR1((type_descriptor() ) ) ; 28 | 29 | PR1 ((type_descriptor() ) ) ; 30 | PR1 ((type_descriptor() ) ) ; 31 | PR1 ((type_descriptor() ) ) ; 32 | PR1 ((type_descriptor() ) ) ; 33 | PR1 ((type_descriptor() ) ) ; 34 | PR1 ((type_descriptor() ) ) ; 35 | PR1 ((type_descriptor() ) ) ; 36 | PR1 ((type_descriptor() ) ) ; 37 | 38 | { cout << "\n\n *** Test is_integral ***\n"; 39 | PR1 (LVV_IS_INTEGRAL(int)); 40 | PR1 (LVV_IS_INTEGRAL(float)); 41 | PR1 (LVV_IS_INTEGRAL(double)); 42 | } 43 | 44 | cout << "********* RATIO_<> **********\n"; 45 | CHECK_ARE_EQUAL ((ratio_<2>::denominator), 1); 46 | CHECK_ARE_EQUAL ((ratio_<2,3>::denominator), 3); 47 | CHECK_ARE_EQUAL ((ratio_<2,3>::numerator), 2); 48 | CHECK_ARE_FP_EQUAL ((ratio_<2,3>::convert()), float(2./3.)); 49 | CHECK_ARE_FP_EQUAL ((ratio_<2,3>::convert()), 0); 50 | CHECK_ARE_FP_EQUAL ((ratio_<1,2>::convert()), 1./2.); 51 | CHECK_ARE_FP_EQUAL ((ratio_<0,3>::convert()), float(0.)); 52 | CHECK_ARE_FP_EQUAL ((ratio_<-2,3>::convert()),float(2./-3.)); 53 | CHECK_ARE_FP_EQUAL ((ratio_<1,1000>::convert()), float(0.001)); 54 | 55 | //fixed_user::type> fu; 56 | 57 | cout << "********* FP<> **********\n"; 58 | CHECK_ARE_EQUAL ((fp::value), float(0.2)); 59 | CHECK_ARE_EQUAL ((fp::value), 2); 60 | CHECK_ARE_EQUAL ((fp::value), 20); 61 | 62 | 63 | cout << "********* INT_<> **********\n"; 64 | CHECK_ARE_EQUAL ((int_<3>::value), 3); 65 | CHECK_ARE_EQUAL ((int_<-3>::value), -3); 66 | CHECK_ARE_EQUAL ((int_<3>::numerator), 3); 67 | CHECK_ARE_EQUAL ((int_<3>::denominator), 1); 68 | CHECK_ARE_FP_EQUAL ((int_<3>::convert()), 3.); 69 | 70 | cout << "********* PLUS<> and MINUS<> **********\n"; 71 | CHECK_ARE_FP_EQUAL ((lvv::plus < ratio_<1,3>, ratio_<1,3> >::type::convert()), 2./3.); 72 | CHECK_ARE_FP_EQUAL ((lvv::plus < ratio_<1,3>, int_<2> >::type::convert()), 2.+1./3.); 73 | CHECK_ARE_FP_EQUAL ((lvv::minus< ratio_<1,3>, int_<2> >::type::convert()), 1./3.-2.); 74 | CHECK_ARE_FP_EQUAL ((lvv::minus< int_<2>, ratio_<1,3> >::type::convert()), 2.-1./3.); 75 | 76 | 77 | //cout << type_descriptor < double>() << endl; 78 | 79 | cout << " ***** IPOW *******\n"; /////////////////////////////////////////////// 80 | CHECKeq((lvv::ipow<3,0>::value), 1); 81 | CHECKeq((lvv::ipow<3,1>::value), 3); 82 | CHECKeq((lvv::ipow<3,2>::value), 9); 83 | 84 | cout << " ***** ILOG2 *******\n"; /////////////////////////////////////////////// 85 | CHECKeq((lvv::ilog2<1>::value), 0); 86 | CHECKeq((lvv::ilog2<2>::value), 1); 87 | CHECKeq((lvv::ilog2<4>::value), 2); 88 | CHECKeq((lvv::ilog2<256>::value), 8); 89 | 90 | CHECK_EXIT; 91 | #ifndef ONE 92 | #endif // ONE 93 | 94 | } 95 | -------------------------------------------------------------------------------- /u-powi.cc: -------------------------------------------------------------------------------- 1 | 2 | //#include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | using namespace lvv; 8 | /////////////////////////////////////////////////////////////////// 9 | int 10 | main() { 11 | setup_fpe(); 12 | cerr << setprecision(numeric_limits::digits10+4) << boolalpha; 13 | cout << setprecision(numeric_limits::digits10+4) << boolalpha; 14 | 15 | 16 | cout << "\n\n *** Test POWI() ***\n"; 17 | cout << std::boolalpha; 18 | 19 | CHECK(eq(powi(3.33, 0), 1. )); 20 | CHECK(eq(powi(3.33, 1), 3.33 )); 21 | CHECK(eq(powi(3.33, 2), 11.0889 )); 22 | CHECK(eq(powi(3.33, 3), 36.926037 )); 23 | CHECK(eq(powi(3.33, 4), 122.96370321)); 24 | CHECK(eq(powi(0. , 4), 0. )); 25 | 26 | 27 | cout << (all_pass ? "\n------------ all pass ------------\n" : "\n!!!!!!!!! SOME FAILED !!!!!!!!\n"); 28 | exit(all_pass ? 0 : 1); 29 | } 30 | 31 | 32 | -------------------------------------------------------------------------------- /u-token.cc: -------------------------------------------------------------------------------- 1 | 2 | #include "check.h" 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | #include "token.h" 11 | #include 12 | 13 | 14 | int main() { 15 | 16 | //////////////////////////////////////////////////////// GET_TB / GET_TE 17 | pos_t b,e, tb,te; 18 | 19 | pos_t s_empty = ""; 20 | pos_t s_s = " "; 21 | pos_t s_a = "a"; 22 | pos_t s_aaa = "aaa"; 23 | pos_t s_saaa = " aaa"; 24 | pos_t s_aaas = "aaa "; 25 | pos_t s_saaas = " aaa "; 26 | 27 | #define GET_TB(S) get_tb(S, S+strlen(S)) 28 | #define GET_TE(S) get_tb(S, S+strlen(S)) 29 | 30 | CHECK( GET_TB(s_empty) == s_empty); 31 | CHECK( GET_TB(s_s) == s_s+2); 32 | CHECK( GET_TB(s_a) == s_a); 33 | CHECK( GET_TB(s_aaa) == s_aaa); 34 | CHECK( GET_TB(s_saaa) == s_saaa+2); 35 | CHECK( GET_TB(s_saaas) == s_saaas+2); 36 | 37 | b=s_empty; e=b+strlen(b); tb=get_tb(b,e); te=get_te(tb,e); CHECK_ARE_EQUAL(te-tb,0); 38 | b=s_a; e=b+strlen(b); tb=get_tb(b,e); te=get_te(tb,e); CHECK_ARE_EQUAL(te-tb,1); CHECK(std::equal(tb,te,"a" )); 39 | b=s_aaa; e=b+strlen(b); tb=get_tb(b,e); te=get_te(tb,e); CHECK_ARE_EQUAL(te-tb,3); CHECK(std::equal(tb,te,"aaa")); 40 | b=s_aaas; e=b+strlen(b); tb=get_tb(b,e); te=get_te(tb,e); CHECK_ARE_EQUAL(te-tb,3); CHECK(std::equal(tb,te,"aaa")); 41 | b=s_saaa; e=b+strlen(b); tb=get_tb(b,e); te=get_te(tb,e); CHECK_ARE_EQUAL(te-tb,3); CHECK(std::equal(tb,te,"aaa")); 42 | b=s_saaas; e=b+strlen(b); tb=get_tb(b,e); te=get_te(tb,e); CHECK_ARE_EQUAL(te-tb,3); CHECK(std::equal(tb,te,"aaa")); 43 | 44 | 45 | /* 46 | { 47 | pos_t b = "\" (as in, \"What in the Sam Hill is that?\"). Its"; 48 | pos_t e = b+strlen(b); 49 | pos_t tb; 50 | pos_t te = b; 51 | while ((tb=get_tb(te,e)) != e) { 52 | te=get_te(tb,e); 53 | cerr << string(tb,te) << endl; 54 | } 55 | } 56 | 57 | */ 58 | 59 | //////////////////////////////////////////////////////// ARE_EQUAL_TOKEN_CHAINS 60 | CHECK( are_equal_token_chains("", "")); 61 | CHECK( are_equal_token_chains("", " ")); 62 | CHECK( are_equal_token_chains("", " ")); 63 | CHECK( are_equal_token_chains(" ", " ")); 64 | CHECK( are_equal_token_chains("\t", "\n")); 65 | CHECK( are_equal_token_chains("a", "a")); 66 | CHECK( ! are_equal_token_chains("a", "b")); 67 | CHECK( are_equal_token_chains(" a", "a ")); 68 | CHECK( are_equal_token_chains("aa\tbb", " aa bb ")); 69 | CHECK( are_equal_token_chains(" aa \n bb\t\n", "aa bb")); 70 | CHECK( are_equal_token_chains("A b C", "A b C")); 71 | 72 | CHECK( are_equal_token_chains("1 2 3", "1 2 3")); 73 | CHECK( ! are_equal_token_chains("1 2 3", "1 2 E")); 74 | CHECK( ! are_equal_token_chains("1 2 3", "E 2 3")); 75 | 76 | CHECK( are_equal_token_chains("1 2 3 4", "1 2 3 4")); 77 | CHECK( ! are_equal_token_chains("1 2 3 4", "1 2 3 E")); 78 | CHECK( ! are_equal_token_chains("E 2 3 4", "1 2 3 4")); 79 | 80 | CHECK( are_equal_token_chains("1 2 3 4 5", "1 2 3 4 5")); 81 | CHECK( ! are_equal_token_chains("1 2 3 4 5", "1 2 3 4 E")); 82 | CHECK( ! are_equal_token_chains("E 2 3 4 5", "1 2 3 4 5")); 83 | 84 | CHECK( are_equal_token_chains("1 2 3 4 5 6", "1 2 3 4 5 6")); 85 | CHECK( ! are_equal_token_chains("1 2 3 4 5 6", "1 2 3 4 5 E")); 86 | CHECK( ! are_equal_token_chains("E 2 3 4 5 6", "1 2 3 4 5 6")); 87 | 88 | CHECK( are_equal_token_chains("1 2 3 4 5 6 7", "1 2 3 4 5 6 7")); 89 | CHECK( ! are_equal_token_chains("1 2 3 4 5 6 7", "1 2 3 4 5 6 E")); 90 | CHECK( ! are_equal_token_chains("E 2 3 4 5 6 7", "1 2 3 4 5 6 7")); 91 | 92 | //////////////////////////////////////////////////////// IS_HEAD_OF 93 | pos_t unused; 94 | CHECK( is_head_of("", "",unused)); 95 | CHECK( is_head_of("", " ",unused)); 96 | CHECK( is_head_of("", " ",unused)); 97 | CHECK( is_head_of(" ", " ",unused)); 98 | CHECK( is_head_of("\t", "\n",unused)); 99 | CHECK( is_head_of("a", "a",unused)); 100 | CHECK( ! is_head_of("a", "b",unused)); 101 | CHECK( is_head_of(" a", "a ",unused)); 102 | CHECK( is_head_of("aa\tbb", " aa bb ",unused)); 103 | CHECK( is_head_of(" aa \n bb\t\n", "aa bb",unused)); 104 | CHECK( is_head_of("A b C", "A b C",unused)); 105 | 106 | CHECK( is_head_of("", "e",unused)); 107 | CHECK( is_head_of("", " e",unused)); 108 | CHECK( is_head_of("", " e",unused)); 109 | CHECK( is_head_of(" ", " e",unused)); 110 | CHECK( is_head_of("\t", "\ne",unused)); 111 | CHECK( ! is_head_of("a", "ae",unused)); 112 | CHECK( ! is_head_of("a", "be",unused)); 113 | CHECK( is_head_of(" a", "a e",unused)); 114 | CHECK( is_head_of("aa\tbb", " aa bb e",unused)); 115 | CHECK( ! is_head_of(" aa \n bb\t\n", "aa bbe",unused)); 116 | CHECK( ! is_head_of("A b C", "A b Ce",unused)); 117 | 118 | 119 | //////////////////////////////////////////////////////// UNICODE 120 | { 121 | const char us[] = u8"Леонид Волницкий"; 122 | const octet* p=(const octet*)us; 123 | const octet* e=p+strlen(us); 124 | codepoint cp; 125 | __ us; 126 | while (get_codepoint_from_utf8(p, e, cp)) { 127 | __ cp, p; 128 | } 129 | } 130 | 131 | CHECK_EXIT; 132 | } 133 | --------------------------------------------------------------------------------