|
| 1 | +"use strict"; |
| 2 | + |
| 3 | +function assert(actual, expected, message) { |
| 4 | + if (arguments.length == 1) |
| 5 | + expected = true; |
| 6 | + |
| 7 | + if (actual === expected) |
| 8 | + return; |
| 9 | + |
| 10 | + if (actual !== null && expected !== null |
| 11 | + && typeof actual == 'object' && typeof expected == 'object' |
| 12 | + && actual.toString() === expected.toString()) |
| 13 | + return; |
| 14 | + |
| 15 | + throw Error("assertion failed: got |" + actual + "|" + |
| 16 | + ", expected |" + expected + "|" + |
| 17 | + (message ? " (" + message + ")" : "")); |
| 18 | +} |
| 19 | + |
| 20 | +function assertThrows(err, func) |
| 21 | +{ |
| 22 | + var ex; |
| 23 | + ex = false; |
| 24 | + try { |
| 25 | + func(); |
| 26 | + } catch(e) { |
| 27 | + ex = true; |
| 28 | + assert(e instanceof err); |
| 29 | + } |
| 30 | + assert(ex, true, "exception expected"); |
| 31 | +} |
| 32 | + |
| 33 | +// load more elaborate version of assert if available |
| 34 | +try { __loadScript("test_assert.js"); } catch(e) {} |
| 35 | + |
| 36 | +/*----------------*/ |
| 37 | + |
| 38 | +/* a must be < b */ |
| 39 | +function test_less(a, b) |
| 40 | +{ |
| 41 | + assert(a < b); |
| 42 | + assert(!(b < a)); |
| 43 | + assert(a <= b); |
| 44 | + assert(!(b <= a)); |
| 45 | + assert(b > a); |
| 46 | + assert(!(a > b)); |
| 47 | + assert(b >= a); |
| 48 | + assert(!(a >= b)); |
| 49 | + assert(a != b); |
| 50 | + assert(!(a == b)); |
| 51 | +} |
| 52 | + |
| 53 | +/* a must be numerically equal to b */ |
| 54 | +function test_eq(a, b) |
| 55 | +{ |
| 56 | + assert(a == b); |
| 57 | + assert(b == a); |
| 58 | + assert(!(a != b)); |
| 59 | + assert(!(b != a)); |
| 60 | + assert(a <= b); |
| 61 | + assert(b <= a); |
| 62 | + assert(!(a < b)); |
| 63 | + assert(a >= b); |
| 64 | + assert(b >= a); |
| 65 | + assert(!(a > b)); |
| 66 | +} |
| 67 | + |
| 68 | +function test_divrem(div1, a, b, q) |
| 69 | +{ |
| 70 | + var div, divrem, t; |
| 71 | + div = BigInt[div1]; |
| 72 | + divrem = BigInt[div1 + "rem"]; |
| 73 | + assert(div(a, b) == q); |
| 74 | + t = divrem(a, b); |
| 75 | + assert(t[0] == q); |
| 76 | + assert(a == b * q + t[1]); |
| 77 | +} |
| 78 | + |
| 79 | +function test_idiv1(div, a, b, r) |
| 80 | +{ |
| 81 | + test_divrem(div, a, b, r[0]); |
| 82 | + test_divrem(div, -a, b, r[1]); |
| 83 | + test_divrem(div, a, -b, r[2]); |
| 84 | + test_divrem(div, -a, -b, r[3]); |
| 85 | +} |
| 86 | + |
| 87 | +/* QuickJS BigInt extensions */ |
| 88 | +function test_bigint_ext() |
| 89 | +{ |
| 90 | + var r; |
| 91 | + assert(BigInt.floorLog2(0n) === -1n); |
| 92 | + assert(BigInt.floorLog2(7n) === 2n); |
| 93 | + |
| 94 | + assert(BigInt.sqrt(0xffffffc000000000000000n) === 17592185913343n); |
| 95 | + r = BigInt.sqrtrem(0xffffffc000000000000000n); |
| 96 | + assert(r[0] === 17592185913343n); |
| 97 | + assert(r[1] === 35167191957503n); |
| 98 | + |
| 99 | + test_idiv1("tdiv", 3n, 2n, [1n, -1n, -1n, 1n]); |
| 100 | + test_idiv1("fdiv", 3n, 2n, [1n, -2n, -2n, 1n]); |
| 101 | + test_idiv1("cdiv", 3n, 2n, [2n, -1n, -1n, 2n]); |
| 102 | + test_idiv1("ediv", 3n, 2n, [1n, -2n, -1n, 2n]); |
| 103 | +} |
| 104 | + |
| 105 | +function test_bigfloat() |
| 106 | +{ |
| 107 | + var e, a, b, sqrt2; |
| 108 | + |
| 109 | + assert(typeof 1n === "bigint"); |
| 110 | + assert(typeof 1l === "bigfloat"); |
| 111 | + assert(1 == 1.0l); |
| 112 | + assert(1 !== 1.0l); |
| 113 | + |
| 114 | + test_less(2l, 3l); |
| 115 | + test_eq(3l, 3l); |
| 116 | + |
| 117 | + test_less(2, 3l); |
| 118 | + test_eq(3, 3l); |
| 119 | + |
| 120 | + test_less(2.1, 3l); |
| 121 | + test_eq(Math.sqrt(9), 3l); |
| 122 | + |
| 123 | + test_less(2n, 3l); |
| 124 | + test_eq(3n, 3l); |
| 125 | + |
| 126 | + e = new BigFloatEnv(128); |
| 127 | + assert(e.prec == 128); |
| 128 | + a = BigFloat.sqrt(2l, e); |
| 129 | + assert(a === BigFloat.parseFloat("0x1.6a09e667f3bcc908b2fb1366ea957d3e", 0, e)); |
| 130 | + assert(e.inexact === true); |
| 131 | + assert(BigFloat.fpRound(a) == 0x1.6a09e667f3bcc908b2fb1366ea95l); |
| 132 | + |
| 133 | + b = BigFloatEnv.setPrec(BigFloat.sqrt.bind(null, 2), 128); |
| 134 | + assert(a === b); |
| 135 | + |
| 136 | + assert(BigFloat.isNaN(BigFloat(NaN))); |
| 137 | + assert(BigFloat.isFinite(1l)); |
| 138 | + assert(!BigFloat.isFinite(1l/0l)); |
| 139 | + |
| 140 | + assert(BigFloat.abs(-3l) === 3l); |
| 141 | + assert(BigFloat.sign(-3l) === -1l); |
| 142 | + |
| 143 | + assert(BigFloat.exp(0.2l) === 1.2214027581601698339210719946396742l); |
| 144 | + assert(BigFloat.log(3l) === 1.0986122886681096913952452369225256l); |
| 145 | + assert(BigFloat.pow(2.1l, 1.6l) === 3.277561666451861947162828744873745l); |
| 146 | + |
| 147 | + assert(BigFloat.sin(-1l) === -0.841470984807896506652502321630299l); |
| 148 | + assert(BigFloat.cos(1l) === 0.5403023058681397174009366074429766l); |
| 149 | + assert(BigFloat.tan(0.1l) === 0.10033467208545054505808004578111154l); |
| 150 | + |
| 151 | + assert(BigFloat.asin(0.3l) === 0.30469265401539750797200296122752915l); |
| 152 | + assert(BigFloat.acos(0.4l) === 1.1592794807274085998465837940224159l); |
| 153 | + assert(BigFloat.atan(0.7l) === 0.610725964389208616543758876490236l); |
| 154 | + assert(BigFloat.atan2(7.1l, -5.1l) === 2.1937053809751415549388104628759813l); |
| 155 | + |
| 156 | + assert(BigFloat.floor(2.5l) === 2l); |
| 157 | + assert(BigFloat.ceil(2.5l) === 3l); |
| 158 | + assert(BigFloat.trunc(-2.5l) === -2l); |
| 159 | + assert(BigFloat.round(2.5l) === 3l); |
| 160 | + |
| 161 | + assert(BigFloat.fmod(3l,2l) === 1l); |
| 162 | + assert(BigFloat.remainder(3l,2l) === -1l); |
| 163 | + |
| 164 | + /* string conversion */ |
| 165 | + assert((1234.125l).toString(), "1234.125"); |
| 166 | + assert((1234.125l).toFixed(2), "1234.13"); |
| 167 | + assert((1234.125l).toFixed(2, "down"), "1234.12"); |
| 168 | + assert((1234.125l).toExponential(), "1.234125e+3"); |
| 169 | + assert((1234.125l).toExponential(5), "1.23413e+3"); |
| 170 | + assert((1234.125l).toExponential(5, BigFloatEnv.RNDZ), "1.23412e+3"); |
| 171 | + assert((1234.125l).toPrecision(6), "1234.13"); |
| 172 | + assert((1234.125l).toPrecision(6, BigFloatEnv.RNDZ), "1234.12"); |
| 173 | + |
| 174 | + /* string conversion with binary base */ |
| 175 | + assert((0x123.438l).toString(16), "123.438"); |
| 176 | + assert((0x323.438l).toString(16), "323.438"); |
| 177 | + assert((0x723.438l).toString(16), "723.438"); |
| 178 | + assert((0xf23.438l).toString(16), "f23.438"); |
| 179 | + assert((0x123.438l).toFixed(2, BigFloatEnv.RNDNA, 16), "123.44"); |
| 180 | + assert((0x323.438l).toFixed(2, BigFloatEnv.RNDNA, 16), "323.44"); |
| 181 | + assert((0x723.438l).toFixed(2, BigFloatEnv.RNDNA, 16), "723.44"); |
| 182 | + assert((0xf23.438l).toFixed(2, BigFloatEnv.RNDNA, 16), "f23.44"); |
| 183 | + assert((0x0.0000438l).toFixed(6, BigFloatEnv.RNDNA, 16), "0.000044"); |
| 184 | + assert((0x1230000000l).toFixed(1, BigFloatEnv.RNDNA, 16), "1230000000.0"); |
| 185 | + assert((0x123.438l).toPrecision(5, BigFloatEnv.RNDNA, 16), "123.44"); |
| 186 | + assert((0x123.438l).toPrecision(5, BigFloatEnv.RNDZ, 16), "123.43"); |
| 187 | + assert((0x323.438l).toPrecision(5, BigFloatEnv.RNDNA, 16), "323.44"); |
| 188 | + assert((0x723.438l).toPrecision(5, BigFloatEnv.RNDNA, 16), "723.44"); |
| 189 | + assert((-0xf23.438l).toPrecision(5, BigFloatEnv.RNDD, 16), "-f23.44"); |
| 190 | + assert((0x123.438l).toExponential(4, BigFloatEnv.RNDNA, 16), "1.2344p+8"); |
| 191 | +} |
| 192 | + |
| 193 | +function test_bigdecimal() |
| 194 | +{ |
| 195 | + assert(1m === 1m); |
| 196 | + assert(1m !== 2m); |
| 197 | + test_less(1m, 2m); |
| 198 | + test_eq(2m, 2m); |
| 199 | + |
| 200 | + test_less(1, 2m); |
| 201 | + test_eq(2, 2m); |
| 202 | + |
| 203 | + test_less(1.1, 2m); |
| 204 | + test_eq(Math.sqrt(4), 2m); |
| 205 | + |
| 206 | + test_less(2n, 3m); |
| 207 | + test_eq(3n, 3m); |
| 208 | + |
| 209 | + assert(BigDecimal("1234.1") === 1234.1m); |
| 210 | + assert(BigDecimal(" 1234.1") === 1234.1m); |
| 211 | + assert(BigDecimal(" 1234.1 ") === 1234.1m); |
| 212 | + |
| 213 | + assert(BigDecimal(0.1) === 0.1m); |
| 214 | + assert(BigDecimal(123) === 123m); |
| 215 | + assert(BigDecimal(true) === 1m); |
| 216 | + |
| 217 | + assert(123m + 1m === 124m); |
| 218 | + assert(123m - 1m === 122m); |
| 219 | + |
| 220 | + assert(3.2m * 3m === 9.6m); |
| 221 | + assert(10m / 2m === 5m); |
| 222 | + assertThrows(RangeError, () => { 10m / 3m } ); |
| 223 | + |
| 224 | + assert(10m % 3m === 1m); |
| 225 | + assert(-10m % 3m === -1m); |
| 226 | + |
| 227 | + assert(1234.5m ** 3m === 1881365963.625m); |
| 228 | + assertThrows(RangeError, () => { 2m ** 3.1m } ); |
| 229 | + assertThrows(RangeError, () => { 2m ** -3m } ); |
| 230 | + |
| 231 | + assert(BigDecimal.sqrt(2m, |
| 232 | + { roundingMode: "half-even", |
| 233 | + maximumSignificantDigits: 4 }) === 1.414m); |
| 234 | + assert(BigDecimal.sqrt(101m, |
| 235 | + { roundingMode: "half-even", |
| 236 | + maximumFractionDigits: 3 }) === 10.050m); |
| 237 | + assert(BigDecimal.sqrt(0.002m, |
| 238 | + { roundingMode: "half-even", |
| 239 | + maximumFractionDigits: 3 }) === 0.045m); |
| 240 | + |
| 241 | + assert(BigDecimal.round(3.14159m, |
| 242 | + { roundingMode: "half-even", |
| 243 | + maximumFractionDigits: 3 }) === 3.142m); |
| 244 | + |
| 245 | + assert(BigDecimal.add(3.14159m, 0.31212m, |
| 246 | + { roundingMode: "half-even", |
| 247 | + maximumFractionDigits: 2 }) === 3.45m); |
| 248 | + assert(BigDecimal.sub(3.14159m, 0.31212m, |
| 249 | + { roundingMode: "down", |
| 250 | + maximumFractionDigits: 2 }) === 2.82m); |
| 251 | + assert(BigDecimal.mul(3.14159m, 0.31212m, |
| 252 | + { roundingMode: "half-even", |
| 253 | + maximumFractionDigits: 3 }) === 0.981m); |
| 254 | + assert(BigDecimal.mod(3.14159m, 0.31211m, |
| 255 | + { roundingMode: "half-even", |
| 256 | + maximumFractionDigits: 4 }) === 0.0205m); |
| 257 | + assert(BigDecimal.div(20m, 3m, |
| 258 | + { roundingMode: "half-even", |
| 259 | + maximumSignificantDigits: 3 }) === 6.67m); |
| 260 | + assert(BigDecimal.div(20m, 3m, |
| 261 | + { roundingMode: "half-even", |
| 262 | + maximumFractionDigits: 50 }) === |
| 263 | + 6.66666666666666666666666666666666666666666666666667m); |
| 264 | + |
| 265 | + /* string conversion */ |
| 266 | + assert((1234.125m).toString(), "1234.125"); |
| 267 | + assert((1234.125m).toFixed(2), "1234.13"); |
| 268 | + assert((1234.125m).toFixed(2, "down"), "1234.12"); |
| 269 | + assert((1234.125m).toExponential(), "1.234125e+3"); |
| 270 | + assert((1234.125m).toExponential(5), "1.23413e+3"); |
| 271 | + assert((1234.125m).toExponential(5, "down"), "1.23412e+3"); |
| 272 | + assert((1234.125m).toPrecision(6), "1234.13"); |
| 273 | + assert((1234.125m).toPrecision(6, "down"), "1234.12"); |
| 274 | + assert((-1234.125m).toPrecision(6, "floor"), "-1234.13"); |
| 275 | +} |
| 276 | + |
| 277 | +test_bigint_ext(); |
| 278 | +test_bigfloat(); |
| 279 | +test_bigdecimal(); |
0 commit comments