Annotation of researchv10no/cmd/sml/src/boot/math.sml, revision 1.1

1.1     ! root        1: (* Copyright 1989 by AT&T Bell Laboratories *)
        !             2: (* The following functions were adapted from the 4.3BSD math library.
        !             3:    Eventually, each machine supported should have a hand-coded math
        !             4:    functor with more efficient versions of these functions.
        !             5: 
        !             6: ***************************************************************************
        !             7: *                                                                         * 
        !             8: * Copyright (c) 1985 Regents of the University of California.             *
        !             9: *                                                                         * 
        !            10: * Use and reproduction of this software are granted  in  accordance  with *
        !            11: * the terms and conditions specified in  the  Berkeley  Software  License *
        !            12: * Agreement (in particular, this entails acknowledgement of the programs' *
        !            13: * source, and inclusion of this notice) with the additional understanding *
        !            14: * that  all  recipients  should regard themselves as participants  in  an *
        !            15: * ongoing  research  project and hence should  feel  obligated  to report *
        !            16: * their  experiences (good or bad) with these elementary function  codes, *
        !            17: * using "sendbug 4bsd-bugs@BERKELEY", to the authors.                     *
        !            18: *                                                                         *
        !            19: * K.C. Ng, with Z-S. Alex Liu, S. McDonald, P. Tang, W. Kahan.            *
        !            20: * Revised on 5/10/85, 5/13/85, 6/14/85, 8/20/85, 8/27/85, 9/11/85.        *
        !            21: *                                                                         *
        !            22: ***************************************************************************
        !            23: 
        !            24: *)
        !            25: 
        !            26: signature MATH =
        !            27:   sig
        !            28:     exception Sqrt and Exp and Ln
        !            29:     val sqrt : real -> real
        !            30:     val sin : real -> real
        !            31:     val cos : real -> real
        !            32:     val arctan : real -> real
        !            33:     val exp : real -> real
        !            34:     val ln : real -> real
        !            35:   end
        !            36: 
        !            37: structure Math : MATH = struct
        !            38: 
        !            39: structure Assembly : ASSEMBLY = Core.Assembly
        !            40: 
        !            41: infix 7 * /
        !            42: infix 6 + -
        !            43: infix 4 > < >= <=
        !            44: 
        !            45: exception Real = Assembly.Real
        !            46: exception Sqrt
        !            47: exception Exp
        !            48: exception Ln
        !            49: 
        !            50: val scalb = Assembly.A.scalb
        !            51: val logb = Assembly.A.logb
        !            52: 
        !            53: val ~ = InLine.fneg
        !            54: val op + = InLine.fadd
        !            55: val op - = InLine.fsub
        !            56: val op * = InLine.fmul
        !            57: val op / = InLine.fdiv
        !            58: val op > = InLine.fgt
        !            59: val op < = InLine.flt
        !            60: val op >= = InLine.fge
        !            61: val op <= = InLine.fle
        !            62: 
        !            63: val ieql = InLine.ieql
        !            64: val ineq = InLine.ineq
        !            65: val feql = InLine.feql
        !            66: 
        !            67: val negone = ~1.0
        !            68: val zero = 0.0
        !            69: val half = 0.5
        !            70: val one = 1.0
        !            71: val two = 2.0
        !            72: val four = 4.0
        !            73: 
        !            74: fun copysign(a,b) =
        !            75:       case (a<zero,b<zero) of
        !            76:              (true,true) => a
        !            77:            | (false,false) => a
        !            78:            | _ => ~a
        !            79: 
        !            80: fun abs x = if x < zero then ~x else x
        !            81: fun mod(a,b) = InLine.-(a,InLine.*(InLine.div(a,b),b))
        !            82: local fun rtoi (pred,init) =
        !            83:          let fun loop n =
        !            84:              if pred n
        !            85:              then init
        !            86:              else let val (i,r) = loop(n * half)
        !            87:                       val i' = InLine.lshift(i,1)
        !            88:                       val r' = r+r
        !            89:                   in if n-r' < one then (i',r') else (InLine.+(i',1),r'+one)
        !            90:                   end
        !            91:          in loop
        !            92:          end
        !            93:       val pton = rtoi(fn x => x < one, (0,zero))
        !            94:       val nton = rtoi(fn x => x >= negone, (~1,negone))
        !            95:       fun fl n = if n < zero then nton n else pton n
        !            96:       fun tr n = #1(pton n)
        !            97: in 
        !            98: fun truncate n = if n < zero then InLine.~(tr(~n)) else tr n
        !            99: val floor = Assembly.A.floor
        !           100: fun realfloor n = #2(fl n)
        !           101: fun ceiling n = InLine.~(floor(~n))
        !           102: end
        !           103: local fun loop 0 = zero
        !           104:         | loop n = let val x = two * loop(InLine.rshift(n,1))
        !           105:                   in case InLine.andb(n,1) of 0 => x | 1 => x + one
        !           106:                   end
        !           107: in fun real n = if InLine.<(n,0) then ~(loop(InLine.~ n)) else loop n
        !           108: end
        !           109: 
        !           110: (* Not a true drem - rounding on .5 should go to the even case. *)
        !           111: fun drem(x,y) =
        !           112:     let val n = x/y+half
        !           113:        val N = if abs n < 9.007199254741E15 (* about 2^53 *)
        !           114:                then realfloor n
        !           115:                       handle Real _ =>
        !           116:                         scalb(realfloor(scalb(n,InLine.~(logb n))),logb n)
        !           117:                else n
        !           118:     in  x - N * y
        !           119:     end
        !           120: 
        !           121: (* sin/cos *)
        !           122: local
        !           123:     val S0 = ~1.6666666666666463126E~1
        !           124:     val S1 =  8.3333333332992771264E~3
        !           125:     val S2 = ~1.9841269816180999116E~4
        !           126:     val S3 =  2.7557309793219876880E~6
        !           127:     val S4 = ~2.5050225177523807003E~8
        !           128:     val S5 =  1.5868926979889205164E~10
        !           129: in  fun sin__S z = (z*(S0+z*(S1+z*(S2+z*(S3+z*(S4+z*S5))))))
        !           130: end
        !           131: 
        !           132: local
        !           133:     val C0 =  4.1666666666666504759E~2
        !           134:     val C1 = ~1.3888888888865301516E~3
        !           135:     val C2 =  2.4801587269650015769E~5
        !           136:     val C3 = ~2.7557304623183959811E~7
        !           137:     val C4 =  2.0873958177697780076E~9
        !           138:     val C5 = ~1.1250289076471311557E~11
        !           139: in  fun cos__C z = (z*z*(C0+z*(C1+z*(C2+z*(C3+z*(C4+z*C5))))))
        !           140: end
        !           141: 
        !           142: val PIo4   =  7.8539816339744827900E~1
        !           143: val PIo2   =  1.5707963267948965580E0
        !           144: val PI3o4  =  2.3561944901923448370E0
        !           145: val PI     =  3.1415926535897931160E0
        !           146: val PI2    =  6.2831853071795862320E0
        !           147: 
        !           148: local
        !           149:     val thresh =  2.6117239648121182150E~1
        !           150: in  fun S y = y + y * sin__S(y*y)
        !           151:     fun C y =
        !           152:        let val yy = y*y
        !           153:            val c = cos__C yy
        !           154:            val Y = yy/two
        !           155:        in  if Y < thresh then one - (Y - c)
        !           156:            else half - (Y - half - c)
        !           157:        end
        !           158: end
        !           159:     fun sin x =
        !           160:        let val x = drem(x,PI2)
        !           161:            val a = abs x
        !           162:            val y = if a >= PI3o4 then copysign(PI-a,x) else a
        !           163:        in  if y >= PIo4 then copysign(C(PIo2-a),x)
        !           164:            else S y
        !           165:        end
        !           166: 
        !           167:     fun cos x =
        !           168:        let val x = drem(x,PI2)
        !           169:            val a = abs x
        !           170:            val (s,y) = if a >= PI3o4
        !           171:                            then (fn x => ~x,PI-a)
        !           172:                            else (fn x => x,a)
        !           173:        in  if y < PIo4 then s(C y)
        !           174:            else S(PIo2-a)
        !           175:        end
        !           176: 
        !           177: local
        !           178:     val p1 =  1.3887401997267371720E~2
        !           179:     val p2 =  3.3044019718331897649E~5
        !           180:     val q1 =  1.1110813732786649355E~1
        !           181:     val q2 =  9.9176615021572857300E~4
        !           182: in  fun exp__E(x:real,c:real) =
        !           183:        let val small=1.0E~19
        !           184:            val x = abs x
        !           185:            val z = x*x
        !           186:            val p = z*(p1+z*p2)
        !           187:            val q = z*(q1+z*q2)
        !           188:            val xp= x*p 
        !           189:            val xh= x*half
        !           190:            val w = xh-(q-xp)
        !           191:            val p = p+p
        !           192:            val c = c+x*((xh*w-(q-(p+xp)))/(one-w)+c)
        !           193:        in  if(copysign(x,one)>small) then z*half+c
        !           194:            else copysign(zero,x) (* could be inexact *)
        !           195:        end
        !           196: end
        !           197: 
        !           198: (* for exp and ln *)
        !           199: val ln2hi = 6.9314718036912381649E~1
        !           200: val ln2lo = 1.9082149292705877000E~10
        !           201: val sqrt2 = 1.4142135623730951455E0
        !           202: val lnhuge =  7.1602103751842355450E2
        !           203: val lntiny = ~7.5137154372698068983E2
        !           204: val invln2 =  1.4426950408889633870E0
        !           205: 
        !           206: fun exp(x:real) =
        !           207:     let fun exp_norm() =
        !           208:            let (* argument reduction : x --> x - k*ln2 *)
        !           209:                val k = floor(invln2*x+copysign(half,x)) (* k=NINT(x/ln2) *)
        !           210:                val K = real k
        !           211:                (* express x-k*ln2 as z+c *)
        !           212:                val hi = x-K*ln2hi
        !           213:                val lo = K*ln2lo
        !           214:                val z = hi - lo
        !           215:                val c = (hi-z)-lo
        !           216:                (* return 2^k*[expm1(x) + 1] *)
        !           217:                val z = z + exp__E(z,c)
        !           218:            in  scalb(z+one,k)
        !           219:            end
        !           220:     in if x <= lnhuge then if x >= lntiny
        !           221:                            then exp_norm() handle Real _ => raise Exp
        !           222:                            else zero (* exp(-big#) underflows to zero *)
        !           223:                                      (* exp(-INF) is zero *)
        !           224:        else raise Exp (* exp(INF) is INF, exp(+big#) overflows to INF *)
        !           225:     end
        !           226: 
        !           227: local
        !           228:     val L1 = 6.6666666666667340202E~1
        !           229:     val L2 = 3.9999999999416702146E~1
        !           230:     val L3 = 2.8571428742008753154E~1
        !           231:     val L4 = 2.2222198607186277597E~1
        !           232:     val L5 = 1.8183562745289935658E~1
        !           233:     val L6 = 1.5314087275331442206E~1
        !           234:     val L7 = 1.4795612545334174692E~1
        !           235: in  fun log__L(z) = z*(L1+z*(L2+z*(L3+z*(L4+z*(L5+z*(L6+z*L7))))))
        !           236: end
        !           237: 
        !           238: fun ln(x:real) =
        !           239:     let fun findln() =
        !           240:        let (* argument reduction *)
        !           241:            val k = logb(x)
        !           242:            val x = scalb(x,InLine.~ k)
        !           243:            val (x,k) = if ieql(k,~1022) (* subnormal no. *)
        !           244:                    then let val n = logb(x)
        !           245:                         in  (scalb(x,InLine.~ n),InLine.+(k,n)) end
        !           246:                    else (x,k)
        !           247:            val (k,x) = if x >= sqrt2 then (InLine.+(k,1),x*half) else (k,x)
        !           248:            val K = real k
        !           249:            val x = x - one
        !           250:            (* compute log(1+x) *)
        !           251:            val s = x/(two+x)
        !           252:            val t = x*x*half
        !           253:            val z = K*ln2lo+s*(t+log__L(s*s))
        !           254:            val x = x + (z - t)
        !           255:        in  K*ln2hi+x end
        !           256:     in  if x <= zero then raise Ln
        !           257:        else findln() handle Real _ => raise Ln
        !           258:     end
        !           259: 
        !           260: local
        !           261:     val small=1.0E~9
        !           262:     val big=1.0E18
        !           263:     val athfhi =  4.6364760900080609352E~1
        !           264:     val athflo =  4.6249969567426939759E~18
        !           265:     val at1fhi =  9.8279372324732905408E~1
        !           266:     val at1flo = ~2.4407677060164810007E~17
        !           267:     val a1     =  3.3333333333333942106E~1
        !           268:     val a2     = ~1.9999999999979536924E~1
        !           269:     val a3     =  1.4285714278004377209E~1
        !           270:     val a4     = ~1.1111110579344973814E~1
        !           271:     val a5     =  9.0908906105474668324E~2
        !           272:     val a6     = ~7.6919217767468239799E~2
        !           273:     val a7     =  6.6614695906082474486E~2
        !           274:     val a8     = ~5.8358371008508623523E~2
        !           275:     val a9     =  4.9850617156082015213E~2
        !           276:     val a10    = ~3.6700606902093604877E~2
        !           277:     val a11    =  1.6438029044759730479E~2
        !           278: in
        !           279: fun atan2(y:real,x:real) =
        !           280:     let (* copy down the sign of y and x *)
        !           281:        val signy = copysign(one,y)
        !           282:        val signx = copysign(one,x)
        !           283:        exception Done of real
        !           284:        fun findatan2(x,y,t) =
        !           285:            let (* begin argument reduction *)
        !           286:                val k = floor(four * (t+0.0625))
        !           287:                val (hi,lo,t) =
        !           288:                        if t < 2.4375 then
        !           289:                        (* truncate 4(t+1/16) to integer for branching *)
        !           290:                        case k of
        !           291:                        (* t is in [0,7/16] *)
        !           292:                              0 => if t < small
        !           293:                                   then raise Done
        !           294:                                           (copysign(if signx>zero then t 
        !           295:                                                                   else PI-t,
        !           296:                                                     signy))
        !           297:                                   else (zero,zero,t)
        !           298:                            | 1 => if t < small
        !           299:                                   then raise Done
        !           300:                                           (copysign(if signx>zero then t 
        !           301:                                                                   else PI-t,
        !           302:                                                     signy))
        !           303:                                   else (zero,zero,t)
        !           304:                        (* t is in [7/16,11/16] *)
        !           305:                            | 2 => (athfhi,athflo,((y+y)-x)/(x+x+y))
        !           306:                        (* t is in [11/16,19/16] *)
        !           307:                            | 3 => (PIo4,zero,(y-x)/(x+y))
        !           308:                            | 4 => (PIo4,zero,(y-x)/(x+y))
        !           309:                        (* t is in [19/16,39/16] *)
        !           310:                            | _ => let val z = y-x
        !           311:                                       val y = y+y+y
        !           312:                                       val t = x+x
        !           313:                                   in (at1fhi,at1flo,( (z+z)-x ) / ( t + y ))
        !           314:                                   end
        !           315:                        (* end of if (t < 2.4375) *)
        !           316:                        else let val t = if t <= big
        !           317:                                         (* t is in [2.4375, big] *)
        !           318:                                         then ~x / y
        !           319:                                         (* t is in [big, INF] *)
        !           320:                                         else zero
        !           321:                             in (PIo2,zero,t) end
        !           322:                (* end of argument reduction *)
        !           323:                (* compute atan(t) for t in [~.4375, .4375] *)
        !           324:                val z = t*t
        !           325:                val z = t*(z*(a1+z*(a2+z*(a3+z*(a4+z*(a5+z*(a6+z*(a7+z*(a8+
        !           326:                        z*(a9+z*(a10+z*a11)))))))))))
        !           327:                val z = lo - z
        !           328:                val z = z + t
        !           329:                val z = z + hi
        !           330:            in  copysign(if signx>zero then z else PI-z,signy)
        !           331:            end
        !           332:     in
        !           333:     (* if x is 1.0, compute *)
        !           334:        if feql(x,one) then findatan2(x,copysign(y,one),y) handle Done r => r
        !           335:     (* when y = 0 *)
        !           336:        else if feql(y,zero) then if feql(signx,one) then y else copysign(PI,signy)
        !           337:     (* when x = 0 *)
        !           338:        else if feql(x,zero) then copysign(PIo2,signy)
        !           339:        else (* compute y/x *)
        !           340:            let val x = copysign(x,one)
        !           341:                val y = copysign(y,one)
        !           342:                val k = logb(y)
        !           343:                val m = InLine.-(k,logb(x))
        !           344:                val (t,y,x) = if InLine.>(m,60) then (big+big,y,x)
        !           345:                              else if InLine.<(m,~80) then (y/x,y,x)
        !           346:                              else (y/x,scalb(y,InLine.~ k),
        !           347:                                        scalb(x,InLine.~ k))
        !           348:            in  findatan2(x,y,t) handle Done r => r end
        !           349:     end
        !           350: end
        !           351: 
        !           352: fun arctan(x:real) = atan2(x,one)
        !           353: 
        !           354: fun sqrt(x: real) =
        !           355:       if x<=zero then if x<zero then raise Sqrt else x
        !           356:       else 
        !           357:         let val k = 6 (* log base 2 of the precision *)
        !           358:            val n = InLine.rshift(logb(x),1)
        !           359:            val x = scalb(x, InLine.~(InLine.lshift(n,1)))
        !           360:            fun iter(0,g) = g
        !           361:               | iter(i,g) = iter(InLine.-(i,1), half * (g + x/g))
        !           362:          in scalb(iter(k,one),n)
        !           363:         end
        !           364: 
        !           365: end

unix.superglobalmegacorp.com

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