diff --git a/runtime/scripts/jme-builtins.js b/runtime/scripts/jme-builtins.js index 6d2b5b7b6..edd9d1b14 100644 --- a/runtime/scripts/jme-builtins.js +++ b/runtime/scripts/jme-builtins.js @@ -979,10 +979,10 @@ newBuiltin('-u', [TDecimal], TDecimal, function(a){ return a.negated(); }); newBuiltin('+', [TDecimal,TDecimal], TDecimal, function(a,b){ return a.plus(b); }); newBuiltin('+', [TNum,TDecimal], TDecimal, function(a,b){ return math.ensure_decimal(a).plus(b); }); newBuiltin('-', [TDecimal,TDecimal], TDecimal, function(a,b){ return a.minus(b); }); -newBuiltin('-', [TNum,TDecimal], TDecimal, function(a,b){ return (new math.ComplexDecimal(new Decimal(a))).minus(b); }); +newBuiltin('-', [TNum,TDecimal], TDecimal, function(a,b){ return math.ensure_decimal(a).minus(b); }); newBuiltin('*', [TDecimal,TDecimal], TDecimal, function(a,b){ return a.times(b); }); newBuiltin('/', [TDecimal,TDecimal], TDecimal, function(a,b){ return a.dividedBy(b); }); -newBuiltin('/', [TNum,TDecimal], TDecimal, function(a,b){ return (new math.ComplexDecimal(new Decimal(a))).dividedBy(b); }); +newBuiltin('/', [TNum,TDecimal], TDecimal, function(a,b){ return math.ensure_decimal(a).dividedBy(b); }); newBuiltin('abs', [TDecimal], TDecimal, function(a){ return a.absoluteValue(); }); newBuiltin('ceil', [TDecimal], TDecimal, function(a){ return a.re.ceil(); }); newBuiltin('cos', [TDecimal], TDecimal, function(a){ return a.re.cos(); }); @@ -1032,7 +1032,7 @@ newBuiltin('min', [sig.listof(sig.type('decimal'))], TDecimal, function(l) { ret newBuiltin('dpformat',[TDecimal,TNum], TString, function(a,dp) {return a.toFixed(dp); }); newBuiltin('tonearest',[TDecimal,TDecimal], TDecimal, function(a,x) {return a.toNearest(x.re); }); newBuiltin('^',[TDecimal,TDecimal], TDecimal, function(a,b) {return a.pow(b); }); -newBuiltin('^', [TInt,TDecimal], TDecimal, function(a,b) { return (new math.ComplexDecimal(math.numberToDecimal(a))).pow(b); }); +newBuiltin('^', [TInt,TDecimal], TDecimal, function(a,b) { return math.ensure_decimal(a).pow(b); }); newBuiltin('sigformat',[TDecimal,TNum], TString, function(a,sf) {return a.toPrecision(sf); }); function_with_precision_info('siground', function(a,dp) {return a.toSignificantDigits(dp); }, TDecimal, 'sigfig'); newBuiltin('formatnumber', [TDecimal,TString], TString, function(n,style) {return math.niceComplexDecimal(n,{style:style});}); diff --git a/tests/jme-runtime.js b/tests/jme-runtime.js index 09879edec..8e7c46dfb 100644 --- a/tests/jme-runtime.js +++ b/tests/jme-runtime.js @@ -2697,9 +2697,11 @@ var math = Numbas.math = /** @lends Numbas.math */ { } rel_tol = rel_tol===undefined ? 1e-15 : rel_tol; abs_tol = abs_tol===undefined ? 1e-15: abs_tol; + if(a.complex || b.complex) { return math.abs(math.sub(a,b)) < abs_tol; } + return Math.abs(a-b) <= Math.max( rel_tol * Math.max(Math.abs(a), Math.abs(b)), abs_tol ); }, @@ -14110,10 +14112,10 @@ newBuiltin('-u', [TDecimal], TDecimal, function(a){ return a.negated(); }); newBuiltin('+', [TDecimal,TDecimal], TDecimal, function(a,b){ return a.plus(b); }); newBuiltin('+', [TNum,TDecimal], TDecimal, function(a,b){ return math.ensure_decimal(a).plus(b); }); newBuiltin('-', [TDecimal,TDecimal], TDecimal, function(a,b){ return a.minus(b); }); -newBuiltin('-', [TNum,TDecimal], TDecimal, function(a,b){ return (new math.ComplexDecimal(new Decimal(a))).minus(b); }); +newBuiltin('-', [TNum,TDecimal], TDecimal, function(a,b){ return math.ensure_decimal(a).minus(b); }); newBuiltin('*', [TDecimal,TDecimal], TDecimal, function(a,b){ return a.times(b); }); newBuiltin('/', [TDecimal,TDecimal], TDecimal, function(a,b){ return a.dividedBy(b); }); -newBuiltin('/', [TNum,TDecimal], TDecimal, function(a,b){ return (new math.ComplexDecimal(new Decimal(a))).dividedBy(b); }); +newBuiltin('/', [TNum,TDecimal], TDecimal, function(a,b){ return math.ensure_decimal(a).dividedBy(b); }); newBuiltin('abs', [TDecimal], TDecimal, function(a){ return a.absoluteValue(); }); newBuiltin('ceil', [TDecimal], TDecimal, function(a){ return a.re.ceil(); }); newBuiltin('cos', [TDecimal], TDecimal, function(a){ return a.re.cos(); }); @@ -14163,7 +14165,7 @@ newBuiltin('min', [sig.listof(sig.type('decimal'))], TDecimal, function(l) { ret newBuiltin('dpformat',[TDecimal,TNum], TString, function(a,dp) {return a.toFixed(dp); }); newBuiltin('tonearest',[TDecimal,TDecimal], TDecimal, function(a,x) {return a.toNearest(x.re); }); newBuiltin('^',[TDecimal,TDecimal], TDecimal, function(a,b) {return a.pow(b); }); -newBuiltin('^', [TInt,TDecimal], TDecimal, function(a,b) { return (new math.ComplexDecimal(math.numberToDecimal(a))).pow(b); }); +newBuiltin('^', [TInt,TDecimal], TDecimal, function(a,b) { return math.ensure_decimal(a).pow(b); }); newBuiltin('sigformat',[TDecimal,TNum], TString, function(a,sf) {return a.toPrecision(sf); }); function_with_precision_info('siground', function(a,dp) {return a.toSignificantDigits(dp); }, TDecimal, 'sigfig'); newBuiltin('formatnumber', [TDecimal,TString], TString, function(n,style) {return math.niceComplexDecimal(n,{style:style});}); diff --git a/tests/jme/jme-tests.mjs b/tests/jme/jme-tests.mjs index 0743f28c3..30784b150 100644 --- a/tests/jme/jme-tests.mjs +++ b/tests/jme/jme-tests.mjs @@ -660,6 +660,7 @@ Numbas.queueScript('jme_tests',['qunit','jme','jme-rules','jme-display','jme-cal assert.notOk(Numbas.jme.builtinScope.evaluate('iszero(dec(pi)-arccos(-1))').value,'dec(pi) uses more accurate pi than Math.PI'); deepCloseEqual(assert, evaluateNumber('dec(1+2i)/dec(3+4i)'),math.complex(11/25,2/25),'dec(1+2i)/(3+4i)'); deepCloseEqual(assert, Numbas.jme.builtinScope.evaluate('(1+2i)+dec(3)').value,new math.ComplexDecimal(new Decimal(4),new Decimal(2)),'(1+2i)+dec(3)'); + deepCloseEqual(assert, evaluate('i - dec(1)').value, new math.ComplexDecimal(new Decimal(-1), new Decimal(1)), 'i - dec(1)'); for(let a of [1,-1,2,-2,9,-9]) { for(let b of [0,1,-1,2,-2,0.5,-0.5,1.5,-0.5,3,-3]) { diff --git a/tests/numbas-runtime.js b/tests/numbas-runtime.js index 13d315bfc..d03833ceb 100644 --- a/tests/numbas-runtime.js +++ b/tests/numbas-runtime.js @@ -2698,9 +2698,11 @@ var math = Numbas.math = /** @lends Numbas.math */ { } rel_tol = rel_tol===undefined ? 1e-15 : rel_tol; abs_tol = abs_tol===undefined ? 1e-15: abs_tol; + if(a.complex || b.complex) { return math.abs(math.sub(a,b)) < abs_tol; } + return Math.abs(a-b) <= Math.max( rel_tol * Math.max(Math.abs(a), Math.abs(b)), abs_tol ); }, @@ -14098,10 +14100,10 @@ newBuiltin('-u', [TDecimal], TDecimal, function(a){ return a.negated(); }); newBuiltin('+', [TDecimal,TDecimal], TDecimal, function(a,b){ return a.plus(b); }); newBuiltin('+', [TNum,TDecimal], TDecimal, function(a,b){ return math.ensure_decimal(a).plus(b); }); newBuiltin('-', [TDecimal,TDecimal], TDecimal, function(a,b){ return a.minus(b); }); -newBuiltin('-', [TNum,TDecimal], TDecimal, function(a,b){ return (new math.ComplexDecimal(new Decimal(a))).minus(b); }); +newBuiltin('-', [TNum,TDecimal], TDecimal, function(a,b){ return math.ensure_decimal(a).minus(b); }); newBuiltin('*', [TDecimal,TDecimal], TDecimal, function(a,b){ return a.times(b); }); newBuiltin('/', [TDecimal,TDecimal], TDecimal, function(a,b){ return a.dividedBy(b); }); -newBuiltin('/', [TNum,TDecimal], TDecimal, function(a,b){ return (new math.ComplexDecimal(new Decimal(a))).dividedBy(b); }); +newBuiltin('/', [TNum,TDecimal], TDecimal, function(a,b){ return math.ensure_decimal(a).dividedBy(b); }); newBuiltin('abs', [TDecimal], TDecimal, function(a){ return a.absoluteValue(); }); newBuiltin('ceil', [TDecimal], TDecimal, function(a){ return a.re.ceil(); }); newBuiltin('cos', [TDecimal], TDecimal, function(a){ return a.re.cos(); }); @@ -14151,7 +14153,7 @@ newBuiltin('min', [sig.listof(sig.type('decimal'))], TDecimal, function(l) { ret newBuiltin('dpformat',[TDecimal,TNum], TString, function(a,dp) {return a.toFixed(dp); }); newBuiltin('tonearest',[TDecimal,TDecimal], TDecimal, function(a,x) {return a.toNearest(x.re); }); newBuiltin('^',[TDecimal,TDecimal], TDecimal, function(a,b) {return a.pow(b); }); -newBuiltin('^', [TInt,TDecimal], TDecimal, function(a,b) { return (new math.ComplexDecimal(math.numberToDecimal(a))).pow(b); }); +newBuiltin('^', [TInt,TDecimal], TDecimal, function(a,b) { return math.ensure_decimal(a).pow(b); }); newBuiltin('sigformat',[TDecimal,TNum], TString, function(a,sf) {return a.toPrecision(sf); }); function_with_precision_info('siground', function(a,dp) {return a.toSignificantDigits(dp); }, TDecimal, 'sigfig'); newBuiltin('formatnumber', [TDecimal,TString], TString, function(n,style) {return math.niceComplexDecimal(n,{style:style});});