Skip to content

Commit eb05083

Browse files
committed
Tweak tests and precision accuracy
1 parent bd9bebc commit eb05083

File tree

3 files changed

+113
-27
lines changed

3 files changed

+113
-27
lines changed

precision/index.js

+95-21
Original file line numberDiff line numberDiff line change
@@ -12,88 +12,93 @@ export function configurePrecision (engine, constructor, compatible = true) {
1212

1313
engine.addMethod('+', {
1414
method: (data) => {
15-
if (typeof data === 'string') return constructor(data)
16-
if (typeof data === 'number') return constructor(data)
17-
let res = constructor(data[0])
15+
if (typeof data === 'string') return new constructor(data)
16+
if (typeof data === 'number') return new constructor(data)
17+
let res = new constructor(data[0])
1818
for (let i = 1; i < data.length; i++) res = res.plus(data[i])
1919
return res
2020
},
2121
compile: (args, buildState) => {
2222
if (Array.isArray(args)) {
23-
let res = buildState.compile`(engine.precision(${args[0]}))`
23+
let res = buildState.compile`(new engine.precision(${args[0]}))`
2424
for (let i = 1; i < args.length; i++) res = buildState.compile`(${res}.plus(${args[i]}))`
2525
return res
2626
}
2727
return false
28-
}
28+
},
29+
traverse: true
2930
}, { optimizeUnary: true, sync: true, deterministic: true })
3031

3132
engine.addMethod('-', {
3233
method: (data) => {
33-
if (typeof data === 'string') return constructor(data).mul(-1)
34-
if (typeof data === 'number') return constructor(data).mul(-1)
35-
let res = constructor(data[0])
34+
if (typeof data === 'string') return new constructor(data).mul(-1)
35+
if (typeof data === 'number') return new constructor(data).mul(-1)
36+
let res = new constructor(data[0])
3637
if (data.length === 1) return res.mul(-1)
3738
for (let i = 1; i < data.length; i++) res = res.minus(data[i])
3839
return res
3940
},
4041
compile: (args, buildState) => {
4142
if (Array.isArray(args)) {
42-
let res = buildState.compile`(engine.precision(${args[0]}))`
43+
let res = buildState.compile`(new engine.precision(${args[0]}))`
4344
if (args.length === 1) return buildState.compile`(${res}.mul(-1))`
4445
for (let i = 1; i < args.length; i++) res = buildState.compile`(${res}.minus(${args[i]}))`
4546
return res
4647
}
4748
return false
48-
}
49+
},
50+
traverse: true
4951
}, { optimizeUnary: true, sync: true, deterministic: true })
5052

5153
engine.addMethod('*', {
5254
method: (data) => {
53-
let res = constructor(data[0])
55+
let res = new constructor(data[0])
5456
for (let i = 1; i < data.length; i++) res = res.mul(data[i])
5557
return res
5658
},
5759
compile: (args, buildState) => {
5860
if (Array.isArray(args)) {
59-
let res = buildState.compile`(engine.precision(${args[0]}))`
61+
let res = buildState.compile`(new engine.precision(${args[0]}))`
6062
for (let i = 1; i < args.length; i++) res = buildState.compile`(${res}.mul(${args[i]}))`
6163
return res
6264
}
6365
return false
64-
}
66+
},
67+
traverse: true
6568
}, { sync: true, deterministic: true })
6669

6770
engine.addMethod('/', {
6871
method: (data) => {
69-
let res = constructor(data[0])
72+
let res = new constructor(data[0])
7073
for (let i = 1; i < data.length; i++) res = res.div(data[i])
7174
return res
7275
},
7376
compile: (args, buildState) => {
7477
if (Array.isArray(args)) {
75-
let res = buildState.compile`(engine.precision(${args[0]}))`
78+
let res = buildState.compile`(new engine.precision(${args[0]}))`
7679
for (let i = 1; i < args.length; i++) res = buildState.compile`(${res}.div(${args[i]}))`
7780
return res
7881
}
7982
return false
80-
}
83+
},
84+
traverse: true
8185
}, { sync: true, deterministic: true })
8286

8387
engine.addMethod('%', {
8488
method: (data) => {
85-
let res = constructor(data[0])
89+
let res = new constructor(data[0])
8690
for (let i = 1; i < data.length; i++) res = res.mod(data[i])
8791
return res
8892
},
8993
compile: (args, buildState) => {
9094
if (Array.isArray(args)) {
91-
let res = buildState.compile`(engine.precision(${args[0]}))`
95+
let res = buildState.compile`(new engine.precision(${args[0]}))`
9296
for (let i = 1; i < args.length; i++) res = buildState.compile`(${res}.mod(${args[i]}))`
9397
return res
9498
}
9599
return false
96-
}
100+
},
101+
traverse: true
97102
}, { sync: true, deterministic: true })
98103

99104
engine.addMethod('===', {
@@ -109,7 +114,8 @@ export function configurePrecision (engine, constructor, compatible = true) {
109114
if (args[i - 1] !== args[i]) return false
110115
}
111116
return true
112-
}
117+
},
118+
traverse: true
113119
}, { sync: true, deterministic: true })
114120

