Annotation of researchv10no/cmd/sml/src/bignums/realconst.sml, revision 1.1

1.1     ! root        1: (* Copyright 1989 by AT&T Bell Laboratories *)
        !             2: (*
        !             3: RealConst: generate ML real constants.
        !             4: RealConst uses long multiplication to find the correct bit pattern for
        !             5: the real.  This method is slow, but accurate, and works to any precision,
        !             6: which means that floats can be cross-compiled correctly.
        !             7: 
        !             8: The function emitreal should take (int * bool array * int) which represents
        !             9: a real value as (sign * fraction * exponent).
        !            10: The sign is 0 if the real is positive, 1 if negative.
        !            11: The fraction is a boolean array representing the bits; note that the most
        !            12: significant bit is in position 0.
        !            13: The exponent is the binary exponent of the normalized fraction.
        !            14: "Normalized" here means a number between 0 and 1.
        !            15: 
        !            16: The algorithm works inefficient on forms like 10000000.0; forms like 1E7 (with
        !            17: no bogus zeros) are better.  Also inefficient on forms like 0E23 or 1E~212.
        !            18: *)
        !            19: 
        !            20: signature PRIMREAL = sig
        !            21: val significant : int
        !            22: val outofrange : string -> unit
        !            23: val emitreal : (int * bool array * int) -> unit
        !            24: end
        !            25: 
        !            26: signature REALCONST = sig
        !            27: val realconst : string -> unit
        !            28: end
        !            29: 
        !            30: functor RealConst(P : PRIMREAL) : REALCONST =
        !            31: struct
        !            32: 
        !            33: open P
        !            34: 
        !            35: (* Use more than the required precision, then round at the end.  Because
        !            36:    bigints are signed, this is actually one bit less precision than you might
        !            37:    think.  This criterion works well enough for the 53 bits required by
        !            38:    Vax G format and IEEE double format, but has not been tested with other
        !            39:    values of significant. *)
        !            40: val precision = significant + 16 - ((significant + 8) mod 8)
        !            41: 
        !            42: (* A float is a WHOLE "fraction" and an exponent base TWO. *)
        !            43: type float = {frac : Bigint.bigint, exp : int}
        !            44: 
        !            45: val bigint = Bigint.bigint
        !            46: val plus = Bigint.+
        !            47: val times = Bigint.*
        !            48: infix plus times
        !            49: 
        !            50: (* Take a bigint and return a bool array of bits which will represent the
        !            51:    fraction.  The high (1/2) bit is in array position 0.  Assumes that
        !            52:    the bigint is positive.  This will work if the bigint is smaller than
        !            53:    the array or vice versa;  however, the number will be truncated, not
        !            54:    rounded. *)
        !            55: fun makebits (f,n) =
        !            56:     let val s = Bigint.size f
        !            57:        val bits = array(n,false)
        !            58:        fun onebit b = Bigint.getbit(f,s-1-b)
        !            59:        fun copybit n = (update(bits,n,onebit n); copybit (n+1))
        !            60:                        handle Subscript => ()
        !            61:     in  copybit 0;
        !            62:        bits
        !            63:     end
        !            64: 
        !            65: (* round a float to n significant digits *)
        !            66: local val one = bigint 1 in
        !            67: fun round (float as {frac=f,exp=e},n) =
        !            68:     let val shift = Bigint.size f + 1 - n
        !            69:     in
        !            70:        if shift <= 0 then float
        !            71:        else {frac = if Bigint.getbit(f,shift-1)
        !            72:                     then Bigint.>>(f, shift) plus one
        !            73:                     else Bigint.>>(f, shift),
        !            74:              exp = e + shift}
        !            75:     end
        !            76: end
        !            77: 
        !            78: (* maketenth:  create the float of one tenth, to any number of significant
        !            79:    digits, with no rounding on the last digit. *)
        !            80: local val zero = bigint 0 and one = bigint 1 and two = bigint 2 in
        !            81: fun maketenth 1 = {frac=one,exp= ~4}
        !            82:   | maketenth n =
        !            83:     let val {frac,exp} = maketenth(n-1)
        !            84:        val rec tenthbit = fn 0 => zero | 1 => one
        !            85:                            | 2 => one | 3 => zero | n => tenthbit(n mod 4)
        !            86:        val f = (frac times two) plus tenthbit n
        !            87:        val e = exp - 1
        !            88:     in
        !            89:        {frac=f,exp=e}
        !            90:     end
        !            91: end
        !            92: 
        !            93: (* float values ten and one tenth, to the correct precision. *)
        !            94: val ten = {frac=bigint 5, exp = 1}
        !            95: val tenth = round(maketenth(precision+1),precision)
        !            96: 
        !            97: (* Multiplies two floats together to the correct precision *)
        !            98: fun mult {frac=f1,exp=e1} {frac=f2,exp=e2} =
        !            99:     let val f = f1 times f2
        !           100:        val e : int = e1 + e2
        !           101:            (* shouldn't need the type constraint, our comp bug *)
        !           102:     in
        !           103:        round({frac=f,exp=e},precision)
        !           104:     end
        !           105: 
        !           106: (* Create a dynamic array of powers of ten *)
        !           107: structure DFA = Dynamic(struct open Array
        !           108:                               type float = {frac : Bigint.bigint, exp : int}
        !           109:                               type elem = unit->float
        !           110:                               type array = elem array
        !           111:                           end)
        !           112: local open DFA
        !           113:       exception Unknown
        !           114:       fun makelem e = (fn () => e)
        !           115:       val one = {frac=bigint 1,exp=0}
        !           116: in
        !           117:     val pos10 = array(fn () => raise Unknown)  (* 10^2^n *)
        !           118:     val _ = update(pos10,0,makelem ten)
        !           119:     val neg10 = array(fn () => raise Unknown)  (* 10^~2^n *)
        !           120:     val _ = update(neg10,0,makelem tenth)
        !           121:     fun access(arr,n) = (arr sub n) ()
        !           122:                        handle Unknown => let val last = access(arr,n-1)
        !           123:                                               val new = mult last last
        !           124:                                           in  update(arr,n,makelem new);
        !           125:                                               new
        !           126:                                           end
        !           127: 
        !           128:     fun pow10_2 0 = one
        !           129:       | pow10_2 n = if n > 0 then access(pos10,n-1) else access(neg10,~n-1)
        !           130:     fun raisepower(f,0) = f
        !           131:       | raisepower(f,e) =
        !           132:            let val sign = if e<0 then ~1 else 1
        !           133:                fun power(f,p) = mult f (pow10_2(sign*p))
        !           134:                fun raisep(f,0,_) = f
        !           135:                  | raisep(f,e,p) =
        !           136:                    if Bits.andb(e,1) = 1 then raisep(power(f,p),Bits.rshift(e,1),p+1)
        !           137:                    else raisep(f,Bits.rshift(e,1),p+1)
        !           138:            in  raisep(f,abs e,1)
        !           139:            end
        !           140: end
        !           141: 
        !           142: (* Takes a string list of the form {digit*.[digit*]}, and returns a bigint and
        !           143:    the exponent base 10.  Requires that the list contain a decimal point and
        !           144:    no trailing zeros (useless zeros after the decimal point). *)
        !           145: local val ten = bigint 10 and zero = bigint 0 in
        !           146: fun reducefrac f =
        !           147:     let fun getexp nil = 0
        !           148:          | getexp ("."::_) = 0
        !           149:          | getexp (_::tl) = getexp tl - 1
        !           150:        fun getwhole nil = zero
        !           151:          | getwhole ("."::tl) = getwhole tl
        !           152:          | getwhole ("0"::tl) = ten times getwhole tl
        !           153:          | getwhole (n::tl) = bigint(ord n - ord "0") plus (ten times getwhole tl)
        !           154:        val backwards = rev f
        !           155:        val whole = getwhole backwards
        !           156:        val exp = getexp backwards
        !           157:     in
        !           158:        (whole,exp)
        !           159:     end
        !           160: end
        !           161: 
        !           162: exception Toobig
        !           163: 
        !           164: (* Takes a legal ML float string and returns an (int * bigint * int)
        !           165:    which is the sign, whole "fraction", and power of ten exponent *)
        !           166: fun getparts s =
        !           167:     let datatype trailing = SIGNIFICANT | TRAILING
        !           168:        (* separate the fraction from the exponent, adding a decimal point if
        !           169:           there is none and eliminating trailing zeros *)
        !           170:        fun separate (nil,s) = (nil,nil,s)
        !           171:          | separate ("E"::tl,SIGNIFICANT) = (["."],tl,SIGNIFICANT)
        !           172:          | separate ("E"::tl,TRAILING) = (nil,tl,TRAILING)
        !           173:          | separate ("0"::tl,s) =
        !           174:                let val (r,e,s) = separate(tl,s)
        !           175:                in  case s of TRAILING => (r,e,TRAILING)
        !           176:                            | SIGNIFICANT => ("0"::r,e,SIGNIFICANT)
        !           177:                end
        !           178:          | separate ("."::tl,_) =
        !           179:                let val (r,e,_) = separate(tl,TRAILING)
        !           180:                in  ("."::r,e,SIGNIFICANT)
        !           181:                end
        !           182:          | separate (hd::tl,s) =
        !           183:                let val (r,e,_) = separate(tl,s)
        !           184:                in  (hd::r,e,SIGNIFICANT)
        !           185:                end
        !           186:        val (unsigned,sign) = case explode s of "~"::more => (more,1)
        !           187:                                              | other => (other,0)
        !           188:        val (frac_s,exp_s,_) = separate(unsigned,SIGNIFICANT)
        !           189:        fun atoi strlist =
        !           190:            let val numlist = map (fn n => ord n - ord "0") strlist
        !           191:            in  List.revfold (fn (a:int,b) => b*10 + a) numlist 0
        !           192:            end
        !           193:        val exp10 = (case exp_s of nil => 0
        !           194:                                 | "~"::more => ~(atoi more)
        !           195:                                 | other => atoi other)
        !           196:                    handle Overflow => raise Toobig
        !           197:        val (frac,exp) = reducefrac frac_s
        !           198:     in 
        !           199:        (sign,frac,exp10 + exp)
        !           200:     end
        !           201: 
        !           202: (* Takes a legal ML float string and returns an (int * bool array * int)
        !           203:    which is the sign, fraction (with the high(1/2) bit in array posn 0),
        !           204:    and exponent.  This is the form expected by the functor parameter
        !           205:    emitreal. *)
        !           206: fun makereal f = 
        !           207:     let val (sign,frac10,exp10) = getparts f
        !           208:        val float = raisepower(round({frac=frac10,exp=0},precision),exp10)
        !           209:        val (newf as {frac,exp}) = round(float,significant+1)
        !           210:        val size = Bigint.size frac
        !           211:        val bits = makebits(frac,significant)
        !           212:     in
        !           213:        case size of 0 => (0,bits,0)
        !           214:                   | _ => (sign,bits,exp + size)
        !           215:     end
        !           216: 
        !           217: fun realconst f = emitreal(makereal f)
        !           218:                  handle Toobig => (outofrange f; emitreal(makereal "0.0"))
        !           219: 
        !           220: end (* functor RealConst *)

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.