/** * Test if (X + a) ^ n != X ^ n + a (mod X ^ r - 1,n) */ int check_poly(mpz_t n, mpz_t a, mpz_t r) { unsigned int i, terms, equality_holds; mpz_t tmp, neg_a, loop; mpz_init(tmp); mpz_init(neg_a); mpz_init(loop); terms = mpz_get_ui(r) + 1; mpz_t* poly = init_poly(terms); mpz_t* ptmp = init_poly(terms); mpz_t* stmp; mpz_mul_ui(neg_a, a, -1); mpz_set(poly[0], neg_a); mpz_set_ui(poly[1], 1); for (mpz_set_ui(loop, 2); mpz_cmp(loop, n) <= 0; mpz_mul(loop, loop, loop)) { polymul(ptmp, poly, terms, poly, terms, n); stmp = poly; poly = ptmp; ptmp = stmp; } mpz_t* xMinusA = init_poly(2); mpz_set(ptmp[0], neg_a); mpz_set_ui(ptmp[1], 1); for (; mpz_cmp(loop, n) <= 0; mpz_add_ui(loop, loop, 1)) { polymul(ptmp, poly, terms, xMinusA, 2, n); stmp = poly; poly = ptmp; ptmp = stmp; } clear_poly(xMinusA, 2); equality_holds = TRUE; if (mpz_cmp(poly[0], neg_a) != 0 || mpz_cmp_ui(poly[terms - 1], 1) != 0) { equality_holds = FALSE; } else { for (i = 1; i < terms - 1; i++) { if (mpz_cmp_ui(poly[i], 0) != 0) { equality_holds = FALSE; break; } } } clear_poly(poly, terms); clear_poly(ptmp, terms); mpz_clear(tmp); mpz_clear(neg_a); mpz_clear(loop); return equality_holds; }
int main( ) { struct poly p1, p2, p3 ; system ( "cls" ) ; initpoly ( &p1 ) ; initpoly ( &p2 ) ; initpoly ( &p3 ) ; polyappend ( &p1, 1, 4 ) ; polyappend ( &p1, 2, 3 ) ; polyappend ( &p1, 2, 2 ) ; polyappend ( &p1, 2, 1 ) ; polyappend ( &p2, 2, 3 ) ; polyappend ( &p2, 3, 2 ) ; polyappend ( &p2, 4, 1 ) ; p3 = polymul ( p1, p2 ) ; printf ( "First polynomial:\n" ) ; display ( p1 ) ; printf ( "Second polynomial:\n" ) ; display ( p2 ) ; printf ( "Resultant polynomial:\n" ) ; display ( p3 ) ; return 0 ; }
void fpe_mul_c(fpe_t rop, const fpe_t op1, const fpe_t op2) { mydouble h[24]; polymul(h,op1->v,op2->v); degred(h); coeffred_round_par(h); int i; for (i=0;i<12;i++) rop->v[i] = h[i]; }
// Square an fp2e, store result in rop: void fp2e_square_c(fp2e_t rop, const fp2e_t op) { #ifdef N_OPS sqfp2ctr += 1; #endif fpe_t a1, b1, r1, r2; mydouble ropa[24], ropb[24]; fp2e_to_2fpe(a1, b1, op); int i; /* CheckDoubles are not smart enough to recognize * binomial formula to compute b^2-a^2 */ #ifdef CHECK mydouble d1[24]; polymul(d1, a1->v, a1->v); polymul(ropb, b1->v, b1->v); polymul(ropa, b1->v, a1->v); for (i = 0; i < 23; i++) { ropb[i] -= d1[i]; ropa[i] *= 2; } #else fpe_t t1, t2, t3; for (i = 0; i < 12; i++) { t1->v[i] = a1->v[i] + b1->v[i]; t2->v[i] = b1->v[i] - a1->v[i]; t3->v[i] = 2 * b1->v[i]; } polymul(ropa, a1->v, t3->v); polymul(ropb, t1->v, t2->v); #endif degred(ropa); degred(ropb); coeffred_round_par(ropa); coeffred_round_par(ropb); fpe_set_doublearray(r1, ropa); fpe_set_doublearray(r2, ropb); _2fpe_to_fp2e(rop, r1, r2); }
// Multiply two fp2e, store result in rop: void fp2e_mul_c(fp2e_t rop, const fp2e_t op1, const fp2e_t op2) { #ifdef N_OPS mulfp2ctr += 1; #endif fpe_t a1, b1, a2, b2, r1, r2; mydouble a3[24], b3[24]; int i; mydouble t0[24], t1[24], t2[24], t3[24]; fp2e_to_2fpe(a1, b1, op1); fp2e_to_2fpe(a2, b2, op2); polymul(t1, a1->v, b2->v); // t1 = a1*b2 polymul(t2, b1->v, a2->v); // t2 = b1*a2 for (i = 0; i < 12; i++) // t3 = 1*a1 { t3[i] = 1 * a1->v[i]; } polymul(t3, t3, a2->v); // t3 = 1*a1*a2 polymul(t0, b1->v, b2->v); // t0 = b1*b2 for (i = 0; i < 23; i++) { a3[i] = t1[i] + t2[i]; // a3 = a1*b2 + b1*a2 b3[i] = t0[i] - t3[i]; // b3 = b1*b2 - 1*a1*a2 } degred(a3); degred(b3); coeffred_round_par(a3); coeffred_round_par(b3); fpe_set_doublearray(r1, a3); fpe_set_doublearray(r2, b3); _2fpe_to_fp2e(rop, r1, r2); }
// // Measure Whisker Segment Features // -------------------------------- // <face_axis> indicates the orientation of the mouse head with respect to // the image. // <face_axis> == 'x' --> horizontally (along x axis) // <face_axis> == 'y' --> vertically (along y axis) // void Whisker_Seg_Measure( Whisker_Seg *w, double *dest, int facex, int facey, char face_axis ) { float path_length, // median_score, // root_angle_deg, // side poly mean_curvature, //(side) poly quad? (depends on side for sign) follicle_x, // side follicle_y, // side tip_x, // side tip_y; // side float *x = w->x, *y = w->y, *s = w->scores; int len = w->len, idx_follicle, idx_tip; float dx; static double *cumlen = NULL; static size_t cumlen_size = 0; cumlen = request_storage( cumlen, &cumlen_size, sizeof(double), len, "measure: cumlen"); cumlen[0] = 0.0; // path length // ----------- // XXX: an alternate approach would be to compute the polynomial fit // and do quadrature on that. Might be more precise. // Although, need cumlen (a.k.a cl) for polyfit anyway { float *ax = x + 1, *ay = y + 1, *bx = x, *by = y; double *cl = cumlen + 1, *clm = cumlen; while( ax < x + len ) *cl++ = (*clm++) + hypotf( (*ax++) - (*bx++), (*ay++) - (*by++) ); path_length = cl[-1]; } // median score // ------------ { qsort( s, len, sizeof(float), _score_cmp ); if(len&1) // odd median_score = s[ (len-1)/2 ]; else //even median_score = ( s[len/2 - 1] + s[len/2] )/2.0; } // Follicle and root positions // --------------------------- dx = _side( w, facex, facey, &idx_follicle, &idx_tip ); follicle_x = x[ idx_follicle ]; follicle_y = y[ idx_follicle ]; tip_x = x[ idx_tip ]; tip_y = y[ idx_tip ]; // Polynomial based measurements // (Curvature and angle) // ----------------------------- { double px[ MEASURE_POLY_FIT_DEGREE+1 ], py[ MEASURE_POLY_FIT_DEGREE+1 ], xp[ MEASURE_POLY_FIT_DEGREE+1 ], yp[ MEASURE_POLY_FIT_DEGREE+1 ], xpp[ MEASURE_POLY_FIT_DEGREE+1 ], ypp[ MEASURE_POLY_FIT_DEGREE+1 ], mul1[ 2*MEASURE_POLY_FIT_DEGREE ], mul2[ 2*MEASURE_POLY_FIT_DEGREE ], num[ 2*MEASURE_POLY_FIT_DEGREE ], den[ 2*MEASURE_POLY_FIT_DEGREE ]; static double *t = NULL; static size_t t_size = 0; static double *xd = NULL; static size_t xd_size = 0; static double *yd = NULL; static size_t yd_size = 0; static double *workspace = NULL; static size_t workspace_size = 0; int i; const int pad = MIN( MEASURE_POLY_END_PADDING, len/4 ); // parameter for parametric polynomial representation t = request_storage(t, &t_size, sizeof(double), len, "measure"); xd = request_storage(xd, &xd_size, sizeof(double), len, "measure"); yd = request_storage(yd, &yd_size, sizeof(double), len, "measure"); { int i = len; // convert floats to doubles while(i--) { xd[i] = x[i]; yd[i] = y[i]; } } for( i=0; i<len; i++ ) t[i] = cumlen[i] / path_length; // [0 to 1] #ifdef DEBUG_MEASURE_POLYFIT_ERROR assert(t[0] == 0.0 ); assert( (t[len-1] - 1.0)<1e-6 ); #endif // polynomial fit workspace = request_storage( workspace, &workspace_size, sizeof(double), polyfit_size_workspace( len, 2*MEASURE_POLY_FIT_DEGREE ), //need 2*degree for curvature eval later "measure: polyfit workspace" ); polyfit( t+pad, xd+pad, len-2*pad, MEASURE_POLY_FIT_DEGREE, px, workspace ); polyfit_reuse( yd+pad, len-2*pad, MEASURE_POLY_FIT_DEGREE, py, workspace ); #ifdef DEBUG_MEASURE_POLYFIT_ERROR { double err = 0.0; int i; for( i=pad; i<len-2*pad; i++ ) err += hypot( xd[i] - polyval( px, MEASURE_POLY_FIT_DEGREE, t[i] ), yd[i] - polyval( py, MEASURE_POLY_FIT_DEGREE, t[i] ) ); err /= ((float)len); debug("Polyfit root mean squared residual: %f\n", err ); assert( err < 1.0 ); } #endif // first derivative memcpy( xp, px, sizeof(double) * ( MEASURE_POLY_FIT_DEGREE+1 ) ); memcpy( yp, py, sizeof(double) * ( MEASURE_POLY_FIT_DEGREE+1 ) ); polyder_ip( xp, MEASURE_POLY_FIT_DEGREE+1, 1 ); polyder_ip( yp, MEASURE_POLY_FIT_DEGREE+1, 1 ); // second derivative memcpy( xpp, xp, sizeof(double) * ( MEASURE_POLY_FIT_DEGREE+1 ) ); memcpy( ypp, yp, sizeof(double) * ( MEASURE_POLY_FIT_DEGREE+1 ) ); polyder_ip( xpp, MEASURE_POLY_FIT_DEGREE+1, 1 ); polyder_ip( ypp, MEASURE_POLY_FIT_DEGREE+1, 1 ); // Root angle // ---------- { double teval = (idx_follicle == 0) ? t[pad] : t[len-pad-1]; static const double rad2deg = 180.0/M_PI; switch(face_axis) { case 'h': case 'x': root_angle_deg = atan2( dx*polyval(yp, MEASURE_POLY_FIT_DEGREE, teval ), dx*polyval(xp, MEASURE_POLY_FIT_DEGREE, teval ) ) * rad2deg; break; case 'v': case 'y': root_angle_deg = atan2( dx*polyval(xp, MEASURE_POLY_FIT_DEGREE, teval ), dx*polyval(yp, MEASURE_POLY_FIT_DEGREE, teval ) ) * rad2deg; break; default: error("In Whisker_Seg_Measure\n" "\tParameter <face_axis> must take on a value of 'x' or 'y'\n" "\tGot value %c\n",face_axis); } } // Mean curvature // -------------- // Use the most naive of integration schemes { double *V = workspace; // done with workspace, so reuse it for vandermonde matrix (just alias it here) static double *evalnum = NULL, *evalden = NULL; static size_t evalnum_size = 0, evalden_size = 0; size_t npoints = len-2*pad; evalnum = request_storage( evalnum, &evalnum_size, sizeof(double), npoints, "numerator" ); evalden = request_storage( evalden, &evalden_size, sizeof(double), npoints, "denominator" ); Vandermonde_Build( t+pad, npoints, 2*MEASURE_POLY_FIT_DEGREE, V ); // used for polynomial evaluation // numerator memset( mul1, 0, 2*MEASURE_POLY_FIT_DEGREE*sizeof(double) ); memset( mul2, 0, 2*MEASURE_POLY_FIT_DEGREE*sizeof(double) ); polymul( xp, MEASURE_POLY_FIT_DEGREE+1, ypp, MEASURE_POLY_FIT_DEGREE+1, mul1 ); polymul( yp, MEASURE_POLY_FIT_DEGREE+1, xpp, MEASURE_POLY_FIT_DEGREE+1, mul2 ); polysub( mul1, 2*MEASURE_POLY_FIT_DEGREE, mul2, 2*MEASURE_POLY_FIT_DEGREE, num ); // denominator memset( mul1, 0, 2*MEASURE_POLY_FIT_DEGREE*sizeof(double) ); memset( mul2, 0, 2*MEASURE_POLY_FIT_DEGREE*sizeof(double) ); polymul( xp, MEASURE_POLY_FIT_DEGREE+1, xp, MEASURE_POLY_FIT_DEGREE+1, mul1 ); polymul( yp, MEASURE_POLY_FIT_DEGREE+1, yp, MEASURE_POLY_FIT_DEGREE+1, mul2 ); polyadd( mul1, 2*MEASURE_POLY_FIT_DEGREE, mul2, 2*MEASURE_POLY_FIT_DEGREE, den ); // Eval matmul( V, npoints, MEASURE_POLY_FIT_DEGREE*2, num, MEASURE_POLY_FIT_DEGREE*2, 1, evalnum ); matmul( V, npoints, MEASURE_POLY_FIT_DEGREE*2, den, MEASURE_POLY_FIT_DEGREE*2, 1, evalden ); // compute kappa at each t { int i; for(i=0; i<npoints; i++ ) evalnum[i] /= pow( evalden[i], 3.0/2.0 )*dx; //dx is 1 or -1 so dx = 1/dx; mean_curvature = evalnum[0] * (t[1]-t[0]); for(i=1; i<npoints; i++ ) mean_curvature += evalnum[i] * ( t[i]-t[i-1] ); } } } // fill in fields dest[0] = path_length; dest[1] = median_score; dest[2] = root_angle_deg; dest[3] = mean_curvature; dest[4] = follicle_x; dest[5] = follicle_y; dest[6] = tip_x; dest[7] = tip_y; }