Home My Page Projects Code Snippets Project Openings diderot
 Summary Activity Tracker Tasks SCM

# SCM Repository

[diderot] Annotation of /trunk/src/common/float-lit.sml
 [diderot] / trunk / src / common / float-lit.sml

# Annotation of /trunk/src/common/float-lit.sml

Revision 26 - (view) (download)

 1 : jhr 26 (* float-lit.sml 2 : * 3 : * COPYRIGHT (c) 2010 The Diderot Project (http://diderot.cs.uchicago.edu) 4 : * All rights reserved. 5 : * 6 : * Internal representation of floating-point literals with limited 7 : * support for arithmetic. 8 : *) 9 : 10 : structure FloatLit :> sig 11 : 12 : type float 13 : 14 : val isZero : float -> bool 15 : 16 : (* return the representation of +/-0.0 *) 17 : val zero : bool ->float 18 : 19 : (* plus and minus one *) 20 : val one : float 21 : val m_one : float 22 : 23 : (* negate a float *) 24 : val negate : float -> float 25 : 26 : (* equality, comparisons, and hashing functions *) 27 : val same : (float * float) -> bool 28 : val compare : (float * float) -> order 29 : val hash : float -> word 30 : 31 : (* create a float from pieces: isNeg is true if the number is negative, whole 32 : * is the whole-number part, frac is the fractional part, and exp is the 33 : * exponent. This function may raise Overflow, when the exponent of the 34 : * normalized representation is too small or too large. 35 : *) 36 : val float : {isNeg : bool, whole : string, frac : string, exp : int} -> float 37 : val toString : float -> string 38 : 39 : (* external representation (for pickling) *) 40 : val toBytes : float -> Word8Vector.vector 41 : val fromBytes : Word8Vector.vector -> float 42 : 43 : end = struct 44 : 45 : structure SS = Substring 46 : structure W = Word 47 : structure W8V = Word8Vector 48 : 49 : (* The value {isNeg, digits=[d0, ..., dn], exp} represents the number 50 : * 51 : * [+/-] 0.d0...dn * 10^exp 52 : * 53 : * where the sign is negative if isNeg is true. 54 : *) 55 : type float = {isNeg : bool, digits : int list, exp : int} 56 : 57 : fun isZero {isNeg, digits=[0], exp} = true 58 : | isZero _ = false 59 : 60 : fun zero isNeg = {isNeg = isNeg, digits = [0], exp = 0} 61 : 62 : val one = {isNeg = false, digits = [1], exp = 1} 63 : val m_one = {isNeg = true, digits = [1], exp = 1} 64 : 65 : (* negate a float *) 66 : fun negate {isNeg, digits, exp} = 67 : {isNeg = not isNeg, digits = digits, exp = exp} 68 : 69 : (* equality, comparisons, and hashing functions *) 70 : fun same (f1 : float, f2 : float) = 71 : (#isNeg f1 = #isNeg f2) andalso (#exp f1 = #exp f2) 72 : andalso (#digits f1 = #digits f2) 73 : 74 : fun compare (f1 : float, f2 : float) = (case (#isNeg f1, #isNeg f2) 75 : of (false, true) => GREATER 76 : | (true, false) => LESS 77 : | _ => (case Int.compare(#exp f1, #exp f2) 78 : of EQUAL => let 79 : fun cmp ([], []) = EQUAL 80 : | cmp ([], _) = LESS 81 : | cmp (_, []) = GREATER 82 : | cmp (d1::r1, d2::r2) = (case Int.compare(d1, d2) 83 : of EQUAL => cmp(r1, r2) 84 : | order => order 85 : (* end case *)) 86 : in 87 : cmp (#digits f1, #digits f2) 88 : end 89 : | order => order 90 : (* end case *)) 91 : (* end case *)) 92 : 93 : fun hash {isNeg, digits, exp} = let 94 : fun hashDigits ([], h, _) = h 95 : | hashDigits (d::r, h, i) = 96 : hashDigits (r, W.<<(W.fromInt d, i+0w4), W.andb(i+0w1, 0wxf)) 97 : in 98 : hashDigits(digits, W.fromInt exp, 0w0) 99 : end 100 : 101 : fun float {isNeg, whole, frac, exp} = let 102 : fun cvtDigit (c, l) = (Char.ord c - Char.ord #"0") :: l 103 : fun isZero #"0" = true | isZero _ = false 104 : (* whole digits with leading zeros removed *) 105 : val whole = SS.dropl isZero (SS.full whole) 106 : (* fractional digits with trailing zeros removed *) 107 : val frac = SS.dropr isZero (SS.full frac) 108 : (* normalize by stripping leading zero digits *) 109 : fun normalize {isNeg, digits=[], exp} = zero isNeg 110 : | normalize {isNeg, digits=0::r, exp} = 111 : normalize {isNeg=isNeg, digits=r, exp=exp-1} 112 : | normalize flt = flt 113 : in 114 : case SS.foldr cvtDigit (SS.foldr cvtDigit [] frac) whole 115 : of [] => zero isNeg 116 : | digits => normalize { 117 : isNeg = isNeg, 118 : digits = digits, 119 : exp = exp + SS.size whole 120 : } 121 : (* end case *) 122 : end 123 : 124 : fun toString {isNeg, digits, exp} = let 125 : val s = if isNeg then "-0." else "0." 126 : val e = if exp < 0 127 : then ["e-", Int.toString(~exp)] 128 : else ["e", Int.toString exp] 129 : in 130 : concat(s :: List.foldr (fn (d, ds) => Int.toString d :: ds) e digits) 131 : end 132 : 133 : 134 : 135 : (***** external representation (for pickling) ***** 136 : * 137 : * The representation we use is a sequence of bytes: 138 : * 139 : * [sign, d0, ..., dn, exp0, ..., exp3] 140 : * 141 : * where 142 : * sign == 0 or 1 143 : * di == ith digit 144 : * expi == ith byte of exponent (exp0 is lsb, exp3 is msb). 145 : * 146 : * NOTE: we could pack the sign and digits into 4-bit nibbles, but we are keeping 147 : * things simple for now. 148 : *) 149 : 150 : fun toBytes {isNeg, digits, exp} = let 151 : val sign = if isNeg then 0w1 else 0w0 152 : val digits = List.map Word8.fromInt digits 153 : val exp' = W.fromInt exp 154 : fun byte i = Word8.fromLargeWord(W.toLargeWord((W.>>(exp', 0w8*i)))) 155 : val exp = [byte 0w0, byte 0w1, byte 0w2, byte 0w3] 156 : in 157 : Word8Vector.fromList(sign :: (digits @ exp)) 158 : end 159 : 160 : fun fromBytes v = let 161 : val ndigits = W8V.length v - 5 162 : fun error () = raise Fail "Bogus float pickle" 163 : val _ = if (ndigits < 1) then error() else () 164 : val isNeg = (case W8V.sub(v, 0) 165 : of 0w0 => false 166 : | 0w1 => true 167 : | _ => error() 168 : (* end case *)) 169 : fun digit i = Word8.toInt(W8V.sub(v, i+1)) 170 : fun byte i = W.<<( 171 : W.fromLargeWord(Word8.toLargeWord(W8V.sub(v, ndigits+1+i))), 172 : W.fromInt(8*i)) 173 : val exp = W.toIntX(W.orb(byte 3, W.orb(byte 2, W.orb(byte 1, byte 0)))) 174 : in 175 : {isNeg = isNeg, digits = List.tabulate(ndigits, digit), exp = exp} 176 : end 177 : 178 : end 179 :

 root@smlnj-gforge.cs.uchicago.edu ViewVC Help Powered by ViewVC 1.0.0