void log(RR& res, const RR& x) { if (x <= 0) Error("argument to log must be positive"); long p = RR::precision(); RR::SetPrecision(p + NumBits(p) + 10); RR y; long n; // re-write x = 2^n * (1 - y), where -1/2 < y < 1/4 (so 3/4 < 1-y < 3/2) if (x > 0.75 && x < 1.5) { n = 0; sub(y, 1, x); } else { n = Lg2(x) - 1; RR t; power2(t, -n); mul(t, t, x); while (t > 1.5) { mul(t, t, 0.5); n++; } sub(y, 1, t); } // compute s = - ln(1-y) by power series expansion RR s, s1, t, t1; s = 0; xcopy(t, y); xcopy(t1, y); long i; for (i = 2; ; i++) { add(s1, s, t); if (s == s1) break; xcopy(s, s1); mul(t1, t1, y); div(t, t1, i); } if (n == 0) t = 0; else { ComputeLn2(t); mul(t, t, n); } RR::SetPrecision(p); sub(res, t, s); }
long ComputeMax10Power() { RRPush push; RR::SetPrecision(NTL_BITS_PER_LONG); RR ln2, ln10; ComputeLn2(ln2); ComputeLn10(ln10); long k = to_long( to_RR(NTL_OVFBND/2) * ln2 / ln10 ); return k; }
ostream& operator<<(ostream& s, const xdouble& a) { if (a == 0) { s << "0"; return s; } RRPush push; long temp_p = long(log(fabs(log(fabs(a))) + 1.0)/log(2.0)) + 10; RR::SetPrecision(temp_p); RR ln2, ln10, log_2_10; ComputeLn2(ln2); ComputeLn10(ln10); log_2_10 = ln10/ln2; ZZ log_10_a = to_ZZ( (to_RR(a.e)*to_RR(2*NTL_XD_HBOUND_LOG) + log(fabs(a.x))/log(2.0))/log_2_10); xdouble b; long neg; if (a < 0) { b = -a; neg = 1; } else { b = a; neg = 0; } ZZ k = xdouble::OutputPrecision() - log_10_a; xdouble c, d; c = PowerOf10(to_ZZ(xdouble::OutputPrecision())); d = PowerOf10(log_10_a); b = b / d; b = b * c; while (b < c) { b = b * 10.0; k++; } while (b >= c) { b = b / 10.0; k--; } b = b + 0.5; k = -k; ZZ B; conv(B, b); long bp_len = xdouble::OutputPrecision()+10; UniqueArray<char> bp_store; bp_store.SetLength(bp_len); char *bp = bp_store.get(); long len, i; len = 0; do { if (len >= bp_len) LogicError("xdouble output: buffer overflow"); bp[len] = IntValToChar(DivRem(B, B, 10)); len++; } while (B > 0); for (i = 0; i < len/2; i++) { char tmp; tmp = bp[i]; bp[i] = bp[len-1-i]; bp[len-1-i] = tmp; } i = len-1; while (bp[i] == '0') i--; k += (len-1-i); len = i+1; bp[len] = '\0'; if (k > 3 || k < -len - 3) { // use scientific notation if (neg) s << "-"; s << "0." << bp << "e" << (k + len); } else { long kk = to_long(k); if (kk >= 0) { if (neg) s << "-"; s << bp; for (i = 0; i < kk; i++) s << "0"; } else if (kk <= -len) { if (neg) s << "-"; s << "0."; for (i = 0; i < -len-kk; i++) s << "0"; s << bp; } else { if (neg) s << "-"; for (i = 0; i < len+kk; i++) s << bp[i]; s << "."; for (i = len+kk; i < len; i++) s << bp[i]; } } return s; }