Annotation of OpenXM_contrib/PHC/Ada/Math_Lib/Numbers/multprec_floating_numbers.adb, Revision 1.1.1.1
1.1 maekawa 1: with Standard_Mathematical_Functions; use Standard_Mathematical_Functions;
2:
3: package body Multprec_Floating_Numbers is
4:
5: -- NOTES ON THE IMPLEMENTATION :
6: -- 0) See the notes in the bodies of Multprec_{Natural,Integer}_Numbers.
7: -- 1) 0.0 must have zero fraction and zero exponent.
8: -- 2) The truncate and round operations all depend on the decimal radix.
9: -- 3) The function "Decimal_Places" occupies a central place.
10: -- 4) The normalized representation has a nonzero least significant digit.
11:
12: tol : constant double_float := 10.0**(-8);
13:
14: -- AUXILIARIES :
15:
16: function Truncate ( f : double_float ) return integer is
17:
18: i : integer := integer(f);
19:
20: begin
21: if i >= 0
22: then if double_float(i) > f + tol
23: then i := i-1;
24: end if;
25: else if double_float(i) < f - tol
26: then i := i+1;
27: end if;
28: end if;
29: return i;
30: end Truncate;
31:
32: function Max_Size ( i1,i2 : Integer_Number ) return natural is
33:
34: -- DESCRIPTION :
35: -- Return the maximal size of i1 and i2.
36:
37: sz1 : constant natural := Size(i1);
38: sz2 : constant natural := Size(i2);
39:
40: begin
41: if sz1 > sz2
42: then return sz1;
43: else return sz2;
44: end if;
45: end Max_Size;
46:
47: procedure Shift_Left ( n : in out Natural_Number; ns : out natural ) is
48:
49: -- DESCRIPTION :
50: -- Shifts n until the leading coefficient is larger than Base/10.
51: -- The number ns on return equals the number of shifts.
52:
53: begin
54: if (Empty(n) or else Equal(n,0))
55: then ns := 0;
56: else ns := 0;
57: while (Coefficient(n,Size(n)) < Base/10) loop
58: Mul(n,10);
59: ns := ns+1;
60: end loop;
61: end if;
62: end Shift_Left;
63:
64: procedure Shift_Right ( n : in out Natural_Number; ns : out natural ) is
65:
66: -- DESCRIPTION :
67: -- Shifts n until the last digit in the least significant coefficient
68: -- of n is different from zero.
69: -- The number ns on return equals the number of shifts.
70:
71: cff : natural;
72:
73: begin
74: if (Empty(n) or else Equal(n,0))
75: then ns := 0;
76: else ns := 0;
77: cff := Coefficient(n,0) mod 10;
78: while (cff = 0) loop
79: Div(n,10);
80: ns := ns+1;
81: cff := Coefficient(n,0) mod 10;
82: end loop;
83: end if;
84: end Shift_Right;
85:
86: procedure Shift_Right ( i : in out Integer_Number; ns : out natural ) is
87:
88: -- DESCRIPTION :
89: -- Applies the Shift_Right to the number representation of i.
90:
91: ni : Natural_Number;
92:
93: begin
94: if Empty(i)
95: then ns := 0;
96: else --ni := Unsigned(i);
97: Copy(Unsigned(i),ni); -- avoid sharing
98: Shift_Right(ni,ns);
99: if Sign(i) < 0
100: then Clear(i); i := Create(ni); Min(i);
101: else Clear(i); i := Create(ni);
102: end if;
103: Clear(ni);
104: end if;
105: end Shift_Right;
106:
107: procedure Normalize ( f : in out Floating_Number ) is
108:
109: -- DESCRIPTION :
110: -- Normalizes the representation of f so that its fraction has as
111: -- rightmost digit a nonzero number.
112:
113: ns : natural;
114:
115: begin
116: Shift_Right(f.fraction,ns);
117: Add(f.exponent,ns);
118: end Normalize;
119:
120: procedure Adjust_Expo ( f : in out double_float;
121: expo : in Integer_Number ) is
122:
123: -- DESCRIPTION :
124: -- Multiplies f with 10**expo.
125:
126: cnt : Integer_Number;
127:
128: begin
129: Copy(expo,cnt);
130: while cnt > 0 loop
131: f := f*10.0;
132: Sub(cnt,1);
133: end loop;
134: while cnt < 0 loop
135: f := f/10.0;
136: Add(cnt,1);
137: end loop;
138: Clear(cnt);
139: end Adjust_Expo;
140:
141: -- CONSTRUCTORS :
142:
143: function Create ( i : integer ) return Floating_Number is
144:
145: res : Floating_Number;
146:
147: begin
148: res.fraction := Create(i);
149: res.exponent := Create(0);
150: Normalize(res);
151: return res;
152: end Create;
153:
154: function Create ( i : Integer_Number ) return Floating_Number is
155:
156: res : Floating_Number;
157:
158: begin
159: res.fraction := +i;
160: res.exponent := Create(0);
161: Normalize(res);
162: return res;
163: end Create;
164:
165: function Create ( fraction,exponent : integer ) return Floating_Number is
166:
167: res : Floating_Number;
168:
169: begin
170: res.fraction := Create(fraction);
171: res.exponent := Create(exponent);
172: Normalize(res);
173: return res;
174: end Create;
175:
176: function Create ( fraction : Integer_Number;
177: exponent : integer ) return Floating_Number is
178:
179: res : Floating_Number;
180:
181: begin
182: res.fraction := +fraction;
183: res.exponent := Create(exponent);
184: Normalize(res);
185: return res;
186: end Create;
187:
188: function Create ( fraction : integer;
189: exponent : Integer_Number ) return Floating_Number is
190:
191: res : Floating_Number;
192:
193: begin
194: res.fraction := Create(fraction);
195: res.exponent := +exponent;
196: Normalize(res);
197: return res;
198: end Create;
199:
200: function Create ( fraction,exponent : Integer_Number )
201: return Floating_Number is
202:
203: res : Floating_Number;
204:
205: begin
206: res.fraction := +fraction;
207: res.exponent := +exponent;
208: Normalize(res);
209: return res;
210: end Create;
211:
212: function Create ( f : double_float ) return Floating_Number is
213:
214: -- NOTE :
215: -- To avoid rounding errors, comparison operations are prefered
216: -- above relying on intermediate results of calculations, although
217: -- rounding errors still occur!
218:
219: res : Floating_Number;
220: ten : Integer_Number;
221: wrkflt,fltexp,lowflt,uppflt,incflt : double_float;
222: intexp : integer;
223: fraction,exponent,intinc : Integer_Number;
224:
225: begin
226: if f = 0.0
227: then res := Create(0);
228: return res;
229: end if;
230: if f > 0.0
231: then wrkflt := f;
232: else wrkflt := -f;
233: end if;
234: fltexp := LOG10(wrkflt);
235: intexp := Truncate(fltexp);
236: if intexp < 15
237: then wrkflt := wrkflt*(10.0**(15-intexp));
238: exponent := Create(intexp-15);
239: intexp := 15;
240: else exponent := Create(0);
241: end if;
242: lowflt := 10.0**intexp;
243: uppflt := 10.0**(intexp+1);
244: while lowflt > wrkflt loop
245: intexp := intexp-1;
246: lowflt := 10.0**intexp;
247: uppflt := 10.0**(intexp+1);
248: end loop;
249: ten := Create(10);
250: fraction := ten**intexp;
251: for k in 1..16 loop
252: incflt := 10.0**intexp;
253: intinc := ten**intexp;
254: uppflt := lowflt;
255: for i in 1..10 loop
256: uppflt := uppflt + incflt;
257: exit when (uppflt > wrkflt);
258: lowflt := uppflt;
259: Add(fraction,intinc);
260: end loop;
261: intexp := intexp - 1;
262: Clear(intinc);
263: end loop;
264: Clear(ten);
265: if f < 0.0
266: then Min(fraction);
267: end if;
268: res := Create(fraction,exponent);
269: Normalize(res);
270: return res;
271: end Create;
272:
273: -- SELECTORS :
274:
275: function Fraction ( f : Floating_Number ) return Integer_Number is
276: begin
277: return f.fraction;
278: end Fraction;
279:
280: function Exponent ( f : Floating_Number ) return Integer_Number is
281: begin
282: return f.exponent;
283: end Exponent;
284:
285: function Size_Fraction ( f : Floating_Number ) return natural is
286: begin
287: return Size(Fraction(f));
288: end Size_Fraction;
289:
290: function Size_Exponent ( f : Floating_Number ) return natural is
291: begin
292: return Size(Exponent(f));
293: end Size_Exponent;
294:
295: function Decimal_Places_Fraction ( f : Floating_Number ) return natural is
296: begin
297: return Decimal_Places(Fraction(f));
298: end Decimal_Places_Fraction;
299:
300: function Decimal_Places_Exponent ( f : Floating_Number ) return natural is
301: begin
302: return Decimal_Places(Exponent(f));
303: end Decimal_Places_Exponent;
304:
305: function Decimal_to_Size ( deci : natural ) return natural is
306:
307: res : natural;
308: exp : constant natural := Multprec_Natural_Numbers.Exponent;
309:
310: begin
311: res := deci/exp;
312: if res*exp < deci
313: then res := res+1;
314: end if;
315: return res;
316: end Decimal_to_Size;
317:
318: function AbsVal ( f : Floating_Number ) return Floating_Number is
319:
320: res : Floating_Number;
321:
322: begin
323: if Negative(f.fraction)
324: then res.fraction := -f.fraction;
325: else res.fraction := +f.fraction;
326: end if;
327: res.exponent := +f.exponent;
328: return res;
329: end AbsVal;
330:
331: -- COMPARISON AND COPYING :
332:
333: function Equal ( f1 : Floating_Number; f2 : double_float ) return boolean is
334:
335: ff2 : Floating_Number := Create(f2);
336: res : boolean := Equal(f1,ff2);
337:
338: begin
339: Clear(ff2);
340: return res;
341: end Equal;
342:
343: function Equal ( f1,f2 : Floating_Number ) return boolean is
344:
345: res : boolean;
346: f1deci : constant natural := Decimal_Places(f1.fraction);
347: f2deci : constant natural := Decimal_Places(f2.fraction);
348: f1expo : Integer_Number := f1.exponent + f1deci;
349: f2expo : Integer_Number := f2.exponent + f2deci;
350: mulfra : Integer_Number;
351:
352: begin
353: if Equal(f1expo,f2expo)
354: then if f1deci = f2deci
355: then res := Equal(f1.fraction,f2.fraction);
356: else if f1deci < f2deci
357: then mulfra := f1.fraction*10;
358: for i in 1..(f2deci-f1deci-1) loop
359: Mul(mulfra,10);
360: end loop;
361: res := Equal(mulfra,f2.fraction);
362: else mulfra := f2.fraction*10;
363: for i in 1..(f1deci-f2deci-1) loop
364: Mul(mulfra,10);
365: end loop;
366: res := Equal(f1.fraction,mulfra);
367: end if;
368: Clear(mulfra);
369: end if;
370: else res := false;
371: end if;
372: Clear(f1expo); Clear(f2expo);
373: return res;
374: end Equal;
375:
376: function "<" ( f1 : double_float; f2 : Floating_Number ) return boolean is
377:
378: ff1 : Floating_Number := Create(f1);
379: res : boolean := (ff1 < f2);
380:
381: begin
382: Clear(ff1);
383: return res;
384: end "<";
385:
386: function "<" ( f1 : Floating_Number; f2 : double_float ) return boolean is
387:
388: ff2 : Floating_Number := Create(f2);
389: res : boolean := (f1 < ff2);
390:
391: begin
392: Clear(ff2);
393: return res;
394: end "<";
395:
396: function "<" ( f1,f2 : Floating_Number ) return boolean is
397:
398: res : boolean;
399: f1deci : constant natural := Decimal_Places(f1.fraction);
400: f2deci : constant natural := Decimal_Places(f2.fraction);
401: f1expo : Integer_Number := f1.exponent + f1deci;
402: f2expo : Integer_Number := f2.exponent + f2deci;
403: mulfra : Integer_Number;
404:
405: begin
406: if (f1expo < f2expo)
407: then if Sign(f2.fraction) > 0
408: then res := true;
409: elsif Sign(f2.fraction) < 0
410: then res := false;
411: else res := (Sign(f1.fraction) < 0);
412: end if;
413: elsif (f1expo > f2expo)
414: then if Sign(f1.fraction) > 0
415: then res := false;
416: elsif Sign(f1.fraction) < 0
417: then res := true;
418: else res := (Sign(f2.fraction) > 0);
419: end if;
420: else if f1deci = f2deci
421: then res := (f1.fraction < f2.fraction);
422: else if f1deci < f2deci
423: then mulfra := f1.fraction*10;
424: for i in 1..(f2deci-f1deci-1) loop
425: Mul(mulfra,10);
426: end loop;
427: res := (mulfra < f2.fraction);
428: else mulfra := f2.fraction*10;
429: for i in 1..(f1deci-f2deci-1) loop
430: Mul(mulfra,10);
431: end loop;
432: res := (f1.fraction < mulfra);
433: end if;
434: Clear(mulfra);
435: end if;
436: end if;
437: Clear(f1expo); Clear(f2expo);
438: return res;
439: end "<";
440:
441: function ">" ( f1 : double_float; f2 : Floating_Number ) return boolean is
442:
443: ff1 : Floating_Number := Create(f1);
444: res : boolean := (ff1 > f2);
445:
446: begin
447: Clear(ff1);
448: return res;
449: end ">";
450:
451: function ">" ( f1 : Floating_Number; f2 : double_float ) return boolean is
452:
453: ff2 : Floating_Number := Create(f2);
454: res : boolean := (f1 > ff2);
455:
456: begin
457: Clear(ff2);
458: return res;
459: end ">";
460:
461: function ">" ( f1,f2 : Floating_Number ) return boolean is
462:
463: res : boolean;
464: f1deci : constant natural := Decimal_Places(f1.fraction);
465: f2deci : constant natural := Decimal_Places(f2.fraction);
466: f1expo : Integer_Number := f1.exponent + f1deci;
467: f2expo : Integer_Number := f2.exponent + f2deci;
468: mulfra : Integer_Number;
469:
470: begin
471: if (f1expo > f2expo)
472: then if Sign(f1.fraction) > 0
473: then res := true;
474: elsif Sign(f1.fraction) < 0
475: then res := false;
476: else res := (Sign(f2.fraction) < 0);
477: end if;
478: elsif (f1expo < f2expo)
479: then if Sign(f2.fraction) > 0
480: then res := false;
481: elsif Sign(f2.fraction) < 0
482: then res := true;
483: else res := (Sign(f1.fraction) > 0);
484: end if;
485: else if f1deci = f2deci
486: then res := (f1.fraction > f2.fraction);
487: else if f1deci < f2deci
488: then mulfra := f1.fraction*10;
489: for i in 1..(f2deci-f1deci-1) loop
490: Mul(mulfra,10);
491: end loop;
492: res := (mulfra > f2.fraction);
493: else mulfra := f2.fraction*10;
494: for i in 1..(f1deci-f2deci-1) loop
495: Mul(mulfra,10);
496: end loop;
497: res := (f1.fraction > mulfra);
498: end if;
499: Clear(mulfra);
500: end if;
501: end if;
502: Clear(f1expo); Clear(f2expo);
503: return res;
504: end ">";
505:
506: procedure Copy ( f1 : in Floating_Number; f2 : in out Floating_Number ) is
507: begin
508: Clear(f2);
509: Copy(f1.fraction,f2.fraction);
510: Copy(f1.exponent,f2.exponent);
511: end Copy;
512:
513: -- EXPANDING AND SHORTENING THE MANTISSA :
514:
515: function Expand ( i : Integer_Number; k : natural )
516: return Array_of_Naturals is
517:
518: -- DESCRIPTION :
519: -- Returns the expanded coefficient vector of i.
520:
521: cff : constant Array_of_Naturals := Coefficients(Unsigned(i));
522: res : Array_of_Naturals(cff'first..cff'last+k);
523:
524: begin
525: res(cff'range) := cff(cff'range);
526: res(cff'last+1..res'last) := (cff'last+1..res'last => 0);
527: return res;
528: end Expand;
529:
530: procedure Truncate ( i : in Integer_Number; k : in natural;
531: trc : out Array_of_Naturals; exp : out integer ) is
532:
533: -- DESCRIPTION :
534: -- On return is the truncated coefficient vector of i and the number
535: -- of decimal places that are lost, or gained when exp is positive.
536:
537: n : Natural_Number;
538: ns : natural; -- #shifts = #decimal places gained
539:
540: begin
541: Copy(Unsigned(i),n);
542: Shift_Left(n,ns);
543: exp := k*Multprec_Natural_Numbers.Exponent - ns;
544: declare
545: cff : constant Array_of_Naturals := Coefficients(n);
546: begin
547: for i in trc'range loop
548: trc(i) := cff(i+k);
549: end loop;
550: Clear(n);
551: end;
552: end Truncate;
553:
554: procedure Truncate ( i : in out Integer_Number; k : in natural;
555: exp : out integer ) is
556:
557: n : Natural_Number := Unsigned(i);
558: neg : constant boolean := Negative(i);
559: ns : natural;
560: newint : Integer_Number;
561:
562: begin
563: Shift_Left(n,ns);
564: exp := k*Multprec_Natural_Numbers.Exponent - ns;
565: declare
566: cff : constant Array_of_Naturals := Coefficients(n);
567: trc : Array_of_Naturals(cff'first..cff'last-k);
568: begin
569: for i in trc'range loop
570: trc(i) := cff(i+k);
571: end loop;
572: newint := Create(trc);
573: i := newint; --Copy(newint,i); --Clear(newint);
574: if neg
575: then Min(i);
576: end if;
577: end;
578: Clear(n);
579: end Truncate;
580:
581: procedure Round ( i : in Integer_Number; k : in natural;
582: trc : out Array_of_Naturals; exp : out integer ) is
583:
584: -- DESCRIPTION :
585: -- On return is the rounded coefficient vector of i and the number
586: -- of decimal places that are lost, or gained when exp is positive.
587:
588: n : Natural_Number := Unsigned(i);
589: ns : natural; -- #shifts = #decimal places gained
590:
591: begin
592: Shift_Left(n,ns);
593: exp := k*Multprec_Natural_Numbers.Exponent - ns;
594: declare
595: cff : constant Array_of_Naturals := Coefficients(n);
596: begin
597: for i in trc'range loop
598: trc(i) := cff(i+k);
599: end loop;
600: if k > 0
601: then if cff(k-1) >= Multprec_Natural_Numbers.Base/2
602: then trc(0) := trc(0)+1;
603: end if;
604: end if;
605: end;
606: Clear(n);
607: end Round;
608:
609: function Expand ( f : Floating_Number; k : natural ) return Floating_Number is
610:
611: res : Floating_Number;
612: cff : constant Array_of_Naturals := Expand(f.fraction,k);
613:
614: begin
615: res.fraction := Create(Create(cff));
616: if Negative(f.fraction)
617: then Min(res.fraction);
618: end if;
619: Copy(f.exponent,res.exponent);
620: Normalize(res);
621: return res;
622: end Expand;
623:
624: procedure Expand ( f : in out Floating_Number; k : in natural ) is
625:
626: cff : constant Array_of_Naturals := Expand(f.fraction,k);
627: neg : constant boolean := Negative(f.fraction);
628:
629: begin
630: Clear(f.fraction);
631: f.fraction := Create(Create(cff));
632: if neg
633: then Min(f.fraction);
634: end if;
635: Normalize(f);
636: end Expand;
637:
638: function Round ( f : Floating_Number ) return double_float is
639:
640: res : double_float;
641: szf,ns : natural;
642: n : Natural_Number;
643: expo : Integer_Number;
644:
645: begin
646: if (Empty(f.fraction) or else Equal(f.fraction,0))
647: then res := 0.0;
648: else Copy(Unsigned(f.fraction),n);
649: Shift_Left(n,ns);
650: expo := f.exponent - ns;
651: szf := Size(n);
652: while Coefficient(n,szf) = 0 and szf > 0 loop
653: szf := szf - 1;
654: end loop;
655: res := double_float(Coefficient(n,szf));
656: if szf >= 1
657: then res := res*double_float(Multprec_Natural_Numbers.Base)
658: + double_float(Coefficient(n,szf-1));
659: if szf >= 2
660: then if Coefficient(n,szf-2) > Multprec_Natural_Numbers.Base/2
661: then res := res+1.0;
662: end if;
663: ns := (szf - 1)*Multprec_Natural_Numbers.Exponent;
664: Add(expo,ns);
665: end if;
666: end if;
667: Adjust_Expo(res,expo);
668: Clear(n); Clear(expo);
669: end if;
670: return res;
671: end Round;
672:
673: function Round ( f : Floating_Number; k : natural ) return Floating_Number is
674:
675: res : Floating_Number;
676: cff : Array_of_Naturals(0..(Size(f.fraction)-k));
677: exp : integer;
678:
679: begin
680: Round(f.fraction,k,cff,exp);
681: res.fraction := Create(Create(cff));
682: if Negative(f.fraction)
683: then Min(res.fraction);
684: end if;
685: Copy(f.exponent,res.exponent);
686: Add(res.exponent,exp);
687: Normalize(res);
688: return res;
689: end Round;
690:
691: procedure Round ( f : in out Floating_Number; k : in natural ) is
692:
693: exp : integer;
694: n : Natural_Number;
695: neg : constant boolean := Negative(f.fraction);
696: ns : natural;
697:
698: begin
699: Copy(Unsigned(f.fraction),n);
700: Shift_Left(n,ns);
701: exp := k*Multprec_Natural_Numbers.Exponent - ns;
702: declare
703: cff : constant Array_of_Naturals := Coefficients(n);
704: trc : Array_of_Naturals(cff'first..cff'last-k);
705: begin
706: for i in trc'range loop
707: trc(i) := cff(i+k);
708: end loop;
709: if k > 0
710: then if cff(k-1) >= Multprec_Natural_Numbers.Base/2
711: then trc(0) := trc(0)+1;
712: end if;
713: end if;
714: Clear(f.fraction);
715: f.fraction := Create(trc);
716: if neg
717: then Min(f.fraction);
718: end if;
719: end;
720: Clear(n);
721: Add(f.exponent,exp);
722: Normalize(f);
723: end Round;
724:
725: function Trunc ( f : Floating_Number ) return double_float is
726:
727: res : double_float;
728: szf,ns : natural;
729: n : Natural_Number;
730: expo : Integer_Number;
731:
732: begin
733: if (Empty(f.fraction) or else Equal(f.fraction,0))
734: then res := 0.0;
735: else n := Unsigned(f.fraction);
736: Shift_Left(n,ns);
737: expo := f.exponent - ns;
738: szf := Size(n);
739: while Coefficient(n,szf) = 0 and szf > 0 loop
740: szf := szf - 1;
741: end loop;
742: res := double_float(Coefficient(f.fraction,szf));
743: if szf >= 1
744: then res := res*double_float(Multprec_Natural_Numbers.Base)
745: + double_float(Coefficient(f.fraction,szf-1));
746: if szf >= 2
747: then ns := (szf - 1)*Multprec_Natural_Numbers.Exponent;
748: Add(expo,ns);
749: end if;
750: end if;
751: Adjust_Expo(res,expo);
752: Clear(n); Clear(expo);
753: end if;
754: return res;
755: end Trunc;
756:
757: function Trunc ( f : Floating_Number; k : natural ) return Floating_Number is
758:
759: res : Floating_Number;
760: cff : Array_of_Naturals(0..(Size(f.fraction)-k));
761: exp : integer;
762:
763: begin
764: Truncate(f.fraction,k,cff,exp);
765: res.fraction := Create(Create(cff));
766: if Negative(f.fraction)
767: then Min(res.fraction);
768: end if;
769: Copy(f.exponent,res.exponent);
770: Add(res.exponent,exp);
771: return res;
772: end Trunc;
773:
774: procedure Trunc ( f : in out Floating_Number; k : in natural ) is
775:
776: exp : integer;
777: n : Natural_Number;
778: neg : constant boolean := Negative(f.fraction);
779: ns : natural;
780:
781: begin
782: Copy(Unsigned(f.fraction),n);
783: Shift_Left(n,ns);
784: exp := k*Multprec_Natural_Numbers.Exponent - ns;
785: declare
786: cff : constant Array_of_Naturals := Coefficients(n);
787: trc : Array_of_Naturals(cff'first..cff'last-k);
788: begin
789: for i in trc'range loop
790: trc(i) := cff(i+k);
791: end loop;
792: Clear(f.fraction);
793: f.fraction := Create(trc);
794: if neg
795: then Min(f.fraction);
796: end if;
797: end;
798: Clear(n);
799: Add(f.exponent,exp);
800: end Trunc;
801:
802: procedure Set_Size ( f : in out Floating_Number; k : in natural ) is
803:
804: sz : constant natural := Size_Fraction(f);
805:
806: begin
807: if sz > k
808: then Round(f,sz-k);
809: elsif sz < k
810: then Expand(f,k-sz);
811: end if;
812: end Set_Size;
813:
814: -- ARITHMETIC OPERATIONS as functions (no data sharing) :
815:
816: function "+" ( f1 : Floating_Number; f2 : double_float )
817: return Floating_Number is
818:
819: ff2 : Floating_Number := Create(f2);
820: res : Floating_Number := f1+ff2;
821:
822: begin
823: Clear(ff2);
824: return res;
825: end "+";
826:
827: function "+" ( f1 : double_float; f2 : Floating_Number )
828: return Floating_Number is
829: begin
830: return f2+f1;
831: end "+";
832:
833: function "+" ( f1,f2 : Floating_Number ) return Floating_Number is
834:
835: res : Floating_Number;
836: maxsz,diff_size,max_diff : integer;
837: diff_expo : Integer_Number;
838: cnt : natural;
839:
840: begin
841: if (Empty(f1.fraction) or else Equal(f1.fraction,0))
842: then Copy(f2,res);
843: elsif (Empty(f2.fraction) or else Equal(f2.fraction,0))
844: then Copy(f1,res);
845: else maxsz := Max_Size(f1.fraction,f2.fraction) + 1;
846: if Equal(f1.exponent,f2.exponent)
847: then res.fraction := f1.fraction + f2.fraction;
848: Copy(f1.exponent,res.exponent);
849: else diff_expo := f1.exponent - f2.exponent;
850: max_diff := maxsz*Multprec_Natural_Numbers.Exponent;
851: if diff_expo > 0
852: then Copy(f1.fraction,res.fraction);
853: if diff_expo < 2*max_diff
854: then cnt := Create(diff_expo);
855: for i in 1..cnt loop
856: Mul(res.fraction,10);
857: end loop;
858: Add(res.fraction,f2.fraction);
859: Copy(f2.exponent,res.exponent);
860: else Copy(f1.exponent,res.exponent);
861: end if;
862: else Copy(f2.fraction,res.fraction);
863: Min(diff_expo);
864: if diff_expo < 2*max_diff
865: then cnt := Create(diff_expo);
866: for i in 1..cnt loop
867: Mul(res.fraction,10);
868: end loop;
869: Add(res.fraction,f1.fraction);
870: Copy(f1.exponent,res.exponent);
871: else Copy(f2.exponent,res.exponent);
872: end if;
873: end if;
874: Clear(diff_expo);
875: end if;
876: diff_size := Size(res.fraction) + 1 - maxsz;
877: if diff_size > 0
878: then Round(res,diff_size);
879: else Normalize(res);
880: end if;
881: end if;
882: return res;
883: end "+";
884:
885: function "+" ( f : Floating_Number ) return Floating_Number is
886:
887: res : Floating_Number;
888:
889: begin
890: Copy(f,res);
891: return res;
892: end "+";
893:
894: function "-" ( f : Floating_Number ) return Floating_Number is
895:
896: res : Floating_Number;
897:
898: begin
899: Copy(f,res);
900: Min(res.fraction);
901: return res;
902: end "-";
903:
904: function "-" ( f1 : Floating_Number; f2 : double_float )
905: return Floating_Number is
906:
907: minf2 : double_float := -f2;
908: res : Floating_Number := f1+minf2;
909:
910: begin
911: return res;
912: end "-";
913:
914: function "-" ( f1 : double_float; f2 : Floating_Number )
915: return Floating_Number is
916:
917: ff1 : Floating_Number := Create(f1);
918: res : Floating_Number := ff1 - f2;
919:
920: begin
921: Clear(ff1);
922: return res;
923: end "-";
924:
925: function "-" ( f1,f2 : Floating_Number ) return Floating_Number is
926:
927: res,minf2 : Floating_Number;
928:
929: begin
930: minf2.exponent := f2.exponent;
931: minf2.fraction := -f2.fraction;
932: res := f1 + minf2;
933: Clear(minf2.fraction);
934: return res;
935: end "-";
936:
937: function "*" ( f1 : Floating_Number; f2 : double_float )
938: return Floating_Number is
939:
940: ff2 : Floating_Number := Create(f2);
941: res : Floating_Number := f1*ff2;
942:
943: begin
944: Clear(ff2);
945: return res;
946: end "*";
947:
948: function "*" ( f1 : double_float; f2 : Floating_Number )
949: return Floating_Number is
950:
951: ff1 : Floating_Number := Create(f1);
952: res : Floating_Number := ff1*f2;
953:
954: begin
955: Clear(ff1);
956: return res;
957: end "*";
958:
959: function "*" ( f1,f2 : Floating_Number ) return Floating_Number is
960:
961: res : Floating_Number;
962: diffsize : integer;
963:
964: begin
965: if not (Empty(f1.fraction) or else Equal(f1.fraction,0))
966: then if not (Empty(f2.fraction) or else Equal(f2.fraction,0))
967: then res.fraction := f1.fraction*f2.fraction;
968: res.exponent := f1.exponent+f2.exponent;
969: diffsize := Size(res.fraction)
970: - Max_Size(f1.fraction,f2.fraction);
971: if diffsize > 0
972: then Round(res,diffsize);
973: end if;
974: Normalize(res);
975: end if;
976: end if;
977: return res;
978: end "*";
979:
980: function "**" ( f : double_float; n : Natural_Number )
981: return Floating_Number is
982:
983: ff : Floating_Number := Create(f);
984: res : Floating_Number := ff**n;
985:
986: begin
987: Clear(ff);
988: return res;
989: end "**";
990:
991: function "**" ( f : Floating_Number; n : Natural_Number )
992: return Floating_Number is
993:
994: res : Floating_Number;
995: cnt : Natural_Number;
996:
997: begin
998: if (Empty(n) or else Equal(n,0))
999: then res := Create(1);
1000: else Copy(f,res);
1001: cnt := Create(1);
1002: while cnt < n loop
1003: Mul(res,f);
1004: Add(cnt,1);
1005: end loop;
1006: Clear(cnt);
1007: Normalize(res);
1008: end if;
1009: return res;
1010: end "**";
1011:
1012: function "**" ( f : Floating_Number; i : integer ) return Floating_Number is
1013:
1014: res : Floating_Number;
1015:
1016: begin
1017: if i = 0
1018: then res := Create(1.0);
1019: else if i > 0
1020: then Copy(f,res);
1021: for j in 1..(i-1) loop
1022: Mul(res,f);
1023: end loop;
1024: else res := Create(1);
1025: for j in 1..(-i) loop
1026: Div(res,f);
1027: end loop;
1028: end if;
1029: Normalize(res);
1030: end if;
1031: return res;
1032: end "**";
1033:
1034: function "**" ( f : double_float; i : Integer_Number )
1035: return Floating_Number is
1036:
1037: ff : Floating_Number := Create(f);
1038: res : Floating_Number := ff**i;
1039:
1040: begin
1041: Clear(ff);
1042: return res;
1043: end "**";
1044:
1045: function "**" ( f : Floating_Number; i : Integer_Number )
1046: return Floating_Number is
1047:
1048: res : Floating_Number;
1049: cnt,n : Natural_Number;
1050:
1051: begin
1052: if (Empty(i) or else Equal(i,0))
1053: then res := Create(1);
1054: else n := Unsigned(i);
1055: if i > 0
1056: then Copy(f,res);
1057: cnt := Create(1);
1058: while cnt < n loop
1059: Mul(res,f);
1060: Add(cnt,1);
1061: end loop;
1062: else res := Create(1);
1063: cnt := Create(0);
1064: while cnt < n loop
1065: Div(res,f);
1066: Add(cnt,1);
1067: end loop;
1068: end if;
1069: Clear(cnt);
1070: Normalize(res);
1071: end if;
1072: return res;
1073: end "**";
1074:
1075: function "/" ( f1 : Floating_Number; f2 : double_float )
1076: return Floating_Number is
1077:
1078: ff2 : Floating_Number := Create(f2);
1079: res : Floating_Number := f1/ff2;
1080:
1081: begin
1082: Clear(ff2);
1083: return res;
1084: end "/";
1085:
1086: function "/" ( f1 : double_float; f2 : Floating_Number )
1087: return Floating_Number is
1088:
1089: ff1 : Floating_Number := Create(f1);
1090: res : Floating_Number := ff1/f2;
1091:
1092: begin
1093: Clear(ff1);
1094: return res;
1095: end "/";
1096:
1097: function Pos_Div ( f1,f2 : Floating_Number ) return Floating_Number is
1098:
1099: -- DESCRIPTION :
1100: -- This division only applies when f1 and f2 are both positive.
1101:
1102: res : Floating_Number;
1103: rmd_frac,new_rmd_frac : Integer_Number;
1104: diffsize : integer;
1105: maxsz : natural := Max_Size(f1.fraction,f2.fraction);
1106:
1107: begin
1108: Div(f1.fraction,f2.fraction,res.fraction,rmd_frac);
1109: res.exponent := f1.exponent - f2.exponent;
1110: diffsize := Size(res.fraction) - maxsz;
1111: if not Equal(rmd_frac,0)
1112: then while diffsize <= 0 loop
1113: while rmd_frac < f2.fraction loop
1114: Mul(rmd_frac,10);
1115: Mul(res.fraction,10);
1116: Sub(res.exponent,1);
1117: end loop;
1118: Div(rmd_frac,f2.fraction,new_rmd_frac);
1119: Add(res.fraction,rmd_frac);
1120: Clear(rmd_frac); rmd_frac := new_rmd_frac;
1121: diffsize := Size(res.fraction) - maxsz;
1122: exit when Equal(rmd_frac,0);
1123: end loop;
1124: end if;
1125: Clear(rmd_frac);
1126: if diffsize > 0
1127: then Round(res,diffsize);
1128: end if;
1129: Normalize(res);
1130: return res;
1131: end Pos_Div;
1132:
1133: function "/" ( f1,f2 : Floating_Number ) return Floating_Number is
1134:
1135: res,minf1,minf2 : Floating_Number;
1136:
1137: begin
1138: if not (Empty(f1.fraction) or else Equal(f1.fraction,0))
1139: then if not (Empty(f2.fraction) or else Equal(f2.fraction,0))
1140: then if Multprec_Integer_Numbers.Positive(f1.fraction)
1141: then if Multprec_Integer_Numbers.Positive(f2.fraction)
1142: then res := Pos_Div(f1,f2);
1143: else minf2.fraction := -f2.fraction;
1144: minf2.exponent := f2.exponent;
1145: res := Pos_Div(f1,minf2);
1146: Clear(minf2.fraction);
1147: Min(res);
1148: end if;
1149: else minf1.fraction := -f1.fraction;
1150: minf1.exponent := f1.exponent;
1151: if Multprec_Integer_Numbers.Positive(f2.fraction)
1152: then res := Pos_Div(minf1,f2);
1153: Min(res);
1154: else minf2.fraction := -f2.fraction;
1155: minf2.exponent := f2.exponent;
1156: res := Pos_Div(minf1,minf2);
1157: Clear(minf2.fraction);
1158: end if;
1159: Clear(minf1.fraction);
1160: end if;
1161: else raise NUMERIC_ERROR;
1162: end if;
1163: end if;
1164: return res;
1165: end "/";
1166:
1167: -- ARITHMETIC OPERATIONS as procedures for memory management :
1168:
1169: procedure Add ( f1 : in out Floating_Number; f2 : in double_float ) is
1170:
1171: ff2 : Floating_Number := Create(f2);
1172:
1173: begin
1174: Add(f1,ff2);
1175: Clear(ff2);
1176: end Add;
1177:
1178: procedure Add ( f1 : in out Floating_Number; f2 : in Floating_Number ) is
1179:
1180: res : Floating_Number;
1181: maxsz,diff_size,max_diff : integer;
1182: diff_expo : Integer_Number;
1183: cnt : natural;
1184:
1185: begin
1186: if (Empty(f1.fraction) or else Equal(f1.fraction,0))
1187: then Copy(f2,f1);
1188: elsif (Empty(f2.fraction) or else Equal(f2.fraction,0))
1189: then null;
1190: else maxsz := Max_Size(f1.fraction,f2.fraction) + 1;
1191: if Equal(f1.exponent,f2.exponent)
1192: then Add(f1.fraction,f2.fraction);
1193: else diff_expo := f1.exponent - f2.exponent;
1194: max_diff := maxsz*Multprec_Natural_Numbers.Exponent;
1195: if diff_expo > 0
1196: then if diff_expo < 2*max_diff
1197: then cnt := Create(diff_expo);
1198: for i in 1..cnt loop
1199: Mul(f1.fraction,10);
1200: end loop;
1201: Add(f1.fraction,f2.fraction);
1202: Copy(f2.exponent,f1.exponent);
1203: else null;
1204: end if;
1205: else Copy(f2.fraction,res.fraction);
1206: Min(diff_expo);
1207: if diff_expo < 2*max_diff
1208: then cnt := Create(diff_expo);
1209: for i in 1..cnt loop
1210: Mul(res.fraction,10);
1211: end loop;
1212: Add(f1.fraction,res.fraction);
1213: Clear(res.fraction);
1214: else Copy(f2.exponent,f1.exponent);
1215: Clear(f1.fraction);
1216: f1.fraction := res.fraction;
1217: end if;
1218: end if;
1219: Clear(diff_expo);
1220: end if;
1221: diff_size := Size(f1.fraction) + 1 - maxsz;
1222: if diff_size > 0
1223: then Round(f1,diff_size);
1224: else Normalize(f1);
1225: end if;
1226: end if;
1227: end Add;
1228:
1229: procedure Sub ( f1 : in out Floating_Number; f2 : in double_float ) is
1230:
1231: minf2 : double_float := -f2;
1232:
1233: begin
1234: Add(f1,minf2);
1235: end Sub;
1236:
1237: procedure Sub ( f1 : in out Floating_Number; f2 : in Floating_Number ) is
1238:
1239: minf2 : Floating_Number;
1240:
1241: begin
1242: minf2.exponent := f2.exponent;
1243: minf2.fraction := -f2.fraction;
1244: Add(f1,minf2);
1245: Clear(minf2.fraction);
1246: end Sub;
1247:
1248: procedure Min ( f : in out Floating_Number ) is
1249: begin
1250: Min(f.fraction);
1251: end Min;
1252:
1253: procedure Mul ( f1 : in out Floating_Number; f2 : in double_float ) is
1254:
1255: ff2 : Floating_Number := Create(f2);
1256:
1257: begin
1258: Mul(f1,ff2);
1259: Clear(ff2);
1260: end Mul;
1261:
1262: procedure Mul ( f1 : in out Floating_Number; f2 : in Floating_Number ) is
1263:
1264: diffsize,maxsize : integer;
1265:
1266: begin
1267: if Empty(f2.fraction)
1268: then Clear(f1);
1269: elsif Equal(f2.fraction,0)
1270: then Clear(f1);
1271: elsif Empty(f1.fraction)
1272: then null;
1273: elsif Equal(f1.fraction,0)
1274: then null;
1275: else maxsize := Max_Size(f1.fraction,f2.fraction);
1276: Mul(f1.fraction,f2.fraction);
1277: Add(f1.exponent,f2.exponent);
1278: diffsize := Size(f1.fraction) - maxsize;
1279: if diffsize > 0
1280: then Round(f1,diffsize);
1281: end if;
1282: Normalize(f1);
1283: end if;
1284: end Mul;
1285:
1286: procedure Div ( f1 : in out Floating_Number; f2 : in double_float ) is
1287:
1288: ff2 : Floating_Number := Create(f2);
1289:
1290: begin
1291: Div(f1,ff2);
1292: Clear(ff2);
1293: end Div;
1294:
1295: procedure Pos_Div ( f1 : in out Floating_Number; f2 : in Floating_Number ) is
1296:
1297: -- DESCRIPTION :
1298: -- Does the division in case f1 and f2 are both positive.
1299:
1300: rmd_frac,new_rmd_frac : Integer_Number;
1301: diffsize : integer;
1302: maxsz : natural := Max_Size(f1.fraction,f2.fraction);
1303:
1304: begin
1305: Div(f1.fraction,f2.fraction,rmd_frac);
1306: Sub(f1.exponent,f2.exponent);
1307: diffsize := Size(f1.fraction) - maxsz;
1308: if not Equal(rmd_frac,0)
1309: then while diffsize <= 0 loop
1310: while rmd_frac < f2.fraction loop
1311: Mul(rmd_frac,10);
1312: Mul(f1.fraction,10);
1313: Sub(f1.exponent,1);
1314: end loop;
1315: Div(rmd_frac,f2.fraction,new_rmd_frac);
1316: Add(f1.fraction,rmd_frac);
1317: Clear(rmd_frac); rmd_frac := new_rmd_frac;
1318: diffsize := Size(f1.fraction) - maxsz;
1319: exit when Equal(rmd_frac,0);
1320: end loop;
1321: end if;
1322: Clear(rmd_frac);
1323: if diffsize > 0
1324: then Round(f1,diffsize);
1325: end if;
1326: Normalize(f1);
1327: end Pos_Div;
1328:
1329: procedure Div ( f1 : in out Floating_Number; f2 : in Floating_Number ) is
1330:
1331: minf1,minf2 : Floating_Number;
1332:
1333: begin
1334: if not (Empty(f1.fraction) or else Equal(f1.fraction,0))
1335: then if not (Empty(f2.fraction) or else Equal(f2.fraction,0))
1336: then if Multprec_Integer_Numbers.Positive(f1.fraction)
1337: then if Multprec_Integer_Numbers.Positive(f2.fraction)
1338: then Pos_Div(f1,f2);
1339: else minf2.fraction := -f2.fraction;
1340: minf2.exponent := f2.exponent;
1341: Pos_Div(f1,minf2);
1342: Clear(minf2.fraction); Min(f1);
1343: end if;
1344: else minf1 := -f1;
1345: if Multprec_Integer_Numbers.Positive(f2.fraction)
1346: then Pos_Div(minf1,f2);
1347: Clear(f1); f1 := minf1; Min(f1);
1348: else minf2.fraction := -f2.fraction;
1349: minf2.exponent := f2.exponent;
1350: Pos_Div(minf1,minf2);
1351: Clear(minf2.fraction);
1352: Clear(f1); f1 := minf1;
1353: end if;
1354: end if;
1355: else raise NUMERIC_ERROR;
1356: end if;
1357: end if;
1358: end Div;
1359:
1360: -- DESTRUCTOR :
1361:
1362: procedure Clear ( f : in out Floating_Number ) is
1363: begin
1364: Clear(f.fraction);
1365: Clear(f.exponent);
1366: end Clear;
1367:
1368: end Multprec_Floating_Numbers;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>