mirror of https://github.com/CGAL/cgal
1287 lines
36 KiB
C++
1287 lines
36 KiB
C++
/****************************************************************************
|
|
* Core Library Version 1.7, August 2004
|
|
* Copyright (c) 1995-2004 Exact Computation Project
|
|
* All rights reserved.
|
|
*
|
|
* This file is part of CORE (http://cs.nyu.edu/exact/core/); you may
|
|
* redistribute it under the terms of the Q Public License version 1.0.
|
|
* See the file LICENSE.QPL distributed with CORE.
|
|
*
|
|
* Licensees holding a valid commercial license may use this file in
|
|
* accordance with the commercial license agreement provided with the
|
|
* software.
|
|
*
|
|
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
|
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
*
|
|
*
|
|
* File: BigFloat.cpp
|
|
* Synopsis:
|
|
* BigFloat numbers with error bounds
|
|
*
|
|
* EXACTNESS PROPERTY:
|
|
* ==================
|
|
* For BigFloats that are exact (i.e., error=0),
|
|
* addition/subtraction and multiplication return the
|
|
* exact result (i.e., error=0). We also introduce the operation
|
|
* div2(), which simply divides a BigFloat by 2,
|
|
* but this again preserves exactness. Such exactness
|
|
* properties are used in our Newton iteration/Sturm Sequences.
|
|
*
|
|
* Written by
|
|
* Chee Yap <yap@cs.nyu.edu>
|
|
* Chen Li <chenli@cs.nyu.edu>
|
|
* Zilin Du <zilin@cs.nyu.edu>
|
|
*
|
|
* WWW URL: http://cs.nyu.edu/exact/
|
|
* Email: exact@cs.nyu.edu
|
|
*
|
|
* $URL$
|
|
* $Id$
|
|
***************************************************************************/
|
|
|
|
#include <ctype.h>
|
|
#include <CGAL/CORE/BigFloat.h>
|
|
#include <CGAL/CORE/Expr.h>
|
|
|
|
CORE_BEGIN_NAMESPACE
|
|
|
|
|
|
////////////////////////////////////////////////////////////
|
|
// Misc Helper Functions
|
|
////////////////////////////////////////////////////////////
|
|
|
|
BigInt FiveTo(unsigned long exp) {
|
|
if (exp == 0)
|
|
return BigInt(1);
|
|
else if (exp == 1)
|
|
return BigInt(5);
|
|
else {
|
|
BigInt x = FiveTo(exp / 2);
|
|
|
|
x = x * x;
|
|
|
|
if (exp & 1)
|
|
x *= 5;
|
|
|
|
return x;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////
|
|
// class BigFloat
|
|
////////////////////////////////////////////////////////////
|
|
|
|
// STATIC BIGFLOAT CONSTANTS
|
|
// ZERO
|
|
const BigFloat& BigFloat::getZero() {
|
|
static BigFloat Zero(0);
|
|
return Zero;
|
|
}
|
|
// ONE
|
|
const BigFloat& BigFloat::getOne() {
|
|
static BigFloat One(1);
|
|
return One;
|
|
}
|
|
|
|
// A special constructor for BigFloat from Expr
|
|
// -- this method is somewhat of an anomaly (we normally do not expect
|
|
// BigFloats to know about Expr).
|
|
BigFloat::BigFloat(const Expr& E, const extLong& r, const extLong& a)
|
|
: RCBigFloat(new BigFloatRep()) {
|
|
*this = E.approx(r, a).BigFloatValue(); // lazy implementaion, any other way?
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////
|
|
// class BigFloatRep
|
|
////////////////////////////////////////////////////////////
|
|
|
|
BigFloatRep::BigFloatRep(double d) : m(0), err(0), exp(0) {
|
|
if (d != 0.0) {
|
|
int isNegative = 0;
|
|
|
|
if (d < 0.0) {
|
|
isNegative = 1;
|
|
d = - d;
|
|
}
|
|
|
|
int binExp;
|
|
double f = frexp(d, &binExp);
|
|
|
|
exp = chunkFloor(binExp);
|
|
|
|
long s = binExp - bits(exp);
|
|
|
|
long stop = 0;
|
|
double intPart;
|
|
|
|
// convert f into a BigInt
|
|
while (f != 0.0 && stop < DBL_MAX_CHUNK) {
|
|
f = ldexp(f, (int)CHUNK_BIT);
|
|
f = modf(f, &intPart);
|
|
m <<= CHUNK_BIT;
|
|
m += (long)intPart;
|
|
exp--;
|
|
stop++;
|
|
}
|
|
#ifdef CORE_DEBUG
|
|
assert (s >= 0);
|
|
#endif
|
|
|
|
if (s)
|
|
m <<= s;
|
|
if (isNegative)
|
|
negate(m);
|
|
}
|
|
}//BigFloatRep constructor
|
|
|
|
// approximation
|
|
void BigFloatRep::trunc(const BigInt& I, const extLong& r, const extLong& a) {
|
|
if (sign(I)) {
|
|
long tr = chunkFloor((- r + bitLength(I)).asLong());
|
|
long ta = chunkFloor(- a.asLong());
|
|
long t;
|
|
|
|
if (r.isInfty() || a.isTiny())
|
|
t = ta;
|
|
else if (a.isInfty())
|
|
t = tr;
|
|
else
|
|
t = ta < tr ? tr : ta;
|
|
|
|
if (t > 0) { // BigInt remainder;
|
|
m = chunkShift(I, - t);
|
|
err = 1;
|
|
exp = t;
|
|
} else { // t <= 0
|
|
m = I;
|
|
err = 0;
|
|
exp = 0;
|
|
}
|
|
} else {// I == 0
|
|
m = 0;
|
|
err = 0;
|
|
exp = 0;
|
|
}
|
|
}
|
|
|
|
void BigFloatRep :: truncM(const BigFloatRep& B, const extLong& r, const extLong& a) {
|
|
if (sign(B.m)) {
|
|
long tr = chunkFloor((- 1 - r + bitLength(B.m)).asLong());
|
|
long ta = chunkFloor(- 1 - a.asLong()) - B.exp;
|
|
long t;
|
|
|
|
if (r.isInfty() || a.isTiny())
|
|
t = ta;
|
|
else if (a.isInfty())
|
|
t = tr;
|
|
else
|
|
t = ta < tr ? tr : ta;
|
|
|
|
if (t >= chunkCeil(clLg(B.err))) {
|
|
m = chunkShift(B.m, - t);
|
|
err = 2;
|
|
exp = B.exp + t;
|
|
} else // t < chunkCeil(clLg(B.err))
|
|
core_error(std::string("BigFloat error: truncM called with stricter")
|
|
+ "precision than current error.", __FILE__, __LINE__, true);
|
|
} else {// B.m == 0
|
|
long t = chunkFloor(- a.asLong()) - B.exp;
|
|
|
|
if (t >= chunkCeil(clLg(B.err))) {
|
|
m = 0;
|
|
err = 1;
|
|
exp = B.exp + t;
|
|
} else // t < chunkCeil(clLg(B.err))
|
|
core_error(std::string("BigFloat error: truncM called with stricter")
|
|
+ "precision than current error.", __FILE__, __LINE__, true);
|
|
}
|
|
}
|
|
|
|
// This is the main approximation function
|
|
// REMARK: would be useful to have a self-modifying version
|
|
// of this function (e.g., for Newton).
|
|
void BigFloatRep::approx(const BigFloatRep& B,
|
|
const extLong& r, const extLong& a) {
|
|
if (B.err) {
|
|
if (1 + clLg(B.err) <= bitLength(B.m))
|
|
truncM(B, r + 1, a);
|
|
else // 1 + clLg(B.err) > lg(B.m)
|
|
truncM(B, CORE_posInfty, a);
|
|
} else {// B.err == 0
|
|
trunc(B.m, r, a - bits(B.exp));
|
|
exp += B.exp;
|
|
}
|
|
// Call normalization globally -- IP 10/9/98
|
|
normal();
|
|
}
|
|
|
|
void BigFloatRep::div(const BigInt& N, const BigInt& D,
|
|
const extLong& r, const extLong& a) {
|
|
if (sign(D)) {
|
|
if (sign(N)) {
|
|
long tr = chunkFloor((- r + bitLength(N) - bitLength(D) - 1).asLong());
|
|
long ta = chunkFloor(- a.asLong());
|
|
|
|
if (r.isInfty() || a.isTiny())
|
|
exp = ta;
|
|
else if (a.isInfty())
|
|
exp = tr;
|
|
else
|
|
exp = ta < tr ? tr : ta;
|
|
|
|
BigInt remainder;
|
|
|
|
// divide(chunkShift(N, - exp), D, m, remainder);
|
|
div_rem(m, remainder, chunkShift(N, - exp), D);
|
|
|
|
if (exp <= 0 && sign(remainder) == 0)
|
|
err = 0;
|
|
else
|
|
err = 1;
|
|
} else {// N == 0
|
|
m = 0;
|
|
err = 0;
|
|
exp = 0;
|
|
}
|
|
} else // D == 0
|
|
core_error( "BigFloat error: zero divisor.", __FILE__, __LINE__, true);
|
|
|
|
// Call normalization globally -- IP 10/9/98
|
|
normal();
|
|
}//div
|
|
|
|
// error-normalization
|
|
void BigFloatRep::normal() {
|
|
long le = flrLg(err);
|
|
|
|
if (le >= CHUNK_BIT + 2) { // so we do not carry more than 16 = CHUNK_BIT + 2
|
|
// bits of error
|
|
long f = chunkFloor(--le); // f is roughly equal to floor(le/CHUNK_BIT)
|
|
long bits_f = bits(f); // f chunks will have bits_f many bits
|
|
#ifdef CORE_DEBUG
|
|
assert (bits_f >= 0);
|
|
#endif
|
|
|
|
m >>= bits_f; // reduce mantissa by bits_f many bits
|
|
err >>= bits_f; // same for err
|
|
err += 2; // why 2?
|
|
exp += f;
|
|
}
|
|
if (err == 0) // unlikely, if err += 2 above
|
|
eliminateTrailingZeroes();
|
|
}
|
|
|
|
// bigNormal(err)
|
|
// convert a bigInt error value (=err) into an error that fits into
|
|
// a long number. This is done by
|
|
// by increasing the exponent, and corresponding decrease
|
|
// in the bit lengths of the mantissa and error.
|
|
//
|
|
void BigFloatRep::bigNormal(BigInt& bigErr) {
|
|
long le = bitLength(bigErr);
|
|
|
|
if (le < CHUNK_BIT + 2) {
|
|
err = ulongValue(bigErr);
|
|
} else {
|
|
long f = chunkFloor(--le);
|
|
long bits_f = bits(f);
|
|
#ifdef CORE_DEBUG
|
|
assert(bits_f >= 0);
|
|
#endif
|
|
|
|
m >>= bits_f;
|
|
bigErr >>= bits_f;
|
|
err = ulongValue(bigErr) + 2; // you need to add "2" because "1" comes
|
|
// from truncation error in the mantissa, and another
|
|
// "1" comes from the truncation error in the bigErr.
|
|
// (But there is danger of overflow...)
|
|
exp += f;
|
|
}
|
|
|
|
if (err == 0)
|
|
eliminateTrailingZeroes();
|
|
}
|
|
|
|
// ARITHMETIC:
|
|
// Addition
|
|
void BigFloatRep::add(const BigFloatRep& x, const BigFloatRep& y) {
|
|
long expDiff = x.exp - y.exp;
|
|
|
|
if (expDiff > 0) {// x.exp > y.exp
|
|
if (!x.err) {
|
|
m = chunkShift(x.m, expDiff) + y.m;
|
|
err = y.err;
|
|
exp = y.exp;
|
|
} else {// x.err > 0
|
|
m = x.m + chunkShift(y.m, - expDiff); // negative shift!
|
|
err = x.err + 5; // To account for y.err (but why 5?)
|
|
exp = x.exp; //
|
|
// normal();
|
|
}
|
|
} else if (!expDiff) {// x.exp == y.exp
|
|
m = x.m + y.m;
|
|
err = x.err + y.err;
|
|
exp = x.exp;
|
|
// normal();
|
|
} else {// x.exp < y.exp
|
|
if (!y.err) {
|
|
m = x.m + chunkShift(y.m, - expDiff);
|
|
err = x.err;
|
|
exp = x.exp;
|
|
} else {// y.err > 0
|
|
m = chunkShift(x.m, expDiff) + y.m;
|
|
err = y.err + 5;
|
|
exp = y.exp;
|
|
// normal();
|
|
}
|
|
}
|
|
// Call normalization globally -- IP 10/9/98
|
|
normal();
|
|
}
|
|
|
|
// Subtraction
|
|
void BigFloatRep::sub(const BigFloatRep& x, const BigFloatRep& y) {
|
|
long expDiff = x.exp - y.exp;
|
|
|
|
if (expDiff > 0) {// x.exp > y.exp
|
|
if (!x.err) {
|
|
m = chunkShift(x.m, expDiff) - y.m;
|
|
err = y.err;
|
|
exp = y.exp;
|
|
} else {// x.err > 0
|
|
m = x.m - chunkShift(y.m, - expDiff);
|
|
err = x.err + 5;
|
|
exp = x.exp;
|
|
// normal();
|
|
}
|
|
} else if (!expDiff) {
|
|
m = x.m - y.m;
|
|
err = x.err + y.err;
|
|
exp = x.exp;
|
|
// normal();
|
|
} else { // x.exp < y.exp
|
|
if (!y.err) {
|
|
m = x.m - chunkShift(y.m, - expDiff);
|
|
err = x.err;
|
|
exp = x.exp;
|
|
} else {// y.err > 0
|
|
m = chunkShift(x.m, expDiff) - y.m;
|
|
err = y.err + 5;
|
|
exp = y.exp;
|
|
// normal();
|
|
}
|
|
}
|
|
// Call normalization globally -- IP 10/9/98
|
|
normal();
|
|
}
|
|
|
|
void BigFloatRep::mul(const BigFloatRep& x, const BigFloatRep& y) {
|
|
m = x.m * y.m;
|
|
exp = x.exp + y.exp;
|
|
// compute error (new code, much faster. Zilin Du, Nov 2003)
|
|
if (x.err == 0 && y.err == 0) {
|
|
err = 0;
|
|
eliminateTrailingZeroes();
|
|
} else {
|
|
BigInt bigErr(0);
|
|
if (y.err != 0)
|
|
bigErr += abs(x.m)*y.err;
|
|
if (x.err != 0)
|
|
bigErr += abs(y.m)*x.err;
|
|
if (x.err !=0 && y.err != 0)
|
|
bigErr += x.err*y.err;
|
|
bigNormal(bigErr);
|
|
}
|
|
}
|
|
// BigFloat div2 will half the value of x, exactly with NO error
|
|
// REMARK: should generalize this to dividing by any power of 2
|
|
// We need this in our use of BigFloats to maintain isolation
|
|
// intervals (e.g., in Sturm sequences) --Chee/Vikram 4/2003
|
|
//
|
|
void BigFloatRep :: div2(const BigFloatRep& x) {
|
|
if (isEven(x.m)) {
|
|
m = (x.m >> 1);
|
|
exp = x.exp ;
|
|
} else {
|
|
m = (x.m << static_cast<unsigned long>(CHUNK_BIT-1));
|
|
exp = x.exp -1;
|
|
}
|
|
}
|
|
|
|
// Converts a BigFloat interval into one BigFloat with almost same error bound
|
|
// This routine ignores the errors in inputs a and b.
|
|
// But you cannot really ignore them since, they are taken into account
|
|
// when you compute "r.sub(a,b)"...
|
|
void BigFloatRep::centerize(const BigFloatRep& a, const BigFloatRep& b) {
|
|
if ((a.m == b.m) && (a.err == b.err) && (a.exp == b.exp)) {
|
|
m = a.m;
|
|
err = a.err;
|
|
exp = a.exp;
|
|
return;
|
|
}
|
|
|
|
BigFloatRep r;
|
|
r.sub(a, b);
|
|
r.div2(r);
|
|
|
|
//setup mantissa and exponent, but not error bits
|
|
// But this already sets the error bits? Chee
|
|
add(a,b);
|
|
div2(*this);
|
|
// error bits = ceil ( B^{-exp}*|a-b|/2 )
|
|
|
|
// bug fixed: possible overflow on converting
|
|
// Zilin & Vikram, 08/24/04
|
|
// err = 1 + longValue(chunkShift(r.m, r.exp - exp));
|
|
BigInt E = chunkShift(r.m, r.exp - exp);
|
|
bigNormal(E);
|
|
}
|
|
|
|
// BigFloat Division, computing x/y:
|
|
// Unlike +,-,*, this one takes a relative precision bound R
|
|
// Note that R is only used when x and y are error-free!
|
|
// (This remark means that we may be less efficient than we could be)
|
|
//
|
|
// Assert( R>0 && R< CORE_Infty )
|
|
//
|
|
void BigFloatRep :: div(const BigFloatRep& x, const BigFloatRep& y,
|
|
const extLong& R) {
|
|
if (!y.isZeroIn()) { // y.m > y.err, so we are not dividing by 0
|
|
if (!x.err && !y.err) {
|
|
if (R < 0 || R.isInfty()) //Oct 9, 2002: fixed major bug! [Zilin/Chee]
|
|
div(x.m, y.m, defBFdivRelPrec, CORE_posInfty);
|
|
else
|
|
div(x.m, y.m, R, CORE_posInfty);
|
|
exp += x.exp - y.exp; // chen: adjust exp.
|
|
} else {// x.err > 0 or y.err > 0
|
|
BigInt bigErr, errRemainder;
|
|
|
|
if (x.isZeroIn()) { // x.m <= x.err
|
|
m = 0;
|
|
exp = x.exp - y.exp;
|
|
|
|
div_rem(bigErr, errRemainder, abs(x.m) + static_cast<long>(x.err),
|
|
abs(y.m) - static_cast<long>(y.err));
|
|
} else { // x.m > x.err
|
|
long lx = bitLength(x.m);
|
|
long ly = bitLength(y.m);
|
|
long r;
|
|
|
|
if (!x.err) // x.err == 0 and y.err > 0
|
|
r = ly + 2;
|
|
else if(!y.err) // x.err > 0 and y.err == 0
|
|
r = lx + 2;
|
|
else // x.err > 0 and y.err > 0
|
|
r = lx < ly ? lx + 2: ly + 2;
|
|
|
|
long t = chunkFloor(- r + lx - ly - 1);
|
|
BigInt remainder;
|
|
|
|
div_rem(m, remainder, chunkShift(x.m, - t), y.m);
|
|
exp = t + x.exp - y.exp;
|
|
|
|
long delta = ((t > 0) ? 2 : 0);
|
|
|
|
// Chen Li: 9/9/99
|
|
// here again, it use ">>" operator with a negative
|
|
// right operand. So the result is not well defined.
|
|
// Erroneous code:
|
|
// divide(abs(remainder) + (static_cast<long>(x.err) >> bits(t))
|
|
// + delta + static_cast<long>(y.err) * abs(m),
|
|
// abs(y.m) - static_cast<long>(y.err),
|
|
// bigErr,
|
|
// errRemainder);
|
|
// New code:
|
|
BigInt errx_over_Bexp = x.err;
|
|
long bits_Bexp = bits(t);
|
|
if (bits_Bexp >= 0) {
|
|
errx_over_Bexp >>= bits_Bexp;
|
|
} else {
|
|
errx_over_Bexp <<= (-bits_Bexp);
|
|
}
|
|
|
|
// divide(abs(remainder) + errx_over_Bexp
|
|
// + delta + static_cast<long>(y.err) * abs(m),
|
|
// abs(y.m) - static_cast<long>(y.err),
|
|
// bigErr,
|
|
// errRemainder);
|
|
div_rem(bigErr, errRemainder,
|
|
abs(remainder) + errx_over_Bexp + delta + static_cast<long>(y.err) * abs(m),
|
|
abs(y.m) - static_cast<long>(y.err));
|
|
}
|
|
|
|
if (sign(errRemainder))
|
|
++bigErr;
|
|
|
|
bigNormal(bigErr);
|
|
}
|
|
} else {// y.m <= y.err
|
|
core_error("BigFloat error: possible zero divisor.",
|
|
__FILE__, __LINE__, true);
|
|
}
|
|
|
|
// Call normalization globally -- IP 10/9/98
|
|
// normal(); -- Chen: after calling bigNormal, this call is redundant.
|
|
}// BigFloatRep::div
|
|
|
|
// squareroot for BigInt argument, without initial approximation
|
|
// sqrt(x,a) computes sqrt of x to absolute precision a.
|
|
// -- this is where Newton is applied
|
|
// -- this is called by BigFloatRep::sqrt(BigFloat, extLong)
|
|
void BigFloatRep::sqrt(const BigInt& x, const extLong& a) {
|
|
sqrt(x, a, BigFloat(x, 0, 0));
|
|
} // sqrt(BigInt x, extLong a) , without initial approx
|
|
|
|
// sqrt(x,a,A) where
|
|
// x = bigInt whose sqrt is to be computed
|
|
// a = absolute precision bound
|
|
// A = initial approximation in BigFloat
|
|
// -- this is where Newton is applied
|
|
// -- it is called by BigFloatRep::sqrt(BigFloatRep, extLong, BigFloat)
|
|
void BigFloatRep::sqrt(const BigInt& x, const extLong& a, const BigFloat& A) {
|
|
if (sign(x) == 0) {
|
|
m = 0;
|
|
err = 0;
|
|
exp = 0;
|
|
} else if (x == 1) {
|
|
m = 1;
|
|
err = 0;
|
|
exp = 0;
|
|
} else {// main case
|
|
// here is where we use the initial approximation
|
|
m = A.m();
|
|
err = 0;
|
|
exp = A.exp();
|
|
|
|
BigFloatRep q, z;
|
|
extLong aa;
|
|
// need this to make sure that in case the
|
|
// initial approximation A is less than sqrt(x)
|
|
// then Newton iteration will still proceed at
|
|
// least one step.
|
|
bool firstTime = true;
|
|
for (;;) {
|
|
aa = a - bits(exp);
|
|
q.div(x, m, CORE_posInfty, aa);
|
|
q.err = 0;
|
|
q.exp -= exp;
|
|
|
|
z.sub(*this, q); // this=current approximation, so z = this - q
|
|
/*if (sign(z.m) <= 0 || z.MSB() < - a) // justification: see Koji's
|
|
break; // thesis (p. 28) which states
|
|
// that we can exit when
|
|
// " (*this) <= q + 2**(-a)"
|
|
*/
|
|
// The preceding code is replaced by what follows:
|
|
if (z.MSB() < -a)
|
|
break;
|
|
if (sign(z.m) <= 0) {
|
|
if (firstTime)
|
|
firstTime = false;
|
|
else
|
|
break;
|
|
}
|
|
|
|
z.add(*this, q);
|
|
// Chen Li: a bug fixed here.
|
|
// m = z.m >> 1;
|
|
// err = 0;
|
|
// exp = z.exp;
|
|
if ((z.m > 1) && isEven(z.m)) {
|
|
m = z.m >> 1; // exact division by 2
|
|
err = 0;
|
|
exp = z.exp;
|
|
} else { // need to shift left before division by 2
|
|
m = chunkShift(z.m, 1) >> 1;
|
|
err = 0;
|
|
exp = z.exp - 1;
|
|
}//else
|
|
}//for
|
|
}//else
|
|
} // sqrt of BigInt, with initial approx
|
|
|
|
// MAIN ENTRY INTO SQRT FUNCTION (BIGFLOAT ARGUMENT, WITHOUT INITIAL APPROX)
|
|
void BigFloatRep::sqrt(const BigFloatRep& x, const extLong& a) {
|
|
sqrt(x, a, BigFloat(x.m, 0, x.exp));
|
|
} //sqrt(BigFloat, extLong a)
|
|
|
|
// MAIN ENTRY INTO SQRT FUNCTION (BIGFLOAT ARGUMENT WITH INITIAL APPROXIMATION)
|
|
void BigFloatRep::sqrt(const BigFloatRep& x, const extLong& a, const BigFloat& A) {
|
|
// This computes the sqrt of x to absolute precision a, starting with
|
|
// the initial approximation A
|
|
if (sign(x.m) >= 0) { // x.m >= 0
|
|
int delta = x.exp & 1; // delta=0 if x.exp is even, otherwise delta=1
|
|
|
|
if (x.isZeroIn()) { // x.m <= x.err
|
|
m = 0;
|
|
if (!x.err)
|
|
err = 0;
|
|
else { // x.err > 0
|
|
err = (long)(std::sqrt((double)x.err));
|
|
err++;
|
|
err <<= 1;
|
|
if (delta)
|
|
err <<= HALF_CHUNK_BIT;
|
|
}
|
|
exp = x.exp >> 1;
|
|
normal();
|
|
} else {
|
|
long aExp = A.exp() - (x.exp >> 1);
|
|
BigFloat AA( chunkShift(A.m(), delta), 0, aExp);
|
|
|
|
if (!x.err) { // x.m > x.err = 0 (ERROR FREE CASE)
|
|
BigFloatRep z;
|
|
extLong ppp;
|
|
if (a.isInfty()) //Oct 9, 2002: fixed major bug! [Zilin/Chee]
|
|
ppp = defBFsqrtAbsPrec;
|
|
else
|
|
ppp = a + EXTLONG_ONE;
|
|
extLong absp = ppp + bits(x.exp >> 1);
|
|
|
|
z.sqrt(chunkShift(x.m, delta), absp, AA); // call sqrt(BigInt, a, AA)
|
|
|
|
long p = (absp + bits(z.exp)).asLong();
|
|
|
|
// Next, normalize the error:
|
|
if (p <= 0) {
|
|
m = z.m;
|
|
// Chen Li: a bug fixed
|
|
// BigInt bigErr = 1 << (-p);
|
|
BigInt bigErr(1);
|
|
bigErr = bigErr << static_cast<unsigned long>(-p);
|
|
exp = z.exp + (x.exp >> 1);
|
|
bigNormal(bigErr);
|
|
} else { // p > 0
|
|
m = chunkShift(z.m, chunkCeil(p));
|
|
long r = CHUNK_BIT - 1 - (p + CHUNK_BIT - 1) % CHUNK_BIT;
|
|
#ifdef CORE_DEBUG
|
|
assert(r >= 0);
|
|
#endif
|
|
|
|
err = 1 >> r;
|
|
exp = - chunkCeil(ppp.asLong());
|
|
normal();
|
|
}
|
|
} else { // x.m > x.err > 0 (mantissa has error)
|
|
BigFloatRep z;
|
|
extLong absp=-flrLg(x.err)+bitLength(x.m)-(bits(delta) >> 1)+EXTLONG_FOUR;
|
|
|
|
z.sqrt(chunkShift(x.m, delta), absp, AA);
|
|
|
|
long qqq = - 1 + (bitLength(x.m) >> 1) - delta * HALF_CHUNK_BIT;
|
|
long qq = qqq - clLg(x.err);
|
|
long q = qq + bits(z.exp);
|
|
|
|
if (q <= 0) {
|
|
m = z.m;
|
|
long qqqq = - qqq - bits(z.exp);
|
|
// Chen Li (09/08/99), a bug fixed here:
|
|
// BigInt bigErr = x.err << - qqqq;
|
|
// when (-qqqq) is negative, the result is not correct.
|
|
// how "<<" and ">>" process negative second operand is
|
|
// not well defined. Seems it just take it as a unsigned
|
|
// integer and extract the last few bits.
|
|
// x.err is a long number which easily overflows.
|
|
// From page 22 of Koji's paper, I think the exponent is
|
|
// wrong here. So I rewrote it as:
|
|
BigInt bigErr = x.err;
|
|
if (qqqq >= 0) {
|
|
bigErr <<= qqqq;
|
|
} else {
|
|
bigErr >>= (-qqqq);
|
|
++bigErr; // we need to keep its ceiling.
|
|
}
|
|
|
|
exp = z.exp + (x.exp >> 1);
|
|
bigNormal(bigErr);
|
|
} else { // q > 0
|
|
m = chunkShift(z.m, chunkCeil(q));
|
|
long r = CHUNK_BIT - 1 - (q + CHUNK_BIT - 1) % CHUNK_BIT;
|
|
#ifdef CORE_DEBUG
|
|
assert(r >= 0);
|
|
#endif
|
|
|
|
err = 1 >> r;
|
|
exp = (x.exp >> 1) - chunkCeil(qq);
|
|
normal();
|
|
}
|
|
} // end of case with error in mantissa
|
|
}//else
|
|
} else
|
|
core_error("BigFloat error: squareroot called with negative operand.",
|
|
__FILE__, __LINE__, true);
|
|
} //sqrt with initial approximation
|
|
|
|
// compareMExp(x)
|
|
// returns 1 if *this > x
|
|
// 0 if *this = x,
|
|
// -1 if *this < x,
|
|
//
|
|
// Main comparison method for BigFloat
|
|
// This is called by BigFloat::compare()
|
|
// BE CAREFUL: The error bits are ignored!
|
|
// Need another version if we want to take care of error bits
|
|
|
|
int BigFloatRep :: compareMExp(const BigFloatRep& x) const {
|
|
int st = sign(m);
|
|
int sx = sign(x.m);
|
|
|
|
if (st > sx)
|
|
return 1;
|
|
else if (st == 0 && sx == 0)
|
|
return 0;
|
|
else if (st < sx)
|
|
return - 1;
|
|
else { // need to compare m && exp
|
|
long expDiff = exp - x.exp;
|
|
|
|
if (expDiff > 0) // exp > x.exp
|
|
return cmp(chunkShift(m, expDiff), x.m);
|
|
else if (!expDiff)
|
|
return cmp(m, x.m);
|
|
else // exp < x.exp
|
|
return cmp(m, chunkShift(x.m, - expDiff));
|
|
}
|
|
}
|
|
|
|
// 3/6/2000:
|
|
// This is a private function used by BigFloatRep::operator<<
|
|
// to get the exact value
|
|
// of floor(log10(M * 2^ e)) where E is an initial guess.
|
|
// We will return the correct E which satisfies
|
|
// 10^E <= M * 2^e < 10^{E+1}
|
|
// But we convert this into
|
|
// mm <= M < 10.mm
|
|
|
|
long BigFloatRep :: adjustE( long E, BigInt M, long ee) const {
|
|
if (M<0)
|
|
M=-M;
|
|
BigInt mm(1);
|
|
if (ee > 0)
|
|
M = (M<<static_cast<unsigned long>(ee));
|
|
else
|
|
mm = (mm << static_cast<unsigned long>(-ee));
|
|
if (E > 0)
|
|
mm *= (FiveTo(E)<< static_cast<unsigned long>(E));
|
|
else
|
|
M *= (FiveTo(-E) << static_cast<unsigned long>(-E));
|
|
|
|
if (M < mm) {
|
|
do {
|
|
E--;
|
|
M *= 10;
|
|
} while (M < mm);
|
|
} else if (M >= 10*mm) {
|
|
mm *= 10;
|
|
do {
|
|
E++;
|
|
mm *= 10;
|
|
} while (M >= mm);
|
|
}
|
|
return E;
|
|
}
|
|
|
|
BigFloatRep::DecimalOutput
|
|
BigFloatRep::toDecimal(unsigned int width, bool Scientific) const {
|
|
BigFloatRep::DecimalOutput decOut; // to be returned
|
|
if (err > 0) {
|
|
decOut.isExact = false;
|
|
} else { // err == 0
|
|
decOut.isExact = true;
|
|
}
|
|
|
|
if (err > 0 && err >= abs(m)) {
|
|
// if err is larger than mantissa, sign and significant values
|
|
// can not be determined.
|
|
core_error("BigFloat error: Error is too big!",
|
|
__FILE__, __LINE__, false);
|
|
decOut.rep = "0.0e0"; // error is too big
|
|
decOut.isScientific = false;
|
|
decOut.noSignificant = 0;
|
|
decOut.errorCode = 1; // sign of this number is unknown
|
|
return decOut;
|
|
}
|
|
|
|
decOut.sign = sign(m);
|
|
decOut.errorCode = 0;
|
|
|
|
BigInt M(m); // temporary mantissa
|
|
long lm = bitLength(M); // binary length of mantissa
|
|
long e2 = bits(exp); // binary shift length represented by exponent
|
|
long le = clLg(err); // binary length of err
|
|
if (le == -1)
|
|
le = 0;
|
|
|
|
long L10 = 0;
|
|
if (M != 0) {
|
|
L10 = (long)std::floor((lm + e2) / lgTenM);
|
|
L10 = adjustE(L10, m, e2); // L10: floor[log10(M 2^(e2))], M != 0
|
|
} else {
|
|
L10 = 0;
|
|
}
|
|
// Convention: in the positional format, when the output is
|
|
// the following string of 8 characters:
|
|
// (d0, d1, d2, d3, ".", d4, d5, d6, d7)
|
|
// then the decimal point is said to be in the 4th position.
|
|
// E.g., (d0, ".", d1, d2) has the decimal point in the 1st position.
|
|
// The value of L10 says that the decimal point of output should be at
|
|
// the (L10 + 1)st position. This is
|
|
// true regardingless of whether M = 0 or not. For zero, we output
|
|
// {0.0*} so L10=0. In general, the |value| is less than 10
|
|
// if and only if L10 is 0 and the
|
|
// decimal point is in the 1st place. Note that L10 is defined even if
|
|
// the output is an integer (in which case it does not physically appear
|
|
// but conceptually terminates the sequence of digits).
|
|
|
|
// First, get the decimal representaion of (m * B^(exp)).
|
|
if (e2 < 0) {
|
|
M *= FiveTo(-e2); // M = x * 10^(-e2)
|
|
} else if (e2 > 0) {
|
|
M <<= e2; // M = x * 2^(e2)
|
|
}
|
|
|
|
std::string decRep = M.get_str();
|
|
// Determine the "significant part" of this string, i.e. the part which
|
|
// is guaranteed to be correct in the presence of error,
|
|
// except that the last digit which might be subject to +/- 1.
|
|
|
|
if (err != 0) { // valid = number of significant digits
|
|
unsigned long valid = floorlg10(m) - (long)std::floor(std::log10(float(err)));
|
|
if (decRep.length() > valid) {
|
|
decRep.erase(valid);
|
|
}
|
|
}
|
|
|
|
// All the digits in decM are correct, except the last one might
|
|
// subject to an error +/- 1.
|
|
|
|
if ((decRep[0] == '+') || (decRep[0] == '-')) {
|
|
decRep.erase(0, 1);
|
|
}
|
|
|
|
// Second, make choice between positional representation
|
|
// and scientific notation. Use scientific notation when:
|
|
// 0) if scientific notation flag is on
|
|
// 1) err * B^exp >= 1, the error contribute to the integral part.
|
|
// 2) (1 + L10) >= width, there is not have enough places to hold the
|
|
// positional representation, not including decimal point.
|
|
// 3) The distance between the first significant digit and decimal
|
|
// point is too large for the width limit. This is equivalent to
|
|
// Either ((L10 >= 0 and (L10 + 1) > width))
|
|
// Or ((L10 < 0) and (-L10 + 1) > width).
|
|
|
|
if (Scientific ||
|
|
((err > 0) && (le + e2) >= 0) || // if err*B^exp >= 1
|
|
((L10 >= 0) && (L10 + 1 >= (long)width )) ||
|
|
((L10 < 0) && (-L10 + 1 > (long)width ))) {
|
|
// use scientific notation
|
|
decRep = round(decRep, L10, width);
|
|
decOut.noSignificant = width;
|
|
decRep.insert(1, ".");
|
|
if (L10 != 0) {
|
|
decRep += 'e';
|
|
if (L10 > 0) {
|
|
decRep += '+';
|
|
} else { // L10 < 0
|
|
decRep += '-';
|
|
}
|
|
char eBuf[48]; // enought to hold long number L10
|
|
int ne = 0;
|
|
if ((ne = sprintf(eBuf, "%ld", labs(L10))) >= 0) {
|
|
eBuf[ne] = '\0';
|
|
} else {
|
|
//perror("BigFloat.cpp: Problem in outputing the exponent!");
|
|
core_error("BigFloat error: Problem in outputing the exponent",
|
|
__FILE__, __LINE__, true);
|
|
}
|
|
decRep += eBuf;
|
|
decOut.isScientific = true;
|
|
}
|
|
} else {
|
|
// use conventional positional notation.
|
|
if (L10 >= 0) { // x >= 1 or x == 0 and L10 + 1 <= width
|
|
// round when necessary
|
|
if (decRep.length() > width ) {
|
|
decRep = round(decRep, L10, width );
|
|
if (decRep.length() > width ) {
|
|
// overflow happens! use scientific notation
|
|
return toDecimal(width, true);
|
|
}
|
|
}
|
|
decOut.noSignificant = decRep.length();
|
|
if (L10 + 1 < (long)width ) {
|
|
decRep.insert(L10 + 1, ".");
|
|
} else { // L10 + 1 == width
|
|
// do nothing
|
|
}
|
|
} else { // L10 < 0, 0 < x < 1
|
|
// (-L10) leading zeroes, including one to the left of decimal dot
|
|
// need to be added in beginning.
|
|
decRep = std::string(-L10, '0') + decRep;
|
|
// then round when necessary
|
|
if (decRep.length() > width ) {
|
|
decRep = round(decRep, L10, width );
|
|
// cannot overflow since there are L10 leading zeroes.
|
|
}
|
|
decOut.noSignificant = decRep.length() - (-L10);
|
|
decRep.insert(1, ".");
|
|
}
|
|
decOut.isScientific = false;
|
|
}
|
|
#ifdef CORE_DEBUG
|
|
assert(decOut.noSignificant >= 0);
|
|
#endif
|
|
|
|
decOut.rep = decRep;
|
|
return decOut;
|
|
}//toDecimal
|
|
|
|
std::string BigFloatRep::round(std::string inRep, long& L10, unsigned int width) const {
|
|
// round inRep so that the length would not exceed width.
|
|
if (inRep.length() <= width)
|
|
return inRep;
|
|
|
|
int i = width; // < length
|
|
bool carry = false;
|
|
|
|
if ((inRep[i] >= '5') && (inRep[i] <= '9')) {
|
|
carry = true;
|
|
i--;
|
|
while ((i >= 0) && carry) {
|
|
if (carry) {
|
|
inRep[i] ++;
|
|
if (inRep[i] > '9') {
|
|
inRep[i] = '0';
|
|
carry = true;
|
|
} else {
|
|
carry = false;
|
|
}
|
|
}
|
|
i-- ;
|
|
}
|
|
|
|
if ((i < 0) && carry) { // overflow
|
|
inRep.insert(inRep.begin(), '1');
|
|
L10 ++;
|
|
width ++;
|
|
}
|
|
}
|
|
|
|
return inRep.substr(0, width);
|
|
}//round(string,width)
|
|
|
|
|
|
// This function fromString(str, prec) is similar to the
|
|
// constructor Real(char * str, extLong prec)
|
|
// See the file Real.cc for the differences
|
|
|
|
void BigFloatRep :: fromString(const char *str, const extLong & prec ) {
|
|
// NOTE: prec defaults to defBigFloatInputDigits (see BigFloat.h)
|
|
// check that prec is not INFTY
|
|
if (prec.isInfty())
|
|
core_error("BigFloat error: infinite precision not allowed",
|
|
__FILE__, __LINE__, true);
|
|
|
|
const char *e = strchr(str, 'e');
|
|
int dot = 0;
|
|
long e10 = 0;
|
|
if (e != NULL)
|
|
e10 = atol(e+1); // e10 is decimal precision of the input string
|
|
// i.e., input is A/10^{e10}.
|
|
else {
|
|
e = str + strlen(str);
|
|
#ifdef CORE_DEBUG
|
|
assert(*e == '\0');
|
|
#endif
|
|
|
|
}
|
|
|
|
const char *p = str;
|
|
if (*p == '-' || *p == '+')
|
|
p++;
|
|
m = 0;
|
|
exp = 0;
|
|
|
|
for (; p < e; p++) {
|
|
if (*p == '.') {
|
|
dot = 1;
|
|
continue;
|
|
}
|
|
m = m * 10 + (*p - '0');
|
|
if (dot)
|
|
e10--;
|
|
}
|
|
|
|
BigInt one = 1;
|
|
long t = (e10 < 0) ? -e10 : e10;
|
|
BigInt ten = FiveTo(t) * (one << static_cast<unsigned long>(t));
|
|
|
|
// HERE IS WHERE WE USE THE SYSTEM CONSTANT
|
|
// defBigFloatInputDigits
|
|
// Note: this constant is rather similar to defInputDigits which
|
|
// is used by Real and Expr for controlling
|
|
// input accuracy. The difference is that defInputDigits can
|
|
// be CORE_INFTY, but defBigFloatInputDigits must be finite.
|
|
|
|
if (e10 < 0)
|
|
div(m, ten, CORE_posInfty, 4 * prec);
|
|
else
|
|
m *= ten;
|
|
if (*str == '-')
|
|
m = -m;
|
|
}//BigFloatRep::fromString
|
|
|
|
std::istream& BigFloatRep :: operator >>(std::istream& i) {
|
|
int size = 20;
|
|
char *str = new char[size];
|
|
char *p = str;
|
|
char c;
|
|
int d = 0, e = 0, s = 0;
|
|
// d=1 means dot is found
|
|
// e=1 means 'e' or 'E' is found
|
|
// int done = 0;
|
|
|
|
// Chen Li: fixed a bug, the original statement is
|
|
// for (i.get(c); c == ' '; i.get(c));
|
|
// use isspace instead of testing c == ' ', since it must also
|
|
// skip tab, catridge/return, etc.
|
|
// Change to:
|
|
// int status;
|
|
do {
|
|
c = i.get();
|
|
} while (isspace(c)); /* loop if met end-of-file, or
|
|
char read in is white-space. */
|
|
// Chen Li, "if (c == EOF)" is unsafe since c is of char type and
|
|
// EOF is of int tyep with a negative value -1
|
|
if (i.eof()) {
|
|
i.clear(std::ios::eofbit | std::ios::failbit);
|
|
return i;
|
|
}
|
|
|
|
// the current content in "c" should be the first non-whitespace char
|
|
if (c == '-' || c == '+') {
|
|
*p++ = c;
|
|
i.get(c);
|
|
}
|
|
|
|
for (; isdigit(c) || (!d && c=='.') ||
|
|
(!e && ((c=='e') || (c=='E'))) || (!s && (c=='-' || c=='+')); i.get(c)) {
|
|
if (!e && (c == '-' || c == '+'))
|
|
break;
|
|
// Chen Li: put one more rule to prohibite input like
|
|
// xxxx.xxxe+xxx.xxx:
|
|
if (e && (c == '.'))
|
|
break;
|
|
if (p - str == size) {
|
|
char *t = str;
|
|
str = new char[size*2];
|
|
memcpy(str, t, size);
|
|
delete [] t;
|
|
p = str + size;
|
|
size *= 2;
|
|
}
|
|
#ifdef CORE_DEBUG
|
|
assert((p-str) < size);
|
|
#endif
|
|
|
|
*p++ = c;
|
|
if (c == '.')
|
|
d = 1;
|
|
// Chen Li: fix a bug -- the sign of exponent can not happen before
|
|
// the character "e" appears! It must follow the "e' actually.
|
|
// if (e || c == '-' || c == '+') s = 1;
|
|
if (e)
|
|
s = 1;
|
|
if ((c == 'e') || (c=='E'))
|
|
e = 1;
|
|
}
|
|
|
|
// chenli: make sure that the p is still in the range
|
|
if (p - str >= size) {
|
|
int len = p - str;
|
|
char *t = str;
|
|
str = new char[len + 1];
|
|
memcpy(str, t, len);
|
|
delete [] t;
|
|
p = str + len;
|
|
}
|
|
|
|
#ifdef CORE_DEBUG
|
|
assert(p - str < size);
|
|
#endif
|
|
|
|
*p = '\0';
|
|
i.putback(c);
|
|
fromString(str);
|
|
delete [] str;
|
|
return i;
|
|
}//operator >>
|
|
|
|
|
|
// BigFloatRep::toDouble()
|
|
// converts the BigFloat to a machine double
|
|
// This is a dangerous function as the method
|
|
// is silent when it does not fit into a machine double!
|
|
// ToDo: fix this by return a machine NaN, +/- Infinity, +/- 0,
|
|
// when appropriate.
|
|
// Return NaN when error is larger than mantissa
|
|
// Return +/- Infinity if BigFloat is too big
|
|
// Return +/- 0 if BigFloat is too small
|
|
#ifdef _MSC_VER
|
|
#pragma warning(disable: 4723)
|
|
#endif
|
|
double BigFloatRep :: toDouble() const {
|
|
if (m == 0)
|
|
return (sign(m) * 0.0);
|
|
|
|
long e2 = bits(exp);
|
|
long le = clLg(err); // if err=0, le will be -1
|
|
if (le == -1)
|
|
le = 0;
|
|
|
|
BigInt M = m >> static_cast<unsigned long>(le);// remove error bits in mantissa
|
|
|
|
// Below, we want to return NaN by computing 0.0/0.0.
|
|
// To avoid compiler warnings about divide by zero, we do this:
|
|
|
|
double foolCompilerZero;
|
|
foolCompilerZero = 0.0;
|
|
|
|
// COMMENT: we should directly store the
|
|
// special IEEE values NaN, +/-Infinity, +/-0 in the code!!
|
|
|
|
if (M == 0)
|
|
return ( 0.0/foolCompilerZero ) ; // return NaN
|
|
|
|
e2 += le; // adjust exponent corresponding to error bits
|
|
|
|
int len = bitLength(M) - 53; // this is positive if M is too large
|
|
|
|
if (len > 0) {
|
|
M >>= len;
|
|
e2 += len;
|
|
}
|
|
|
|
double tt = doubleValue(M);
|
|
|
|
int ee = e2 + bitLength(M) - 1; // real exponent.
|
|
|
|
if (ee >= 1024) // overflow!
|
|
return ( sign(m)/foolCompilerZero ); // return a signed infinity
|
|
|
|
if (ee <= -1075) // underflow!
|
|
// NOTE: if (-52 < ee <= 0) get denormalized number
|
|
return ( sign(m) * 0.0 ); // return signed zero.
|
|
|
|
// Execute this loop if e2 < 0;
|
|
for (int i = 0; i > e2; i--)
|
|
tt /= 2;
|
|
|
|
// Execute this loop if e2 > 0;
|
|
for (int j = 0; j < e2; j++)
|
|
tt *= 2;
|
|
|
|
return tt;
|
|
}//toDouble
|
|
#ifdef _MSC_VER
|
|
#pragma warning(default: 4723)
|
|
#endif
|
|
BigInt BigFloatRep::toBigInt() const {
|
|
long e2 = bits(exp);
|
|
long le = clLg(err);
|
|
if (le == -1)
|
|
le = 0;
|
|
#ifdef CORE_DEBUG
|
|
assert (le >= 0);
|
|
#endif
|
|
|
|
BigInt M = m >> static_cast<unsigned long>(le); // discard the contaminated bits.
|
|
e2 += le; // adjust the exponent
|
|
|
|
if (e2 < 0)
|
|
return M >> static_cast<unsigned long>(-e2);
|
|
else if (e2 > 0)
|
|
return M << static_cast<unsigned long>(e2);
|
|
else
|
|
return M;
|
|
}
|
|
|
|
long BigFloatRep :: toLong() const {
|
|
// convert a BigFloat to a long integer, rounded toward -\infty.
|
|
long e2 = bits(exp);
|
|
long le = clLg(err);
|
|
#ifdef CORE_DEBUG
|
|
assert (le >= 0);
|
|
#endif
|
|
|
|
BigInt M = m >> static_cast<unsigned long>(le); // discard the contaminated bits.
|
|
e2 += le; // adjust the exponent
|
|
long t;
|
|
if (e2 < 0)
|
|
t = ulongValue(M >> static_cast<unsigned long>(-e2));
|
|
else if (e2 > 0)
|
|
t = ulongValue(M << static_cast<unsigned long>(e2));
|
|
else
|
|
t = ulongValue(M);
|
|
// t = M.as_long();
|
|
// Note: as_long() will return LONG_MAX in case of overflow.
|
|
|
|
return t;
|
|
}
|
|
|
|
// pow(r,n) function for BigFloat
|
|
// Note: power(r,n) calls pow(r,n)
|
|
BigFloat pow(const BigFloat& r, unsigned long n) {
|
|
if (n == 0)
|
|
return BigFloat(1);
|
|
else if (n == 1)
|
|
return r;
|
|
else {
|
|
BigFloat x = r;
|
|
while ((n % 2) == 0) { // n is even
|
|
x *= x;
|
|
n >>= 1;
|
|
}
|
|
BigFloat u = x;
|
|
while (true) {
|
|
n >>= 1;
|
|
if (n == 0)
|
|
return u;
|
|
x *= x;
|
|
if ((n % 2) == 1) // n is odd
|
|
u *= x;
|
|
}
|
|
//return u; // unreachable
|
|
}
|
|
}//pow
|
|
|
|
// experimental
|
|
BigFloat root(const BigFloat& x, unsigned long k,
|
|
const extLong& a, const BigFloat& A) {
|
|
if (x.sign() == 0) {
|
|
return BigFloat(0);
|
|
} else if (x == 1) {
|
|
return BigFloat(1);
|
|
} else {
|
|
BigFloat q, del, zz;
|
|
BigFloat z = A;
|
|
BigFloat bk = long(k);
|
|
for (; ;) {
|
|
zz = pow(z, k-1);
|
|
q = x.div(zz, a);
|
|
q.makeExact();
|
|
del = z - q;
|
|
del.makeExact();
|
|
if (del.MSB() < -a)
|
|
break;
|
|
z = ((bk-1)*z + q).div(bk, a);
|
|
// newton's iteration: z_{n+1}=((k-1)z_n+x/z_n^{k-1})/k
|
|
z.makeExact();
|
|
}
|
|
return z;
|
|
}
|
|
}//root
|
|
|
|
CORE_END_NAMESPACE
|