aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/lux/data/number/i64.lux
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--stdlib/source/lux/data/number/i64.lux40
1 files changed, 24 insertions, 16 deletions
diff --git a/stdlib/source/lux/data/number/i64.lux b/stdlib/source/lux/data/number/i64.lux
index 79bf7632d..249ae9046 100644
--- a/stdlib/source/lux/data/number/i64.lux
+++ b/stdlib/source/lux/data/number/i64.lux
@@ -143,25 +143,33 @@
[conjunction ..true ..and]
)
-(type: #export (Sub size)
- {#narrow (-> I64 (I64 size))
- #wide (-> (I64 size) I64)
- #equivalence (Equivalence (I64 size))})
+(signature: #export (Sub size)
+ (: (Equivalence (I64 size))
+ &equivalence)
+ (: Nat
+ width)
+ (: (-> I64 (I64 size))
+ narrow)
+ (: (-> (I64 size) I64)
+ widen))
(def: #export (sub width)
(Ex [size] (-> Nat (Maybe (Sub size))))
(if (.and (n.> 0 width)
(n.< ..width width))
- (let [top (dec width)
- shift (n.- width ..width)
- sign (..bit top)
- number (..mask (dec width))]
- (#.Some {#narrow (function (narrow value)
- (..or (|> value (..and ..sign) (..logic-right-shift shift))
- (|> value (..and number))))
- #wide (function (wide value)
- (|> (..or (|> value (..and sign) (..left-shift shift))
- (|> value (..clear top)))
- .i64))
- #equivalence ..equivalence}))
+ (let [sign-shift (n.- width ..width)
+ sign (..bit (dec width))
+ mantissa (..mask (dec width))
+ co-mantissa (..xor (.i64 -1) mantissa)]
+ (#.Some (: Sub
+ (structure
+ (def: &equivalence ..equivalence)
+ (def: width width)
+ (def: (narrow value)
+ (..or (|> value (..and ..sign) (..logic-right-shift sign-shift))
+ (|> value (..and mantissa))))
+ (def: (widen value)
+ (.i64 (case (.nat (..and sign value))
+ 0 value
+ _ (..or co-mantissa value))))))))
#.None))