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