float-finite-product-quotient.tri (4359B)
1 -- Benchmark-only finite signed multiplication and nonzero-divisor division. 2 -- Checked interface matches finite.tri; error 3 rejects a zero divisor. 3 !import native_math as N 4 !import kernels as K 5 !import fast as F 6 !import finite as B 7 !import adders as A 8 !export * 9 check operation a b = K.lazy (_ : t t 2) 10 (_ : K.lazy (_ : t t 1) (_ : t (t t) (operation a b)) 11 (K.either (N.equal (B.exponent a) 2047) (N.equal (B.exponent b) 2047))) 12 (K.either (N.gte a 18446744073709551616) (N.gte b 18446744073709551616)) 13 product kernel a b = let da = B.decode a in let db = B.decode b in 14 let negative = K.xor (B.sign da) (B.sign db) in K.lazy 15 (_ : B.zero negative) 16 (_ : B.signed negative (F.selective (N.subtract (N.add (B.scale da) (B.scale db)) 2304) 17 (kernel (B.mant da) (B.mant db)))) 18 (K.either (N.zero (B.mant da)) (N.zero (B.mant db))) 19 nativeProduct = product N.multiply 20 orderedProduct = product A.orderedMultiply 21 -- Exact control: divide a 109-bit numerator by the normalized divisor. 22 nativeQuotient a b = N.divMod (F.shiftPositive 56 a) b 23 -- Produce the exact quotient/remainder by consuming 56 fractional bits. 24 -- Initial quotient is 0 or 1 because 1/2 < a/b < 2. 25 walk count divisor q r = K.lazy (_ : t q r) 26 (_ : K.lazy (_ : t (F.shiftPositive count q) 0) 27 (_ : let shifted = F.zeros1 r in K.lazy 28 (_ : walk (N.predecessor count) divisor (K.node t q) shifted) 29 (_ : walk (N.predecessor count) divisor (N.successor (K.node t q)) (N.subtract shifted divisor)) 30 (N.lt shifted divisor)) (N.zero r)) (N.zero count) 31 boundedQuotient a b = K.lazy (_ : walk 56 b 0 a) 32 (_ : walk 56 b 1 (N.subtract a b)) (N.lt a b) 33 -- Round-to-odd retains the discarded rational remainder. At least three 34 -- working bits survive normalization, so this only feeds immediate final RNE. 35 jam split = let q = K.head split in K.lazy (_ : q) 36 (_ : K.choose q (N.successor q) (N.zero (K.tail split))) (N.odd q) 37 quotient kernel a b = let da = B.decode a in let db = B.decode b in 38 let negative = K.xor (B.sign da) (B.sign db) in K.lazy 39 (_ : B.zero negative) 40 (_ : B.signed negative (F.selective (N.subtract (N.add 2248 (B.scale da)) (B.scale db)) 41 (jam (kernel (B.mant da) (B.mant db))))) (N.zero (B.mant da)) 42 -- Range/nonfinite checks precede division-by-zero rejection; error codes are 43 -- domain errors in this finite-input test interface. 44 checkedQuotient kernel a b = let result = check (quotient kernel) a b in K.lazy 45 (_ : K.lazy (_ : t t 3) (_ : result) (N.zero (B.mant (B.decode b)))) 46 (_ : result) (K.head result) 47 nativeMultiplyOne x = check nativeProduct (K.head x) (K.tail x) 48 orderedMultiplyOne x = check orderedProduct (K.head x) (K.tail x) 49 nativeDivideOne x = checkedQuotient nativeQuotient (K.head x) (K.tail x) 50 boundedDivideOne x = checkedQuotient boundedQuotient (K.head x) (K.tail x) 51 nativeMultiplies xs = K.map nativeMultiplyOne xs 52 orderedMultiplies xs = K.map orderedMultiplyOne xs 53 nativeDivides xs = K.map nativeDivideOne xs 54 boundedDivides xs = K.map boundedDivideOne xs 55 nativeRawOne x = nativeQuotient (K.head x) (K.tail x) 56 boundedRawOne x = boundedQuotient (K.head x) (K.tail x) 57 nativeRaw xs = K.map nativeRawOne xs 58 boundedRaw xs = K.map boundedRawOne xs 59 spin x = spin x 60 productZeroDemand x = product (spin x) 0 1 61 quotientZeroDemand x = quotient (spin x) 0 1 62 jamOddDemand x = jam (t 7 (spin x)) 63 rangeDemand x = check nativeProduct 18446744073709551616 (spin x) 64 walkExactDemand x = walk 56 (spin x) 1 0 65 -- Negative rounding controls: separate precision/quantum cuts and dropped remainder. 66 truncateKernel a b = t (K.head (boundedQuotient a b)) 0 67 truncateDivideOne x = checkedQuotient truncateKernel (K.head x) (K.tail x) 68 truncateDivides xs = K.map truncateDivideOne xs 69 doubleProduct a b = let da = B.decode a in let db = B.decode b in 70 let n = N.multiply (B.mant da) (B.mant db) in 71 let cut = N.subtract (K.width n) 53 in let first = K.roundL cut n in 72 let result = F.selective (N.add cut (N.subtract (N.add (B.scale da) (B.scale db)) 2304)) (K.head first) in 73 let ix = K.either (K.tail first) (K.head (K.tail result)) in 74 B.signed (K.xor (B.sign da) (B.sign db)) 75 (t (K.head result) (t ix (K.both ix (N.lt (K.head result) 4503599627370496)))) 76 doubleProductOne x = check doubleProduct (K.head x) (K.tail x) 77 doubleProducts xs = K.map doubleProductOne xs 78 divisionRejectDemand x = checkedQuotient (spin x) 1 0