diff --git a/src/expression/embeddedDocs/function/arithmetic/ceil.js b/src/expression/embeddedDocs/function/arithmetic/ceil.js index ae6afb8f52..ef29722167 100644 --- a/src/expression/embeddedDocs/function/arithmetic/ceil.js +++ b/src/expression/embeddedDocs/function/arithmetic/ceil.js @@ -2,14 +2,19 @@ export const ceilDocs = { name: 'ceil', category: 'Arithmetic', syntax: [ - 'ceil(x)' + 'ceil(x)', + 'ceil(x, n)', + 'ceil(unit, valuelessUnit)', + 'ceil(unit, n, valuelessUnit)' ], description: 'Round a value towards plus infinity. If x is complex, both real and imaginary part are rounded towards plus infinity.', examples: [ 'ceil(3.2)', 'ceil(3.8)', - 'ceil(-4.2)' + 'ceil(-4.2)', + 'ceil(3.241cm, cm)', + 'ceil(3.241cm, 2, cm)' ], seealso: ['floor', 'fix', 'round'] } diff --git a/src/expression/embeddedDocs/function/arithmetic/fix.js b/src/expression/embeddedDocs/function/arithmetic/fix.js index eb6302104e..e324fa9c6e 100644 --- a/src/expression/embeddedDocs/function/arithmetic/fix.js +++ b/src/expression/embeddedDocs/function/arithmetic/fix.js @@ -2,7 +2,10 @@ export const fixDocs = { name: 'fix', category: 'Arithmetic', syntax: [ - 'fix(x)' + 'fix(x)', + 'fix(x, n)', + 'fix(unit, valuelessUnit)', + 'fix(unit, n, valuelessUnit)' ], description: 'Round a value towards zero. If x is complex, both real and imaginary part are rounded towards zero.', @@ -10,7 +13,9 @@ export const fixDocs = { 'fix(3.2)', 'fix(3.8)', 'fix(-4.2)', - 'fix(-4.8)' + 'fix(-4.8)', + 'fix(3.241cm, cm)', + 'fix(3.241cm, 2, cm)' ], seealso: ['ceil', 'floor', 'round'] } diff --git a/src/expression/embeddedDocs/function/arithmetic/floor.js b/src/expression/embeddedDocs/function/arithmetic/floor.js index af78e187e7..ce6c55f22e 100644 --- a/src/expression/embeddedDocs/function/arithmetic/floor.js +++ b/src/expression/embeddedDocs/function/arithmetic/floor.js @@ -2,14 +2,19 @@ export const floorDocs = { name: 'floor', category: 'Arithmetic', syntax: [ - 'floor(x)' + 'floor(x)', + 'floor(x, n)', + 'floor(unit, valuelessUnit)', + 'floor(unit, n, valuelessUnit)' ], description: 'Round a value towards minus infinity.If x is complex, both real and imaginary part are rounded towards minus infinity.', examples: [ 'floor(3.2)', 'floor(3.8)', - 'floor(-4.2)' + 'floor(-4.2)', + 'floor(3.241cm, cm)', + 'floor(3.241cm, 2, cm)' ], seealso: ['ceil', 'fix', 'round'] } diff --git a/src/function/arithmetic/ceil.js b/src/function/arithmetic/ceil.js index 4d4c7a0ea1..339f0dce95 100644 --- a/src/function/arithmetic/ceil.js +++ b/src/function/arithmetic/ceil.js @@ -50,6 +50,8 @@ export const createCeil = /* #__PURE__ */ factory(name, dependencies, ({ typed, * * math.ceil(x) * math.ceil(x, n) + * math.ceil(unit, valuelessUnit) + * math.ceil(unit, n, valuelessUnit) * * Examples: * @@ -67,6 +69,12 @@ export const createCeil = /* #__PURE__ */ factory(name, dependencies, ({ typed, * math.ceil(c) // returns Complex 4 - 2i * math.ceil(c, 1) // returns Complex 3.3 - 2.7i * + * const unit = math.unit('3.241 cm') + * const cm = math.unit('cm') + * const mm = math.unit('mm') + * math.ceil(unit, 1, cm) // returns Unit 3.3 cm + * math.ceil(unit, 1, mm) // returns Unit 32.5 mm + * * math.ceil([3.2, 3.8, -4.7]) // returns Array [4, 4, -4] * math.ceil([3.21, 3.82, -4.71], 1) // returns Array [3.3, 3.9, -4.7] * @@ -74,9 +82,10 @@ export const createCeil = /* #__PURE__ */ factory(name, dependencies, ({ typed, * * floor, fix, round * - * @param {number | BigNumber | Fraction | Complex | Array | Matrix} x Number to be rounded + * @param {number | BigNumber | Fraction | Complex | Unit | Array | Matrix} x Value to be rounded * @param {number | BigNumber | Array} [n=0] Number of decimals - * @return {number | BigNumber | Fraction | Complex | Array | Matrix} Rounded value + * @param {Unit} [valuelessUnit] A valueless unit + * @return {number | BigNumber | Fraction | Complex | Unit | Array | Matrix} Rounded value */ return typed('ceil', { number: ceilNumber.signatures.number, @@ -122,6 +131,20 @@ export const createCeil = /* #__PURE__ */ factory(name, dependencies, ({ typed, return x.ceil(n.toNumber()) }, + 'Unit, number, Unit': typed.referToSelf(self => function (x, n, unit) { + const valueless = x.toNumeric(unit) + return unit.multiply(self(valueless, n)) + }), + + 'Unit, BigNumber, Unit': typed.referToSelf(self => (x, n, unit) => self(x, n.toNumber(), unit)), + + 'Array | Matrix, number | BigNumber, Unit': typed.referToSelf(self => (x, n, unit) => { + // deep map collection, skip zeros since ceil(0) = 0 + return deepMap(x, (value) => self(value, n, unit), true) + }), + + 'Array | Matrix | Unit, Unit': typed.referToSelf(self => (x, unit) => self(x, 0, unit)), + 'Array | Matrix': typed.referToSelf(self => (x) => { // deep map collection, skip zeros since ceil(0) = 0 return deepMap(x, self, true) diff --git a/src/function/arithmetic/fix.js b/src/function/arithmetic/fix.js index f0e8a39aaa..90f59ea80b 100644 --- a/src/function/arithmetic/fix.js +++ b/src/function/arithmetic/fix.js @@ -33,6 +33,8 @@ export const createFix = /* #__PURE__ */ factory(name, dependencies, ({ typed, C * * math.fix(x) * math.fix(x,n) + * math.fix(unit, valuelessUnit) + * math.fix(unit, n, valuelessUnit) * * Examples: * @@ -50,6 +52,12 @@ export const createFix = /* #__PURE__ */ factory(name, dependencies, ({ typed, C * math.fix(c) // returns Complex 3 - 2i * math.fix(c, 1) // returns Complex 3.2 -2.7i * + * const unit = math.unit('3.241 cm') + * const cm = math.unit('cm') + * const mm = math.unit('mm') + * math.fix(unit, 1, cm) // returns Unit 3.2 cm + * math.fix(unit, 1, mm) // returns Unit 32.4 mm + * * math.fix([3.2, 3.8, -4.7]) // returns Array [3, 3, -4] * math.fix([3.2, 3.8, -4.7], 1) // returns Array [3.2, 3.8, -4.7] * @@ -57,9 +65,10 @@ export const createFix = /* #__PURE__ */ factory(name, dependencies, ({ typed, C * * ceil, floor, round * - * @param {number | BigNumber | Fraction | Complex | Array | Matrix} x Number to be rounded - * @param {number | BigNumber | Array} [n=0] Number of decimals - * @return {number | BigNumber | Fraction | Complex | Array | Matrix} Rounded value + * @param {number | BigNumber | Fraction | Complex | Unit | Array | Matrix} x Value to be rounded + * @param {number | BigNumber | Array} [n=0] Number of decimals + * @param {Unit} [valuelessUnit] A valueless unit + * @return {number | BigNumber | Fraction | Complex | Unit | Array | Matrix} Rounded value */ return typed('fix', { number: fixNumber.signatures.number, @@ -103,6 +112,20 @@ export const createFix = /* #__PURE__ */ factory(name, dependencies, ({ typed, C return x.s < 0 ? ceil(x, n) : floor(x, n) }, + 'Unit, number, Unit': typed.referToSelf(self => function (x, n, unit) { + const valueless = x.toNumeric(unit) + return unit.multiply(self(valueless, n)) + }), + + 'Unit, BigNumber, Unit': typed.referToSelf(self => (x, n, unit) => self(x, n.toNumber(), unit)), + + 'Array | Matrix, number | BigNumber, Unit': typed.referToSelf(self => (x, n, unit) => { + // deep map collection, skip zeros since fix(0) = 0 + return deepMap(x, (value) => self(value, n, unit), true) + }), + + 'Array | Matrix | Unit, Unit': typed.referToSelf(self => (x, unit) => self(x, 0, unit)), + 'Array | Matrix': typed.referToSelf(self => (x) => { // deep map collection, skip zeros since fix(0) = 0 return deepMap(x, self, true) diff --git a/src/function/arithmetic/floor.js b/src/function/arithmetic/floor.js index 4129d5561b..449111df7c 100644 --- a/src/function/arithmetic/floor.js +++ b/src/function/arithmetic/floor.js @@ -49,6 +49,8 @@ export const createFloor = /* #__PURE__ */ factory(name, dependencies, ({ typed, * * math.floor(x) * math.floor(x, n) + * math.floor(unit, valuelessUnit) + * math.floor(unit, n, valuelessUnit) * * Examples: * @@ -66,6 +68,12 @@ export const createFloor = /* #__PURE__ */ factory(name, dependencies, ({ typed, * math.floor(c) // returns Complex 3 - 3i * math.floor(c, 1) // returns Complex 3.2 -2.8i * + * const unit = math.unit('3.241 cm') + * const cm = math.unit('cm') + * const mm = math.unit('mm') + * math.floor(unit, 1, cm) // returns Unit 3.2 cm + * math.floor(unit, 1, mm) // returns Unit 32.4 mm + * * math.floor([3.2, 3.8, -4.7]) // returns Array [3, 3, -5] * math.floor([3.21, 3.82, -4.71], 1) // returns Array [3.2, 3.8, -4.8] * @@ -77,9 +85,10 @@ export const createFloor = /* #__PURE__ */ factory(name, dependencies, ({ typed, * * ceil, fix, round * - * @param {number | BigNumber | Fraction | Complex | Array | Matrix} x Number to be rounded + * @param {number | BigNumber | Fraction | Complex | Unit | Array | Matrix} x Value to be rounded * @param {number | BigNumber | Array} [n=0] Number of decimals - * @return {number | BigNumber | Fraction | Complex | Array | Matrix} Rounded value + * @param {Unit} [valuelessUnit] A valueless unit + * @return {number | BigNumber | Fraction | Complex | Unit | Array | Matrix} Rounded value */ return typed('floor', { number: floorNumber.signatures.number, @@ -125,6 +134,20 @@ export const createFloor = /* #__PURE__ */ factory(name, dependencies, ({ typed, return x.floor(n.toNumber()) }, + 'Unit, number, Unit': typed.referToSelf(self => function (x, n, unit) { + const valueless = x.toNumeric(unit) + return unit.multiply(self(valueless, n)) + }), + + 'Unit, BigNumber, Unit': typed.referToSelf(self => (x, n, unit) => self(x, n.toNumber(), unit)), + + 'Array | Matrix, number | BigNumber, Unit': typed.referToSelf(self => (x, n, unit) => { + // deep map collection, skip zeros since floor(0) = 0 + return deepMap(x, (value) => self(value, n, unit), true) + }), + + 'Array | Matrix | Unit, Unit': typed.referToSelf(self => (x, unit) => self(x, 0, unit)), + 'Array | Matrix': typed.referToSelf(self => (x) => { // deep map collection, skip zeros since floor(0) = 0 return deepMap(x, self, true) diff --git a/src/function/arithmetic/round.js b/src/function/arithmetic/round.js index 7e585fb5af..1f48fa13e7 100644 --- a/src/function/arithmetic/round.js +++ b/src/function/arithmetic/round.js @@ -71,7 +71,7 @@ export const createRound = /* #__PURE__ */ factory(name, dependencies, ({ typed, * @param {number | BigNumber | Fraction | Complex | Unit | Array | Matrix} x Value to be rounded * @param {number | BigNumber | Array} [n=0] Number of decimals * @param {Unit} [valuelessUnit] A valueless unit - * @return {number | BigNumber | Fraction | Complex | Array | Matrix} Rounded value + * @return {number | BigNumber | Fraction | Complex | Unit | Array | Matrix} Rounded value */ return typed(name, { number: function (x) { @@ -154,16 +154,12 @@ export const createRound = /* #__PURE__ */ factory(name, dependencies, ({ typed, 'Unit, BigNumber, Unit': typed.referToSelf(self => (x, n, unit) => self(x, n.toNumber(), unit)), - 'Unit, Unit': typed.referToSelf(self => (x, unit) => self(x, 0, unit)), - - 'Array | Matrix, number, Unit': typed.referToSelf(self => (x, n, unit) => { + 'Array | Matrix, number | BigNumber, Unit': typed.referToSelf(self => (x, n, unit) => { // deep map collection, skip zeros since round(0) = 0 return deepMap(x, (value) => self(value, n, unit), true) }), - 'Array | Matrix, BigNumber, Unit': typed.referToSelf(self => (x, n, unit) => self(x, n.toNumber(), unit)), - - 'Array | Matrix, Unit': typed.referToSelf(self => (x, unit) => self(x, 0, unit)), + 'Array | Matrix | Unit, Unit': typed.referToSelf(self => (x, unit) => self(x, 0, unit)), 'Array | Matrix': typed.referToSelf(self => x => { // deep map collection, skip zeros since round(0) = 0 diff --git a/test/typescript-tests/testTypes.ts b/test/typescript-tests/testTypes.ts index 735ac1148b..acce2c029e 100644 --- a/test/typescript-tests/testTypes.ts +++ b/test/typescript-tests/testTypes.ts @@ -1,3 +1,5 @@ +import * as assert from 'assert' +import { expectTypeOf } from 'expect-type' import { AccessorNode, addDependencies, @@ -21,15 +23,19 @@ import { Help, Index, IndexNode, + isSymbolNode, LUDecomposition, MathArray, MathCollection, MathJsChain, MathJsFunctionName, MathNode, + MathNodeCommon, MathNumericType, + MathScalarType, MathType, Matrix, + Node, ObjectNode, OperatorNode, OperatorNodeFn, @@ -41,15 +47,9 @@ import { SimplifyRule, SLUDecomposition, SymbolNode, - MathNodeCommon, Unit, - UnitPrefix, - Node, - isSymbolNode, - MathScalarType + UnitPrefix } from 'mathjs' -import * as assert from 'assert' -import { expectTypeOf } from 'expect-type' // This file serves a dual purpose: // 1) examples of how to use math.js in TypeScript @@ -649,6 +649,9 @@ Chaining examples expectTypeOf(math.chain([1]).ceil()).toMatchTypeOf< MathJsChain >() + expectTypeOf( + math.chain(math.unit('5.2cm')).ceil(math.unit('cm')) + ).toMatchTypeOf>() // fix expectTypeOf(math.chain(1).fix()).toMatchTypeOf< @@ -657,6 +660,9 @@ Chaining examples expectTypeOf(math.chain([1]).fix()).toMatchTypeOf< MathJsChain >() + expectTypeOf( + math.chain(math.unit('5.2cm')).fix(math.unit('cm')) + ).toMatchTypeOf>() // floor expectTypeOf(math.chain(1).floor()).toMatchTypeOf< @@ -665,6 +671,12 @@ Chaining examples expectTypeOf(math.chain([1]).floor()).toMatchTypeOf< MathJsChain >() + expectTypeOf( + math.chain(math.unit('5.2cm')).floor(math.unit('cm')) + ).toMatchTypeOf>() + expectTypeOf( + math.chain(math.unit('5.2cm')).round(2, math.unit('cm')) + ).toMatchTypeOf>() // round expectTypeOf(math.chain(1).round()).toMatchTypeOf< @@ -1450,6 +1462,9 @@ Math types examples: Type results after multiplying 'MathTypes' with matrices [5, 6, 7, 8] ] + const cde: MathArray = [1] + const def: MathArray = [2] + const Mbcd = math.matrix(bcd) const Mabc = math.matrix(abc) @@ -1462,6 +1477,7 @@ Math types examples: Type results after multiplying 'MathTypes' with matrices const _r2 = math.multiply(a, b) // 1D JS Array + const _r12 = math.multiply(cde, def) // equal 2 const r3 = math.multiply(abc, bcd) const _r31 = r3[1] // By default least promised valid syntax @@ -1777,6 +1793,54 @@ Function ceil examples math.complex(3.3, -2.7) ) + // unit input + const u1 = math.unit(3.2, 'cm') + const u2 = math.unit('cm') + const u3 = math.unit(5.51, 'cm') + + // unit array input + const unitArray: MathArray = [u1, u3] + const array = [u1, u3, 1] + array.pop() + const array2 = [ + [u1, u3], + [1, 5] + ] + array2.pop() + + assert.deepStrictEqual(math.ceil(u1, u2), math.unit(4, 'cm')) + assert.deepStrictEqual(math.ceil(u1, 1, u2), math.unit(3.2, 'cm')) + assert.deepStrictEqual(math.ceil(unitArray, 1, math.unit('cm')), [ + math.unit(3.2, 'cm'), + math.unit(5.6, 'cm') + ]) + + // Can assert that the array is a Unit[] + assert.deepStrictEqual(math.ceil(array as Unit[], 1, math.unit('cm')), [ + math.unit(3.2, 'cm'), + math.unit(5.6, 'cm') + ]) + + // Can assert that the array is a Unit[][] + assert.deepStrictEqual(math.ceil(array2 as Unit[][], 1, math.unit('cm')), [ + [math.unit(3.2, 'cm'), math.unit(5.6, 'cm')] + ]) + + // unit matrix input + const unitMatrix = math.matrix(unitArray) + const matrix = math.matrix([u1, u3]) + + assert.deepStrictEqual( + math.ceil(unitMatrix, 1, math.unit('cm')), + math.matrix([math.unit(3.2, 'cm'), math.unit(5.6, 'cm')]) + ) + + // Can assert that the matrix is a Matrix + assert.deepStrictEqual( + math.ceil(matrix as Matrix, 1, math.unit('cm')), + math.matrix([math.unit(3.2, 'cm'), math.unit(5.6, 'cm')]) + ) + // array input assert.deepStrictEqual(math.ceil([3.2, 3.8, -4.7]), [4, 4, -4]) assert.deepStrictEqual(math.ceil([3.21, 3.82, -4.71], 1), [3.3, 3.9, -4.7]) @@ -1853,6 +1917,23 @@ Function fix examples math.complex(3.2, -2.7) ) + // unit input + const u1 = math.unit(3.2, 'cm') + const u2 = math.unit('cm') + const u3 = math.unit(5.51, 'cm') + const unitArray = [u1, u3] + const unitMatrix = math.matrix(unitArray) + assert.deepStrictEqual(math.fix(u1, u2), math.unit(3, 'cm')) + assert.deepStrictEqual(math.fix(u1, 1, u2), math.unit(3.2, 'cm')) + assert.deepStrictEqual(math.fix(unitArray, 1, math.unit('cm')), [ + math.unit(3.2, 'cm'), + math.unit(5.5, 'cm') + ]) + assert.deepStrictEqual( + math.fix(unitMatrix, 1, math.unit('cm')), + math.matrix([math.unit(3.2, 'cm'), math.unit(5.5, 'cm')]) + ) + // array input assert.deepStrictEqual(math.fix([3.2, 3.8, -4.7]), [3, 3, -4]) assert.deepStrictEqual(math.fix([3.21, 3.82, -4.71], 1), [3.2, 3.8, -4.7]) @@ -1929,6 +2010,23 @@ Function floor examples math.complex(3.2, -2.8) ) + // unit input + const u1 = math.unit(3.2, 'cm') + const u2 = math.unit('cm') + const u3 = math.unit(5.51, 'cm') + const unitArray = [u1, u3] + const unitMatrix = math.matrix(unitArray) + assert.deepStrictEqual(math.floor(u1, u2), math.unit(3, 'cm')) + assert.deepStrictEqual(math.floor(u1, 1, u2), math.unit(3.2, 'cm')) + assert.deepStrictEqual(math.floor(unitArray, 1, math.unit('cm')), [ + math.unit(3.2, 'cm'), + math.unit(5.5, 'cm') + ]) + assert.deepStrictEqual( + math.floor(unitMatrix, 1, math.unit('cm')), + math.matrix([math.unit(3.2, 'cm'), math.unit(5.5, 'cm')]) + ) + // array input assert.deepStrictEqual(math.floor([3.2, 3.8, -4.7]), [3, 3, -5]) assert.deepStrictEqual(math.floor([3.21, 3.82, -4.71], 1), [3.2, 3.8, -4.8]) @@ -2006,13 +2104,28 @@ Function round examples ) // unit input + const u1 = math.unit(3.2, 'cm') + const u2 = math.unit('cm') + const u3 = math.unit(5.51, 'cm') + const unitArray = [u1, u3] + const unitMatrix = math.matrix(unitArray) + assert.deepStrictEqual(math.round(u1, u2), math.unit(3, 'cm')) + assert.deepStrictEqual(math.round(u1, 1, u2), math.unit(3.2, 'cm')) + assert.deepStrictEqual( + math.round(u1, math.bignumber(1), u2), + math.unit(3.2, 'cm') + ) + assert.deepStrictEqual(math.round(unitArray, 1, math.unit('cm')), [ + math.unit(3.2, 'cm'), + math.unit(5.5, 'cm') + ]) assert.deepStrictEqual( - math.round(math.unit('5.21 cm'), math.unit('cm')), - math.unit('5 cm') + math.round(unitArray, math.bignumber(1), math.unit('cm')), + [math.unit(3.2, 'cm'), math.unit(5.5, 'cm')] ) assert.deepStrictEqual( - math.round(math.unit('5.21 cm'), 1, math.unit('cm')), - math.unit('5.2 cm') + math.round(unitMatrix, 1, math.unit('cm')), + math.matrix([math.unit(3.2, 'cm'), math.unit(5.5, 'cm')]) ) // array input diff --git a/test/unit-tests/function/arithmetic/ceil.test.js b/test/unit-tests/function/arithmetic/ceil.test.js index e4a40508a2..b9315d29cd 100644 --- a/test/unit-tests/function/arithmetic/ceil.test.js +++ b/test/unit-tests/function/arithmetic/ceil.test.js @@ -148,6 +148,34 @@ describe('ceil', function () { assert.deepStrictEqual(ceil(bignumber(-799999.9999999999)), bignumber(-800000)) }) + it('should ceil units', function () { + assert.deepStrictEqual(ceil(unit('5.01 inch'), unit('inch')), unit('6 inch')) + assert.deepStrictEqual(ceil(unit('3.12345 cm'), 3, unit('cm')), unit('3.124 cm')) + assert.deepStrictEqual(ceil(unit('3.12345 cm'), unit('cm')), unit('4 cm')) + assert.deepStrictEqual(ceil(unit('2 inch'), unit('cm')), unit('6 cm')) + assert.deepStrictEqual(ceil(unit('2 inch'), 1, unit('cm')), unit('5.1 cm')) + + // bignumber values + assert.deepStrictEqual(ceil(unit('3.12345 cm'), bignumber(2), unit('cm')), unit('3.13 cm')) + assert.deepStrictEqual(ceil(unit(bignumber('2'), 'inch'), unit('cm')), unit(bignumber('6'), 'cm')) + assert.deepStrictEqual(ceil(unit(bignumber('2'), 'inch'), bignumber(1), unit('cm')), unit(bignumber('5.1'), 'cm')) + + // first argument is a collection + assert.deepStrictEqual(ceil([unit('2 inch'), unit('3 inch')], unit('cm')), [unit('6 cm'), unit('8 cm')]) + assert.deepStrictEqual(ceil(matrix([unit('2 inch'), unit('3 inch')]), unit('cm')), matrix([unit('6 cm'), unit('8 cm')])) + }) + + it('should throw an error if used with a unit without valueless unit', function () { + assert.throws(function () { ceil(unit('5cm')) }, TypeError, 'Function ceil(unit) not supported') + assert.throws(function () { ceil(unit('5cm'), 2) }, TypeError, 'Function ceil(unit) not supported') + assert.throws(function () { ceil(unit('5cm'), bignumber(2)) }, TypeError, 'Function ceil(unit) not supported') + }) + + it('should throw an error if used with a unit with a second unit that is not valueless', function () { + assert.throws(function () { ceil(unit('2 inch'), 1, unit('10 cm')) }, Error) + assert.throws(function () { ceil(unit('2 inch'), unit('10 cm')) }, Error) + }) + it('should throw an error for units', function () { assert.throws(function () { ceil(unit('5cm')) }, TypeError, 'Function ceil(unit) not supported') }) diff --git a/test/unit-tests/function/arithmetic/fix.test.js b/test/unit-tests/function/arithmetic/fix.test.js index 821123cc6b..74cf373a34 100644 --- a/test/unit-tests/function/arithmetic/fix.test.js +++ b/test/unit-tests/function/arithmetic/fix.test.js @@ -173,6 +173,39 @@ describe('fix', function () { assert.strictEqual(fix(-799999.9999999999, 3), -800000) }) + it('should fix units', function () { + assert.deepStrictEqual(fix(unit('5.99 inch'), unit('inch')), unit('5 inch')) + assert.deepStrictEqual(fix(unit('3.12345 cm'), 3, unit('cm')), unit('3.123 cm')) + assert.deepStrictEqual(fix(unit('3.12345 cm'), unit('cm')), unit('3 cm')) + assert.deepStrictEqual(fix(unit('2 inch'), unit('cm')), unit('5 cm')) + assert.deepStrictEqual(fix(unit('2 inch'), 1, unit('cm')), unit('5 cm')) + assert.deepStrictEqual(fix(unit('-1.9 inch'), unit('cm')), unit('-4 cm')) + + // bignumber values + assert.deepStrictEqual(fix(unit('3.12345 cm'), bignumber(2), unit('cm')), unit('3.12 cm')) + assert.deepStrictEqual(fix(unit(bignumber('2'), 'inch'), unit('cm')), unit(bignumber('5'), 'cm')) + assert.deepStrictEqual(fix(unit(bignumber('2'), 'inch'), bignumber(1), unit('cm')), unit(bignumber('5.0'), 'cm')) + + // first argument is a collection + assert.deepStrictEqual(fix([unit('2 inch'), unit('3 inch')], unit('cm')), [unit('5 cm'), unit('7 cm')]) + assert.deepStrictEqual(fix(matrix([unit('2 inch'), unit('3 inch')]), unit('cm')), matrix([unit('5 cm'), unit('7 cm')])) + }) + + it('should throw an error if used with a unit without valueless unit', function () { + assert.throws(function () { fix(unit('5cm')) }, TypeError, 'Function fix(unit) not supported') + assert.throws(function () { fix(unit('5cm'), 2) }, TypeError, 'Function fix(unit) not supported') + assert.throws(function () { fix(unit('5cm'), bignumber(2)) }, TypeError, 'Function fix(unit) not supported') + }) + + it('should throw an error if used with a unit with a second unit that is not valueless', function () { + assert.throws(function () { fix(unit('2 inch'), 1, unit('10 cm')) }, Error) + assert.throws(function () { fix(unit('2 inch'), unit('10 cm')) }, Error) + }) + + it('should throw an error with a unit', function () { + assert.throws(function () { fix(unit('5cm')) }, TypeError, 'Function fix(unit) not supported') + }) + it('should throw an error on unit as parameter', function () { // unit assert.throws(function () { fix(unit('5cm')) }, TypeError, 'Function fix(unit) not supported') diff --git a/test/unit-tests/function/arithmetic/floor.test.js b/test/unit-tests/function/arithmetic/floor.test.js index 36ec8763fa..a8acc77f8b 100644 --- a/test/unit-tests/function/arithmetic/floor.test.js +++ b/test/unit-tests/function/arithmetic/floor.test.js @@ -12,7 +12,7 @@ const i = math.i const sparse = math.sparse describe('floor', function () { - it('should round booleans correctly', function () { + it('should floor booleans correctly', function () { assert.strictEqual(floor(true), 1) assert.strictEqual(floor(false), 0) }) @@ -148,6 +148,34 @@ describe('floor', function () { assert.deepStrictEqual(floor(bignumber(-30000.000000000004)), bignumber(-30000)) }) + it('should floor units', function () { + assert.deepStrictEqual(floor(unit('5.99 inch'), unit('inch')), unit('5 inch')) + assert.deepStrictEqual(floor(unit('3.12345 cm'), 3, unit('cm')), unit('3.123 cm')) + assert.deepStrictEqual(floor(unit('3.12345 cm'), unit('cm')), unit('3 cm')) + assert.deepStrictEqual(floor(unit('2 inch'), unit('cm')), unit('5 cm')) + assert.deepStrictEqual(floor(unit('2 inch'), 1, unit('cm')), unit('5 cm')) + + // bignumber values + assert.deepStrictEqual(floor(unit('3.12345 cm'), bignumber(2), unit('cm')), unit('3.12 cm')) + assert.deepStrictEqual(floor(unit(bignumber('2'), 'inch'), unit('cm')), unit(bignumber('5'), 'cm')) + assert.deepStrictEqual(floor(unit(bignumber('2'), 'inch'), bignumber(1), unit('cm')), unit(bignumber('5.0'), 'cm')) + + // first argument is a collection + assert.deepStrictEqual(floor([unit('2 inch'), unit('3 inch')], unit('cm')), [unit('5 cm'), unit('7 cm')]) + assert.deepStrictEqual(floor(matrix([unit('2 inch'), unit('3 inch')]), unit('cm')), matrix([unit('5 cm'), unit('7 cm')])) + }) + + it('should throw an error if used with a unit without valueless unit', function () { + assert.throws(function () { floor(unit('5cm')) }, TypeError, 'Function floor(unit) not supported') + assert.throws(function () { floor(unit('5cm'), 2) }, TypeError, 'Function floor(unit) not supported') + assert.throws(function () { floor(unit('5cm'), bignumber(2)) }, TypeError, 'Function floor(unit) not supported') + }) + + it('should throw an error if used with a unit with a second unit that is not valueless', function () { + assert.throws(function () { floor(unit('2 inch'), 1, unit('10 cm')) }, Error) + assert.throws(function () { floor(unit('2 inch'), unit('10 cm')) }, Error) + }) + it('should throw an error with a unit', function () { assert.throws(function () { floor(unit('5cm')) }, TypeError, 'Function floor(unit) not supported') }) @@ -226,9 +254,9 @@ describe('floor', function () { }) it('should throw an error if requested number of decimals is incorrect', function () { - assert.throws(function () { floor(2.5, 1.5) }, Error, 'Number of decimals in function round must be an integer') - assert.throws(function () { floor(2.5, -2) }, Error, ' Number of decimals in function round must be in the range of 0-15') - assert.throws(function () { floor(2.5, Infinity) }, Error, ' Number of decimals in function round must be in the range of 0-15') + assert.throws(function () { floor(2.5, 1.5) }, Error, 'Number of decimals in function floor must be an integer') + assert.throws(function () { floor(2.5, -2) }, Error, ' Number of decimals in function floor must be in the range of 0-15') + assert.throws(function () { floor(2.5, Infinity) }, Error, ' Number of decimals in function floor must be in the range of 0-15') }) it('should LaTeX floor', function () { diff --git a/types/index.d.ts b/types/index.d.ts index 16f4d16192..1e1ff5fc24 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -10,11 +10,11 @@ export type NoLiteralType = T extends number ? boolean : T -// TODO: introduce generics for MathCollection, MathMatrix, and MathArray export type MathNumericType = number | BigNumber | bigint | Fraction | Complex export type MathScalarType = MathNumericType | Unit -export type MathArray = MathNumericType[] | MathNumericType[][] // TODO: MathArray can also contain Unit -export type MathCollection = MathArray | Matrix +export type MathGeneric = T +export type MathArray = T[] | T[][] +export type MathCollection = MathArray | Matrix export type MathType = MathScalarType | MathCollection export type MathExpression = string | string[] | MathCollection @@ -751,6 +751,11 @@ export interface MathJsInstance extends MathJsFactory { format?: 'sparse' | 'dense', dataType?: string ): Matrix + matrix( + data: MathCollection, + format?: 'sparse' | 'dense', + dataType?: string + ): Matrix /** * Create a number or convert a string, boolean, or unit to a number. @@ -1147,6 +1152,14 @@ export interface MathJsInstance extends MathJsFactory { n?: number | BigNumber ): NoLiteralType ceil(x: MathNumericType, n: U): U + ceil>(x: U, unit: Unit): U + ceil(x: Unit, unit: Unit): Unit + ceil(x: Unit, n: number | BigNumber, unit: Unit): Unit + ceil>( + x: U, + n: number | BigNumber, + unit: Unit + ): U /** * Round a value towards zero. For matrices, the function is evaluated @@ -1160,6 +1173,14 @@ export interface MathJsInstance extends MathJsFactory { n?: number | BigNumber ): NoLiteralType fix(x: MathNumericType, n: U): U + fix>(x: U, unit: Unit): U + fix(x: Unit, unit: Unit): Unit + fix(x: Unit, n: number | BigNumber, unit: Unit): Unit + fix>( + x: U, + n: number | BigNumber, + unit: Unit + ): U /** * Round a value towards minus infinity. For matrices, the function is @@ -1173,6 +1194,14 @@ export interface MathJsInstance extends MathJsFactory { n?: number | BigNumber ): NoLiteralType floor(x: MathNumericType, n: U): U + floor>(x: U, unit: Unit): U + floor(x: Unit, unit: Unit): Unit + floor(x: Unit, n: number | BigNumber, unit: Unit): Unit + floor>( + x: U, + n: number | BigNumber, + unit: Unit + ): U /** * Round a value towards the nearest integer. For matrices, the function @@ -1186,10 +1215,14 @@ export interface MathJsInstance extends MathJsFactory { n?: number | BigNumber ): NoLiteralType round(x: MathNumericType, n: U): U - round(x: U, unit: Unit): U + round>(x: U, unit: Unit): U round(x: Unit, unit: Unit): Unit round(x: Unit, n: number | BigNumber, unit: Unit): Unit - round(x: U, n: number | BigNumber, unit: Unit): U + round>( + x: U, + n: number | BigNumber, + unit: Unit + ): U // End of group of rounding functions @@ -1361,7 +1394,7 @@ export interface MathJsInstance extends MathJsFactory { multiply(x: T, y: T[]): T multiply(x: T[], y: T): T - multiply(x: T, y: T): T + multiply>(x: T, y: T): T multiply(x: Unit, y: Unit): Unit multiply(x: number, y: number): number multiply(x: MathType, y: MathType): MathType @@ -3965,7 +3998,7 @@ export const { varianceTransformDependencies }: Record -export interface Matrix { +export interface Matrix { type: string storage(): string datatype(): string @@ -3982,7 +4015,7 @@ export interface Matrix { // eslint-disable-next-line @typescript-eslint/no-explicit-any set(index: number[], value: any, defaultValue?: number | string): Matrix resize(size: MathCollection, defaultValue?: number | string): Matrix - clone(): Matrix + clone(): Matrix size(): number[] map( // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -3994,8 +4027,8 @@ export interface Matrix { callback: (a: any, b: number[], c: Matrix) => void, skipZeros?: boolean ): void - toArray(): MathArray - valueOf(): MathArray + toArray(): MathArray + valueOf(): MathArray format( // eslint-disable-next-line @typescript-eslint/no-explicit-any options?: FormatOptions | number | BigNumber | ((value: any) => string) @@ -4005,7 +4038,7 @@ export interface Matrix { toJSON(): any // eslint-disable-next-line @typescript-eslint/no-explicit-any diagonal(k?: number | BigNumber): any[] - swapRows(i: number, j: number): Matrix + swapRows(i: number, j: number): Matrix } export interface MatrixCtor { @@ -4995,6 +5028,25 @@ export interface MathJsChain { this: MathJsChain, n?: number | BigNumber | MathCollection ): MathJsChain + ceil( + this: MathJsChain, + n: U + ): MathJsChain + ceil(this: MathJsChain, unit: Unit): MathJsChain + ceil>( + this: MathJsChain, + unit: Unit + ): MathJsChain + ceil( + this: MathJsChain, + n: number | BigNumber, + unit: Unit + ): MathJsChain + ceil>( + this: MathJsChain, + n: number | BigNumber, + unit: Unit + ): MathJsChain /** * Round a value towards zero. For matrices, the function is evaluated @@ -5005,6 +5057,25 @@ export interface MathJsChain { this: MathJsChain, n?: number | BigNumber | MathCollection ): MathJsChain + fix( + this: MathJsChain, + n: U + ): MathJsChain + fix(this: MathJsChain, unit: Unit): MathJsChain + fix>( + this: MathJsChain, + unit: Unit + ): MathJsChain + fix( + this: MathJsChain, + n: number | BigNumber, + unit: Unit + ): MathJsChain + fix>( + this: MathJsChain, + n: number | BigNumber, + unit: Unit + ): MathJsChain /** * Round a value towards minus infinity. For matrices, the function is @@ -5015,6 +5086,25 @@ export interface MathJsChain { this: MathJsChain, n?: number | BigNumber | MathCollection ): MathJsChain + floor( + this: MathJsChain, + n: U + ): MathJsChain + floor(this: MathJsChain, unit: Unit): MathJsChain + floor>( + this: MathJsChain, + unit: Unit + ): MathJsChain + floor( + this: MathJsChain, + n: number | BigNumber, + unit: Unit + ): MathJsChain + floor>( + this: MathJsChain, + n: number | BigNumber, + unit: Unit + ): MathJsChain /** * Round a value towards the nearest integer. For matrices, the function @@ -5030,7 +5120,7 @@ export interface MathJsChain { n: U ): MathJsChain round(this: MathJsChain, unit: Unit): MathJsChain - round( + round>( this: MathJsChain, unit: Unit ): MathJsChain @@ -5039,7 +5129,7 @@ export interface MathJsChain { n: number | BigNumber, unit: Unit ): MathJsChain - round( + round>( this: MathJsChain, n: number | BigNumber, unit: Unit