Skip to content

Commit

Permalink
fix: Refactors per comments and 1 bonus doc test (isInteger)
Browse files Browse the repository at this point in the history
  • Loading branch information
gwhitney committed Jan 13, 2025
1 parent 749f07a commit f47a97e
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 59 deletions.
27 changes: 13 additions & 14 deletions src/function/arithmetic/log.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { factory } from '../../utils/factory.js'
import { promoteLogarithm } from '../../utils/bigint.js'
import { logNumber } from '../../plain/number/index.js'

const name = 'log'
Expand Down Expand Up @@ -41,36 +42,34 @@ export const createLog = /* #__PURE__ */ factory(name, dependencies, ({ typed, t
* @return {number | BigNumber | Fraction | Complex}
* Returns the logarithm of `x`
*/
function complexLog (c) {
return c.log()
}

function complexLogNumber (x) {
return complexLog(new Complex(x, 0))
}

return typed(name, {
number: function (x) {
if (x >= 0 || config.predictable) {
return logNumber(x)
} else {
// negative value -> complex value computation
return new Complex(x, 0).log()
return complexLogNumber(x)
}
},

bigint: function (x) {
if (x > 0 || config.predictable) {
if (x <= 0) return NaN
const s = x.toString(16)
const s15 = s.substring(0, 15)
return nlg16 * (s.length - s15.length) + logNumber(Number('0x' + s15))
}
return new Complex(x.toNumber(), 0).log()
},
bigint: promoteLogarithm(nlg16, logNumber, config, complexLogNumber),

Complex: function (x) {
return x.log()
},
Complex: complexLog,

BigNumber: function (x) {
if (!x.isNegative() || config.predictable) {
return x.ln()
} else {
// downgrade to number, return Complex valued result
return new Complex(x.toNumber(), 0).log()
return complexLogNumber(x.toNumber())
}
},

Expand Down
31 changes: 15 additions & 16 deletions src/function/arithmetic/log10.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { factory } from '../../utils/factory.js'
import { deepMap } from '../../utils/collection.js'
import { log10Number } from '../../plain/number/index.js'
import { promoteLogarithm } from '../../utils/bigint.js'
import { deepMap } from '../../utils/collection.js'
import { factory } from '../../utils/factory.js'

const name = 'log10'
const dependencies = ['typed', 'config', 'Complex']
Expand Down Expand Up @@ -32,36 +33,34 @@ export const createLog10 = /* #__PURE__ */ factory(name, dependencies, ({ typed,
* @return {number | BigNumber | Complex | Array | Matrix}
* Returns the 10-base logarithm of `x`
*/

function complexLog (c) {
return c.log().div(Math.LN10)
}

function complexLogNumber (x) {
return complexLog(new Complex(x, 0))
}
return typed(name, {
number: function (x) {
if (x >= 0 || config.predictable) {
return log10Number(x)
} else {
// negative value -> complex value computation
return new Complex(x, 0).log().div(Math.LN10)
return complexLogNumber(x)
}
},

bigint: function (x) {
if (x > 0 || config.predictable) {
if (x <= 0) return NaN
const s = x.toString(16)
const s15 = s.substring(0, 15)
return log16 * (s.length - s15.length) + log10Number(Number('0x' + s15))
}
return new Complex(x.toNumber(), 0).log().div(Math.LN10)
},
bigint: promoteLogarithm(log16, log10Number, config, complexLogNumber),

Complex: function (x) {
return new Complex(x).log().div(Math.LN10)
},
Complex: complexLog,

BigNumber: function (x) {
if (!x.isNegative() || config.predictable) {
return x.log()
} else {
// downgrade to number, return Complex valued result
return new Complex(x.toNumber(), 0).log().div(Math.LN10)
return complexLogNumber(x.toNumber())
}
},

Expand Down
23 changes: 10 additions & 13 deletions src/function/arithmetic/log2.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { factory } from '../../utils/factory.js'
import { deepMap } from '../../utils/collection.js'
import { log2Number } from '../../plain/number/index.js'
import { promoteLogarithm } from '../../utils/bigint.js'
import { deepMap } from '../../utils/collection.js'
import { factory } from '../../utils/factory.js'

const name = 'log2'
const dependencies = ['typed', 'config', 'Complex']
Expand Down Expand Up @@ -31,25 +32,21 @@ export const createLog2 = /* #__PURE__ */ factory(name, dependencies, ({ typed,
* @return {number | BigNumber | Complex | Array | Matrix}
* Returns the 2-base logarithm of `x`
*/
function complexLog2Number (x) {
return _log2Complex(new Complex(x, 0))
}

return typed(name, {
number: function (x) {
if (x >= 0 || config.predictable) {
return log2Number(x)
} else {
// negative value -> complex value computation
return _log2Complex(new Complex(x, 0))
return complexLog2Number(x)
}
},

bigint: function (x) {
if (x > 0 || config.predictable) {
if (x <= 0) return NaN
const s = x.toString(16)
const s15 = s.substring(0, 15)
return 4 * (s.length - s15.length) + log2Number(Number('0x' + s15))
}
return _log2Complex(new Complex(x.toNumber(), 0))
},
bigint: promoteLogarithm(4, log2Number, config, complexLog2Number),

Complex: _log2Complex,

Expand All @@ -58,7 +55,7 @@ export const createLog2 = /* #__PURE__ */ factory(name, dependencies, ({ typed,
return x.log(2)
} else {
// downgrade to number, return Complex valued result
return _log2Complex(new Complex(x.toNumber(), 0))
return complexLog2Number(x.toNumber())
}
},

Expand Down
10 changes: 3 additions & 7 deletions src/function/relational/larger.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,6 @@ const dependencies = [
'SparseMatrix'
]

function bigLarger (config) {
return function (x, y) {
return x.gt(y) && !bigNearlyEqual(x, y, config.relTol, config.absTol)
}
}

export const createLarger = /* #__PURE__ */ factory(name, dependencies, ({ typed, config, bignumber, matrix, DenseMatrix, concat, SparseMatrix }) => {
const matAlgo03xDSf = createMatAlgo03xDSf({ typed })
const matAlgo07xSSf = createMatAlgo07xSSf({ typed, SparseMatrix })
Expand Down Expand Up @@ -62,7 +56,9 @@ export const createLarger = /* #__PURE__ */ factory(name, dependencies, ({ typed
* @param {number | BigNumber | bigint | Fraction | boolean | Unit | string | Array | Matrix} y Second value to compare
* @return {boolean | Array | Matrix} Returns true when the x is larger than y, else returns false
*/
const bignumLarger = bigLarger(config)
function bignumLarger (x, y) {
return x.gt(y) && !bigNearlyEqual(x, y, config.relTol, config.absTol)
}

return typed(
name,
Expand Down
10 changes: 3 additions & 7 deletions src/function/relational/smaller.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,6 @@ const dependencies = [
'SparseMatrix'
]

function bigSmaller (config) {
return function (x, y) {
return x.lt(y) && !bigNearlyEqual(x, y, config.relTol, config.absTol)
}
}

export const createSmaller = /* #__PURE__ */ factory(name, dependencies, ({ typed, config, bignumber, matrix, DenseMatrix, concat, SparseMatrix }) => {
const matAlgo03xDSf = createMatAlgo03xDSf({ typed })
const matAlgo07xSSf = createMatAlgo07xSSf({ typed, SparseMatrix })
Expand Down Expand Up @@ -62,7 +56,9 @@ export const createSmaller = /* #__PURE__ */ factory(name, dependencies, ({ type
* @param {number | BigNumber | bigint | Fraction | boolean | Unit | string | Array | Matrix} y Second value to compare
* @return {boolean | Array | Matrix} Returns true when the x is smaller than y, else returns false
*/
const bignumSmaller = bigSmaller(config)
function bignumSmaller (x, y) {
return x.lt(y) && !bigNearlyEqual(x, y, config.relTol, config.absTol)
}

return typed(
name,
Expand Down
2 changes: 1 addition & 1 deletion src/function/utils/isInteger.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const createIsInteger = /* #__PURE__ */ factory(name, dependencies, ({ ty
* math.isInteger(math.fraction(4)) // returns true
* math.isInteger('3') // returns true
* math.isInteger([3, 0.5, -2]) // returns [true, false, true]
* math.isInteger(math.complex('2-4i')) // throws an error
* math.isInteger(math.complex('2-4i')) // throws TypeError
*
* See also:
*
Expand Down
27 changes: 27 additions & 0 deletions src/utils/bigint.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* Build a bigint logarithm function from a number logarithm,
* still returning a number. The idea is that 15 hexadecimal digits
* (60 bits) saturates the mantissa of the log, and each additional hex
* digit effectively just adds the log of 16 to the resulting value. So
* convert the most significant 15 hex digits to a number and take its
* log, and then add the log of 16 for each additional hex digit that
* was in the bigint.
* For negative numbers (complex logarithms), following the bignum
* implementation, it just downgrades to number and uses the complex result.
* @param {number} log16 the log of 16
* @param {(number) -> number} numberLog the logarithm function for numbers
* @param {ConfigurationObject} config the mathjs configuration
* @param {(number) -> Complex} cplx the associated Complex log
* @returns {(bigint) -> number} the corresponding logarithm for bigints
*/
export function promoteLogarithm (log16, numberLog, config, cplx) {
return function (b) {
if (b > 0 || config.predictable) {
if (b <= 0) return NaN
const s = b.toString(16)
const s15 = s.substring(0, 15)
return log16 * (s.length - s15.length) + numberLog(Number('0x' + s15))
}
return cplx(b.toNumber())
}
}
10 changes: 9 additions & 1 deletion test/node-tests/doc.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ function extractValue (spec) {

const knownProblems = new Set([
'isZero', 'isPositive', 'isNumeric', 'isNegative', 'isNaN',
'isInteger', 'hasNumericValue', 'clone', 'print', 'hex', 'format', 'to', 'sin',
'hasNumericValue', 'clone', 'hex', 'format', 'to', 'sin',
'cos', 'atan2', 'atan', 'asin', 'asec', 'acsc', 'acoth', 'acot', 'max',
'setUnion', 'unequal', 'equal', 'deepEqual', 'compareNatural', 'randomInt',
'random', 'pickRandom', 'kldivergence', 'xor', 'or', 'not', 'and', 'distance',
Expand Down Expand Up @@ -145,6 +145,14 @@ function checkExpectation (want, got) {
}
return approxEqual(got, want, 1e-9)
}
if (
typeof want === 'string'

Check failure on line 149 in test/node-tests/doc.test.js

View workflow job for this annotation

GitHub Actions / lint

Expected indentation of 4 spaces but found 6

Check failure on line 149 in test/node-tests/doc.test.js

View workflow job for this annotation

GitHub Actions / build-and-test

Expected indentation of 4 spaces but found 6
&& typeof got === 'string'

Check failure on line 150 in test/node-tests/doc.test.js

View workflow job for this annotation

GitHub Actions / lint

'&&' should be placed at the end of the line

Check failure on line 150 in test/node-tests/doc.test.js

View workflow job for this annotation

GitHub Actions / build-and-test

'&&' should be placed at the end of the line
&& want.endsWith('Error')

Check failure on line 151 in test/node-tests/doc.test.js

View workflow job for this annotation

GitHub Actions / lint

'&&' should be placed at the end of the line

Check failure on line 151 in test/node-tests/doc.test.js

View workflow job for this annotation

GitHub Actions / build-and-test

'&&' should be placed at the end of the line
&& got.startsWith(want)

Check failure on line 152 in test/node-tests/doc.test.js

View workflow job for this annotation

GitHub Actions / lint

'&&' should be placed at the end of the line

Check failure on line 152 in test/node-tests/doc.test.js

View workflow job for this annotation

GitHub Actions / build-and-test

'&&' should be placed at the end of the line
) {
return true // we obtained the expected error type

Check failure on line 154 in test/node-tests/doc.test.js

View workflow job for this annotation

GitHub Actions / lint

Expected indentation of 4 spaces but found 6

Check failure on line 154 in test/node-tests/doc.test.js

View workflow job for this annotation

GitHub Actions / lint

Multiple spaces found before '// we obtained...'

Check failure on line 154 in test/node-tests/doc.test.js

View workflow job for this annotation

GitHub Actions / build-and-test

Expected indentation of 4 spaces but found 6

Check failure on line 154 in test/node-tests/doc.test.js

View workflow job for this annotation

GitHub Actions / build-and-test

Multiple spaces found before '// we obtained...'
}
if (typeof want !== 'undefined') {
return approxDeepEqual(got, want)
} else {
Expand Down

0 comments on commit f47a97e

Please sign in to comment.