From 6ec26219b1b79d81ba0f3b742994daaa73a79864 Mon Sep 17 00:00:00 2001 From: Brooks Smith Date: Sun, 5 Nov 2023 23:52:39 +1100 Subject: [PATCH 1/9] If fn has rawArgs set, pass unevaluated args --- src/expression/node/OperatorNode.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/expression/node/OperatorNode.js b/src/expression/node/OperatorNode.js index 21eeeb744c..39b09d4ec3 100644 --- a/src/expression/node/OperatorNode.js +++ b/src/expression/node/OperatorNode.js @@ -5,6 +5,7 @@ import { getSafeProperty, isSafeMethod } from '../../utils/customs.js' import { getAssociativity, getPrecedence, isAssociativeWith, properties } from '../operators.js' import { latexOperators } from '../../utils/latex.js' import { factory } from '../../utils/factory.js' +import { createSubScope } from '../../utils/scope.js' const name = 'OperatorNode' const dependencies = [ @@ -304,7 +305,14 @@ export const createOperatorNode = /* #__PURE__ */ factory(name, dependencies, ({ return arg._compile(math, argNames) }) - if (evalArgs.length === 1) { + if (typeof fn === 'function' && fn.rawArgs === true) { + // pass unevaluated parameters (nodes) to the function + // "raw" evaluation + const rawArgs = this.args + return function evalOperatorNode (scope, args, context) { + return fn(rawArgs, math, createSubScope(scope, args), scope) + } + } else if (evalArgs.length === 1) { const evalArg0 = evalArgs[0] return function evalOperatorNode (scope, args, context) { return fn(evalArg0(scope, args, context)) From 736986a677219c7da732cda28a851edeeccbaba1 Mon Sep 17 00:00:00 2001 From: Brooks Smith Date: Sun, 5 Nov 2023 23:53:42 +1100 Subject: [PATCH 2/9] Add shared helper function for evaluating truthiness --- .../transform/utils/testCondition.js | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/expression/transform/utils/testCondition.js diff --git a/src/expression/transform/utils/testCondition.js b/src/expression/transform/utils/testCondition.js new file mode 100644 index 0000000000..d6ff1576a1 --- /dev/null +++ b/src/expression/transform/utils/testCondition.js @@ -0,0 +1,31 @@ +import { isBigNumber, isComplex, isUnit } from '../../../utils/is.js' + +/** + * Test the truthiness of a scalar condition + * @param {number, boolean, BigNumber, Complex, Unit} condition + * @returns {boolean} Returns the truthiness of the condition + */ +export function testCondition (condition) { + if (typeof condition === 'number' || + typeof condition === 'boolean') { + return !!condition + } + if (condition === null || condition === undefined) { + return false + } + if (isBigNumber(condition)) { + return !condition.isZero() + } + + if (isComplex(condition)) { + return !!((condition.re || condition.im)) + } + + if (isUnit(condition)) { + return !!condition.value + } + + if (condition === null || condition === undefined) { + return false + } +} From 11f1e2357ac91a8b65753438578675ff98858093 Mon Sep 17 00:00:00 2001 From: Brooks Smith Date: Sun, 5 Nov 2023 23:55:00 +1100 Subject: [PATCH 3/9] Add and & or transform functions for lazy evaluation --- src/expression/transform/and.transform.js | 26 +++++++++++++++++++++++ src/expression/transform/or.transform.js | 26 +++++++++++++++++++++++ src/factoriesAny.js | 2 ++ 3 files changed, 54 insertions(+) create mode 100644 src/expression/transform/and.transform.js create mode 100644 src/expression/transform/or.transform.js diff --git a/src/expression/transform/and.transform.js b/src/expression/transform/and.transform.js new file mode 100644 index 0000000000..9ab6c86f11 --- /dev/null +++ b/src/expression/transform/and.transform.js @@ -0,0 +1,26 @@ +import { createAnd } from '../../function/logical/and.js' +import { factory } from '../../utils/factory.js' +import { testCondition } from './utils/testCondition.js' +import { isBigNumber, isBoolean, isComplex, isNode, isNumber, isUnit } from '../../utils/is.js' + +const name = 'and' +const dependencies = ['typed', 'matrix', 'zeros', 'add', 'equalScalar', 'not', 'concat'] + +export const createAndTransform = /* #__PURE__ */ factory(name, dependencies, ({ typed, matrix, equalScalar, zeros, not, concat }) => { + const and = createAnd({ typed, matrix, equalScalar, zeros, not, concat }) + + function andTransform (args, math, scope) { + const condition1 = isNode(args[0]) ? args[0].compile().evaluate(scope) : args[0] + if (isNumber(condition1) || isBoolean(condition1) || isBigNumber(condition1) || isComplex(condition1) || isUnit(condition1)) { + if (!testCondition(condition1)) { + return false + } + } + const condition2 = isNode(args[1]) ? args[1].compile().evaluate(scope) : args[1] + return and(condition1, condition2) + } + + andTransform.rawArgs = true + + return andTransform +}, { isTransformFunction: true }) diff --git a/src/expression/transform/or.transform.js b/src/expression/transform/or.transform.js new file mode 100644 index 0000000000..c739de7a37 --- /dev/null +++ b/src/expression/transform/or.transform.js @@ -0,0 +1,26 @@ +import { createOr } from '../../function/logical/or.js' +import { factory } from '../../utils/factory.js' +import { testCondition } from './utils/testCondition.js' +import { isBigNumber, isBoolean, isComplex, isNode, isNumber, isUnit } from '../../utils/is.js' + +const name = 'or' +const dependencies = ['typed', 'matrix', 'equalScalar', 'DenseMatrix', 'concat'] + +export const createOrTransform = /* #__PURE__ */ factory(name, dependencies, ({ typed, matrix, equalScalar, DenseMatrix, concat }) => { + const or = createOr({ typed, matrix, equalScalar, DenseMatrix, concat }) + + function orTransform (args, math, scope) { + const condition1 = isNode(args[0]) ? args[0].compile().evaluate(scope) : args[0] + if (isNumber(condition1) || isBoolean(condition1) || isBigNumber(condition1) || isComplex(condition1) || isUnit(condition1)) { + if (testCondition(condition1)) { + return true + } + } + const condition2 = isNode(args[1]) ? args[1].compile().evaluate(scope) : args[1] + return or(condition1, condition2) + } + + orTransform.rawArgs = true + + return orTransform +}, { isTransformFunction: true }) diff --git a/src/factoriesAny.js b/src/factoriesAny.js index 74ab542b7a..e5441a8824 100644 --- a/src/factoriesAny.js +++ b/src/factoriesAny.js @@ -359,3 +359,5 @@ export { createQuantileSeqTransform } from './expression/transform/quantileSeq.t export { createCumSumTransform } from './expression/transform/cumsum.transform.js' export { createVarianceTransform } from './expression/transform/variance.transform.js' export { createPrintTransform } from './expression/transform/print.transform.js' +export { createAndTransform } from './expression/transform/and.transform.js' +export { createOrTransform } from './expression/transform/or.transform.js' From 332b98494c446117180a6f0a6ed831d5396a25f6 Mon Sep 17 00:00:00 2001 From: Brooks Smith Date: Mon, 6 Nov 2023 00:41:05 +1100 Subject: [PATCH 4/9] Add lazy evaluation of bitwise & and | operators --- src/expression/transform/and.transform.js | 6 ++-- src/expression/transform/bitAnd.transform.js | 28 ++++++++++++++++++ src/expression/transform/bitOr.transform.js | 31 ++++++++++++++++++++ src/expression/transform/or.transform.js | 6 ++-- src/factoriesAny.js | 2 ++ 5 files changed, 67 insertions(+), 6 deletions(-) create mode 100644 src/expression/transform/bitAnd.transform.js create mode 100644 src/expression/transform/bitOr.transform.js diff --git a/src/expression/transform/and.transform.js b/src/expression/transform/and.transform.js index 9ab6c86f11..fe864d22af 100644 --- a/src/expression/transform/and.transform.js +++ b/src/expression/transform/and.transform.js @@ -1,7 +1,7 @@ import { createAnd } from '../../function/logical/and.js' import { factory } from '../../utils/factory.js' import { testCondition } from './utils/testCondition.js' -import { isBigNumber, isBoolean, isComplex, isNode, isNumber, isUnit } from '../../utils/is.js' +import { isBigNumber, isBoolean, isComplex, isNumber, isUnit } from '../../utils/is.js' const name = 'and' const dependencies = ['typed', 'matrix', 'zeros', 'add', 'equalScalar', 'not', 'concat'] @@ -10,13 +10,13 @@ export const createAndTransform = /* #__PURE__ */ factory(name, dependencies, ({ const and = createAnd({ typed, matrix, equalScalar, zeros, not, concat }) function andTransform (args, math, scope) { - const condition1 = isNode(args[0]) ? args[0].compile().evaluate(scope) : args[0] + const condition1 = args[0].compile().evaluate(scope) if (isNumber(condition1) || isBoolean(condition1) || isBigNumber(condition1) || isComplex(condition1) || isUnit(condition1)) { if (!testCondition(condition1)) { return false } } - const condition2 = isNode(args[1]) ? args[1].compile().evaluate(scope) : args[1] + const condition2 = args[1].compile().evaluate(scope) return and(condition1, condition2) } diff --git a/src/expression/transform/bitAnd.transform.js b/src/expression/transform/bitAnd.transform.js new file mode 100644 index 0000000000..8d28f043ad --- /dev/null +++ b/src/expression/transform/bitAnd.transform.js @@ -0,0 +1,28 @@ +import { createBitAnd } from '../../function/bitwise/bitAnd.js' +import { factory } from '../../utils/factory.js' +import { isBigNumber, isBoolean, isComplex, isNumber, isUnit } from '../../utils/is.js' + +const name = 'bitAnd' +const dependencies = ['typed', 'matrix', 'zeros', 'add', 'equalScalar', 'not', 'concat'] + +export const createBitAndTransform = /* #__PURE__ */ factory(name, dependencies, ({ typed, matrix, equalScalar, zeros, not, concat }) => { + const and = createBitAnd({ typed, matrix, equalScalar, zeros, not, concat }) + + function bitAndTransform (args, math, scope) { + const condition1 = args[0].compile().evaluate(scope) + if (isNumber(condition1) || isBoolean(condition1) || isBigNumber(condition1) || isComplex(condition1) || isUnit(condition1)) { + if (isNaN(condition1)) { + return NaN + } + if (condition1 === 0 || condition1 === false) { + return 0 + } + } + const condition2 = args[1].compile().evaluate(scope) + return and(condition1, condition2) + } + + bitAndTransform.rawArgs = true + + return bitAndTransform +}, { isTransformFunction: true }) diff --git a/src/expression/transform/bitOr.transform.js b/src/expression/transform/bitOr.transform.js new file mode 100644 index 0000000000..d9eb4fd720 --- /dev/null +++ b/src/expression/transform/bitOr.transform.js @@ -0,0 +1,31 @@ +import { createBitOr } from '../../function/bitwise/bitOr.js' +import { factory } from '../../utils/factory.js' +import { isBigNumber, isBoolean, isComplex, isNumber, isUnit } from '../../utils/is.js' + +const name = 'bitOr' +const dependencies = ['typed', 'matrix', 'equalScalar', 'DenseMatrix', 'concat'] + +export const createBitOrTransform = /* #__PURE__ */ factory(name, dependencies, ({ typed, matrix, equalScalar, DenseMatrix, concat }) => { + const or = createBitOr({ typed, matrix, equalScalar, DenseMatrix, concat }) + + function bitOrTransform (args, math, scope) { + const condition1 = args[0].compile().evaluate(scope) + if (isNumber(condition1) || isBoolean(condition1) || isBigNumber(condition1) || isComplex(condition1) || isUnit(condition1)) { + if (isNaN(condition1)) { + return NaN + } + if (condition1 === (-1)) { + return -1 + } + if (condition1 === true) { + return 1 + } + } + const condition2 = args[1].compile().evaluate(scope) + return or(condition1, condition2) + } + + bitOrTransform.rawArgs = true + + return bitOrTransform +}, { isTransformFunction: true }) diff --git a/src/expression/transform/or.transform.js b/src/expression/transform/or.transform.js index c739de7a37..84966dad70 100644 --- a/src/expression/transform/or.transform.js +++ b/src/expression/transform/or.transform.js @@ -1,7 +1,7 @@ import { createOr } from '../../function/logical/or.js' import { factory } from '../../utils/factory.js' import { testCondition } from './utils/testCondition.js' -import { isBigNumber, isBoolean, isComplex, isNode, isNumber, isUnit } from '../../utils/is.js' +import { isBigNumber, isBoolean, isComplex, isNumber, isUnit } from '../../utils/is.js' const name = 'or' const dependencies = ['typed', 'matrix', 'equalScalar', 'DenseMatrix', 'concat'] @@ -10,13 +10,13 @@ export const createOrTransform = /* #__PURE__ */ factory(name, dependencies, ({ const or = createOr({ typed, matrix, equalScalar, DenseMatrix, concat }) function orTransform (args, math, scope) { - const condition1 = isNode(args[0]) ? args[0].compile().evaluate(scope) : args[0] + const condition1 = args[0].compile().evaluate(scope) if (isNumber(condition1) || isBoolean(condition1) || isBigNumber(condition1) || isComplex(condition1) || isUnit(condition1)) { if (testCondition(condition1)) { return true } } - const condition2 = isNode(args[1]) ? args[1].compile().evaluate(scope) : args[1] + const condition2 = args[1].compile().evaluate(scope) return or(condition1, condition2) } diff --git a/src/factoriesAny.js b/src/factoriesAny.js index e5441a8824..e9ae77caa1 100644 --- a/src/factoriesAny.js +++ b/src/factoriesAny.js @@ -361,3 +361,5 @@ export { createVarianceTransform } from './expression/transform/variance.transfo export { createPrintTransform } from './expression/transform/print.transform.js' export { createAndTransform } from './expression/transform/and.transform.js' export { createOrTransform } from './expression/transform/or.transform.js' +export { createBitAndTransform } from './expression/transform/bitAnd.transform.js' +export { createBitOrTransform } from './expression/transform/bitOr.transform.js' From abb55c8cb4f3f8fdcc11e85e5d45ab258cec9ee6 Mon Sep 17 00:00:00 2001 From: Brooks Smith Date: Mon, 6 Nov 2023 00:41:20 +1100 Subject: [PATCH 5/9] Add unit tests for lazy evaluation --- test/unit-tests/expression/parse.test.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/unit-tests/expression/parse.test.js b/test/unit-tests/expression/parse.test.js index 9af98d4a44..996a4a9d0b 100644 --- a/test/unit-tests/expression/parse.test.js +++ b/test/unit-tests/expression/parse.test.js @@ -1465,6 +1465,10 @@ describe('parse', function () { assert.strictEqual(parseAndEval('true & false'), 0) assert.strictEqual(parseAndEval('false & true'), 0) assert.strictEqual(parseAndEval('false & false'), 0) + + assert.strictEqual(parseAndEval('0 & undefined'), 0) + assert.strictEqual(parseAndEval('false & undefined'), 0) + assert.throws(function () { parseAndEval('true & undefined') }, TypeError) }) it('should parse bitwise xor ^|', function () { @@ -1483,6 +1487,10 @@ describe('parse', function () { assert.strictEqual(parseAndEval('true | false'), 1) assert.strictEqual(parseAndEval('false | true'), 1) assert.strictEqual(parseAndEval('false | false'), 0) + + assert.strictEqual(parseAndEval('-1 | undefined'), -1) + assert.strictEqual(parseAndEval('true | undefined'), 1) + assert.throws(function () { parseAndEval('false | undefined') }, TypeError) }) it('should parse bitwise left shift <<', function () { @@ -1506,6 +1514,10 @@ describe('parse', function () { assert.strictEqual(parseAndEval('true and false'), false) assert.strictEqual(parseAndEval('false and true'), false) assert.strictEqual(parseAndEval('false and false'), false) + + assert.strictEqual(parseAndEval('0 and undefined'), false) + assert.strictEqual(parseAndEval('false and undefined'), false) + assert.throws(function () { parseAndEval('true and undefined') }, TypeError) }) it('should parse logical xor', function () { @@ -1524,6 +1536,10 @@ describe('parse', function () { assert.strictEqual(parseAndEval('true or false'), true) assert.strictEqual(parseAndEval('false or true'), true) assert.strictEqual(parseAndEval('false or false'), false) + + assert.strictEqual(parseAndEval('2 or undefined'), true) + assert.strictEqual(parseAndEval('true or undefined'), true) + assert.throws(function () { parseAndEval('false or undefined') }, TypeError) }) it('should parse logical not', function () { From cb23d6e112922042450a7edaca0a79bb9a69ea08 Mon Sep 17 00:00:00 2001 From: Brooks Smith Date: Mon, 6 Nov 2023 00:50:57 +1100 Subject: [PATCH 6/9] Add lazy evaluation note to docs --- src/function/bitwise/bitAnd.js | 1 + src/function/bitwise/bitOr.js | 1 + src/function/logical/and.js | 1 + src/function/logical/or.js | 1 + 4 files changed, 4 insertions(+) diff --git a/src/function/bitwise/bitAnd.js b/src/function/bitwise/bitAnd.js index 621af4c942..f1842ee35a 100644 --- a/src/function/bitwise/bitAnd.js +++ b/src/function/bitwise/bitAnd.js @@ -23,6 +23,7 @@ export const createBitAnd = /* #__PURE__ */ factory(name, dependencies, ({ typed /** * Bitwise AND two values, `x & y`. * For matrices, the function is evaluated element wise. + * For non-matrices, the function is evaluated lazily. * * Syntax: * diff --git a/src/function/bitwise/bitOr.js b/src/function/bitwise/bitOr.js index 5f24394c24..b0adb98834 100644 --- a/src/function/bitwise/bitOr.js +++ b/src/function/bitwise/bitOr.js @@ -24,6 +24,7 @@ export const createBitOr = /* #__PURE__ */ factory(name, dependencies, ({ typed, /** * Bitwise OR two values, `x | y`. * For matrices, the function is evaluated element wise. + * For non-matrices, the function is evaluated lazily. * For units, the function is evaluated on the lowest print base. * * Syntax: diff --git a/src/function/logical/and.js b/src/function/logical/and.js index a05af90dda..150832e688 100644 --- a/src/function/logical/and.js +++ b/src/function/logical/and.js @@ -26,6 +26,7 @@ export const createAnd = /* #__PURE__ */ factory(name, dependencies, ({ typed, m /** * Logical `and`. Test whether two values are both defined with a nonzero/nonempty value. * For matrices, the function is evaluated element wise. + * For non-matrices, the function is evaluated lazily. * * Syntax: * diff --git a/src/function/logical/or.js b/src/function/logical/or.js index 586e161ed8..3405dad7ca 100644 --- a/src/function/logical/or.js +++ b/src/function/logical/or.js @@ -23,6 +23,7 @@ export const createOr = /* #__PURE__ */ factory(name, dependencies, ({ typed, ma /** * Logical `or`. Test if at least one value is defined with a nonzero/nonempty value. * For matrices, the function is evaluated element wise. + * For non-matrices, the function is evaluated lazily. * * Syntax: * From 11808e34b97fc0a5585870aa60b3e2e23c011537 Mon Sep 17 00:00:00 2001 From: Brooks Smith Date: Sun, 12 Nov 2023 21:42:39 +1100 Subject: [PATCH 7/9] Move documentation to Syntax page --- docs/expressions/syntax.md | 15 +++++++++++---- src/function/bitwise/bitAnd.js | 1 - src/function/bitwise/bitOr.js | 1 - src/function/logical/and.js | 1 - src/function/logical/or.js | 1 - 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/docs/expressions/syntax.md b/docs/expressions/syntax.md index 6b4db1be20..edaebaad04 100644 --- a/docs/expressions/syntax.md +++ b/docs/expressions/syntax.md @@ -121,18 +121,25 @@ See section below | Implicit multiplication `to`, `in` | Unit conversion `<<`, `>>`, `>>>` | Bitwise left shift, bitwise right arithmetic shift, bitwise right logical shift `==`, `!=`, `<`, `>`, `<=`, `>=` | Relational -`&` | Bitwise and +`&` | Bitwise and (lazily evaluated) ^| | Bitwise xor -| | Bitwise or -`and` | Logical and +| | Bitwise or (lazily evaluated) +`and` | Logical and (lazily evaluated) `xor` | Logical xor -`or` | Logical or +`or` | Logical or (lazily evaluated) `?`, `:` | Conditional expression `=` | Assignment `,` | Parameter and column separator `;` | Row separator `\n`, `;` | Statement separators +Lazy evaluation is used where logically possible for bitwise and logical +operators. In the following example, the value of `x` will not even be +evaluated because it cannot effect the final result: +```js +math.evaluate('false and x') // false, no matter what x equals +``` + ## Functions diff --git a/src/function/bitwise/bitAnd.js b/src/function/bitwise/bitAnd.js index f1842ee35a..621af4c942 100644 --- a/src/function/bitwise/bitAnd.js +++ b/src/function/bitwise/bitAnd.js @@ -23,7 +23,6 @@ export const createBitAnd = /* #__PURE__ */ factory(name, dependencies, ({ typed /** * Bitwise AND two values, `x & y`. * For matrices, the function is evaluated element wise. - * For non-matrices, the function is evaluated lazily. * * Syntax: * diff --git a/src/function/bitwise/bitOr.js b/src/function/bitwise/bitOr.js index b0adb98834..5f24394c24 100644 --- a/src/function/bitwise/bitOr.js +++ b/src/function/bitwise/bitOr.js @@ -24,7 +24,6 @@ export const createBitOr = /* #__PURE__ */ factory(name, dependencies, ({ typed, /** * Bitwise OR two values, `x | y`. * For matrices, the function is evaluated element wise. - * For non-matrices, the function is evaluated lazily. * For units, the function is evaluated on the lowest print base. * * Syntax: diff --git a/src/function/logical/and.js b/src/function/logical/and.js index 150832e688..a05af90dda 100644 --- a/src/function/logical/and.js +++ b/src/function/logical/and.js @@ -26,7 +26,6 @@ export const createAnd = /* #__PURE__ */ factory(name, dependencies, ({ typed, m /** * Logical `and`. Test whether two values are both defined with a nonzero/nonempty value. * For matrices, the function is evaluated element wise. - * For non-matrices, the function is evaluated lazily. * * Syntax: * diff --git a/src/function/logical/or.js b/src/function/logical/or.js index 3405dad7ca..586e161ed8 100644 --- a/src/function/logical/or.js +++ b/src/function/logical/or.js @@ -23,7 +23,6 @@ export const createOr = /* #__PURE__ */ factory(name, dependencies, ({ typed, ma /** * Logical `or`. Test if at least one value is defined with a nonzero/nonempty value. * For matrices, the function is evaluated element wise. - * For non-matrices, the function is evaluated lazily. * * Syntax: * From 87bae422dc1963b25882b047c877bdd7a7f4c075 Mon Sep 17 00:00:00 2001 From: Brooks Smith Date: Sun, 12 Nov 2023 21:43:35 +1100 Subject: [PATCH 8/9] Replace `testCondition()` with test evaluation of logical function itself --- src/expression/transform/and.transform.js | 9 ++---- src/expression/transform/or.transform.js | 9 ++---- .../transform/utils/testCondition.js | 31 ------------------- 3 files changed, 6 insertions(+), 43 deletions(-) delete mode 100644 src/expression/transform/utils/testCondition.js diff --git a/src/expression/transform/and.transform.js b/src/expression/transform/and.transform.js index fe864d22af..4212eecefe 100644 --- a/src/expression/transform/and.transform.js +++ b/src/expression/transform/and.transform.js @@ -1,7 +1,6 @@ import { createAnd } from '../../function/logical/and.js' import { factory } from '../../utils/factory.js' -import { testCondition } from './utils/testCondition.js' -import { isBigNumber, isBoolean, isComplex, isNumber, isUnit } from '../../utils/is.js' +import { isCollection } from '../../utils/is.js' const name = 'and' const dependencies = ['typed', 'matrix', 'zeros', 'add', 'equalScalar', 'not', 'concat'] @@ -11,10 +10,8 @@ export const createAndTransform = /* #__PURE__ */ factory(name, dependencies, ({ function andTransform (args, math, scope) { const condition1 = args[0].compile().evaluate(scope) - if (isNumber(condition1) || isBoolean(condition1) || isBigNumber(condition1) || isComplex(condition1) || isUnit(condition1)) { - if (!testCondition(condition1)) { - return false - } + if (!isCollection(condition1) && !and(condition1, true)) { + return false } const condition2 = args[1].compile().evaluate(scope) return and(condition1, condition2) diff --git a/src/expression/transform/or.transform.js b/src/expression/transform/or.transform.js index 84966dad70..029f19bd4c 100644 --- a/src/expression/transform/or.transform.js +++ b/src/expression/transform/or.transform.js @@ -1,7 +1,6 @@ import { createOr } from '../../function/logical/or.js' import { factory } from '../../utils/factory.js' -import { testCondition } from './utils/testCondition.js' -import { isBigNumber, isBoolean, isComplex, isNumber, isUnit } from '../../utils/is.js' +import { isCollection } from '../../utils/is.js' const name = 'or' const dependencies = ['typed', 'matrix', 'equalScalar', 'DenseMatrix', 'concat'] @@ -11,10 +10,8 @@ export const createOrTransform = /* #__PURE__ */ factory(name, dependencies, ({ function orTransform (args, math, scope) { const condition1 = args[0].compile().evaluate(scope) - if (isNumber(condition1) || isBoolean(condition1) || isBigNumber(condition1) || isComplex(condition1) || isUnit(condition1)) { - if (testCondition(condition1)) { - return true - } + if (!isCollection(condition1) && or(condition1, false)) { + return true } const condition2 = args[1].compile().evaluate(scope) return or(condition1, condition2) diff --git a/src/expression/transform/utils/testCondition.js b/src/expression/transform/utils/testCondition.js deleted file mode 100644 index d6ff1576a1..0000000000 --- a/src/expression/transform/utils/testCondition.js +++ /dev/null @@ -1,31 +0,0 @@ -import { isBigNumber, isComplex, isUnit } from '../../../utils/is.js' - -/** - * Test the truthiness of a scalar condition - * @param {number, boolean, BigNumber, Complex, Unit} condition - * @returns {boolean} Returns the truthiness of the condition - */ -export function testCondition (condition) { - if (typeof condition === 'number' || - typeof condition === 'boolean') { - return !!condition - } - if (condition === null || condition === undefined) { - return false - } - if (isBigNumber(condition)) { - return !condition.isZero() - } - - if (isComplex(condition)) { - return !!((condition.re || condition.im)) - } - - if (isUnit(condition)) { - return !!condition.value - } - - if (condition === null || condition === undefined) { - return false - } -} From c5e5f1cb12b63d07fc78ef10ff66b47afc1d6c13 Mon Sep 17 00:00:00 2001 From: Brooks Smith Date: Sun, 12 Nov 2023 21:44:23 +1100 Subject: [PATCH 9/9] Use `isCollection()` to simplify bitwise transform functions --- src/expression/transform/bitAnd.transform.js | 8 ++++---- src/expression/transform/bitOr.transform.js | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/expression/transform/bitAnd.transform.js b/src/expression/transform/bitAnd.transform.js index 8d28f043ad..ff9e709261 100644 --- a/src/expression/transform/bitAnd.transform.js +++ b/src/expression/transform/bitAnd.transform.js @@ -1,16 +1,16 @@ import { createBitAnd } from '../../function/bitwise/bitAnd.js' import { factory } from '../../utils/factory.js' -import { isBigNumber, isBoolean, isComplex, isNumber, isUnit } from '../../utils/is.js' +import { isCollection } from '../../utils/is.js' const name = 'bitAnd' const dependencies = ['typed', 'matrix', 'zeros', 'add', 'equalScalar', 'not', 'concat'] export const createBitAndTransform = /* #__PURE__ */ factory(name, dependencies, ({ typed, matrix, equalScalar, zeros, not, concat }) => { - const and = createBitAnd({ typed, matrix, equalScalar, zeros, not, concat }) + const bitAnd = createBitAnd({ typed, matrix, equalScalar, zeros, not, concat }) function bitAndTransform (args, math, scope) { const condition1 = args[0].compile().evaluate(scope) - if (isNumber(condition1) || isBoolean(condition1) || isBigNumber(condition1) || isComplex(condition1) || isUnit(condition1)) { + if (!isCollection(condition1)) { if (isNaN(condition1)) { return NaN } @@ -19,7 +19,7 @@ export const createBitAndTransform = /* #__PURE__ */ factory(name, dependencies, } } const condition2 = args[1].compile().evaluate(scope) - return and(condition1, condition2) + return bitAnd(condition1, condition2) } bitAndTransform.rawArgs = true diff --git a/src/expression/transform/bitOr.transform.js b/src/expression/transform/bitOr.transform.js index d9eb4fd720..ae04f7de04 100644 --- a/src/expression/transform/bitOr.transform.js +++ b/src/expression/transform/bitOr.transform.js @@ -1,16 +1,16 @@ import { createBitOr } from '../../function/bitwise/bitOr.js' import { factory } from '../../utils/factory.js' -import { isBigNumber, isBoolean, isComplex, isNumber, isUnit } from '../../utils/is.js' +import { isCollection } from '../../utils/is.js' const name = 'bitOr' const dependencies = ['typed', 'matrix', 'equalScalar', 'DenseMatrix', 'concat'] export const createBitOrTransform = /* #__PURE__ */ factory(name, dependencies, ({ typed, matrix, equalScalar, DenseMatrix, concat }) => { - const or = createBitOr({ typed, matrix, equalScalar, DenseMatrix, concat }) + const bitOr = createBitOr({ typed, matrix, equalScalar, DenseMatrix, concat }) function bitOrTransform (args, math, scope) { const condition1 = args[0].compile().evaluate(scope) - if (isNumber(condition1) || isBoolean(condition1) || isBigNumber(condition1) || isComplex(condition1) || isUnit(condition1)) { + if (!isCollection(condition1)) { if (isNaN(condition1)) { return NaN } @@ -22,7 +22,7 @@ export const createBitOrTransform = /* #__PURE__ */ factory(name, dependencies, } } const condition2 = args[1].compile().evaluate(scope) - return or(condition1, condition2) + return bitOr(condition1, condition2) } bitOrTransform.rawArgs = true