Skip to content

Commit 96e6d65

Browse files
committed
Used decimal.js to sanity-check own implementation in tests; wrote primitive fuzzer
1 parent 271960f commit 96e6d65

File tree

9 files changed

+528
-7
lines changed

9 files changed

+528
-7
lines changed

package-lock.json

Lines changed: 7 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"devDependencies": {
2929
"@types/diff": "^4.0.2",
3030
"@types/tape": "^4.2.33",
31+
"decimal.js": "^10.2.0",
3132
"diff": "^4.0.1",
3233
"tape": "^4.10.2",
3334
"ts-node": "^8.1.0",

src/fixed-point-util/is-equal.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {ParseResult} from "./try-parse";
2+
import * as BigIntUtil from "../bigint-util";
23

34
export enum ZeroEqualityAlgorithm {
45
NEGATIVE_AND_POSITIVE_ZERO_ARE_EQUAL = "NEGATIVE_AND_POSITIVE_ZERO_ARE_EQUAL",
@@ -26,13 +27,13 @@ export function isEqual (
2627
if (a.isZero != b.isZero) {
2728
return false;
2829
}
29-
if (a.fixedPointIntegerPartLength != b.fixedPointIntegerPartLength) {
30+
if (!BigIntUtil.equal(a.fixedPointIntegerPartLength, b.fixedPointIntegerPartLength)) {
3031
return false;
3132
}
32-
if (a.fixedPointFractionalPartLength != b.fixedPointFractionalPartLength) {
33+
if (!BigIntUtil.equal(a.fixedPointFractionalPartLength, b.fixedPointFractionalPartLength)) {
3334
return false;
3435
}
35-
if (a.fixedPointLength != b.fixedPointLength) {
36+
if (!BigIntUtil.equal(a.fixedPointLength, b.fixedPointLength)) {
3637
return false;
3738
}
3839
return (

src/floating-point-util/to-integer-and-exponent.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ export function toIntegerAndExponent (
1919
BigInt(arg.fractionalPart.length)
2020
);
2121
const integerPart = (
22+
arg.integerPart == "0" ?
23+
arg.fractionalPart.replace(/^(0+)/, "") :
2224
arg.integerPart + arg.fractionalPart
2325
);
2426
return {

src/floating-point-util/try-parse.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {getBigIntFactoryFunctionOrError} from "../type-util";
22
import * as BigIntUtil from "../bigint-util";
33

4-
export const floatingPointRegex = /^([-+])?([0-9]*\.?[0-9]+)([eE]([-+])?([0-9]+))?$/;
4+
export const floatingPointRegex = /^([-+])?([0-9]+\.?[0-9]*|[0-9]*\.?[0-9]+)([eE]([-+])?([0-9]+))?$/;
55

66
export interface ParseResult {
77
/**
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
import * as tape from "tape";
2+
import * as tm from "../../../../../dist";
3+
import * as decimalJs from "decimal.js";
4+
5+
function test (t : tape.Test, str : string) {
6+
const parsedStr = tm.FixedPointUtil.tryParse(str);
7+
if (parsedStr == undefined) {
8+
t.throws(() => {
9+
new decimalJs.Decimal(str)
10+
}, str);
11+
return;
12+
}
13+
try {
14+
new decimalJs.Decimal(str)
15+
} catch (_err) {
16+
t.fail(`Should parse ${str}`);
17+
return;
18+
}
19+
const decimal = new decimalJs.Decimal(str);
20+
/**
21+
* + str -> FixedPointUtil.tryParse()
22+
* + str -> new Decimal() -> FixedPointUtil.tryParse()
23+
*
24+
* Then, we check if the output is the same.
25+
*/
26+
const parsedDecimal = tm.FixedPointUtil.tryParse(decimal.toString());
27+
if (parsedDecimal == undefined) {
28+
t.fail(`Could not parse ${str} -> ${decimal.toString()}`);
29+
return;
30+
}
31+
32+
t.true(
33+
tm.FixedPointUtil.isEqual(
34+
parsedStr,
35+
parsedDecimal,
36+
tm.FixedPointUtil.ZeroEqualityAlgorithm.NEGATIVE_AND_POSITIVE_ZERO_ARE_EQUAL
37+
),
38+
str
39+
);
40+
t.deepEqual(
41+
parsedStr.getFixedPointString(),
42+
(
43+
parsedDecimal.isZero ?
44+
"-" + parsedDecimal.getFixedPointString() :
45+
parsedDecimal.getFixedPointString()
46+
),
47+
str
48+
);
49+
t.deepEqual(
50+
parsedStr.isInteger,
51+
decimal.isInteger(),
52+
str
53+
);
54+
t.deepEqual(
55+
parsedStr.isNegative,
56+
decimal.isNegative(),
57+
str
58+
);
59+
t.deepEqual(
60+
parsedStr.isZero,
61+
decimal.isZero(),
62+
str
63+
);
64+
}
65+
function findAllPermutations (
66+
possiblePermutations : string[][],
67+
callback : (str : string) => void
68+
) {
69+
let permutationIndex = 0;
70+
71+
while (true) {
72+
let num = permutationIndex;
73+
let str : string[] = [];
74+
for (let i=possiblePermutations.length-1; i>=0; --i) {
75+
const arr = possiblePermutations[i];
76+
const arrIndex = num%arr.length;
77+
const ele = arr[arrIndex];
78+
str.push(ele);
79+
80+
num = Math.floor(num / arr.length);
81+
}
82+
if (num != 0) {
83+
return;
84+
}
85+
callback(str.reverse().join(""));
86+
++permutationIndex;
87+
}
88+
}
89+
tape(__filename, t => {
90+
const possiblePermutations = [
91+
["-"],
92+
[
93+
"",
94+
"0",
95+
"1",
96+
97+
"00",
98+
"01",
99+
"10",
100+
"11",
101+
102+
"000",
103+
"001",
104+
"010",
105+
"011",
106+
107+
"100",
108+
"101",
109+
"110",
110+
"111",
111+
],
112+
["", "."],
113+
[
114+
"",
115+
"0",
116+
"1",
117+
118+
"00",
119+
"01",
120+
"10",
121+
"11",
122+
123+
"000",
124+
"001",
125+
"010",
126+
"011",
127+
128+
"100",
129+
"101",
130+
"110",
131+
"111",
132+
],
133+
[
134+
"",
135+
"e",
136+
"E",
137+
138+
"e+",
139+
"E+",
140+
141+
"e-",
142+
"E-",
143+
],
144+
[
145+
"",
146+
"0",
147+
"1",
148+
149+
"00",
150+
"01",
151+
"10",
152+
"11",
153+
154+
"000",
155+
"001",
156+
"010",
157+
"011",
158+
159+
"100",
160+
"101",
161+
"110",
162+
"111",
163+
],
164+
];
165+
findAllPermutations(
166+
possiblePermutations,
167+
(str) => test(t, str)
168+
);
169+
170+
t.end();
171+
});

0 commit comments

Comments
 (0)