Smart Contract
FlowALPMath
A.6b00ff876c299c61.FlowALPMath
1access(all) contract FlowALPMath {
2
3 access(self) let ufix64Step: UFix128
4 access(self) let ufix64HalfStep: UFix128
5
6 access(all) let decimals: UInt8
7 access(all) let ufix64Decimals: UInt8
8
9 /// Deprecated: Use 1.0 directly
10 access(all) let one: UFix128
11 /// Deprecated: Use 0.0 directly
12 access(all) let zero: UFix128
13
14 access(all) enum RoundingMode: UInt8 {
15 access(all) case RoundDown
16 access(all) case RoundUp
17 access(all) case RoundHalfUp
18 access(all) case RoundEven
19 }
20
21 /// Fast exponentiation for UFix128 with a non-negative integer exponent (seconds).
22 /// Uses exponentiation-by-squaring with truncation at each multiply (fixed-point semantics)
23 access(all) view fun powUFix128(_ base: UFix128, _ expSeconds: UFix64): UFix128 {
24 if expSeconds == 0.0 { return 1.0 }
25 if base == 1.0 { return 1.0 }
26 var result: UFix128 = 1.0
27 var b = base
28 var e = expSeconds
29 // Floor the seconds to an integer count
30 var remaining = UInt64(e)
31 while remaining > 0 {
32 if remaining % 2 == 1 {
33 result = result * b
34 }
35 b = b * b
36 remaining = remaining / 2
37 }
38 return result
39 }
40
41 access(all) view fun toUFix64(_ value: UFix128, rounding: RoundingMode): UFix64 {
42 let truncated = UFix64(value)
43 let truncatedAs128 = UFix128(truncated)
44 let remainder = value - truncatedAs128
45
46 if remainder == 0.0 {
47 return truncated
48 }
49
50 switch rounding {
51 case self.RoundingMode.RoundDown:
52 return truncated
53 case self.RoundingMode.RoundUp:
54 return self.roundUp(truncated)
55 case self.RoundingMode.RoundHalfUp:
56 return remainder >= self.ufix64HalfStep ? self.roundUp(truncated) : truncated
57 case self.RoundingMode.RoundEven:
58 return self.roundHalfToEven(truncated, remainder)
59 default:
60 panic("Unsupported rounding mode")
61 }
62 }
63
64 access(all) view fun toUFix64Round(_ value: UFix128): UFix64 {
65 return self.toUFix64(value, rounding: self.RoundingMode.RoundHalfUp)
66 }
67
68 access(all) view fun toUFix64RoundDown(_ value: UFix128): UFix64 {
69 return self.toUFix64(value, rounding: self.RoundingMode.RoundDown)
70 }
71
72 access(all) view fun toUFix64RoundUp(_ value: UFix128): UFix64 {
73 return self.toUFix64(value, rounding: self.RoundingMode.RoundUp)
74 }
75
76 access(self) view fun roundUp(_ base: UFix64): UFix64 {
77 let increment: UFix64 = 0.00000001
78 return base >= UFix64.max - increment ? UFix64.max : base + increment
79 }
80
81 access(self) view fun roundHalfToEven(_ base: UFix64, _ remainder: UFix128): UFix64 {
82 if remainder < self.ufix64HalfStep {
83 return base
84 }
85 if remainder > self.ufix64HalfStep {
86 return self.roundUp(base)
87 }
88 let scaled = base * 100_000_000.0
89 let scaledInt = UInt64(scaled)
90 return scaledInt % 2 == 1 ? self.roundUp(base) : base
91 }
92
93 init() {
94 self.ufix64Step = 0.00000001
95 self.ufix64HalfStep = self.ufix64Step / 2.0
96 self.decimals = 24
97 self.ufix64Decimals = 8
98
99 self.one = 1.0
100 self.zero = 0.0
101 }
102}
103