Skip to content

Commit f2b4f52

Browse files
committed
feat: convert complex with (near-)zero complex part to bigint
1 parent a024180 commit f2b4f52

File tree

2 files changed

+29
-9
lines changed

2 files changed

+29
-9
lines changed

src/type/bigint.js

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,19 @@ export const createBigint = /* #__PURE__ */ factory(name, dependencies, ({ typed
4545
* math.bigint(true) // returns 1n
4646
* math.bigint([true, false, true, true]) // returns [1n, 0n, 1n, 1n]
4747
* math.bigint(3**50) // returns 717897987691852578422784n
48-
* // note inexactness above from number precision; actual 3n**50n is
49-
* // the bigint 717897987691852588770249n
48+
* // note inexactness above from number precision; actual 3n**50n is
49+
* // the bigint 717897987691852588770249n
50+
*
5051
* math.bigint(3**50, {safe: true}) // throws RangeError
5152
* math.bigint(math.pow(math.bignumber(11), 64)) // returns 4457915684525902395869512133369841539490161434991526715513934826000n
52-
* // similarly inaccurate; last three digits should be 241
53+
* // similarly inaccurate; last three digits should be 241
54+
*
5355
* math.bigint(
5456
* math.pow(math.bignumber(11), 64),
5557
* {safe: true}) // throws RangeError
5658
* math.bigint(math.fraction(13, 2)) // returns 7n
59+
* math.bigint(math.complex(2.5, -0.3)) // returns 3n
60+
* math.bigint(math.complex(-17, 1)) // throws RangeError
5761
* math.bigint(6.5, {round: 'throw'}) // throws RangeError
5862
* math.bigint(6.5, {round: 'floor'}) // returns 6n
5963
* math.bigint(-6.5, {round: 'ceil'}) // returns -6n
@@ -72,7 +76,6 @@ export const createBigint = /* #__PURE__ */ factory(name, dependencies, ({ typed
7276
'': function () {
7377
return 0n
7478
},
75-
7679
null: function (x) {
7780
return 0n
7881
},
@@ -101,6 +104,9 @@ export const createBigint = /* #__PURE__ */ factory(name, dependencies, ({ typed
101104
'number | BigNumber | Fraction': numericToBigint,
102105
'number | BigNumber | Fraction, Object': numericToBigint,
103106

107+
Complex: complexToBigint,
108+
'Complex, Object': complexToBigint,
109+
104110
'Array | Matrix': typed.referToSelf(self => x => deepMap(x, self))
105111
})
106112

@@ -156,7 +162,9 @@ export const createBigint = /* #__PURE__ */ factory(name, dependencies, ({ typed
156162
if (/^0[box]/.test(value)) return BigInt(value)
157163

158164
// Otherwise, have to parse ourselves, because BigInt() doesn't allow
159-
// rounding; it throws on all decimals.
165+
// rounding; it throws on all decimals. We also can't use parseFloat
166+
// because it will go through the `number` type with its potential loss
167+
// of accuracy.
160168
const match = value.match(/^([+-])?(\d*)([.,]\d*)?([eE][+-]?\d+)?$/)
161169
if (!match) {
162170
throw new SyntaxError('invalid BigInt syntax')
@@ -196,5 +204,15 @@ export const createBigint = /* #__PURE__ */ factory(name, dependencies, ({ typed
196204
return intVal + sgn
197205
}
198206

207+
function complexToBigint (z, options = {}) {
208+
if (numericToBigint(z.im, options) !== 0n) {
209+
throw new RangeError(
210+
`Complex number with nonzero imaginary part ${z.im} cannot ` +
211+
'be converted to bigint.'
212+
)
213+
}
214+
return numericToBigint(z.re, options)
215+
}
216+
199217
return bigint
200218
})

test/unit-tests/type/bigint.test.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ describe('bigint', function () {
4444
)
4545
})
4646

47+
it('should convert a Complex to a bigint', function () {
48+
assert.strictEqual(bigint(math.complex(0)), 0n)
49+
assert.strictEqual(bigint(math.complex(6543210.9, 0.49)), 6543211n)
50+
assert.throws(() => bigint(math.complex(0, -0.6)), RangeError)
51+
})
52+
4753
it('should accept a bigint as argument', function () {
4854
assert.strictEqual(bigint(3n), 3n)
4955
assert.strictEqual(bigint(-3n), -3n)
@@ -128,10 +134,6 @@ describe('bigint', function () {
128134
assert.throws(function () { bigint(1, {}, 3) }, /TypeError: Too many arguments/)
129135
})
130136

131-
it('should throw an error if called with a complex number', function () {
132-
assert.throws(function () { bigint(math.complex(2, 3)) }, TypeError)
133-
})
134-
135137
it('should throw an error with wrong type of arguments', function () {
136138
assert.throws(function () { bigint(math.unit('5cm'), 2) }, TypeError)
137139
assert.throws(function () { bigint(math.unit('5cm'), new Date()) }, TypeError)

0 commit comments

Comments
 (0)