Skip to content

Commit e791660

Browse files
committed
- add tests for nthRoot() and integerNthRoot() #1812
- ensure integerNthRoot() is monotonically nondecreasing #1822 - require integerNthRoot() root and radicand to be non-neg - require nthRoot() root to be non-neg
1 parent 1b7a85e commit e791660

File tree

2 files changed

+74
-11
lines changed

2 files changed

+74
-11
lines changed

src/js/base/js-numbers.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1710,8 +1710,12 @@ define("pyret-base/js/js-numbers", function() {
17101710
};
17111711

17121712
var integerNthRoot = function(n, m, errbacks) {
1713+
if (sign(n) < 0)
1714+
errbacks.throwDomainError('integerNthRoot: root ' + n + ' is negative.');
1715+
if (sign(m) < 0)
1716+
errbacks.throwDomainError('integerNthRoot: radicand ' + m + ' is negative.');
17131717
var guessPrev, guessToTheN;
1714-
var guess = m;
1718+
var guess = floor(m);
17151719

17161720
// find closest integral zero of x^n - m = 0 using Newton-Raphson.
17171721
// if k'th guess is x_k, then
@@ -1733,6 +1737,8 @@ define("pyret-base/js/js-numbers", function() {
17331737
};
17341738

17351739
var nthRoot = function(n, m, errbacks) {
1740+
if (sign(n) < 0)
1741+
errbacks.throwDomainError('nthRoot: root ' + n + ' is negative.');
17361742
var mNeg = (sign(m) < 0);
17371743
var mAbs = (mNeg ? abs(m, errbacks) : m);
17381744
var approx;
@@ -4087,8 +4093,10 @@ define("pyret-base/js/js-numbers", function() {
40874093

40884094
// the following exposes innards for testing
40894095
Numbers['_innards'] = {
4096+
integerNthRoot: integerNthRoot,
40904097
liftFixnumInteger: liftFixnumInteger,
40914098
makeNumericBinop: makeNumericBinop,
4099+
nthRoot: nthRoot,
40924100
sign: sign,
40934101
zfill: zfill,
40944102
};

tests/jsnums-test/jsnums-test.js

Lines changed: 65 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ R(["pyret-base/js/js-numbers"], function(JN) {
8989
var bigIntStr = "1" + new Array(309 + 1).join("0"); // 1 followed by 309 0s
9090
expect(JN.fromString(bigIntStr, sampleErrbacks)).toEqual(JN.makeBignum(bigIntStr));
9191

92-
9392
// for sci-not and 'p/q', fromString() and makeBignum()/makeRational() can give
9493
// structurally unequal but operationally equivalent results, so the following fails:
9594
// expect(JN.fromString("1e141", sampleErrbacks)).toEqual(JN.makeBignum("1e141"));
@@ -290,7 +289,7 @@ R(["pyret-base/js/js-numbers"], function(JN) {
290289
JN.toFixnum(Infinity),
291290
0.00001, sampleErrbacks);
292291
})
293-
.toThrowError(/domainError/);
292+
.toThrowError(/overflow/);
294293

295294
});
296295

@@ -344,6 +343,64 @@ R(["pyret-base/js/js-numbers"], function(JN) {
344343

345344
});
346345

346+
it("nthRoot integerNthRoot", function() {
347+
expect(JN.equals(
348+
JN._innards.nthRoot(3, 8, sampleErrbacks),
349+
Math.pow(8, 1/3),
350+
sampleErrbacks))
351+
.toBe(true);
352+
expect(JN.roughlyEquals(
353+
JN._innards.nthRoot(3, 7.5, sampleErrbacks),
354+
Math.pow(7.5, 1/3),
355+
0.00001, sampleErrbacks))
356+
.toBe(true);
357+
expect(JN.roughlyEquals(
358+
JN._innards.nthRoot(3, 8.5, sampleErrbacks),
359+
Math.pow(8.5, 1/3),
360+
0.00001, sampleErrbacks))
361+
.toBe(true);
362+
expect(JN.equals(
363+
JN._innards.nthRoot(3, -8, sampleErrbacks),
364+
- Math.pow(8, 1/3),
365+
sampleErrbacks))
366+
.toBe(true);
367+
expect(JN.roughlyEquals(
368+
JN._innards.nthRoot(3, -7.5, sampleErrbacks),
369+
- Math.pow(7.5, 1/3),
370+
0.00001, sampleErrbacks))
371+
.toBe(true);
372+
expect(JN.roughlyEquals(
373+
JN._innards.nthRoot(3, -8.5, sampleErrbacks),
374+
- Math.pow(8.5, 1/3),
375+
0.00001, sampleErrbacks))
376+
.toBe(true);
377+
expect(function () {
378+
JN._innards.nthRoot(-3, 8, sampleErrbacks);
379+
})
380+
.toThrowError(/root .* negative/);
381+
382+
expect(JN.equals(
383+
JN._innards.integerNthRoot(3, 8, sampleErrbacks),
384+
2, sampleErrbacks))
385+
.toBe(true);
386+
expect(JN.equals(
387+
JN._innards.integerNthRoot(3, 7.5, sampleErrbacks),
388+
1, sampleErrbacks))
389+
.toBe(true);
390+
expect(JN.equals(
391+
JN._innards.integerNthRoot(3, 8.5, sampleErrbacks),
392+
2, sampleErrbacks))
393+
.toBe(true);
394+
expect(function () {
395+
JN._innards.integerNthRoot(3, -8, sampleErrbacks);
396+
})
397+
.toThrowError(/radicand .* negative/);
398+
expect(function () {
399+
JN._innards.integerNthRoot(-3, 8, sampleErrbacks);
400+
})
401+
.toThrowError(/root .* negative/);
402+
403+
});
347404

348405
it("BigInteger methods", function() {
349406

@@ -356,13 +413,13 @@ R(["pyret-base/js/js-numbers"], function(JN) {
356413
// shd raise exception for arg outside [-1, +1]
357414
// but this is not testable via Pyret, because args are always sane
358415
// by the time this method is called
359-
expect(function() { JN.makeBignum(-1.5).asin(sampleErrbacks); }).toThrowError(/domainError/);
360-
expect(function() { JN.makeBignum(+1.5).asin(sampleErrbacks); }).toThrowError(/domainError/);
416+
expect(function() { JN.makeBignum(-1.5).asin(sampleErrbacks); }).toThrowError(/out of domain/);
417+
expect(function() { JN.makeBignum(+1.5).asin(sampleErrbacks); }).toThrowError(/out of domain/);
361418

362419
// BigInteger.*acos
363420
// shd raise exc for arg < -1 or > 1
364-
expect(function() { JN.makeBignum(-1.5).acos(sampleErrbacks); }).toThrowError(/domainError/);
365-
expect(function() { JN.makeBignum(+1.5).acos(sampleErrbacks); }).toThrowError(/domainError/);
421+
expect(function() { JN.makeBignum(-1.5).acos(sampleErrbacks); }).toThrowError(/out of domain/);
422+
expect(function() { JN.makeBignum(+1.5).acos(sampleErrbacks); }).toThrowError(/out of domain/);
366423

367424
// BigInteger.*.atan
368425
// should work
@@ -371,7 +428,7 @@ R(["pyret-base/js/js-numbers"], function(JN) {
371428
// atan2 (perhaps Pyret test is enough)
372429
expect(function () {
373430
JN.atan2(JN.makeBignum(0), JN.makeBignum(0), sampleErrbacks);
374-
}).toThrowError(/domainError/);
431+
}).toThrowError(/out of domain/);
375432

376433
// BigInteger.*.sin
377434
// should work
@@ -385,12 +442,11 @@ R(["pyret-base/js/js-numbers"], function(JN) {
385442
// should work
386443
expect(JN.makeBignum(0).tan(sampleErrbacks)).toEqual(0);
387444

388-
389445
// BigInteger.*.expt calls bnPow, which calls bnpExp
390446
// should raise exception for too-large
391447
expect(function() {
392448
JN.makeBignum(2).expt(JN.makeBignum(0xffffffff + 1), sampleErrbacks);
393-
}).toThrowError(/domainError/);
449+
}).toThrowError(/exponent .* too large/);
394450

395451
// BigInteger.*.log
396452
// should raise exception for arg <= 0
@@ -721,7 +777,6 @@ R(["pyret-base/js/js-numbers"], function(JN) {
721777

722778
});
723779

724-
725780
});
726781

727782
jazz.execute();

0 commit comments

Comments
 (0)