-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathviete.go
81 lines (66 loc) · 1.6 KB
/
viete.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package pidentities
import (
. "github.com/solidifylabs/specops" //lint:ignore ST1001 SpecOps DSL is designed to be dot-imported
"github.com/solidifylabs/specops/stack"
)
// Viete implements Viète's formula.
func Viete() Code {
return convert(viete)
}
func viete() (Code, uint8) {
const bits = 127
// https://en.wikipedia.org/wiki/Vi%C3%A8te%27s_formula
const (
loopCounter = Inverted(DUP1) + iota
precision
result
bigTwo
root
)
const depth = uint(root - loopCounter + 1)
const (
swapCounter = Inverted(SWAP1) + iota
_
swapResult
)
code := Code{
PUSH(0x68a8), // loops left (~25M gas)
PUSH(bits), // precision
Fn(SHL, precision, PUSH(1)), // result
Fn(SHL, precision, PUSH(2)), // constant fixed-precision 2
PUSH0, // root
stack.ExpectDepth(depth),
JUMPDEST("loop"),
stack.SetDepth(depth),
Fn(SHL, precision, // Shift to prepare for sqrt()
Fn(ADD, bigTwo /* top = last root */), // The next radicand is always the last root + 2
),
stack.ExpectDepth(depth),
stack.SetDepth(1), // hack for sqrt() because it expects this; SpecOps needs stack.ExpectDeeperThan().
sqrtWithCleanup(), //
stack.SetDepth(depth), // undo the previous set
Fn(swapResult,
Fn(SHR,
Fn(ADD, precision, PUSH(1)),
Fn(MUL,
result,
root,
),
),
), POP,
stack.ExpectDepth(depth),
Fn(JUMPI,
PUSH("loop"),
Fn(LT,
PUSH0,
Fn(swapCounter, Fn(SUB, loopCounter, PUSH(1))),
),
),
stack.ExpectDepth(depth),
Fn(DIV,
Fn(SHL, precision, bigTwo),
result,
),
}
return code, bits
}