1 (* =========================================================== *)
2 (* Informal arithmetic procedures *)
3 (* Author: Alexey Solovyev *)
5 (* =========================================================== *)
9 needs "arith_options.hl";;
14 module type Informal_nat_sig =
18 val mk_nat : num -> nat
19 val mk_small_nat : int -> nat
20 val dest_nat : nat -> num
21 val eq_nat : nat -> nat -> bool
22 val suc_nat : nat -> nat
23 val pre_nat : nat -> nat
24 val eq0_nat : nat -> bool
25 val gt0_nat : nat -> bool
26 val lt_nat : nat -> nat -> bool
27 val le_nat : nat -> nat -> bool
28 val add_nat : nat -> nat -> nat
29 val sub_nat : nat -> nat -> nat
30 (* If sub_and_le_nat m n = (m - n, true) if n <= m; (n - m, false) if m < n *)
31 val sub_and_le_nat : nat -> nat -> nat * bool
32 val mul_nat : nat -> nat -> nat
33 val div_nat : nat -> nat -> nat
34 val even_nat : nat -> bool
35 val odd_nat : nat -> bool
37 (* normalize_nat m = (n, e) s.t. m = n * base^e, e >= 0 *)
38 val normalize_nat : nat -> nat * int
39 val denormalize_nat : nat * int -> nat
40 (* hi_nat p m = (n, e) s.t. m <= n * base^e and n contains at most p "digits" *)
41 val hi_nat : int -> nat -> nat * int
42 val hi_lt_nat : int -> nat -> nat * int
43 (* lo_nat p m = (n, e) s.t. n * base^e <= m and n contains at most p "digits" *)
44 val lo_nat : int -> nat -> nat * int
49 module Informal_nat : Informal_nat_sig = struct
56 let arith_base = !Arith_options.base;;
59 let result = big_int_of_num n in
60 if sign_big_int result < 0 then zero_big_int else result;;
63 if n < 0 then zero_big_int else big_int_of_int n;;
65 let dest_nat = num_of_big_int;;
67 let eq_nat = eq_big_int;;
69 let suc_nat = succ_big_int;;
72 let result = pred_big_int n in
73 if sign_big_int result < 0 then zero_big_int else result;;
75 let eq0_nat n = sign_big_int n = 0;;
77 let gt0_nat n = sign_big_int n > 0;;
79 let lt_nat = lt_big_int;;
81 let le_nat = le_big_int;;
83 let add_nat = add_big_int;;
86 let result = sub_big_int m n in
87 if sign_big_int result < 0 then zero_big_int else result;;
89 let sub_and_le_nat m n =
90 let result = sub_big_int m n in
91 if sign_big_int result >= 0 then (result, true) else (abs_big_int result, false);;
93 let mul_nat = mult_big_int;;
95 let div_nat = div_big_int;;
97 let two_big_int = big_int_of_int 2;;
99 let even_nat n = sign_big_int (mod_big_int n two_big_int) = 0;;
101 let odd_nat n = sign_big_int (mod_big_int n two_big_int) > 0;;
103 (*******************************)
106 let base_nat = mk_small_nat arith_base;;
108 (* normalize_nat m = (n, e) s.t. m = n * base^e, e >= 0 *)
110 let rec normalize n e =
111 let q, r = quomod_big_int n base_nat in
112 if sign_big_int r > 0 then
115 normalize q (succ e) in
117 if sign_big_int n = 0 then (n, 0) else normalize n 0;;
120 let denormalize_nat (n, e) =
121 mult_big_int n (power_int_positive_int arith_base e);;
125 let max = power_int_positive_int arith_base pp in
127 if lt_big_int m max then
130 let q = div_big_int m base_nat in
133 if sign_big_int m = 0 then
136 let n1, e1 = lo m 0 in
137 let n, e2 = normalize_nat n1 in
142 if pp <= 0 then failwith "hi_nat: pp <= 0" else
143 let max = power_int_positive_int arith_base pp in
145 if lt_big_int m max then
148 let q, r = quomod_big_int m base_nat in
149 if sign_big_int r = 0 then
152 hi (succ_big_int q) (succ e) in
154 if sign_big_int m = 0 then
157 let n1, e1 = hi m 0 in
158 let n, e2 = normalize_nat n1 in
163 hi_nat pp (succ_big_int m);;
170 (* Floating point numbers *)
172 module type Informal_float_sig =
176 val mk_float : num -> int -> ifloat
177 val mk_num_float : num -> ifloat
178 val mk_small_num_float : int -> ifloat
179 val dest_float : ifloat -> bool * num * int
180 val sign_float : ifloat -> bool
181 (* Compares representations, not numbers themselves *)
182 val eq_float : ifloat -> ifloat -> bool
183 val lo_float : int -> ifloat -> ifloat
184 val hi_float : int -> ifloat -> ifloat
185 val neg_float : ifloat -> ifloat
186 val abs_float : ifloat -> ifloat
187 val lt0_float : ifloat -> bool
188 val gt0_float : ifloat -> bool
189 val le0_float : ifloat -> bool
190 val ge0_float : ifloat -> bool
191 val lt_float : ifloat -> ifloat -> bool
192 val le_float : ifloat -> ifloat -> bool
193 val min_float : ifloat -> ifloat -> ifloat
194 val max_float : ifloat -> ifloat -> ifloat
195 val mul_float_eq : ifloat -> ifloat -> ifloat
196 val mul_float_lo : int -> ifloat -> ifloat -> ifloat
197 val mul_float_hi : int -> ifloat -> ifloat -> ifloat
198 val div_float_lo : int -> ifloat -> ifloat -> ifloat
199 val div_float_hi : int -> ifloat -> ifloat -> ifloat
200 val add_float_lo : int -> ifloat -> ifloat -> ifloat
201 val add_float_hi : int -> ifloat -> ifloat -> ifloat
202 val sub_float_lo : int -> ifloat -> ifloat -> ifloat
203 val sub_float_hi : int -> ifloat -> ifloat -> ifloat
204 val sqrt_float_lo : int -> ifloat -> ifloat
205 val sqrt_float_hi : int -> ifloat -> ifloat
208 module Informal_float : Informal_float_sig = struct
212 type ifloat = bool * nat * int;;
214 let min_exp = !Arith_options.min_exp;;
216 (* Creates a non-negative float *)
217 let mk_float n e : ifloat = false, mk_nat n, e + min_exp;;
219 let mk_num_float n = false, mk_nat n, min_exp;;
221 let mk_small_num_float n = false, mk_small_nat n, min_exp;;
223 let zero_float = mk_small_num_float 0;;
225 let dest_float ((s, n, e) : ifloat) = s, dest_nat n, e;;
227 let sign_float ((s,_,_) : ifloat) = s;;
229 let eq_float (s1,n1,e1) (s2,n2,e2) = s1 = s2 && eq_nat n1 n2 && e1 = e2;;
231 let lo_float pp (s,n,e) =
232 let n1, e1 = if s then hi_nat pp n else lo_nat pp n in
235 let hi_float pp (s,n,e) =
236 let n1, e1 = if s then lo_nat pp n else hi_nat pp n in
239 (* Auxiliary num_exp functions *)
243 fun (n1,e1) (n2,e2) ->
245 n1 + denormalize_nat (n2, e2 - e1), e1
247 n2 + denormalize_nat (n1, e1 - e2), e2;;
250 (* Returns (n,e),true if (n1,e1) >= (n2,e2) and (n,e) = (n1,e1) - (n2,e2)
251 Returns (n,e),false if (n1,e1) <= (n2,e2) and (n,e) = (n2,e2) - (n1,e1) *)
253 let (--) = sub_and_le_nat in
254 fun (n1,e1) (n2,e2) ->
256 let a = denormalize_nat (n1, e1 - e2) and
258 let sub, flag = a -- b in
262 b = denormalize_nat (n2, e2 - e1) in
263 let sub, flag = a -- b in
268 let (<=/) = le_nat in
269 fun (n1,e1) (n2,e2) ->
271 n1 <=/ denormalize_nat (n2, e2 - e1)
273 denormalize_nat (n1, e1 - e2) <=/ n2;;
278 fun (n1,e1) (n2,e2) ->
280 n1 </ denormalize_nat (n2, e2 - e1)
282 denormalize_nat (n1, e1 - e2) </ n2;;
288 let neg_float (s,n,e) = (not s, n, e);;
293 let abs_float (_,n,e) = (false, n, e);;
299 let lt0_float (s,n,e) =
300 if not s then false else gt0_nat n;;
302 let gt0_float (s,n,e) =
303 if s then false else gt0_nat n;;
308 let le0_float (s,n,e) =
309 if s then true else eq0_nat n;;
311 let ge0_float (s,n,e) =
312 if s then eq0_nat n else true;;
317 let lt_float (s1,n1,e1) (s2,n2,e2) =
319 if s2 then false else num_exp_lt (n1,e1) (n2,e2)
321 if s2 then num_exp_lt (n2,e2) (n1,e1)
324 if eq0_nat n1 then gt0_nat n2 else true;;
327 let le_float (s1,n1,e1) (s2,n2,e2) =
329 if s2 then num_exp_le (n2,e2) (n1,e1) else true
331 if not s2 then num_exp_le (n1,e1) (n2,e2)
334 if eq0_nat n2 then eq0_nat n1 else false;;
340 let min_float f1 f2 =
341 if le_float f1 f2 then f1 else f2;;
343 let max_float f1 f2 =
344 if le_float f1 f2 then f2 else f1;;
350 if b1 then not b2 else b2;;
353 let mul_float_eq (s1,n1,e1) (s2,n2,e2) =
354 let s = badd s1 s2 in
355 let n = mul_nat n1 n2 in
356 let e = e1 + e2 - min_exp in
358 failwith "mul_float_eq: underflow"
363 let mul_float_lo pp (s1,n1,e1) (s2,n2,e2) =
364 if eq0_nat n1 or eq0_nat n2 then
367 let s = badd s1 s2 in
368 let n' = mul_nat n1 n2 in
369 let n, e' = if s1 = s2 then lo_nat pp n' else hi_nat pp n' in
370 let e = e1 + e2 + e' - min_exp in
372 failwith "mul_float_lo: underflow"
377 let mul_float_hi pp (s1,n1,e1) (s2,n2,e2) =
378 if eq0_nat n1 or eq0_nat n2 then
381 let s = badd s1 s2 in
382 let n' = mul_nat n1 n2 in
383 let n, e' = if s1 = s2 then hi_nat pp n' else lo_nat pp n' in
384 let e = e1 + e2 + e' - min_exp in
386 failwith "mul_float_hi: underflow"
393 let div_float_lo pp (s1,n1,e1) (s2,n2,e2) =
397 let s = badd s1 s2 in
399 let nn1 = denormalize_nat (n1, k) in
400 let n' = div_nat nn1 n2 in
401 let n, e' = if s1 = s2 then lo_nat pp n' else hi_lt_nat pp n' in
402 let e = min_exp + e' + e1 - e2 - k in
404 failwith "div_float_lo: underflow"
409 let div_float_hi pp (s1,n1,e1) (s2,n2,e2) =
413 let s = badd s1 s2 in
415 let nn1 = denormalize_nat (n1, k) in
416 let n' = div_nat nn1 n2 in
417 let n, e' = if s1 = s2 then hi_lt_nat pp n' else lo_nat pp n' in
418 let e = min_exp + e' + e1 - e2 - k in
420 failwith "div_float_hi: underflow"
427 let add_float_lo pp (s1,n1,e1) (s2,n2,e2) =
429 let n', e' = num_exp_add (n1,e1) (n2,e2) in
430 let n, e'' = if s1 then hi_nat pp n' else lo_nat pp n' in
434 let (n', e'), flag = num_exp_sub (n2,e2) (n1,e1) in
436 let n, e'' = lo_nat pp n' in
439 let n, e'' = hi_nat pp n' in
442 let (n', e'), flag = num_exp_sub (n1,e1) (n2,e2) in
444 let n, e'' = lo_nat pp n' in
447 let n, e'' = hi_nat pp n' in
448 (true, n, e' + e'');;
451 let add_float_hi pp (s1,n1,e1) (s2,n2,e2) =
453 let n', e' = num_exp_add (n1,e1) (n2,e2) in
454 let n, e'' = if s1 then lo_nat pp n' else hi_nat pp n' in
458 let (n', e'), flag = num_exp_sub (n2,e2) (n1,e1) in
460 let n, e'' = hi_nat pp n' in
463 let n, e'' = lo_nat pp n' in
466 let (n', e'), flag = num_exp_sub (n1,e1) (n2,e2) in
468 let n, e'' = hi_nat pp n' in
471 let n, e'' = lo_nat pp n' in
472 (true, n, e' + e'');;
477 let sub_float_lo pp f1 f2 = add_float_lo pp f1 (neg_float f2);;
478 let sub_float_hi pp f1 f2 = add_float_hi pp f1 (neg_float f2);;
483 let rec sqrt_float_lo pp (s,n1,e1) =
485 failwith "sqrt_float_lo: negative argument"
487 if e1 land 1 = 1 then
488 sqrt_float_lo pp (s, denormalize_nat (n1, 1), e1 - 1)
491 let f1' = denormalize_nat (n1, p2) in
492 let f1 = Big_int.sqrt_big_int (big_int_of_num (dest_nat f1')) in
493 let n, e' = lo_nat pp (mk_nat (num_of_big_int f1)) in
494 let e = ((e1 + min_exp) lsr 1) + e' - pp in
496 failwith "sqrt_float_lo: underflow"
501 let rec sqrt_float_hi pp (s,n1,e1) =
503 failwith "sqrt_float_hi: negative argument"
505 if e1 land 1 = 1 then
506 sqrt_float_hi pp (s, denormalize_nat (n1, 1), e1 - 1)
509 let x = (big_int_of_num o dest_nat o denormalize_nat) (n1, p2) in
510 let f1' = Big_int.sqrt_big_int x in
511 let f1 = (mk_nat o num_of_big_int) f1' in
513 let ( * ) = Big_int.mult_big_int and
514 (==) = Big_int.eq_big_int in
515 hi_nat pp (if f1' * f1' == x then f1 else suc_nat f1) in
516 let e = ((e1 + min_exp) lsr 1) + e' - pp in
518 failwith "sqrt_float_hi: underflow"
525 (* Interval arithmetic *)
527 module type Informal_interval_sig =
530 val zero_interval : interval
531 val one_interval : interval
532 val two_interval : interval
533 val mk_interval : Informal_float.ifloat * Informal_float.ifloat -> interval
534 val mk_num_interval : num -> interval
535 val mk_small_num_interval : int -> interval
536 val dest_interval : interval -> Informal_float.ifloat * Informal_float.ifloat
537 val round_interval : int -> interval -> interval
538 val neg_interval : interval -> interval
539 val mul_interval : int -> interval -> interval -> interval
540 val div_interval : int -> interval -> interval -> interval
541 val add_interval : int -> interval -> interval -> interval
542 val sub_interval : int -> interval -> interval -> interval
543 val sqrt_interval : int -> interval -> interval
544 val inv_interval : int -> interval -> interval
545 val pow_interval : int -> int -> interval -> interval
546 (* Computes max(-lo, hi) *)
547 val abs_interval : interval -> Informal_float.ifloat
550 module Informal_interval : Informal_interval_sig = struct
552 open Informal_float;;
555 type interval = ifloat * ifloat;;
557 let mk_interval (lo,hi) =
558 if lt_float hi lo then failwith "mk_interval: hi < lo" else (lo,hi);;
560 let mk_num_interval n =
561 let f = mk_num_float n in (f, f);;
563 let mk_small_num_interval n =
564 let f = mk_small_num_float n in (f, f);;
566 let zero_interval = mk_small_num_interval 0;;
567 let one_interval = mk_small_num_interval 1;;
568 let two_interval = mk_small_num_interval 2;;
570 let dest_interval ((lo,hi) : interval) = (lo,hi);;
572 let round_interval pp (lo,hi) = (lo_float pp lo, hi_float pp hi);;
574 let neg_interval (lo,hi) = (neg_float hi, neg_float lo);;
576 let abs_interval (lo,hi) = max_float hi (neg_float lo);;
578 let add_interval pp (lo1,hi1) (lo2,hi2) =
579 (add_float_lo pp lo1 lo2, add_float_hi pp hi1 hi2);;
581 let sub_interval pp (lo1,hi1) (lo2,hi2) =
582 (sub_float_lo pp lo1 hi2, sub_float_hi pp hi1 lo2);;
584 let sqrt_interval pp (lo,hi) =
585 if sign_float lo then
586 failwith "sqrt_interval: negative lower bound"
588 (sqrt_float_lo pp lo, sqrt_float_hi pp hi);;
591 let mul_interval pp (l_lo,l_hi) (r_lo,r_hi) =
592 let s1 = sign_float l_lo and
593 s2 = sign_float l_hi and
594 s3 = sign_float r_lo and
595 s4 = sign_float r_hi in
596 if s1 <> s2 && not s1 then
598 else if s3 <> s4 && not s3 then
601 if s1 <> s2 && s3 <> s4 then
602 let lo1, lo2 = mul_float_lo pp l_lo r_hi, mul_float_lo pp l_hi r_lo and
603 hi1, hi2 = mul_float_hi pp l_lo r_lo, mul_float_hi pp l_hi r_hi in
604 (min_float lo1 lo2, max_float hi1 hi2)
606 let lo1, lo2, hi1, hi2 =
609 l_lo, r_hi, l_hi, r_hi
611 l_hi, r_lo, l_lo, r_lo
615 l_hi, r_lo, l_hi, r_hi
617 l_lo, r_hi, l_lo, r_lo
621 l_lo, r_lo, l_hi, r_hi
623 l_hi, r_lo, l_lo, r_hi
626 l_lo, r_hi, l_hi, r_lo
628 l_hi, r_hi, l_lo, r_lo in
629 (mul_float_lo pp lo1 lo2, mul_float_hi pp hi1 hi2);;
632 let div_interval pp (l_lo,l_hi) (r_lo,r_hi) =
633 let s1 = sign_float l_lo and
634 s2 = sign_float l_hi and
635 s3 = sign_float r_lo and
636 s4 = sign_float r_hi in
637 if s1 <> s2 && not s1 then
639 else if s3 <> s4 then
640 failwith "div_interval: division by an interval containing 0"
642 let lo1, lo2, hi1, hi2 =
646 l_lo, r_hi, l_hi, r_lo
648 l_hi, r_hi, l_lo, r_lo
651 l_lo, r_lo, l_hi, r_hi
653 l_hi, r_lo, l_lo, r_hi
656 l_lo, r_lo, l_hi, r_lo
658 l_hi, r_hi, l_lo, r_hi in
659 (div_float_lo pp lo1 lo2, div_float_hi pp hi1 hi2);;
662 let inv_interval pp int =
663 div_interval pp one_interval int;;
666 let pow_interval pp n int =
673 let i2 = pow (n - 1) in
674 mul_interval pp int i2 in
678 (* Arith_misc.gen_pow (mul_interval pp) one_interval n;; *)
684 module type Informal_atn_sig =
686 val atn_interval : int -> Informal_interval.interval -> Informal_interval.interval
687 val acs_interval : int -> Informal_interval.interval -> Informal_interval.interval
688 val pi_approx_array : Informal_interval.interval array
689 val pi2_approx_array : Informal_interval.interval array
693 module Informal_atn : Informal_atn_sig = struct
695 open Informal_float;;
696 open Informal_interval;;
699 let rec poly_f_interval pp l x =
701 failwith "poly_f_interval: an empty coefficient list"
707 let r = poly_f_interval pp (tl l) x in
708 add_interval pp first (mul_interval pp x r);;
711 let poly_f_even_interval pp l x =
712 let xx = mul_interval pp x x in
713 poly_f_interval pp l xx;;
716 let poly_f_odd_interval pp l x =
717 let even = poly_f_even_interval pp l x in
718 mul_interval pp x even;;
721 let halfatn_interval pp x =
722 let xx = mul_interval pp x x in
723 let one_xx = add_interval pp one_interval xx in
724 let sqrt = sqrt_interval pp one_xx in
725 let one_sqrt = add_interval pp sqrt one_interval in
726 div_interval pp x one_sqrt;;
729 let halfatn4_interval pp x =
730 (halfatn_interval pp o halfatn_interval pp o halfatn_interval pp o halfatn_interval pp) x;;
733 (* Computes an interval for 16 * sum(0..n) (halfatn4_co x) *)
734 let atn_sum_interval =
735 let interval_16 = mk_small_num_interval 16 in
737 let halfatn4 = halfatn4_interval pp x in
738 let poly = poly_f_odd_interval pp l halfatn4 in
739 mul_interval pp interval_16 poly;;
742 let atn0_interval pp l eps x =
743 let sum = atn_sum_interval pp l x in
744 let a, b = dest_interval sum in
745 let _, d = dest_interval eps in
746 let hi = add_float_hi pp b d in
747 let lo = sub_float_lo pp a d in
748 mk_interval (lo, hi);;
751 (* Computes an interval for 2 ^ -(6n + 5) *)
752 let compute_eps1 pp n =
753 let pow = pow_interval pp (6 * n + 5) two_interval in
754 inv_interval pp pow;;
757 let mk_atn_co_table pp n =
759 let l = if (k land 1) = 0 then one_interval else neg_interval (one_interval) in
760 let r = mk_small_num_interval (2 * k + 1) in
761 div_interval pp l r in
766 let x = (float_of_int (pp + 1) *. log (float_of_int Informal_nat.arith_base) /. log (2.0) -. 5.0) /. 6.0 in
767 let n = (int_of_float o ceil) x in
768 if n < 1 then 1 else n;;
770 let atn_co_array = Array.init 21 (fun i -> mk_atn_co_table (i + 1) (n_of_p i));;
771 let eps1_array = Array.init 21 (fun i -> compute_eps1 (i + 1) (n_of_p i));;
774 let atn_interval pp x =
775 atn0_interval pp atn_co_array.(pp) eps1_array.(pp) x;;
778 (* pi approximation *)
779 let pi_approx_array, pi2_approx_array =
781 let x = one_interval in
782 let r1 = atn_interval pp x in
783 let r2 = mul_interval pp (mk_small_num_interval 4) r1 in
785 let float_pi2 = div_interval pp float_pi two_interval in
786 let pi_int0 = mk_small_num_interval 0 in
787 let pi2_int0 = pi_int0 in
788 Array.init 19 (fun i -> if i = 0 then pi_int0 else round_interval i float_pi),
789 Array.init 19 (fun i -> if i = 0 then pi2_int0 else round_interval i float_pi2);;
793 let acs0_interval pp l eps1 x =
794 let int1 = sub_interval pp one_interval (mul_interval pp x x) in
795 let int2 = div_interval pp x (sqrt_interval pp int1) in
796 let atn_int = atn0_interval pp l eps1 int2 in
797 sub_interval pp pi2_approx_array.(pp + 1) atn_int;;
800 let acs_interval pp x =
801 acs0_interval pp atn_co_array.(pp) eps1_array.(pp) x;;