void mpf_reldiff (mpf_t rdiff, mpf_srcptr x, mpf_srcptr y) { if (UNLIKELY (SIZ(x) == 0)) { mpf_set_ui (rdiff, (unsigned long int) (mpf_sgn (y) != 0)); } else { mp_size_t dprec; mpf_t d; TMP_DECL; TMP_MARK; dprec = PREC(rdiff) + ABSIZ(x); ASSERT (PREC(rdiff)+1 == dprec - ABSIZ(x) + 1); PREC(d) = dprec; PTR(d) = TMP_ALLOC_LIMBS (dprec + 1); mpf_sub (d, x, y); SIZ(d) = ABSIZ(d); mpf_div (rdiff, d, x); TMP_FREE; } }
static void mpf_exp(mpf_t res, mpf_t pwr) { mpf_t a; mpf_t f0; int i; mpf_init(a); mpf_set(a, pwr); mpf_init(f0); mpf_set(f0, a); mpf_add_ui(res, a, 1); for (i=2;;i++) { mpf_mul(f0, f0, a); mpf_div_ui(f0, f0, i); if (mpf_sgn(f0) > 0) { if (mpf_cmp(f0, epsilon) < 0) break; } else { if (mpf_cmp(f0, negepsilon) > 0) break; } mpf_add(res, res, f0); } mpf_clear(f0); mpf_clear(a); }
static void mpc_cis(mpc_t res, mpf_t theta) { mpf_t a; mpf_init(a); mpf_set(a, theta); //res = exp(i a) // = cos a + i sin a //converges quickly near the origin mpf_t f0; mpf_ptr rx = mpc_re(res), ry = mpc_im(res); int i; int toggle = 1; mpf_init(f0); mpf_set(f0, a); mpf_set_ui(rx, 1); mpf_set(ry, f0); i = 1; for(;;) { toggle = !toggle; i++; mpf_div_ui(f0, f0, i); mpf_mul(f0, f0, a); if (toggle) { mpf_add(rx, rx, f0); } else { mpf_sub(rx, rx, f0); } i++; mpf_div_ui(f0, f0, i); mpf_mul(f0, f0, a); if (toggle) { mpf_add(ry, ry, f0); } else { mpf_sub(ry, ry, f0); } if (mpf_sgn(f0) > 0) { if (mpf_cmp(f0, epsilon) < 0) break; } else { if (mpf_cmp(f0, negepsilon) > 0) break; } } mpf_clear(f0); mpf_clear(a); }
/** * rasqal_xsd_decimal_is_zero: * @d: decimal * * Test if an XSD decimal is zero. * * Return value: non-0 if decimal is zero **/ int rasqal_xsd_decimal_is_zero(rasqal_xsd_decimal* d) { #if defined(RASQAL_DECIMAL_C99) || defined(RASQAL_DECIMAL_NONE) if(!d->raw) return 1; #endif #ifdef RASQAL_DECIMAL_MPFR if(mpfr_zero_p(d->raw)) return 1; #endif #ifdef RASQAL_DECIMAL_GMP if(!mpf_sgn(d->raw)) return 1; #endif return 0; }
void mpf_reldiff (mpf_t rdiff, mpf_srcptr x, mpf_srcptr y) { if (mpf_cmp_ui (x, 0) == 0) { mpf_set_ui (rdiff, (unsigned long int) (mpf_sgn (y) != 0)); } else { mpf_t d; mp_limb_t tmp_limb[2]; d->_mp_prec = 1; d->_mp_d = tmp_limb; mpf_sub (d, x, y); mpf_abs (d, d); mpf_div (rdiff, d, x); } }
int sg_big_float_get_str(sg_big_float_t *src, enum sg_num_sys sys, sg_vlstr_t * str) { int base = SG_COMPUTE_BASE(sys); if (!src || !str || base <= 0) return -1; mp_exp_t exp; char* s = mpf_get_str(NULL, &exp, base, 0, src->mpf); sg_vlstrcpy(str, s); if (exp != 0) { long mantissa_length = strlen(s); /* rid negative symbol */ if (mpf_sgn(src->mpf) == -1) --mantissa_length; sg_vlstr_t* float_exp = sg_vlstrfmt("e%ld", exp - mantissa_length); sg_vlstrcat(str, sg_vlstrraw(float_exp)); sg_vlstrfree(&float_exp); } free(s); return 0; }
int main (int argc, char **argv) { mp_size_t size; mp_exp_t exp; int reps = 10000; int i; mpf_t u, v, w, x; mp_size_t bprec = SIZE * GMP_LIMB_BITS; mpf_t rerr, limit_rerr; unsigned long ulimb, vlimb; int single_flag; tests_start (); if (argc > 1) { reps = strtol (argv[1], 0, 0); if (argc > 2) bprec = strtol (argv[2], 0, 0); } mpf_set_default_prec (bprec); mpf_init (rerr); mpf_init (limit_rerr); mpf_init (u); mpf_init (v); mpf_init (w); mpf_init (x); for (i = 0; i < reps; i++) { mp_size_t res_prec; res_prec = urandom () % bprec + 1; mpf_set_prec (w, res_prec); mpf_set_prec (x, res_prec); mpf_set_ui (limit_rerr, 1); mpf_div_2exp (limit_rerr, limit_rerr, res_prec - 1); single_flag = 0; if ((urandom () & 1) != 0) { size = urandom () % (2 * SIZE) - SIZE; exp = urandom () % SIZE; mpf_random2 (u, size, exp); } else { ulimb = urandom (); mpf_set_ui (u, ulimb); single_flag = 1; } if ((urandom () & 1) != 0) { size = urandom () % (2 * SIZE) - SIZE; exp = urandom () % SIZE; mpf_random2 (v, size, exp); } else { vlimb = urandom (); mpf_set_ui (v, vlimb); single_flag = 2; } if (mpf_sgn (v) == 0) continue; mpf_div (w, u, v); mpf_mul (x, w, v); mpf_reldiff (rerr, u, x); if (mpf_cmp (rerr, limit_rerr) > 0) { printf ("ERROR in mpf_mul or mpf_div after %d tests\n", i); printf (" u = "); mpf_dump (u); printf (" v = "); mpf_dump (v); printf (" x = "); mpf_dump (x); printf (" w = "); mpf_dump (w); abort (); } if (single_flag == 2) { mpf_div_ui (x, u, vlimb); mpf_reldiff (rerr, w, x); if (mpf_cmp (rerr, limit_rerr) > 0) { printf ("ERROR in mpf_div or mpf_div_ui after %d tests\n", i); printf (" u = "); mpf_dump (u); printf (" v = "); mpf_dump (v); printf (" x = "); mpf_dump (x); printf (" w = "); mpf_dump (w); abort (); } } if (single_flag == 1) { mpf_ui_div (x, ulimb, v); mpf_reldiff (rerr, w, x); if (mpf_cmp (rerr, limit_rerr) > 0) { printf ("ERROR in mpf_div or mpf_ui_div after %d tests\n", i); printf (" u = "); mpf_dump (u); printf (" v = "); mpf_dump (v); printf (" x = "); mpf_dump (x); printf (" w = "); mpf_dump (w); abort (); } } } mpf_clear (rerr); mpf_clear (limit_rerr); mpf_clear (u); mpf_clear (v); mpf_clear (w); mpf_clear (x); tests_end (); exit (0); }
int segment_intersection_2d_test(double ax1, double ay1, double ax2, double ay2, double bx1, double by1, double bx2, double by2, double *x1, double *y1, double *x2, double *y2) { double t; double max_ax, min_ax, max_ay, min_ay; double max_bx, min_bx, max_by, min_by; int sgn_d, sgn_da, sgn_db; int vertical; int f11, f12, f21, f22; mp_exp_t exp; char *s; double d, da, db, ra, rb; if (!initialized) initialize_mpf_vars(); /* TODO: Works for points ? */ G_debug(3, "segment_intersection_2d_test()"); G_debug(3, " ax1 = %.18e, ay1 = %.18e", ax1, ay1); G_debug(3, " ax2 = %.18e, ay2 = %.18e", ax2, ay2); G_debug(3, " bx1 = %.18e, by1 = %.18e", bx1, by1); G_debug(3, " bx2 = %.18e, by2 = %.18e", bx2, by2); f11 = ((ax1 == bx1) && (ay1 == by1)); f12 = ((ax1 == bx2) && (ay1 == by2)); f21 = ((ax2 == bx1) && (ay2 == by1)); f22 = ((ax2 == bx2) && (ay2 == by2)); /* Check for identical segments */ if ((f11 && f22) || (f12 && f21)) { G_debug(4, " identical segments"); *x1 = ax1; *y1 = ay1; *x2 = ax2; *y2 = ay2; return 5; } /* Check for identical endpoints */ if (f11 || f12) { G_debug(4, " connected by endpoints"); *x1 = ax1; *y1 = ay1; return 1; } if (f21 || f22) { G_debug(4, " connected by endpoints"); *x1 = ax2; *y1 = ay2; return 1; } if ((MAX(ax1, ax2) < MIN(bx1, bx2)) || (MAX(bx1, bx2) < MIN(ax1, ax2))) { G_debug(4, " no intersection (disjoint bounding boxes)"); return 0; } if ((MAX(ay1, ay2) < MIN(by1, by2)) || (MAX(by1, by2) < MIN(ay1, ay2))) { G_debug(4, " no intersection (disjoint bounding boxes)"); return 0; } d = (ax2 - ax1) * (by1 - by2) - (ay2 - ay1) * (bx1 - bx2); da = (bx1 - ax1) * (by1 - by2) - (by1 - ay1) * (bx1 - bx2); db = (ax2 - ax1) * (by1 - ay1) - (ay2 - ay1) * (bx1 - ax1); det22(dd, ax2, ax1, bx1, bx2, ay2, ay1, by1, by2); sgn_d = mpf_sgn(dd); s = mpf_get_str(NULL, &exp, 10, 40, dd); G_debug(3, " dd = %sE%d", (s[0] == 0) ? "0" : s, exp); G_debug(3, " d = %.18E", d); if (sgn_d != 0) { G_debug(3, " general position"); det22(dda, bx1, ax1, bx1, bx2, by1, ay1, by1, by2); det22(ddb, ax2, ax1, bx1, ax1, ay2, ay1, by1, ay1); sgn_da = mpf_sgn(dda); sgn_db = mpf_sgn(ddb); ra = da / d; rb = db / d; mpf_div(rra, dda, dd); mpf_div(rrb, ddb, dd); s = mpf_get_str(NULL, &exp, 10, 40, rra); G_debug(4, " rra = %sE%d", (s[0] == 0) ? "0" : s, exp); G_debug(4, " ra = %.18E", ra); s = mpf_get_str(NULL, &exp, 10, 40, rrb); G_debug(4, " rrb = %sE%d", (s[0] == 0) ? "0" : s, exp); G_debug(4, " rb = %.18E", rb); if (sgn_d > 0) { if ((sgn_da < 0) || (mpf_cmp(dda, dd) > 0)) { G_debug(DLEVEL, " no intersection"); return 0; } if ((sgn_db < 0) || (mpf_cmp(ddb, dd) > 0)) { G_debug(DLEVEL, " no intersection"); return 0; } } else { /* if sgn_d < 0 */ if ((sgn_da > 0) || (mpf_cmp(dda, dd) < 0)) { G_debug(DLEVEL, " no intersection"); return 0; } if ((sgn_db > 0) || (mpf_cmp(ddb, dd) < 0)) { G_debug(DLEVEL, " no intersection"); return 0; } } mpf_set_d(delta, ax2 - ax1); mpf_mul(t1, dda, delta); mpf_div(t2, t1, dd); *x1 = ax1 + mpf_get_d(t2); mpf_set_d(delta, ay2 - ay1); mpf_mul(t1, dda, delta); mpf_div(t2, t1, dd); *y1 = ay1 + mpf_get_d(t2); G_debug(2, " intersection at:"); G_debug(2, " xx = %.18e", *x1); G_debug(2, " x = %.18e", ax1 + ra * (ax2 - ax1)); G_debug(2, " yy = %.18e", *y1); G_debug(2, " y = %.18e", ay1 + ra * (ay2 - ay1)); return 1; } G_debug(3, " parallel/collinear..."); return -1; }
/* multi-precision version */ int segment_intersection_2d_e(double ax1, double ay1, double ax2, double ay2, double bx1, double by1, double bx2, double by2, double *x1, double *y1, double *x2, double *y2) { double t; double max_ax, min_ax, max_ay, min_ay; double max_bx, min_bx, max_by, min_by; int sgn_d, sgn_da, sgn_db; int vertical; int f11, f12, f21, f22; mp_exp_t exp; char *s; if (!initialized) initialize_mpf_vars(); /* TODO: Works for points ? */ G_debug(3, "segment_intersection_2d_e()"); G_debug(4, " ax1 = %.18f, ay1 = %.18f", ax1, ay1); G_debug(4, " ax2 = %.18f, ay2 = %.18f", ax2, ay2); G_debug(4, " bx1 = %.18f, by1 = %.18f", bx1, by1); G_debug(4, " bx2 = %.18f, by2 = %.18f", bx2, by2); f11 = ((ax1 == bx1) && (ay1 == by1)); f12 = ((ax1 == bx2) && (ay1 == by2)); f21 = ((ax2 == bx1) && (ay2 == by1)); f22 = ((ax2 == bx2) && (ay2 == by2)); /* Check for identical segments */ if ((f11 && f22) || (f12 && f21)) { G_debug(3, " identical segments"); *x1 = ax1; *y1 = ay1; *x2 = ax2; *y2 = ay2; return 5; } /* Check for identical endpoints */ if (f11 || f12) { G_debug(3, " connected by endpoints"); *x1 = ax1; *y1 = ay1; return 1; } if (f21 || f22) { G_debug(3, " connected by endpoints"); *x1 = ax2; *y1 = ay2; return 1; } if ((MAX(ax1, ax2) < MIN(bx1, bx2)) || (MAX(bx1, bx2) < MIN(ax1, ax2))) { G_debug(3, " no intersection (disjoint bounding boxes)"); return 0; } if ((MAX(ay1, ay2) < MIN(by1, by2)) || (MAX(by1, by2) < MIN(ay1, ay2))) { G_debug(3, " no intersection (disjoint bounding boxes)"); return 0; } det22(dd, ax2, ax1, bx1, bx2, ay2, ay1, by1, by2); sgn_d = mpf_sgn(dd); if (sgn_d != 0) { G_debug(3, " general position"); det22(dda, bx1, ax1, bx1, bx2, by1, ay1, by1, by2); sgn_da = mpf_sgn(dda); /*mpf_div(rra, dda, dd); mpf_div(rrb, ddb, dd); s = mpf_get_str(NULL, &exp, 10, 40, rra); G_debug(4, " ra = %sE%d", (s[0]==0)?"0":s, exp); s = mpf_get_str(NULL, &exp, 10, 24, rrb); G_debug(4, " rb = %sE%d", (s[0]==0)?"0":s, exp); */ if (sgn_d > 0) { if ((sgn_da < 0) || (mpf_cmp(dda, dd) > 0)) { G_debug(3, " no intersection"); return 0; } det22(ddb, ax2, ax1, bx1, ax1, ay2, ay1, by1, ay1); sgn_db = mpf_sgn(ddb); if ((sgn_db < 0) || (mpf_cmp(ddb, dd) > 0)) { G_debug(3, " no intersection"); return 0; } } else { /* if sgn_d < 0 */ if ((sgn_da > 0) || (mpf_cmp(dda, dd) < 0)) { G_debug(3, " no intersection"); return 0; } det22(ddb, ax2, ax1, bx1, ax1, ay2, ay1, by1, ay1); sgn_db = mpf_sgn(ddb); if ((sgn_db > 0) || (mpf_cmp(ddb, dd) < 0)) { G_debug(3, " no intersection"); return 0; } } /*G_debug(3, " ra=%.17g rb=%.17g", mpf_get_d(dda)/mpf_get_d(dd), mpf_get_d(ddb)/mpf_get_d(dd)); */ /*G_debug(3, " sgn_d=%d sgn_da=%d sgn_db=%d cmp(dda,dd)=%d cmp(ddb,dd)=%d", sgn_d, sgn_da, sgn_db, mpf_cmp(dda, dd), mpf_cmp(ddb, dd)); */ mpf_set_d(delta, ax2 - ax1); mpf_mul(t1, dda, delta); mpf_div(t2, t1, dd); *x1 = ax1 + mpf_get_d(t2); mpf_set_d(delta, ay2 - ay1); mpf_mul(t1, dda, delta); mpf_div(t2, t1, dd); *y1 = ay1 + mpf_get_d(t2); G_debug(3, " intersection %.16g, %.16g", *x1, *y1); return 1; } /* segments are parallel or collinear */ det22(dda, bx1, ax1, bx1, bx2, by1, ay1, by1, by2); sgn_da = mpf_sgn(dda); if (sgn_da != 0) { /* segments are parallel */ G_debug(3, " parallel segments"); return 0; } /* segments are colinear. check for overlap */ /* swap endpoints if needed */ /* if segments are vertical, we swap x-coords with y-coords */ vertical = 0; if (ax1 > ax2) { SWAP(ax1, ax2); SWAP(ay1, ay2); } else if (ax1 == ax2) { vertical = 1; if (ay1 > ay2) SWAP(ay1, ay2); SWAP(ax1, ay1); SWAP(ax2, ay2); } if (bx1 > bx2) { SWAP(bx1, bx2); SWAP(by1, by2); } else if (bx1 == bx2) { if (by1 > by2) SWAP(by1, by2); SWAP(bx1, by1); SWAP(bx2, by2); } G_debug(3, " collinear segments"); if ((bx2 < ax1) || (bx1 > ax2)) { G_debug(3, " no intersection"); return 0; } /* there is overlap or connected end points */ G_debug(3, " overlap"); /* a contains b */ if ((ax1 < bx1) && (ax2 > bx2)) { G_debug(3, " a contains b"); if (!vertical) { *x1 = bx1; *y1 = by1; *x2 = bx2; *y2 = by2; } else { *x1 = by1; *y1 = bx1; *x2 = by2; *y2 = bx2; } return 3; } /* b contains a */ if ((ax1 > bx1) && (ax2 < bx2)) { G_debug(3, " b contains a"); if (!vertical) { *x1 = bx1; *y1 = by1; *x2 = bx2; *y2 = by2; } else { *x1 = by1; *y1 = bx1; *x2 = by2; *y2 = bx2; } return 4; } /* general overlap, 2 intersection points */ G_debug(3, " partial overlap"); if ((bx1 > ax1) && (bx1 < ax2)) { /* b1 is in a */ if (!vertical) { *x1 = bx1; *y1 = by1; *x2 = ax2; *y2 = ay2; } else { *x1 = by1; *y1 = bx1; *x2 = ay2; *y2 = ax2; } return 2; } if ((bx2 > ax1) && (bx2 < ax2)) { /* b2 is in a */ if (!vertical) { *x1 = bx2; *y1 = by2; *x2 = ax1; *y2 = ay1; } else { *x1 = by2; *y1 = bx2; *x2 = ay1; *y2 = ax1; } return 2; } /* should not be reached */ G_warning(("segment_intersection_2d() ERROR (should not be reached)")); G_warning("%.16g %.16g", ax1, ay1); G_warning("%.16g %.16g", ax2, ay2); G_warning("x"); G_warning("%.16g %.16g", bx1, by1); G_warning("%.16g %.16g", bx2, by2); return 0; }
//------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ int knumber_float::sign() const { return mpf_sgn(mpf_); }
//------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ bool knumber_float::is_zero() const { return mpf_sgn(mpf_) == 0; }
/** * @brief Print an approximation to stdout (or whatever the output * stream currently selected in the mps_context is). * * @param s A pointer to the current mps_context. * @param i The index of the approxiomation that shall be printed. * @param num The number of zero roots. */ MPS_PRIVATE void mps_outroot (mps_context * s, int i, int num) { long out_digit; out_digit = (long)(LOG10_2 * s->output_config->prec) + 10; /* print format header */ switch (s->output_config->format) { case MPS_OUTPUT_FORMAT_COMPACT: case MPS_OUTPUT_FORMAT_FULL: fprintf (s->outstr, "("); break; case MPS_OUTPUT_FORMAT_VERBOSE: fprintf (s->outstr, "Root(%d) = ", num); break; default: break; } /* print real part */ if (i == ISZERO || s->root[i]->attrs == MPS_ROOT_ATTRS_IMAG) fprintf (s->outstr, "0"); else mps_outfloat (s, mpc_Re (s->root[i]->mvalue), s->root[i]->drad, out_digit, true); /* print format middle part */ switch (s->output_config->format) { case MPS_OUTPUT_FORMAT_BARE: fprintf (s->outstr, " "); break; case MPS_OUTPUT_FORMAT_GNUPLOT: case MPS_OUTPUT_FORMAT_GNUPLOT_FULL: fprintf (s->outstr, "\t"); break; case MPS_OUTPUT_FORMAT_COMPACT: case MPS_OUTPUT_FORMAT_FULL: fprintf (s->outstr, ", "); break; case MPS_OUTPUT_FORMAT_VERBOSE: if (i == ISZERO || mpf_sgn (mpc_Im (s->root[i]->mvalue)) >= 0) fprintf (s->outstr, " + I * "); else fprintf (s->outstr, " - I * "); break; default: break; } /* print imaginary part */ if (i == ISZERO || s->root[i]->attrs == MPS_ROOT_ATTRS_REAL) fprintf (s->outstr, "0"); else mps_outfloat (s, mpc_Im (s->root[i]->mvalue), s->root[i]->drad, out_digit, s->output_config->format != MPS_OUTPUT_FORMAT_VERBOSE); /* If the output format is GNUPLOT_FORMAT_FULL, print out also the radius */ if (s->output_config->format == MPS_OUTPUT_FORMAT_GNUPLOT_FULL) { fprintf (s->outstr, "\t"); rdpe_out_str_u (s->outstr, s->root[i]->drad); fprintf (s->outstr, "\t"); rdpe_out_str_u (s->outstr, s->root[i]->drad); } /* print format ending */ switch (s->output_config->format) { case MPS_OUTPUT_FORMAT_COMPACT: fprintf (s->outstr, ")"); break; case MPS_OUTPUT_FORMAT_FULL: fprintf (s->outstr, ")\n"); if (i != ISZERO) { rdpe_outln_str (s->outstr, s->root[i]->drad); fprintf (s->outstr, "Status: %s, %s, %s\n", MPS_ROOT_STATUS_TO_STRING (s->root[i]->status), MPS_ROOT_ATTRS_TO_STRING (s->root[i]->attrs), MPS_ROOT_INCLUSION_TO_STRING (s->root[i]->inclusion)); } else fprintf (s->outstr, " 0\n ---\n"); break; default: break; } fprintf (s->outstr, "\n"); /* debug info */ if (s->DOLOG) { if (i == ISZERO) fprintf (s->logstr, "zero root %-4d = 0", num); else { fprintf (s->logstr, "Root %-4d = ", i); mpc_out_str_2 (s->logstr, 10, 0, 0, s->root[i]->mvalue); fprintf (s->logstr, "\n"); fprintf (s->logstr, " Radius = "); rdpe_outln_str (s->logstr, s->root[i]->drad); fprintf (s->logstr, " Prec = %ld\n", (long)(mpc_get_prec (s->root[i]->mvalue) / LOG2_10)); fprintf (s->logstr, " Approximation = %s\n", MPS_ROOT_STATUS_TO_STRING (s->root[i]->status)); fprintf (s->logstr, " Attributes = %s\n", MPS_ROOT_ATTRS_TO_STRING (s->root[i]->attrs)); fprintf (s->logstr, " Inclusion = %s\n", MPS_ROOT_INCLUSION_TO_STRING (s->root[i]->inclusion)); fprintf (s->logstr, "--------------------\n"); } } }
static int e_mpf_sgn (mpf_srcptr x) { return mpf_sgn (x); }
void topsin_series (mpf_t a_k, unsigned int k, unsigned int prec) { unsigned int n; mpf_t fourpi, numer, fact, low_bound, term, xterm; mpz_t bino; mpf_set_ui(a_k, 0); /* If k == 0 then we are done */ if (0 == k) return; mpf_init(fourpi); mpf_init(numer); mpf_init(fact); mpf_init(low_bound); mpf_init(term); mpf_init(xterm); mpz_init(bino); fp_two_pi(numer, prec); mpf_neg(numer, numer); // fourpi is actually -4pi^2 mpf_mul(fourpi, numer, numer); mpf_neg(fourpi, fourpi); mpf_set_ui(fact, 1); /* Get the number of binary bits from prec = log_2 10 * prec */ long nbits = (long) floor (3.321 * prec); mpf_div_2exp(low_bound, fact, nbits+32); for (n=0; n<2023123123; n++) { i_binomial(bino, 2*n+k, 2*n); mpf_set_z(term, bino); mpf_mul(xterm, term, numer); mpf_div(term, xterm, fact); mpf_add(a_k, a_k, term); // #define DEBUG 1 #ifdef DEBUG { double h_f, q_f, b_f; h_f = mpf_get_d(h); q_f = mpf_get_d(qmark); b_f = mpf_get_d(bits); printf("duuude place=%d, bitsdone=%ld h=%g q=%g bits=%f s=%d\n", place, bitsdone, h_f, q_f, b_f, mpf_sgn(h)); } #endif // If the term is small enough, we are done. mpf_abs(xterm, term); if (mpf_cmp(xterm, low_bound) < 0) break; // Now iterate mpf_mul(numer, numer, fourpi); mpf_mul_ui(fact, fact, (2*n+3)*2*(n+1)); } if (k%2 == 0) mpf_neg(a_k, a_k); mpf_clear(fourpi); mpf_clear(numer); mpf_clear(fact); mpf_clear(low_bound); mpf_clear(term); mpf_clear(xterm); mpz_clear(bino); }
// See Cohen; my D is -D in his notation. size_t pbc_hilbert(mpz_t **arr, int D) { int a, b; int t; int B = (int)floor(sqrt((double) D / 3.0)); mpc_t alpha; mpc_t j; mpf_t sqrtD; mpf_t f0; darray_t Pz; mpc_t z0, z1, z2; double d = 1.0; int h = 1; int jcount = 1; // Compute required precision. b = D % 2; for (;;) { t = (b*b + D) / 4; a = b; if (a <= 1) { a = 1; goto step535_4; } step535_3: if (!(t % a)) { jcount++; if ((a == b) || (a*a == t) || !b) { d += 1.0 / ((double) a); h++; } else { d += 2.0 / ((double) a); h+=2; } } step535_4: a++; if (a * a <= t) { goto step535_3; } else { b += 2; if (b > B) break; } } //printf("modulus: %f\n", exp(3.14159265358979 * sqrt(D)) * d * 0.5); d *= sqrt(D) * 3.14159265358979 / log(2); precision_init((int)(d + 34)); pbc_info("class number %d, %d bit precision", h, (int) d + 34); darray_init(Pz); mpc_init(alpha); mpc_init(j); mpc_init(z0); mpc_init(z1); mpc_init(z2); mpf_init(sqrtD); mpf_init(f0); mpf_sqrt_ui(sqrtD, D); b = D % 2; h = 0; for (;;) { t = (b*b + D) / 4; if (b > 1) { a = b; } else { a = 1; } step3: if (t % a) { step4: a++; if (a * a <= t) goto step3; } else { // a, b, t/a are coeffs of an appropriate primitive reduced positive // definite form. // Compute j((-b + sqrt{-D})/(2a)). h++; pbc_info("[%d/%d] a b c = %d %d %d", h, jcount, a, b, t/a); mpf_set_ui(f0, 1); mpf_div_ui(f0, f0, 2 * a); mpf_mul(mpc_im(alpha), sqrtD, f0); mpf_mul_ui(f0, f0, b); mpf_neg(mpc_re(alpha), f0); compute_j(j, alpha); if (0) { int i; for (i=Pz->count - 1; i>=0; i--) { printf("P %d = ", i); mpc_out_str(stdout, 10, 4, Pz->item[i]); printf("\n"); } } if (a == b || a * a == t || !b) { // P *= X - j int i, n; mpc_ptr p0; p0 = (mpc_ptr) pbc_malloc(sizeof(mpc_t)); mpc_init(p0); mpc_neg(p0, j); n = Pz->count; if (n) { mpc_set(z1, Pz->item[0]); mpc_add(Pz->item[0], z1, p0); for (i=1; i<n; i++) { mpc_mul(z0, z1, p0); mpc_set(z1, Pz->item[i]); mpc_add(Pz->item[i], z1, z0); } mpc_mul(p0, p0, z1); } darray_append(Pz, p0); } else { // P *= X^2 - 2 Re(j) X + |j|^2 int i, n; mpc_ptr p0, p1; p0 = (mpc_ptr) pbc_malloc(sizeof(mpc_t)); p1 = (mpc_ptr) pbc_malloc(sizeof(mpc_t)); mpc_init(p0); mpc_init(p1); // p1 = - 2 Re(j) mpf_mul_ui(f0, mpc_re(j), 2); mpf_neg(f0, f0); mpf_set(mpc_re(p1), f0); // p0 = |j|^2 mpf_mul(f0, mpc_re(j), mpc_re(j)); mpf_mul(mpc_re(p0), mpc_im(j), mpc_im(j)); mpf_add(mpc_re(p0), mpc_re(p0), f0); n = Pz->count; if (!n) { } else if (n == 1) { mpc_set(z1, Pz->item[0]); mpc_add(Pz->item[0], z1, p1); mpc_mul(p1, z1, p1); mpc_add(p1, p1, p0); mpc_mul(p0, p0, z1); } else { mpc_set(z2, Pz->item[0]); mpc_set(z1, Pz->item[1]); mpc_add(Pz->item[0], z2, p1); mpc_mul(z0, z2, p1); mpc_add(Pz->item[1], z1, z0); mpc_add(Pz->item[1], Pz->item[1], p0); for (i=2; i<n; i++) { mpc_mul(z0, z1, p1); mpc_mul(alpha, z2, p0); mpc_set(z2, z1); mpc_set(z1, Pz->item[i]); mpc_add(alpha, alpha, z0); mpc_add(Pz->item[i], z1, alpha); } mpc_mul(z0, z2, p0); mpc_mul(p1, p1, z1); mpc_add(p1, p1, z0); mpc_mul(p0, p0, z1); } darray_append(Pz, p1); darray_append(Pz, p0); } goto step4; } b+=2; if (b > B) break; } // Round polynomial and assign. int k = 0; { *arr = pbc_malloc(sizeof(mpz_t) * (Pz->count + 1)); int i; for (i=Pz->count - 1; i>=0; i--) { if (mpf_sgn(mpc_re(Pz->item[i])) < 0) { mpf_set_d(f0, -0.5); } else { mpf_set_d(f0, 0.5); } mpf_add(f0, f0, mpc_re(Pz->item[i])); mpz_init((*arr)[k]); mpz_set_f((*arr)[k], f0); k++; mpc_clear(Pz->item[i]); pbc_free(Pz->item[i]); } mpz_init((*arr)[k]); mpz_set_ui((*arr)[k], 1); k++; } darray_clear(Pz); mpc_clear(z0); mpc_clear(z1); mpc_clear(z2); mpf_clear(f0); mpf_clear(sqrtD); mpc_clear(alpha); mpc_clear(j); precision_clear(); return k; }