Permalink
Browse files

fallback on biginteger.sqrt: just switch over to floating point if we…

… can't get the exact answer
  • Loading branch information...
Danny Yoo
Danny Yoo committed Feb 28, 2011
1 parent 4926282 commit d6afb0468bff83bc783efe49621d81da207a6614
Showing with 28 additions and 52 deletions.
  1. +20 −52 src/js-numbers.js
  2. +8 −0 test/tests.js
View
@@ -3749,81 +3749,49 @@ if (typeof(exports) !== 'undefined') {
// adapted for integer-sqrt.
// http://en.wikipedia.org/wiki/Newton's_method#Square_root_of_a_number
var searchIter = function(n, guess) {
- while(!(goodEnough(n, guess))) {
- guess = average(guess,
- floor(divide(n, guess)));
+ while(!(lessThanOrEqual(sqr(guess),n) &&
+ lessThan(n,sqr(add(guess, 1))))) {
+ guess = floor(divide(add(guess,
+ floor(divide(n, guess))),
+ 2));
}
return guess;
};
-
- var average = function (x,y) {
- return floor(divide(add(x,y), 2));
- };
-
- var goodEnough = function(n, guess) {
- return (lessThanOrEqual(sqr(guess),n) &&
- lessThan(n,sqr(add(guess, 1))));
- };
// integerSqrt: -> scheme-number
BigInteger.prototype.integerSqrt = function() {
- if(this.s == 0) {
+ var n;
+ if(sign(this) >= 0) {
return searchIter(this, this);
} else {
- var tmpThis = multiply(this, -1);
- return Complex.makeInstance(0,
- searchIter(tmpThis, tmpThis));
+ n = this.negate();
+ return Complex.makeInstance(0, searchIter(n, n));
}
};
})();
- (function() {
-
-
- // Classic implementation of Newton-Ralphson square-root search.
- // http://en.wikipedia.org/wiki/Newton's_method#Square_root_of_a_number
- var searchIter = function(n, guess) {
- var maxIterations = 100;
- while(Math.abs(guess*guess - n) > 0.000001 &&
- (maxIterations--) > 0) {
- guess = (guess + n/guess) / 2
-
- }
- return guess;
- };
-
+ (function() {
// Get an approximation using integerSqrt, and then start another
// Newton-Ralphson search if necessary.
BigInteger.prototype.sqrt = function() {
- var approx = this.integerSqrt();
- var f;
+ var approx = this.integerSqrt(), fix;
if (eqv(sqr(approx), this)) {
return approx;
}
-
- if (isReal(approx)) {
- if (isFinite(toFixnum(this)) &&
- isFinite(toFixnum(approx))) {
- return FloatPoint.makeInstance(
- searchIter(toFixnum(this), toFixnum(approx)));
+ fix = toFixnum(this);
+ if (isFinite(fix)) {
+ if (fix >= 0) {
+ return FloatPoint.makeInstance(Math.sqrt(fix));
} else {
- return approx;
- }
- } else {
- if (isFinite(toFixnum(this)) &&
- isFinite(toFixnum(imaginaryPart(approx)))) {
return Complex.makeInstance(
- 0,
- FloatPoint.makeInstance(
- searchIter(
- (-toFixnum(this)),
- toFixnum(imaginaryPart(approx)))));
- } else {
- return approx;
+ 0,
+ FloatPoint.makeInstance(Math.sqrt(-fix)));
}
+ } else {
+ return approx;
}
- }
+ };
})();
View
@@ -2194,6 +2194,13 @@ describe('sqrt', {
assertTrue(diffPercent(makeFloat(4893703081.846022),
sqrt(makeBignum("23948329853269253680")))
< 1e-2)
+ assertTrue(diffPercent(sqrt(expt(15, 21)).toFixnum(),
+ 2233357359474.6265)
+ < 2e-10);
+ assertTrue(eqv(sqrt(expt(15, 22)),
+ expt(15, 11)));
+ assertTrue(eqv(sqrt(expt(15, 22)),
+ expt(15, 11)));
},
'rationals': function() {
@@ -2233,6 +2240,7 @@ describe('abs', {
abs(makeBignum("1")));
assertEquals(makeBignum("0"),
abs(makeBignum("0")));
+
},
'rationals': function() {
assertEquals(makeRational(2, 1),

0 comments on commit d6afb04

Please sign in to comment.