Skip to content

Commit

Permalink
Remove support for implicit conversion of null to 0. See #830.
Browse files Browse the repository at this point in the history
  • Loading branch information
josdejong committed Jan 23, 2018
1 parent b9c30eb commit 4469f6b
Show file tree
Hide file tree
Showing 96 changed files with 178 additions and 402 deletions.
2 changes: 2 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ Breaking changes:
alphabetically. This also impacts functions `deepEqual`, `sort`, `min`,
`max`, `median`, and `partitionSelect`. Use `compareNatural` if you
need to sort an array with text. See #680.
- `null` is no longer implicitly casted to a number `0`, so input like
`math.add(2, null)` is no longer supported. See #830, #353.


## 2018-01-17, version 3.20.1
Expand Down
24 changes: 0 additions & 24 deletions lib/core/typed.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,30 +247,6 @@ exports.create = function create(type) {
convert: function (x) {
return +x;
}
}, {
from: 'null',
to: 'number',
convert: function () {
return 0;
}
}, {
from: 'null',
to: 'string',
convert: function () {
return 'null';
}
}, {
from: 'null',
to: 'BigNumber',
convert: function () {
return new type.BigNumber(0);
}
}, {
from: 'null',
to: 'Fraction',
convert: function () {
return new type.Fraction(0);
}
}, {
from: 'Array',
to: 'Matrix',
Expand Down
4 changes: 2 additions & 2 deletions lib/function/arithmetic/norm.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ function factory (type, config, load, typed) {
return x.abs();
},

'boolean | null' : function (x) {
'boolean' : function (x) {
// norm(x) = abs(x)
return Math.abs(x);
},
Expand All @@ -78,7 +78,7 @@ function factory (type, config, load, typed) {
return _norm(x, 2);
},

'number | Complex | BigNumber | boolean | null, number | BigNumber | string': function (x) {
'number | Complex | BigNumber | boolean, number | BigNumber | string': function (x) {
// ignore second parameter, TODO: remove the option of second parameter for these types
return norm(x);
},
Expand Down
2 changes: 1 addition & 1 deletion lib/function/arithmetic/unaryPlus.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ function factory (type, config, load, typed) {
return deepMap(x, unaryPlus, true);
},

'boolean | string | null': function (x) {
'boolean | string': function (x) {
// convert to a number or bignumber
return (config.number == 'BigNumber') ? new type.BigNumber(+x): +x;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/function/logical/and.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ function factory (type, config, load, typed) {
},

'Unit, Unit': function (x, y) {
return and(x.value, y.value);
return and(x.value || 0, y.value || 0);
},

'Matrix, Matrix': function (x, y) {
Expand Down
2 changes: 1 addition & 1 deletion lib/function/logical/not.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ function factory (type, config, load, typed) {
},

'Unit': function (x) {
return not(x.value);
return x.value !== null ? not(x.value) : true;
},

'Array | Matrix': function (x) {
Expand Down
2 changes: 1 addition & 1 deletion lib/function/logical/or.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ function factory (type, config, load, typed) {
},

'Unit, Unit': function (x, y) {
return or(x.value, y.value);
return or(x.value || 0, y.value || 0);
},

'Matrix, Matrix': function (x, y) {
Expand Down
2 changes: 1 addition & 1 deletion lib/function/logical/xor.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ function factory (type, config, load, typed) {
},

'Unit, Unit': function (x, y) {
return xor(x.value, y.value);
return xor(x.value || 0, y.value || 0);
},

'Matrix, Matrix': function (x, y) {
Expand Down
4 changes: 2 additions & 2 deletions lib/function/relational/unequal.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ function factory (type, config, load, typed) {
* Strings are compared by their numerical value.
*
* Values `null` and `undefined` are compared strictly, thus `null` is unequal
* with everything except `null`, and `undefined` is unequal with everying
* except. `undefined`.
* with everything except `null`, and `undefined` is unequal with everything
* except `undefined`.
*
* Syntax:
*
Expand Down
4 changes: 4 additions & 0 deletions lib/type/bignumber/function/bignumber.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ function factory (type, config, load, typed) {
return new type.BigNumber(x.n).div(x.d);
},

'null': function (x) {
return new type.BigNumber(0);
},

'Array | Matrix': function (x) {
return deepMap(x, bignumber);
}
Expand Down
4 changes: 4 additions & 0 deletions lib/type/boolean.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ function factory (type, config, load, typed) {
return !!x;
},

'null': function (x) {
return false;
},

'BigNumber': function (x) {
return !x.isZero();
},
Expand Down
4 changes: 4 additions & 0 deletions lib/type/complex/function/complex.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ function factory (type, config, load, typed) {
return type.Complex(x); // for example '2 + 3i'
},

'null': function (x) {
return type.Complex(0);
},

'Object': function (x) {
if('re' in x && 'im' in x) {
return new type.Complex(x.re, x.im);
Expand Down
4 changes: 4 additions & 0 deletions lib/type/fraction/function/fraction.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ function factory (type, config, load, typed) {
return new type.Fraction(numerator, denominator);
},

'null': function (x) {
return new type.Fraction(0);
},

'BigNumber': function (x) {
return new type.Fraction(x.toString());
},
Expand Down
4 changes: 4 additions & 0 deletions lib/type/number.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ function factory (type, config, load, typed) {
throw new Error('Second argument with valueless unit expected');
},

'null': function (x) {
return 0;
},

'Unit, string | Unit': function (unit, valuelessUnit) {
return unit.toNumber(valuelessUnit);
},
Expand Down
4 changes: 2 additions & 2 deletions lib/type/unit/Unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -789,7 +789,7 @@ function factory (type, config, load, typed, math) {
// This gives correct, but unexpected, results for units with an offset.
// For example, abs(-283.15 degC) = -263.15 degC !!!
var ret = this.clone();
ret.value = abs(ret.value);
ret.value = ret.value !== null ? abs(ret.value) : null;

for(var i in ret.units) {
if(ret.units[i].unit.name === 'VA' || ret.units[i].unit.name === 'VAR') {
Expand Down Expand Up @@ -1176,7 +1176,7 @@ function factory (type, config, load, typed, math) {
// Note: the units value can be any numeric type, but to find the best
// prefix it's enough to work with limited precision of a regular number
// Update: using mathjs abs since we also allow complex numbers
var absValue = abs(this.value);
var absValue = this.value !== null ? abs(this.value) : 0;
var absUnitValue = abs(this.units[0].unit.value);
var bestPrefix = this.units[0].prefix;
if (absValue === 0) {
Expand Down
9 changes: 7 additions & 2 deletions test/function/arithmetic/abs.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ describe('abs', function () {
assert.strictEqual(math.abs(false), 0);
});

it('should return the abs value of null', function () {
assert.strictEqual(math.abs(null), 0);
it('should not support null', function () {
assert.throws(function () {math.abs(null) }, /Unexpected type of argument/);
});

it('should return the abs value of a number', function () {
Expand Down Expand Up @@ -91,8 +91,13 @@ describe('abs', function () {
assert.throws(function () {math.abs(1, 2)}, /TypeError: Too many arguments/);
});

it('should throw an in case of wrong type of arguments', function() {
assert.throws(function () {math.abs(null);}, /TypeError: Unexpected type of argument/);
});

it('should throw an error in case of unsupported types', function () {
assert.throws(function () {math.abs(new Date());}, /TypeError: Unexpected type of argument/);
assert.throws(function () {math.abs(null);}, /TypeError: Unexpected type of argument/);
assert.throws(function () {math.abs(undefined);}, /TypeError: Unexpected type of argument/);
});

Expand Down
10 changes: 6 additions & 4 deletions test/function/arithmetic/addScalar.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,8 @@ describe('add', function() {
assert.equal(add(false, false), 0);
});

it('should add numbers and null', function () {
assert.equal(math.add(null, null), 0);
assert.equal(math.add(null, 1), 1);
assert.equal(math.add(1, null), 1);
it('does not support null', function() {
assert.throws(function () {add(null, 0) }, /Unexpected type of argument/);
});

it('should add mixed numbers and booleans', function() {
Expand Down Expand Up @@ -143,6 +141,10 @@ describe('add', function() {
assert.throws(function () {add(1);}, /TypeError: Too few arguments/);
});

it('should throw an error in case of invalid type of arguments', function() {
assert.throws(function () {add(null, 1);}, /TypeError: Unexpected type of argument/);
});

it('should LaTeX add', function () {
var expression = math.parse('add(1,2)');
assert.equal(expression.toTex(), '\\left(1+2\\right)');
Expand Down
8 changes: 4 additions & 4 deletions test/function/arithmetic/cbrt.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@ describe('cbrt', function() {
assert.equal(cbrt(false), 0);
});

it('should return the cubic root of null', function () {
assert.equal(cbrt(null), 0);
});

it('should return the cubic root of a positive number', function() {
assert.equal(cbrt(0), 0);
assert.equal(cbrt(1), 1);
Expand Down Expand Up @@ -128,6 +124,10 @@ describe('cbrt', function() {
assert.throws(function () {cbrt(1, true, 2)}, /TypeError: Too many arguments/);
});

it('should throw an in case of wrong type of arguments', function() {
assert.throws(function () {cbrt(null);}, /TypeError: Unexpected type of argument/);
});

it('should LaTeX cbrt', function () {
var expression = math.parse('cbrt(2)');
assert.equal(expression.toTex(), '\\sqrt[3]{2}');
Expand Down
8 changes: 4 additions & 4 deletions test/function/arithmetic/ceil.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@ describe('ceil', function() {
assert.equal(ceil(false), 0);
});

it('should return the ceil of null', function () {
assert.equal(math.ceil(null), 0);
});

it('should return the ceil of a number', function() {
approx.equal(ceil(0), 0);
approx.equal(ceil(1), 1);
Expand Down Expand Up @@ -90,6 +86,10 @@ describe('ceil', function() {
assert.throws(function () {ceil(1, 2)}, /TypeError: Too many arguments/);
});

it('should throw an in case of wrong type of arguments', function() {
assert.throws(function () {ceil(null);}, /TypeError: Unexpected type of argument/);
});

it('should LaTeX ceil', function () {
var expression = math.parse('ceil(0.5)');
assert.equal(expression.toTex(), '\\left\\lceil0.5\\right\\rceil');
Expand Down
8 changes: 4 additions & 4 deletions test/function/arithmetic/cube.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ describe('cube', function() {
assert.equal(cube(false), 0);
});

it('should return the cube of null', function () {
assert.equal(math.ceil(null), 0);
});

it('should return the cube of a number', function() {
assert.equal(cube(4), 64);
assert.equal(cube(-2), -8);
Expand Down Expand Up @@ -58,6 +54,10 @@ describe('cube', function() {
assert.throws(function () {cube(1, 2)}, /TypeError: Too many arguments/);
});

it('should throw an in case of wrong type of arguments', function() {
assert.throws(function () {cube(null);}, /TypeError: Unexpected type of argument/);
});

it('should cube each element in a matrix, array or range', function() {
// array, matrix, range
// arrays are evaluated element wise
Expand Down
10 changes: 4 additions & 6 deletions test/function/arithmetic/divide.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,6 @@ describe('divide', function() {
assert.ok(isNaN(divide(false, false)));
});

it('should divide numbers and null', function () {
assert.equal(divide(1, null), Infinity);
assert.equal(divide(null, 1), 0);
assert(isNaN(divide(null, null)));
});

it('should divide mixed numbers and booleans', function() {
assert.equal(divide(2, true), 2);
assert.equal(divide(2, false), Infinity);
Expand Down Expand Up @@ -208,6 +202,10 @@ describe('divide', function() {
assert.throws(function () {divide(2); });
});

it('should throw an in case of wrong type of arguments', function() {
assert.throws(function () {divide(null, 2);}, /TypeError: Unexpected type of argument/);
});

it('should LaTeX divide', function () {
var expression = math.parse('divide(1,2)');
assert.equal(expression.toTex(), '\\frac{1}{2}');
Expand Down
9 changes: 4 additions & 5 deletions test/function/arithmetic/dotDivide.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,15 @@ describe('dotDivide', function() {
assert.equal(dotDivide(false, 2), 0);
});

it('should divide numbers and null', function () {
assert.equal(dotDivide(1, null), Infinity);
assert.equal(dotDivide(null, 1), 0);
});

it('should throw an error if there\'s wrong number of arguments', function() {
assert.throws(function () {dotDivide(2,3,4); });
assert.throws(function () {dotDivide(2); });
});

it('should throw an in case of wrong type of arguments', function() {
assert.throws(function () {dotDivide(null, 1);}, /TypeError: Unexpected type of argument/);
});

it('should divide two complex numbers', function() {
approx.deepEqual(dotDivide(complex('2+3i'), 2), complex('1+1.5i'));
approx.deepEqual(dotDivide(complex('2+3i'), complex('4i')), complex('0.75 - 0.5i'));
Expand Down
9 changes: 4 additions & 5 deletions test/function/arithmetic/dotMultiply.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,6 @@ describe('dotMultiply', function() {
assert.equal(dotMultiply(false, 2), 0);
});

it('should multiply numbers and null', function () {
assert.equal(dotMultiply(1, null), 0);
assert.equal(dotMultiply(null, 1), 0);
});

it('should multiply 2 complex numbers', function() {
// complex
approx.deepEqual(dotMultiply(complex(2, 3), 2), complex(4, 6));
Expand All @@ -66,6 +61,10 @@ describe('dotMultiply', function() {
assert.throws(function () {dotMultiply("hello", 2)});
});

it('should throw an in case of wrong type of arguments', function() {
assert.throws(function () {dotMultiply(null, 1);}, /TypeError: Unexpected type of argument/);
});

describe('Array', function () {

var a = [[1,0],[3,4]];
Expand Down
5 changes: 0 additions & 5 deletions test/function/arithmetic/dotPow.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,6 @@ describe('dotPow', function() {
assert.equal(dotPow(false, 2), 0);
});

it('should exponentiate numbers and null', function () {
assert.equal(dotPow(1, null), 1);
assert.equal(dotPow(null, 1), 0);
});

it('should throw an error in case of invalid number of arguments', function() {
assert.throws(function () {dotPow(1);}, /TypeError: Too few arguments/);
assert.throws(function () {dotPow(1, 2, 3);}, /TypeError: Too many arguments/);
Expand Down
Loading

0 comments on commit 4469f6b

Please sign in to comment.