115121
engine.addMethod('!==', {
@@ -126,6 +132,74 @@ export function configurePrecision (engine, constructor, compatible = true) {
126132
}
127133
return false
128134
},
129-
deterministic: true
135+
traverse: true
136+
}, { sync: true, deterministic: true })
137+
138+
engine.addMethod('>', {
139+
method: (args) => {
140+
if (args.length === 2) {
141+
if (args[0].gt) return args[0].gt(args[1])
142+
if (args[1].lt) return args[1].lt(args[0])
143+
return args[0] > args[1]
144+
}
145+
for (let i = 1; i < args.length; i++) {
146+
if (args[i - 1].gt && !args[i - 1].gt(args[i])) return false
147+
if (args[i].lt && !args[i].lt(args[i - 1])) return false
148+
if (args[i - 1] <= args[i]) return false
149+
}
150+
return true
151+
},
152+
traverse: true
153+
}, { sync: true, deterministic: true })
154+
155+
engine.addMethod('>=', {
156+
method: (args) => {
157+
if (args.length === 2) {
158+
if (args[0].gte) return args[0].gte(args[1])
159+
if (args[1].lte) return args[1].lte(args[0])
160+
return args[0] >= args[1]
161+
}
162+
for (let i = 1; i < args.length; i++) {
163+
if (args[i - 1].gte && !args[i - 1].gte(args[i])) return false
164+
if (args[i].lte && !args[i].lte(args[i - 1])) return false
165+
if (args[i - 1] < args[i]) return false
166+
}
167+
return true
168+
},
169+
traverse: true
170+
}, { sync: true, deterministic: true })
171+
172+
engine.addMethod('<', {
173+
method: (args) => {
174+
if (args.length === 2) {
175+
if (args[0].lt) return args[0].lt(args[1])
176+
if (args[1].gt) return args[1].gt(args[0])
177+
return args[0] < args[1]
178+
}
179+
for (let i = 1; i < args.length; i++) {
180+
if (args[i - 1].lt && !args[i - 1].lt(args[i])) return false
181+
if (args[i].gt && !args[i].gt(args[i - 1])) return false
182+
if (args[i - 1] >= args[i]) return false
183+
}
184+
return true
185+
},
186+
traverse: true
187+
}, { sync: true, deterministic: true })
188+
189+
engine.addMethod('<=', {
190+
method: (args) => {
191+
if (args.length === 2) {
192+
if (args[0].lte) return args[0].lte(args[1])
193+
if (args[1].gte) return args[1].gte(args[0])
194+
return args[0] <= args[1]
195+
}
196+
for (let i = 1; i < args.length; i++) {
197+
if (args[i - 1].lte && !args[i - 1].lte(args[i])) return false
198+
if (args[i].gte && !args[i].gte(args[i - 1])) return false
199+
if (args[i - 1] > args[i]) return false
200+
}
201+
return true
202+
},
203+
traverse: true
130204
}, { sync: true, deterministic: true })
131205
}

precision/scratch.js

+4-5
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,14 @@ Decimal.prototype.toString = function () {
66
return this.toFixed()
77
}
88

9-
Decimal.prototype.valueOf = function () {
10-
return this.toFixed()
11-
}
12-
139
const ieee754Engine = new LogicEngine()
1410
const decimalEngine = new LogicEngine()
1511
configurePrecision(decimalEngine, Decimal.clone({ precision: 100 }))
1612

17-
console.log(decimalEngine.build({ '+': ['85070591730234615847396907784232501249', 100] })().toFixed()) // 85070591730234615847396907784232501349
13+
console.log(ieee754Engine.build({ '*': [9007199254740991, 5] })()) // 45035996273704950, inaccurate
14+
console.log(decimalEngine.build({ '*': [9007199254740991, 5] })()) // 45035996273704955, accurate
15+
16+
console.log(ieee754Engine.run({ '+': [0.1, 0.2] })) // 0.30000000000000004
1817
console.log(decimalEngine.run({ '+': [0.1, 0.2] })) // 0.3
1918

2019
console.log(ieee754Engine.run({ '>': [{ '+': [0.1, 0.2] }, 0.3] })) // true, because 0.1 + 0.2 = 0.30000000000000004

precision/test.js

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { AsyncLogicEngine } from '../index.js'
1+
import { AsyncLogicEngine, LogicEngine } from '../index.js'
22
import { Decimal } from 'decimal.js'
33
import { configurePrecision } from './index.js'
44
import { isDeepStrictEqual } from 'util'
@@ -32,3 +32,16 @@ for (const test of tests) {
3232
}
3333

3434
console.log(count, 'Wrong')
35+
36+
37+
const decimalEngineSync = new LogicEngine(undefined, { compatible: true })
38+
configurePrecision(decimalEngineSync, Decimal.clone({ precision: 100 }))
39+
40+
console.time('built')
41+
for (const test of tests) {
42+
const f = decimalEngineSync.build(test[0])
43+
for (let i = 0; i < 1e5; i++) {
44+
f(test[1])
45+
}
46+
}
47+
console.timeEnd('built')

0 commit comments

Comments
 (0)