Develop and Download Open Source Software

Browse Subversion Repository

Contents of /arithmet.pas

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (show annotations) (download) (as text)
Mon Nov 7 12:03:00 2011 UTC (12 years, 4 months ago) by shiraishikazuo
File MIME type: text/x-pascal
File size: 113320 byte(s)


1 unit arithmet;
2 {$IFDEF FPC}
3 {$MODE DELPHI}{$H+}
4 {$ENDIF}
5
6 (***************************************)
7 (* Copyright (C) 2003, SHIRAISHI Kazuo *)
8 (***************************************)
9
10
11 {$X+}
12 {$T+}
13
14 interface
15
16
17 {***********}
18 {type Number}
19 {***********}
20
21 const
22 HighPrecision=112;
23 PrecisionMargin=4;
24 MaxPlace = HighPrecision+PrecisionMargin;
25
26 var
27 precision: LongInt =3;
28 limit : LongInt =3;
29 {limit: number of intermediate operationg digits;
30 normally precision +1 in multiple precision mode}
31 {limit must <= maxplace}
32 const
33 MaxExpn = 16383; {549;} {HighPrecision;}
34 MinExpn = -maxExpn;
35 const
36 MaxExpnNative=549;
37 var
38 maxExpnDecimal:smallint =10;
39 minExpnDecimal:smallint =-9;
40
41 type
42 PNumber = ^Number;
43 ShortNumber = object
44 places:LongInt; {length in words} {1place=10000}
45 procedure init(p:PNumber);
46 procedure initzero;
47 procedure initone;
48 public//private
49 sign: shortint;
50 tag : byte; {not used}
51 expn: smallint;
52 frac: array[1..3] of LongInt;
53 end;
54
55 LongNumber = object(ShortNumber)
56 fracEx: array[4..HighPrecision] of LongInt;
57 end;
58 Number = object(LongNumber)
59 fracEx2: array[HighPrecision+1..MaxPlace+1] of LongInt;
60 end;
61
62 //procedure subst(var p:PNumber; var n:number);
63 //procedure disposenumber(var p:PNumber);
64
65 type
66 unaryoperation =procedure(var x:number);
67 binaryoperation = procedure (var a,b:Number; var x:Number);
68
69 var
70 zero:PNumber;
71 one:PNumber;
72 ten:PNumber;
73 half:PNumber;
74 MAXNUM:PNumber;
75 decimalPI:PNumber;
76 decimalHalfPI:PNumber;
77
78 const
79 OptionDecimal :boolean = true ;
80
81 //procedure initinteger(var n:number; i:smallint);
82 procedure initlongint(var n:number; i:longint);
83
84 function LongintVal(var a:number; var c:integer):longint;
85 {c=0:normal ; else c:sign}
86 //function wordVal(var a:number; var c:integer):word;
87 {c=0:normal ; else c:sign}
88 //procedure add(var a,b:Number; var x:Number);
89 //procedure sbt(var a,b:Number; var x:Number);
90 //procedure mlt(var a,b:Number; var x:Number);
91 //procedure qtt(var a,b:Number; var x:Number);
92 //procedure Remainder(var a,b:Number; var x:number);
93 //procedure divide(var a,b:number; var x,y:number);
94 //procedure intpower(var a,b:number; var n:number);
95
96
97 //procedure qtt2(var n:number);
98 function sgn(n:PNumber):shortint;
99 function isZero(n:PNumber):boolean;
100 function isinteger(var n:number):boolean;
101 //function compare(var a,b:number):integer;
102 //procedure opposite(var n:Number);
103 procedure oppose(var n:number);
104 //procedure absolute(var n:number);
105 //procedure intpart(var n:number);
106 //procedure fractpart(var n:number);
107 //procedure intround(var n:number);
108 //procedure ceil(var n:number);
109 //procedure BasicInt(var n:number);
110 //procedure EpsDecimal(var n:number);
111 //procedure EpsNative(var n:number);
112 //procedure BasicMod(var a,b:Number; var x:number);
113 //procedure min(var a,b:number; var n:number);
114 //procedure max(var a,b:number; var n:number);
115 procedure round(var x,n:number; var y:number);
116 //procedure truncate(var x,n:number; var y:number);
117 //procedure sqrlong(var a:number);
118 //procedure square(var n:number);
119
120 procedure round9( var n:number);
121 procedure round15( var n:number);
122 type
123 roundprocedure =procedure (var n:number);
124 var RoundExpression:roundprocedure;
125 procedure roundprecision(var n:number);
126 //procedure RoundVariable(var n:number);
127 procedure checkRangeDecimal(var n:number; extyp:integer);
128 //procedure checkRange(var n:number);
129
130 procedure NumericRep(var n:number;var code:integer;var line:ansistring;var cp:integer);
131 procedure NVal(s:ansistring; var n:number);
132 function DStr(var n:Number):ansistring;
133 procedure ConvertToString(const n:number;var digits:ansistring;var exp:integer);
134 procedure roundstring(var s:ansistring; n:integer; var exp:integer);
135
136
137
138 {*******************}
139 {exetended functions}
140 {*******************}
141
142 //procedure power(var a,b:Number; var x:Number);
143 //function logN(var a:number):extended;
144 procedure convert(a:extended; var n:number);
145 function ExtendedVal(var a:Number):extended;
146
147
148
149 var
150 signiwidth:smallint=10;
151 //exradwidth:smallint=2;
152
153 procedure setOpModeDecimal;
154 procedure setOpModeHigh;
155 procedure setOpModeNative;
156 procedure setOpModeRational;
157
158
159
160 {************}
161 implementation
162 {************}
163 uses math,base,sysutils,sconsts,memman;
164 {$ASMMODE intel}
165
166 {var
167 OperationMode:word=0; }
168
169 {****************}
170 {utility routines}
171 {****************}
172
173 (*
174 function FPUerror:boolean;assembler;
175 asm
176 fstsw ax
177 and ax, 0Dh
178 FCLEX
179 jz @L1
180 mov ax,1
181 @L1:
182 end;
183 *)
184
185 function mini(a,b:longint):longint;assembler;
186 asm
187 cmp eax,edx
188 jc @L1
189 mov eax,edx
190 @L1:
191 end;
192
193 procedure movDWF(var src,dst; count:LongInt);assembler; {move DWords forward}
194 asm {move(a^,x^,count*4); }
195 push esi
196 push edi
197 mov esi,src
198 mov edi,dst
199 {mov ecx,count }
200 rep movsd
201 pop edi
202 pop esi
203 end;
204
205 procedure movDWB(var src,dst; count:LongInt);assembler; {move DWords backward}
206 asm {move(a^,x^,count*4); }
207 push esi
208 push edi
209 std
210 mov esi,src
211 mov edi,dst
212 {mov ecx,count}
213 mov eax,ecx
214 dec eax
215 shl eax,2
216 add esi,eax
217 add edi,eax
218 rep movsd
219 cld
220 pop edi
221 pop esi
222 end;
223
224
225
226 {**********}
227 {arithmetic}
228 {**********}
229
230 procedure ShortNumber.init(p:PNumber);
231 begin
232 movDWF(p^,self,p^.places+2)
233 end;
234
235 procedure ShortNumber.initzero;
236 begin
237 init(zero)
238 { movDWF(zero^,self,2)}{������}
239 {
240 places:=0;
241 sign:=0;
242 expn:=minexpn-1;
243 }
244 end;
245
246 procedure ShortNumber.initone;
247 begin
248 init(one)
249 { movDWF(one^,self,3)}
250 {
251 places:=1;
252 sign:=1;
253 expn:=1;
254 frac[1]:=1;
255 }
256 end;
257
258 procedure clear(var a; n:LongInt);assembler;
259 asm
260 push edi
261 mov edi,a
262 mov ecx,n
263 xor eax,eax
264 rep stosd
265 pop edi
266 end;
267
268
269
270 procedure lengthen(var n:number; k:LongInt);
271 begin
272 with n do
273 begin
274 if k>limit then k:=limit;
275 if k>places then
276 begin
277 {for i:=places+1 to k do frac[i]:=0;}
278 clear(frac[1+places],k-places);
279 places:=k
280 end;
281 end;
282 end;
283
284 procedure shorten(var n:number);
285 begin
286 with n do
287 begin
288 while (places>0) and (frac[places]=0) do dec(places);
289 if places=0 then sign:=0;
290 end;
291 end;
292
293 function CompareRepeat(var a,b; n:LongInt):longint;assembler;
294 asm
295 push edi
296 push esi
297 { mov ecx,n }
298 mov esi,a
299 mov edi,b
300 rep cmpsd
301 je @EQ
302 jc @LESS
303 mov eax,1
304 jmp @EXIT
305 @EQ:
306 mov eax,0
307 jmp @EXIT
308 @LESS:
309 mov eax,-1
310 @EXIT:
311 pop esi
312 pop edi
313 end;
314
315
316 function CompareAbs(var a,b:number):longint;
317 var
318 s:longint;
319 i:longint;
320 begin
321 if a.sign=0 then
322 if b.sign=0 then
323 compareabs:=0
324 else
325 compareabs:=-1
326 else if b.sign=0 then
327 compareabs:=1
328 else
329 begin
330 s:=a.expn-b.expn;
331 if s<>0 then
332 CompareAbs:=s
333 else
334 begin
335 {
336 i:=1;
337 while (a.frac[i]=b.frac[i]) and (i<a.places) and (i<b.places) do inc(i);
338 s:=(a.frac[i]-b.frac[i]);
339 }
340 s:=comparerepeat(a.frac[1],b.frac[1],mini(a.places,b.places));
341
342 if s<>0 then
343 compareabs:=s
344 else
345 compareabs:=a.places-b.places;
346 end;
347 end;
348 end;
349
350
351 function compare(var a,b:number):longint;
352 var
353 s:longint;
354 begin
355 s:=a.sign-b.sign;
356 if s<>0 then
357 compare:=s
358 else
359 if a.sign>0 then
360 compare:=compareabs(a,b)
361 else if a.sign<0 then
362 compare:=compareabs(b,a)
363 else
364 compare:=0;
365 end;
366
367
368 procedure shiftLeft(var n:number; r:LongInt);
369 begin
370 { for i:=1 to places-1 do frac[i]:=frac[i+1];}
371 with n do
372 begin
373 if places>1 then movDWF(frac[2],frac[1],places-1);
374 frac[places]:=r;
375 dec(expn);
376 end;
377 end;
378
379 function shiftRight(var n:number; carry:LongInt):LongInt;
380 var
381 p:LongInt;
382 begin
383 with n do
384 begin
385 p:=places;
386 if p<limit then
387 begin
388 shiftright:=0;
389 frac[p+1]:=frac[p];
390 inc(places);
391 end
392 else
393 shiftright:=frac[p];
394 { for i:=p downto 2 do frac[i]:=frac[i-1];}
395 if p>=2 then movDWB(frac[1],frac[2],p-1);
396 frac[1]:=carry;
397 inc(expn);
398 end;
399 end;
400
401 procedure raisesmall(var n:number);
402 var
403 i:LongInt;
404 begin
405 with n do
406 begin
407 i:=places;
408 inc(frac[i]);
409 while frac[i]=1000000000 do
410 begin
411 frac[i]:=0;
412 inc(frac[i-1]);
413 dec(i);
414 dec(places);
415 end;
416 end;
417 end;
418
419
420 procedure carryuptail(var n:number);
421 var
422 i:LongInt;
423 begin
424 with n do
425 begin
426 i:=places;
427 while (frac[i]=1000000000) and (i>1) do
428 begin
429 frac[i]:=0;
430 inc(frac[i-1]);
431 dec(places);
432 dec(i);
433 end;
434 if (i=1) and (frac[1]=1000000000) then
435 begin
436 frac[1]:=1;
437 inc(expn);
438 end;
439 end;
440 end;
441
442 procedure RoundUp(var n:number);
443 begin
444 with n do inc(frac[places]);
445 carryuptail(n);
446 end;
447
448 procedure carryupsub(var f; i:LongInt);assembler;
449 asm
450 {mov eax,f }
451 mov ecx,i
452 {mov edx,ecx }
453 shl edx,2
454 add eax,edx
455 @L1:
456 cmp dword ptr [eax],1000000000
457 jc @L2
458 sub dword ptr [eax],1000000000
459 inc dword ptr [eax-4]
460 @L2:
461 sub eax,4
462 loop @L1
463 (*
464 les di,f
465 mov cx,i
466 mov ax,cx
467 shl ax,1
468 add di,ax
469 @L1:
470 cmp word ptr [es:di],10000
471 jc @L2
472 sub word ptr [es:di],10000
473 inc word ptr [es:di-2]
474 @L2:
475 sub di,2
476 loop @L1
477 *)
478 end;
479
480
481 procedure carryup(var n:number);
482 var
483 i:LongInt;
484
485 begin
486 {
487 for i:=places downto 2 do
488 if (frac[i]>=10000) then
489 begin
490 frac[i]:=frac[i]-10000;
491 inc(frac[i-1]);
492 end;
493 }
494 with n do
495 begin
496 i:=places-1;
497 if i>0 then carryupsub(frac[1],i);
498
499 if (places>0) and (frac[1]>=1000000000) then
500 begin
501 dec(frac[1],1000000000);
502 shiftRight(n,1); {shiftright���������������}
503 { if r>=5000 then raisesmall(n); }
504 end;
505 end;
506 end;
507
508 procedure unborrowsub(var f; i:LongInt);assembler;
509 asm
510 { les eax,f }
511 { mov edx,i }
512 mov ecx,edx
513 shl edx,2
514 add eax,edx
515 @L1:
516 cmp dword ptr [eax],0
517 jge @L2
518 add dword ptr [eax],1000000000
519 dec dword ptr [eax-4]
520 @L2:
521 sub eax,4
522 loop @L1
523 end;
524
525 function unborrow(var n:number):boolean;
526 var
527 i:LongInt;
528 begin
529 unborrow:=true;
530 {
531 for i:=places downto 2 do
532 if frac[i]<0 then
533 begin
534 inc(frac[i],10000);
535 dec(frac[i-1]);
536 end;
537 }
538 with n do
539 begin
540 i:=places-1;
541 if i>0 then unborrowsub(frac[1],i);
542 if frac[1]<0 then
543 unborrow:=false;
544 end;
545 end;
546
547 procedure normalize(var n:number);
548 var
549 count,p:LongInt;
550 begin
551 with n do
552 begin
553 p:=places;
554 count:=0;
555 while (count<p) and (frac[count+1]=0) do
556 begin
557 inc(count);
558 dec(expn);
559 dec(places);
560 end;
561 if (count>0) and (p>count) then
562 {for i:=count+1 to p do
563 frac[i-count]:=frac[i];}
564 movDWF(frac[1+count],frac[1],p-count);
565 if places=0 then
566 sign:=0;
567 end;
568 end;
569
570 procedure checkRange(var n:number);
571 begin
572 with n do
573 begin
574 if sign=0 then exit;
575
576 normalize(n);
577 shorten(n);
578 if (expn<minExpn) then
579 initzero;
580 if (expn<=MaxExpn) or
581 (expn=MaxExpn+1) and (places=1) and (frac[1]=1) then
582 else
583 begin
584 expn:=MaxExpn+1;
585 frac[1]:=1;
586 places:=1;
587 setexception(1002);
588 end;
589 end;
590 end;
591
592 procedure addincrement(var a; var b; p:LongInt);assembler;
593 asm {asuume n>0}
594 push ebx
595 jecxz @L2
596 @L1:
597 mov ebx,[edx]
598 add edx,4 { post-increment}
599 add [eax],ebx
600 add eax,4 { post-increment}
601 loop @L1
602 @L2:
603 pop ebx
604 end;
605
606 procedure subincrement(var a; var b; p:LongInt);assembler;
607 asm {asuume n>0}
608 push ebx
609 jecxz @L2
610 @L1:
611 mov ebx,[edx]
612 add edx,4 { post-increment}
613 sub [eax],ebx
614 add eax,4 { post-increment}
615 loop @L1
616 @L2:
617 pop ebx
618 end;
619
620
621 function partadd(var n:number; var b:number):boolean;
622 var
623 { i,j:integer; }
624 diff:longint;
625 begin
626 with n do
627 begin
628 diff:=expn-b.expn;
629 lengthen(n,diff+b.places);
630 {
631 i:=diff;
632 j:=0;
633 while (i<places) and (j<b.places) do
634 begin
635 inc(i);
636 inc(j);
637 inc(frac[i],b.frac[j]);
638 end;
639 }
640 if diff<limit then
641 addincrement(frac[1+diff],b.frac[1],mini(b.places,limit-diff));
642 carryup(n);
643 partadd:=(frac[1]>=0);
644 end;
645 end;
646
647 procedure addsub(var a,b:Number; var x:Number);
648 {asuume a>0, b>0, a.expn>=b.expn}
649 {no care of signs. x.sign<- a.sign}
650 begin
651 with x do
652 begin
653 init(@a);
654 partadd(x,b);
655 end;
656 end;
657
658 function partsbt(var n:number; var b:number):boolean;
659 var
660 diff:longint;
661 begin
662 with n do
663 begin
664 diff:=expn-b.expn;
665 if diff<0 then begin partsbt:=false; setexception(SystemErr); exit end;
666 lengthen(n,diff+b.places);
667 {
668 i:=diff;
669 j:=0;
670 while (i<places) and (j<b.places) do
671 begin
672 inc(i);
673 inc(j);
674 frac[i]:=frac[i]-b.frac[j];
675 end;
676 }
677 if diff<limit then
678 subincrement(frac[1+diff],b.frac[1],mini(b.places,limit-diff));
679 end;
680 partsbt:=unborrow(n);
681 end;
682
683 function sbtsub(var a,b:number; var x:Number):boolean;
684 { assume a.expn>=b.expn}
685 { no care of signs. a.sign -> x.sign}
686 { result<0 means failure }
687 begin
688 with x do
689 begin
690 init(@a);
691 sbtsub:=partsbt(x,b)
692 end;
693 end;
694
695
696 procedure add(var a,b:Number; var x:Number);
697 var
698 n:number;
699 begin
700 if ((a.sign>0) and (b.sign>0)) or ((a.sign<0) and (b.sign<0)) then
701 begin
702 if a.expn>=b.expn then
703 addsub(a,b,n)
704 else
705 addsub(b,a,n);
706 x.init(@n);
707 end
708 else if a.sign=0 then
709 x.init(@b)
710 else if b.sign=0 then
711 x.init(@a)
712 else
713 begin
714 if (a.expn>=b.expn) and sbtsub(a,b,n) then
715
716 else
717 sbtsub(b,a,n);
718 x.init(@n);
719 end;
720
721 checkrange(x);
722 end;
723
724
725
726
727 procedure sbt(var a,b:Number; var x:Number);
728 var
729 n:number;
730 begin
731 if ((a.sign>0) and (b.sign>0)) or ((a.sign<0) and (b.sign<0)) then
732 begin
733 if (a.expn>=b.expn) and sbtsub(a,b,n) then
734 else
735 begin
736 sbtsub(b,a,n);
737 n.sign:=-n.sign;
738 end ;
739 x.init(@n);
740 end
741 else if a.sign=0 then
742 begin
743 x.init(@b);
744 oppose(x)
745 end
746 else if b.sign=0 then
747 x.init(@a)
748 else
749 begin
750 if a.expn>=b.expn then
751 addsub(a,b,n)
752 else
753 begin
754 addsub(b,a,n);
755 n.sign:=-n.sign;
756 end;
757 x.init(@n);
758 end;
759
760 checkrange(x);
761 end;
762
763 {***************************}
764 {multiplication and division}
765 {***************************}
766
767 const
768 const1000000000 :LongInt = 1000000000;
769
770 procedure unitmlt(a,b:LongInt; var x);assembler;
771 asm {eax,edx} {ecx}
772 mul edx
773 add [ecx],eax
774 adc [ecx+4],edx
775 adc dword ptr [ecx+8],0
776 end;
777
778 procedure carryupmlt(var f);assembler;
779 asm
780 push ebx
781 mov ecx,eax { eax ��� f }
782 mov eax,[ecx+4]
783 mov edx,[ecx+8]
784 div const1000000000
785 mov ebx,eax
786 mov eax,[ecx]
787 div const1000000000
788 mov [ecx],edx
789 add [ecx-16],eax
790 adc [ecx-12],ebx
791 adc dword ptr [ecx-8],0
792 pop ebx
793 end;
794
795
796 procedure mlt(var a,b:number; var x:number);
797 var
798 i,j,p:LongInt;
799 f:array[1..maxplace+2]of array[0..3] of LongInt;
800 sign:shortint;
801 begin
802 if (a.sign=0) or (b.sign=0) then
803 begin
804 x.initzero;
805 exit
806 end;
807 p:=mini(a.places+b.places,limit+2);
808 clear(f,p*4);
809
810 for i:=1 to a.places do
811 if limit+2>i then
812 for j:=1 to mini(b.places, limit+2-i) do
813 unitmlt(a.frac[i],b.frac[j],f[i+j]);
814 for i:=p downto 2 do
815 carryupmlt(f[i]);
816
817 x.expn:=a.expn+b.expn;
818 if f[1][0]=0 then
819 begin
820 dec(x.expn);
821 dec(p);
822 for i:=1 to p do x.frac[i]:=f[i+1][0]
823 end
824 else
825 begin
826 if p>limit then p:=limit;
827 for i:=1 to p do x.frac[i]:=f[i][0];
828 end;
829 x.places:=p;
830 sign:=1;
831 if a.sign<0 then sign:=-1;
832 if b.sign<0 then sign:=-sign;
833 x.sign:=sign;
834 checkRange(x) ;
835 end;
836
837
838 {*********}
839 { division}
840 {*********}
841
842
843
844 procedure partmltsub(a:LongInt; var b; var x);assembler;
845 asm
846 push esi
847 push edi
848 push ebx
849
850 mov esi,b
851 mov edi,x
852 mov ecx,[esi] {b.places}
853 mov ebx,ecx
854 inc ebx
855 shl ebx,2
856 add esi,ebx { ds:si -> b.frac[places]}
857 add edi,ebx { es:di -> x.frac[places]}
858 mov ebx,eax
859 jcxz @L2
860 @L1:
861 mov eax,[esi]
862 mul ebx
863 div const1000000000
864 add [edi+4],edx
865 mov [edi],eax
866 sub esi,4
867 sub edi,4
868 loop @L1
869 @L2:
870 pop ebx
871 pop edi
872 pop esi
873 end;
874
875
876 procedure partmlt(e:smallint; a:LongInt; var b:number; var x:number);
877 begin
878 with x do
879 if (a=0) or (b.sign=0) then
880 initzero
881 else
882 begin
883 places:=b.places+1;
884 sign:=1;
885 expn:=b.expn+e+1;
886
887 frac[places]:=0;
888 { for i:=places downto 1 do frac[i]:=mltunit(a,b.frac[i],frac[i+1]); }
889 partmltsub(a,b,x);
890
891 carryup(x);
892 if frac[1]=0 then
893 shiftleft(x,0);
894 shorten(x);
895 end;
896 end;
897
898 procedure partmlt1(e:smallint; var b:number; var x:number);
899 begin
900 with x do
901 begin
902 init(@b);
903 sign:=1;
904 expn:=expn+e;
905 end;
906 end;
907
908
909 type
910 CompRec=record
911 lo:cardinal;
912 hi:longint;
913 end;
914
915 function LongDiv(var a:comprec; b:LongInt):LongInt;assembler;
916 asm
917 mov ecx,edx
918 mov edx,[eax+4]
919 mov eax,[eax]
920 div ecx
921 end;
922
923
924 function longMul(a,b:LongInt):comprec;
925 begin
926 int64(result):=int64(a)*int64(b);
927 end;
928
929 (*
930 function longMul(a,b:LongInt):comprec;assembler;
931 asm
932 mul edx
933 mov [ecx],eax
934 mov [ecx+4],edx
935 end;
936 *)
937
938 procedure LongAdd(var a,b:comprec);assembler; {a:=a+b}
939 asm
940 mov ecx,[eax]
941 add ecx,[edx]
942 mov [eax],ecx
943 mov ecx,[eax+4]
944 adc ecx,[edx+4]
945 mov [eax+4],ecx
946 end;
947
948 {const Comp1000000000:comp=1000000000;}
949
950 procedure dividesub(var a,b:Number; var q,r:number; division:boolean);
951 var
952 s:number;
953 devident,temp:comprec;
954 carry:LongInt;
955
956 head :LongInt;
957 multi:LongInt;
958 divisor:LongInt;
959
960 procedure heading(var b:number);
961 begin
962 with b do
963 begin
964 if frac[1]<10 then
965 begin
966 multi :=100000000;
967 divisor:=10;
968 end
969 else if frac[1]<100 then
970 begin
971 multi :=10000000;
972 divisor:=100;
973 end
974 else if frac[1]<1000 then
975 begin
976 multi :=1000000;
977 divisor:=1000;
978 end
979 else if frac[1]<10000 then
980 begin
981 multi :=100000;
982 divisor:=10000;
983 end
984 else if frac[1]<100000 then
985 begin
986 multi :=10000;
987 divisor:=100000;
988 end
989 else if frac[1]<1000000 then
990 begin
991 multi :=1000;
992 divisor:=1000000;
993 end
994 else if frac[1]<10000000 then
995 begin
996 multi :=100;
997 divisor:=10000000;
998 end
999 else if frac[1]<100000000 then
1000 begin
1001 multi :=10;
1002 divisor:=100000000;
1003 end
1004 else
1005 begin
1006 multi:=1;
1007 divisor:=1000000000;
1008 end;
1009 if places>1 then
1010 head:=frac[1]*multi+frac[2] div divisor
1011 else
1012 head:=frac[1]*multi ;
1013 end;
1014 end;
1015
1016
1017 procedure partqtt;
1018
1019 begin
1020 with r do
1021 begin
1022 devident:=longmul(frac[1]*multi,1000000000);
1023 if places>=2 then
1024 begin
1025 temp:=longmul(frac[2],multi);
1026 longadd(devident,temp);
1027 if places>=3 then
1028 begin
1029 temp.hi:=0;
1030 temp.lo:=frac[3] div divisor;
1031 longadd(devident,temp);
1032 end;
1033 end;
1034 end;
1035 {
1036 case places of
1037 1:devident:=(frac[1]*comp1000000000)*multi;
1038 2:devident:=(frac[1]*comp1000000000+frac[2])*multi;
1039 else devident:=(frac[1]*comp1000000000+frac[2])*multi+frac[3] div divisor;
1040 end;
1041 }
1042 with q do
1043 begin
1044 frac[places]:=LongDiv(devident,head); {temorary quotient}
1045 if frac[places]>=1000000000 then frac[places]:=999999999;
1046 partmlt(expn-places,frac[places],b,s);
1047 if (s.sign<>0) and not partsbt(r,s) then
1048 repeat
1049 dec(frac[places]);
1050 partmlt1(expn-places,b,s);
1051 until (s.sign=0) or partadd(r,s);
1052 shiftleft(r,carry);
1053 shorten(r);
1054 end;
1055 end;
1056
1057 begin
1058 q.initzero;
1059 r.init(@a);
1060
1061 if b.sign=0 then
1062 setexception(3001)
1063 else if a.sign=0 then
1064 exit;
1065
1066 heading(b);
1067
1068 inc(limit);
1069
1070 r.init(@a);
1071 r.sign:=1;
1072 carry:=shiftright(r,0);
1073 q.sign:=1;
1074 q.expn:=a.expn-b.expn+1;
1075
1076 if division then
1077 begin
1078 q.places:=0;
1079 while (q.places<=limit) and (r.sign>0) do
1080 begin
1081 inc(q.places);
1082 partqtt;
1083 carry:=0;
1084 end;
1085
1086 end
1087 else
1088 begin
1089 q.places:=0;
1090 while (compareabs(r,b)>=0) and (q.places<limit) do
1091 begin
1092 inc(q.places);
1093 partqtt;
1094 carry:=0;
1095 end;
1096
1097 normalize(r);
1098 if a.sign<0 then oppose(r);
1099 end;
1100
1101 carryup(q);
1102 if (q.places>0) and (q.frac[1]=0) then shiftleft(q,0);
1103 shorten(q);
1104 if q.places>limit then q.places:=limit;
1105 if a.sign<0 then oppose(q);
1106 if b.sign<0 then oppose(q);
1107 dec(limit);
1108 end;
1109
1110
1111
1112
1113 procedure qtt(var a,b:Number; var x:number);
1114 var
1115 q,r:number;
1116 begin
1117 dividesub(a,b,q,r,true);
1118 checkrange(q);
1119 x.init(@q);
1120 end;
1121
1122
1123 (*
1124 procedure remainder(var a,b:Number; var x:number);
1125 var
1126 q,r,s:number;
1127 begin
1128 dividesub(a,b,q,r,false);
1129 while compare(r,b)*b.sign>0 do
1130 begin
1131 s.init(@r);
1132 dividesub(s,b,q,r,false);
1133 end;
1134 checkrange(r);
1135 x.init(@r)
1136 end;
1137
1138 procedure divide(var a,b:number; var x,y:number);
1139 var
1140 q,r:number;
1141 begin
1142 dividesub(a,b,q,r,false);
1143 checkrange(q);
1144 checkrange(r);
1145 x.init(@q);
1146 y.init(@r);
1147 if not isinteger(q) then setexception(SystemErr)
1148 end;
1149
1150
1151 procedure qtt2(var n:number);
1152 var
1153 i:smallint;
1154 carry:LongInt;
1155 begin
1156 carry:=0;
1157 with n do
1158 begin
1159 for i:=1 to places do
1160 begin
1161 if carry<>0 then inc(frac[i],1000000000);
1162 carry:=frac[i] and 1;
1163 frac[i]:=frac[i] shr 1;
1164 end;
1165 if (carry=1) and (places<limit) then
1166 begin
1167 inc(places);
1168 frac[places]:=500000000;
1169 end;
1170 end;
1171 normalize(n);
1172 end;
1173 *)
1174
1175 {********}
1176 {rounding}
1177 {********}
1178
1179
1180 {*************}
1181 {round decimal}
1182 {*************}
1183
1184 (*
1185 procedure round10( var n:number);far;
1186 label
1187 EXIT;
1188 begin
1189 asm
1190 les di,n
1191
1192 cmp byte ptr es:[di],3 {if n.places<3 then goto EXIT; }
1193 jb EXIT
1194
1195 cmp word ptr number(es:[di]).frac , 1000
1196 jb @L1 { if (frac[1]>=1000) then }
1197 mov byte ptr es:[di],3 { places:=3; }
1198 mov ax, word ptr number(es:[di]).frac + 4
1199 mov dx,0
1200 mov bx,100
1201 div bx { r:=frac[3] mod 100;}
1202 sub word ptr number(es:[di]).frac + 4 ,dx {frac[3]:=frac[3]-r;}
1203 cmp dx,50
1204 jb EXIT {if r>= 50 then }
1205 add word ptr number(es:[di]).frac + 4 ,100 { frac[3]:=frac[3]+100; }
1206 jmp @L5
1207
1208 @L1:
1209
1210 cmp word ptr number(es:[di]).frac , 100
1211 jb @L2 { if (frac[1]>=100) then }
1212 mov byte ptr es:[di],3 { places:=3; }
1213 mov ax, word ptr number(es:[di]).frac + 4
1214 mov dx,0
1215 mov bx,10
1216 div bx { r:=frac[3] mod 10;}
1217 sub word ptr number(es:[di]).frac + 4 ,dx {frac[3]:=frac[3]-r;}
1218 cmp dx,5
1219 jb EXIT {if r>= 5 then }
1220 add word ptr number(es:[di]).frac + 4 ,10 { frac[3]:=frac[3]+10; }
1221 jmp @L5
1222
1223 @L2:
1224 cmp byte ptr es:[di],4 {if n.places<4 then exit; }
1225 jb EXIT
1226 cmp word ptr number(es:[di]).frac , 10
1227 jb @L3 { if (frac[1]>=100) then }
1228 mov byte ptr es:[di],3 { places:=3; }
1229 cmp word ptr number(es:[di]).frac + 6,5000
1230 jb EXIT {if frac[4]>=5000 then }
1231 inc (word ptr number(es:[di]).frac + 4) {inc(frac[3])}
1232 jmp @L5 {else}
1233
1234 @L3:
1235 mov byte ptr es:[di],4 { places:=4; }
1236 mov ax, word ptr number(es:[di]).frac + 6
1237 mov dx,0
1238 mov bx,1000
1239 div bx { r:=frac[4] mod 1000;}
1240 sub word ptr number(es:[di]).frac + 6 ,dx {frac[4]:=frac[4]-r;}
1241 cmp dx,500
1242 jb EXIT {if r>= 500 then }
1243 add word ptr number(es:[di]).frac + 6 ,1000 { frac[4]:=frac[4]+1000; }
1244
1245 @L5:
1246 end;
1247 carryuptail(n);
1248 EXIT:
1249 shorten(n);
1250 end;
1251
1252 procedure round11( var n:number);far;
1253 label
1254 EXIT;
1255 begin
1256 asm
1257 les di,n
1258
1259 cmp byte ptr es:[di],3 {if n.places<3 then goto EXIT; }
1260 jb EXIT
1261
1262 cmp word ptr number(es:[di]).frac , 1000
1263 jb @L1 { if (frac[1]>=1000) then }
1264 mov byte ptr es:[di],3 { places:=3; }
1265 mov ax, word ptr number(es:[di]).frac + 4
1266 mov dx,0
1267 mov bx,10
1268 div bx { r:=frac[3] mod 10;}
1269 sub word ptr number(es:[di]).frac + 4 ,dx {frac[3]:=frac[3]-r;}
1270 cmp dx,5
1271 jb EXIT {if r>= 5 then }
1272 add word ptr number(es:[di]).frac + 4 ,10 { frac[3]:=frac[3]+10; }
1273 jmp @L5
1274
1275 @L1:
1276 cmp word ptr number(es:[di]).frac , 100
1277 jb @L2 { if (frac[1]>=100) then }
1278 mov byte ptr es:[di],3 { places:=3; }
1279 cmp word ptr number(es:[di]).frac + 6,5000
1280 jb EXIT {if frac[4]>=5000 then }
1281 inc (word ptr number(es:[di]).frac + 4) {inc(frac[3])}
1282 jmp @L5 {else}
1283
1284
1285 @L2:
1286 cmp byte ptr es:[di],4 {if n.places<4 then exit; }
1287 jb EXIT
1288 mov byte ptr es:[di],4 { places:=4; }
1289 cmp word ptr number(es:[di]).frac , 10
1290 jb @L3 { if (frac[1]>=10) then }
1291 mov ax, word ptr number(es:[di]).frac + 6
1292 mov dx,0
1293 mov bx,1000
1294 div bx { r:=frac[4] mod 1000;}
1295 sub word ptr number(es:[di]).frac + 6 ,dx {frac[4]:=frac[4]-r;}
1296 cmp dx,500
1297 jb EXIT {if r>= 500 then }
1298 add word ptr number(es:[di]).frac + 6 ,1000 { frac[4]:=frac[4]+1000; }
1299 jmp @L5 {else}
1300
1301 @L3:
1302 mov ax, word ptr number(es:[di]).frac + 6
1303 mov dx,0
1304 mov bx,100
1305 div bx { r:=frac[4] mod 100;}
1306 sub word ptr number(es:[di]).frac + 6 ,dx {frac[4]:=frac[4]-r;}
1307 cmp dx,50
1308 jb EXIT {if r>= 50 then }
1309 add word ptr number(es:[di]).frac + 6 ,100 { frac[4]:=frac[4]+100; }
1310
1311
1312 @L5:
1313 end;
1314 carryuptail(n);
1315 EXIT:
1316 shorten(n);
1317 end;
1318
1319 procedure round15( var n:number);far;
1320 label
1321 EXIT;
1322 begin
1323 asm
1324 les di,n
1325
1326 cmp byte ptr es:[di],4 {if n.places<4 then goto EXIT; }
1327 jb EXIT
1328
1329 cmp word ptr number(es:[di]).frac , 1000
1330 jb @L1 { if (frac[1]>=1000) then }
1331 mov byte ptr es:[di],4 { places:=4; }
1332 mov ax, word ptr number(es:[di]).frac + 6
1333 mov dx,0
1334 mov bx,10
1335 div bx { r:=frac[4] mod 10;}
1336 sub word ptr number(es:[di]).frac + 6 ,dx {frac[4]:=frac[4]-r;}
1337 cmp dx,5
1338 jb EXIT {if r>= 5 then }
1339 add word ptr number(es:[di]).frac + 6 ,10 { frac[4]:=frac[4]+10; }
1340 jmp @L5
1341
1342 @L1:
1343 cmp word ptr number(es:[di]).frac , 100
1344 jb @L2 { if (frac[1]>=100) then }
1345 mov byte ptr es:[di],4 { places:=4; }
1346 cmp word ptr number(es:[di]).frac + 8,5000
1347 jb EXIT {if frac[5]>=5000 then }
1348 inc (word ptr number(es:[di]).frac + 6) {inc(frac[4])}
1349 jmp @L5 {else}
1350
1351
1352 @L2:
1353 cmp byte ptr es:[di],5 {if n.places<5 then exit; }
1354 jb EXIT
1355 mov byte ptr es:[di],5 { places:=5; }
1356 cmp word ptr number(es:[di]).frac , 10
1357 jb @L3 { if (frac[1]>=10) then }
1358 mov ax, word ptr number(es:[di]).frac + 8
1359 mov dx,0
1360 mov bx,1000
1361 div bx { r:=frac[5] mod 1000;}
1362 sub word ptr number(es:[di]).frac + 8 ,dx {frac[5]:=frac[5]-r;}
1363 cmp dx,500
1364 jb EXIT {if r>= 500 then }
1365 add word ptr number(es:[di]).frac + 8 ,1000 { frac[5]:=frac[5]+1000; }
1366 jmp @L5 {else}
1367
1368 @L3:
1369 mov ax, word ptr number(es:[di]).frac + 8
1370 mov dx,0
1371 mov bx,100
1372 div bx { r:=frac[5] mod 100;}
1373 sub word ptr number(es:[di]).frac + 8 ,dx {frac[5]:=frac[5]-r;}
1374 cmp dx,50
1375 jb EXIT {if r>= 50 then }
1376 add word ptr number(es:[di]).frac + 8 ,100 { frac[5]:=frac[5]+100; }
1377
1378 @L5:
1379 end;
1380 carryuptail(n);
1381 EXIT:
1382 shorten(n);
1383 end;
1384 *)
1385
1386
1387 function round16sub(var n:number):boolean;assembler;
1388 asm
1389 push edi
1390 mov edi,n
1391
1392 cmp dword ptr [edi],1 {if n.places<=1 then goto @exit0; }
1393 jbe @exit0
1394
1395 cmp dword ptr number([edi]).frac , 100000000
1396 jb @L1 { if (frac[1]>=100000000) then }
1397 mov dword ptr [edi],2 { places:=5; }
1398 mov eax, dword ptr number([edi]).frac+4
1399 mov edx,0
1400 mov ecx,100
1401 div ecx { r:=frac[5] mod 10;}
1402 sub dword ptr number([edi]).frac+4 ,edx {frac[5]:=frac[5]-r;}
1403 cmp edx,50
1404 jb @exit0 {if r>= 5 then }
1405 add dword ptr number([edi]).frac+4 ,100 { frac[5]:=frac[5]+10; }
1406 jmp @L9
1407
1408 @L1:
1409
1410 cmp dword ptr number([edi]).frac , 10000000
1411 jb @L2 { if (frac[1]>=100) then }
1412 mov dword ptr [edi],2 { places:=5; }
1413 mov eax, dword ptr number([edi]).frac+4
1414 mov edx,0
1415 mov ecx,10
1416 div ecx { r:=frac[5] mod 10;}
1417 sub dword ptr number([edi]).frac+4 ,edx {frac[5]:=frac[5]-r;}
1418 cmp edx,5
1419 jb @exit0 {if r>= 5 then }
1420 add dword ptr number([edi]).frac+4 ,10 { frac[5]:=frac[5]+10; }
1421 jmp @L9
1422
1423 @L2:
1424
1425 cmp dword ptr [edi],2 {if n.places<=2 then goto @exit0; }
1426 jbe @exit0
1427
1428 cmp dword ptr number([edi]).frac , 1000000
1429 jb @L3 { if (frac[1]>=100) then }
1430 mov dword ptr [edi],2 { places:=2; }
1431 cmp dword ptr number([edi]).frac+8,500000000
1432 jb @exit0 {if frac[3]>=500000000 then }
1433 inc dword ptr number([edi]).frac+4 {inc(frac[2])}
1434 jmp @L9
1435
1436 @L3:
1437
1438 cmp dword ptr number([edi]).frac , 100000
1439 jb @L4 { if (frac[1]>=100) then }
1440 mov dword ptr [edi],3 { places:=5; }
1441 mov eax, dword ptr number([edi]).frac+8
1442 mov edx,0
1443 mov ecx,100000000
1444 div ecx { r:=frac[5] mod 10;}
1445 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
1446 cmp edx,50000000
1447 jb @exit0 {if r>= 5 then }
1448 add dword ptr number([edi]).frac+8 ,100000000 { frac[5]:=frac[5]+10; }
1449 jmp @L9
1450
1451 @L4:
1452
1453 cmp dword ptr number([edi]).frac , 10000
1454 jb @L5 { if (frac[1]>=100) then }
1455 mov dword ptr [edi],3 { places:=5; }
1456 mov eax, dword ptr number([edi]).frac+8
1457 mov edx,0
1458 mov ecx,10000000
1459 div ecx { r:=frac[5] mod 10;}
1460 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
1461 cmp edx,5000000
1462 jb @exit0 {if r>= 5 then }
1463 add dword ptr number([edi]).frac + 8 ,10000000 { frac[5]:=frac[5]+10; }
1464 jmp @L9
1465
1466 @L5:
1467
1468 cmp dword ptr number([edi]).frac , 1000
1469 jb @L6 { if (frac[1]>=100) then }
1470 mov dword ptr [edi],3 { places:=5; }
1471 mov eax, dword ptr number([edi]).frac+8
1472 mov edx,0
1473 mov ecx,1000000
1474 div ecx { r:=frac[5] mod 10;}
1475 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
1476 cmp edx,500000
1477 jb @exit0 {if r>= 5 then }
1478 add dword ptr number([edi]).frac+8 ,1000000 { frac[5]:=frac[5]+10; }
1479 jmp @L9
1480
1481 @L6:
1482
1483 cmp dword ptr number([edi]).frac , 100
1484 jb @L7 { if (frac[1]>=100) then }
1485 mov dword ptr [edi],3 { places:=5; }
1486 mov eax, dword ptr number([edi]).frac+8
1487 mov edx,0
1488 mov ecx,100000
1489 div ecx { r:=frac[5] mod 10;}
1490 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
1491 cmp edx,50000
1492 jb @exit0 {if r>= 5 then }
1493 add dword ptr number([edi]).frac+8 ,100000 { frac[5]:=frac[5]+10; }
1494 jmp @L9
1495
1496 @L7:
1497 cmp dword ptr number([edi]).frac , 10
1498 jb @L8 { if (frac[1]>=100) then }
1499 mov dword ptr [edi],3 { places:=5; }
1500 mov eax, dword ptr number([edi]).frac+8
1501 mov edx,0
1502 mov ecx,10000
1503 div ecx { r:=frac[5] mod 10;}
1504 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
1505 cmp edx,5000
1506 jb @exit0 {if r>= 5 then }
1507 add dword ptr number([edi]).frac+8 ,10000 { frac[5]:=frac[5]+10; }
1508 jmp @L9
1509
1510 @L8:
1511 mov dword ptr [edi],3 { places:=5; }
1512 mov eax, dword ptr number([edi]).frac+8
1513 mov edx,0
1514 mov ecx,1000
1515 div ecx { r:=frac[5] mod 10;}
1516 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
1517 cmp edx,500
1518 jb @exit0 {if r>= 5 then }
1519 add dword ptr number([edi]).frac+8 ,1000 { frac[5]:=frac[5]+10; }
1520 {jmp @L9 } {else}
1521
1522 @L9:
1523 mov eax,1
1524 jmp @exit
1525 @exit0:
1526 xor eax,eax
1527 @exit:
1528 pop edi
1529
1530
1531 end;
1532
1533
1534
1535 procedure round16( var n:number);far;
1536 begin
1537 if round16sub(n) then
1538 carryuptail(n);
1539 shorten(n);
1540 end;
1541
1542
1543 function round15sub(var n:number):boolean;assembler;
1544 asm
1545 push edi
1546 mov edi,n
1547
1548 cmp dword ptr [edi],1 {if n.places<=1 then goto @exit0; }
1549 jbe @exit0
1550
1551 cmp dword ptr number([edi]).frac , 100000000
1552 jb @L1 { if (frac[1]>=100000000) then }
1553 mov dword ptr [edi],2 { places:=5; }
1554 mov eax, dword ptr number([edi]).frac+4
1555 mov edx,0
1556 mov ecx,1000
1557 div ecx { r:=frac[5] mod 10;}
1558 sub dword ptr number([edi]).frac+4 ,edx {frac[5]:=frac[5]-r;}
1559 cmp edx,500
1560 jb @exit0 {if r>= 5 then }
1561 add dword ptr number([edi]).frac+4 ,1000 { frac[5]:=frac[5]+10; }
1562 jmp @L9
1563
1564 @L1:
1565
1566 cmp dword ptr number([edi]).frac , 10000000
1567 jb @L2 { if (frac[1]>=100000000) then }
1568 mov dword ptr [edi],2 { places:=5; }
1569 mov eax, dword ptr number([edi]).frac+4
1570 mov edx,0
1571 mov ecx,100
1572 div ecx { r:=frac[5] mod 10;}
1573 sub dword ptr number([edi]).frac+4 ,edx {frac[5]:=frac[5]-r;}
1574 cmp edx,50
1575 jb @exit0 {if r>= 5 then }
1576 add dword ptr number([edi]).frac+4 ,100 { frac[5]:=frac[5]+10; }
1577 jmp @L9
1578
1579 @L2:
1580
1581 cmp dword ptr number([edi]).frac , 1000000
1582 jb @L3 { if (frac[1]>=100) then }
1583 mov dword ptr [edi],2 { places:=5; }
1584 mov eax, dword ptr number([edi]).frac+4
1585 mov edx,0
1586 mov ecx,10
1587 div ecx { r:=frac[5] mod 10;}
1588 sub dword ptr number([edi]).frac+4 ,edx {frac[5]:=frac[5]-r;}
1589 cmp edx,5
1590 jb @exit0 {if r>= 5 then }
1591 add dword ptr number([edi]).frac+4 ,10 { frac[5]:=frac[5]+10; }
1592 jmp @L9
1593
1594 @L3:
1595
1596 cmp dword ptr [edi],2 {if n.places<=2 then goto @exit0; }
1597 jbe @exit0
1598
1599 cmp dword ptr number([edi]).frac , 100000
1600 jb @L4 { if (frac[1]>=100) then }
1601 mov dword ptr [edi],2 { places:=2; }
1602 cmp dword ptr number([edi]).frac+8,500000000
1603 jb @exit0 {if frac[3]>=500000000 then }
1604 inc dword ptr number([edi]).frac+4 {inc(frac[2])}
1605 jmp @L9
1606
1607 @L4:
1608
1609 cmp dword ptr number([edi]).frac , 10000
1610 jb @L5 { if (frac[1]>=100) then }
1611 mov dword ptr [edi],3 { places:=5; }
1612 mov eax, dword ptr number([edi]).frac+8
1613 mov edx,0
1614 mov ecx,100000000
1615 div ecx { r:=frac[5] mod 10;}
1616 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
1617 cmp edx,50000000
1618 jb @exit0 {if r>= 5 then }
1619 add dword ptr number([edi]).frac+8 ,100000000 { frac[5]:=frac[5]+10; }
1620 jmp @L9
1621
1622 @L5:
1623
1624 cmp dword ptr number([edi]).frac , 1000
1625 jb @L6 { if (frac[1]>=100) then }
1626 mov dword ptr [edi],3 { places:=5; }
1627 mov eax, dword ptr number([edi]).frac+8
1628 mov edx,0
1629 mov ecx,10000000
1630 div ecx { r:=frac[5] mod 10;}
1631 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
1632 cmp edx,5000000
1633 jb @exit0 {if r>= 5 then }
1634 add dword ptr number([edi]).frac + 8 ,10000000 { frac[5]:=frac[5]+10; }
1635 jmp @L9
1636
1637 @L6:
1638
1639 cmp dword ptr number([edi]).frac , 100
1640 jb @L7 { if (frac[1]>=100) then }
1641 mov dword ptr [edi],3 { places:=5; }
1642 mov eax, dword ptr number([edi]).frac+8
1643 mov edx,0
1644 mov ecx,1000000
1645 div ecx { r:=frac[5] mod 10;}
1646 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
1647 cmp edx,500000
1648 jb @exit0 {if r>= 5 then }
1649 add dword ptr number([edi]).frac+8 ,1000000 { frac[5]:=frac[5]+10; }
1650 jmp @L9
1651
1652 @L7:
1653
1654 cmp dword ptr number([edi]).frac , 10
1655 jb @L8 { if (frac[1]>=100) then }
1656 mov dword ptr [edi],3 { places:=5; }
1657 mov eax, dword ptr number([edi]).frac+8
1658 mov edx,0
1659 mov ecx,100000
1660 div ecx { r:=frac[5] mod 10;}
1661 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
1662 cmp edx,50000
1663 jb @exit0 {if r>= 5 then }
1664 add dword ptr number([edi]).frac+8 ,100000 { frac[5]:=frac[5]+10; }
1665 jmp @L9
1666
1667 @L8:
1668 mov dword ptr [edi],3 { places:=5; }
1669 mov eax, dword ptr number([edi]).frac+8
1670 mov edx,0
1671 mov ecx,10000
1672 div ecx { r:=frac[5] mod 10;}
1673 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
1674 cmp edx,5000
1675 jb @exit0 {if r>= 5 then }
1676 add dword ptr number([edi]).frac+8 ,10000 { frac[5]:=frac[5]+10; }
1677 {jmp @L9 } {else}
1678
1679 @L9:
1680 mov eax,1
1681 jmp @exit
1682 @exit0:
1683 xor eax,eax
1684 @exit:
1685 pop edi
1686
1687
1688 end;
1689
1690
1691
1692 procedure round15( var n:number);far;
1693 begin
1694 if round15sub(n) then
1695 carryuptail(n);
1696 shorten(n);
1697 end;
1698
1699
1700 {******}
1701 {ROUND6}
1702 {******}
1703 function round6sub(var n:number):boolean;assembler;
1704 asm
1705 push edi
1706 mov edi,n
1707
1708 cmp dword ptr [edi],0 {if n.places<=1 then goto @exit0; }
1709 jbe @exit0
1710
1711 cmp dword ptr number([edi]).frac , 100000000
1712 jb @L1 { if (frac[1]>=100000000) then }
1713 mov dword ptr [edi],1 { places:=5; }
1714 mov eax, dword ptr number([edi]).frac+0
1715 mov edx,0
1716 mov ecx,1000
1717 div ecx { r:=frac[5] mod 10;}
1718 sub dword ptr number([edi]).frac+0 ,edx {frac[5]:=frac[5]-r;}
1719 cmp edx,500
1720 jb @exit0 {if r>= 5 then }
1721 add dword ptr number([edi]).frac+0 ,1000 { frac[5]:=frac[5]+10; }
1722 jmp @L9
1723
1724 @L1:
1725
1726 cmp dword ptr number([edi]).frac , 10000000
1727 jb @L2 { if (frac[1]>=100000000) then }
1728 mov dword ptr [edi],1 { places:=5; }
1729 mov eax, dword ptr number([edi]).frac+0
1730 mov edx,0
1731 mov ecx,100
1732 div ecx { r:=frac[5] mod 10;}
1733 sub dword ptr number([edi]).frac+0 ,edx {frac[5]:=frac[5]-r;}
1734 cmp edx,50
1735 jb @exit0 {if r>= 5 then }
1736 add dword ptr number([edi]).frac+0 ,100 { frac[5]:=frac[5]+10; }
1737 jmp @L9
1738
1739 @L2:
1740
1741 cmp dword ptr number([edi]).frac , 1000000
1742 jb @L3 { if (frac[1]>=100) then }
1743 mov dword ptr [edi],1 { places:=5; }
1744 mov eax, dword ptr number([edi]).frac+0
1745 mov edx,0
1746 mov ecx,10
1747 div ecx { r:=frac[5] mod 10;}
1748 sub dword ptr number([edi]).frac+0 ,edx {frac[5]:=frac[5]-r;}
1749 cmp edx,5
1750 jb @exit0 {if r>= 5 then }
1751 add dword ptr number([edi]).frac+0 ,10 { frac[5]:=frac[5]+10; }
1752 jmp @L9
1753
1754 @L3:
1755
1756 cmp dword ptr [edi],1 {if n.places<=2 then goto @exit0; }
1757 jbe @exit0
1758
1759 cmp dword ptr number([edi]).frac , 100000
1760 jb @L4 { if (frac[1]>=100) then }
1761 mov dword ptr [edi],1 { places:=2; }
1762 cmp dword ptr number([edi]).frac+4,500000000
1763 jb @exit0 {if frac[3]>=500000000 then }
1764 inc dword ptr number([edi]).frac+0 {inc(frac[2])}
1765 jmp @L9
1766
1767 @L4:
1768
1769 cmp dword ptr number([edi]).frac , 10000
1770 jb @L5 { if (frac[1]>=100) then }
1771 mov dword ptr [edi],2 { places:=5; }
1772 mov eax, dword ptr number([edi]).frac+4
1773 mov edx,0
1774 mov ecx,100000000
1775 div ecx { r:=frac[5] mod 10;}
1776 sub dword ptr number([edi]).frac+4 ,edx {frac[5]:=frac[5]-r;}
1777 cmp edx,50000000
1778 jb @exit0 {if r>= 5 then }
1779 add dword ptr number([edi]).frac+4 ,100000000 { frac[5]:=frac[5]+10; }
1780 jmp @L9
1781
1782 @L5:
1783
1784 cmp dword ptr number([edi]).frac , 1000
1785 jb @L6 { if (frac[1]>=100) then }
1786 mov dword ptr [edi],2 { places:=5; }
1787 mov eax, dword ptr number([edi]).frac+4
1788 mov edx,0
1789 mov ecx,10000000
1790 div ecx { r:=frac[5] mod 10;}
1791 sub dword ptr number([edi]).frac+4 ,edx {frac[5]:=frac[5]-r;}
1792 cmp edx,5000000
1793 jb @exit0 {if r>= 5 then }
1794 add dword ptr number([edi]).frac+4 ,10000000 { frac[5]:=frac[5]+10; }
1795 jmp @L9
1796
1797 @L6:
1798
1799 cmp dword ptr number([edi]).frac , 100
1800 jb @L7 { if (frac[1]>=100) then }
1801 mov dword ptr [edi],2 { places:=5; }
1802 mov eax, dword ptr number([edi]).frac+4
1803 mov edx,0
1804 mov ecx,1000000
1805 div ecx { r:=frac[5] mod 10;}
1806 sub dword ptr number([edi]).frac+4 ,edx {frac[5]:=frac[5]-r;}
1807 cmp edx,500000
1808 jb @exit0 {if r>= 5 then }
1809 add dword ptr number([edi]).frac+4 ,1000000 { frac[5]:=frac[5]+10; }
1810 jmp @L9
1811
1812 @L7:
1813
1814 cmp dword ptr number([edi]).frac , 10
1815 jb @L8 { if (frac[1]>=100) then }
1816 mov dword ptr [edi],2 { places:=5; }
1817 mov eax, dword ptr number([edi]).frac+4
1818 mov edx,0
1819 mov ecx,100000
1820 div ecx { r:=frac[5] mod 10;}
1821 sub dword ptr number([edi]).frac+4 ,edx {frac[5]:=frac[5]-r;}
1822 cmp edx,50000
1823 jb @exit0 {if r>= 5 then }
1824 add dword ptr number([edi]).frac+4 ,100000 { frac[5]:=frac[5]+10; }
1825 jmp @L9
1826
1827 @L8:
1828 mov dword ptr [edi],2 { places:=5; }
1829 mov eax, dword ptr number([edi]).frac+4
1830 mov edx,0
1831 mov ecx,10000
1832 div ecx { r:=frac[5] mod 10;}
1833 sub dword ptr number([edi]).frac+4 ,edx {frac[5]:=frac[5]-r;}
1834 cmp edx,5000
1835 jb @exit0 {if r>= 5 then }
1836 add dword ptr number([edi]).frac+4 ,10000 { frac[5]:=frac[5]+10; }
1837 {jmp @L9 } {else}
1838
1839 @L9:
1840 mov eax,1
1841 jmp @exit
1842 @exit0:
1843 xor eax,eax
1844 @exit:
1845 pop edi
1846
1847
1848 end;
1849
1850
1851
1852 procedure round6( var n:number);far;
1853 begin
1854 if round6sub(n) then
1855 carryuptail(n);
1856 shorten(n);
1857 end;
1858
1859
1860 function round9sub(var n:number):boolean;assembler;
1861 asm
1862 push edi
1863 mov edi,n
1864
1865 cmp dword ptr [edi],1 {if n.places<=1 then goto @exit0; }
1866 jbe @exit0
1867
1868 cmp dword ptr number([edi]).frac , 100000000
1869 jb @L1 { if (frac[1]>=100000000) then }
1870 mov dword ptr [edi],1 { places:=1; }
1871 cmp dword ptr number([edi]).frac+4,500000000
1872 jb @exit0 {if frac[2]>=500000000 then }
1873 inc dword ptr number([edi]).frac {inc(frac[1])}
1874 jmp @L9
1875
1876 @L1:
1877
1878 cmp dword ptr number([edi]).frac , 10000000
1879 jb @L2 { if (frac[1]>=10000000) then }
1880 mov dword ptr [edi],2 { places:=2; }
1881 mov eax, dword ptr number([edi]).frac+4
1882 mov edx,0
1883 mov ecx,100000000
1884 div ecx { r:=frac[2] mod 100000000;}
1885 sub dword ptr number([edi]).frac+4 ,edx {frac[2]:=frac[2]-r;}
1886 cmp edx,50000000
1887 jb @exit0 {if r>= 5 then }
1888 add dword ptr number([edi]).frac+4 ,100000000 { frac[5]:=frac[5]+10; }
1889 jmp @L9
1890
1891 @L2:
1892
1893 cmp dword ptr number([edi]).frac , 1000000
1894 jb @L3 { if (frac[1]>=1000000) then }
1895 mov dword ptr [edi],2 { places:=2; }
1896 mov eax, dword ptr number([edi]).frac+4
1897 mov edx,0
1898 mov ecx,10000000
1899 div ecx { r:=frac[2] mod 10000000;}
1900 sub dword ptr number([edi]).frac+4 ,edx {frac[2]:=frac[2]-r;}
1901 cmp edx,5000000
1902 jb @exit0 {if r>= 5000000 then }
1903 add dword ptr number([edi]).frac + 4 ,10000000 { frac[2]:=frac[2]+10000000; }
1904 jmp @L9
1905
1906 @L3:
1907
1908 cmp dword ptr number([edi]).frac , 100000
1909 jb @L4 { if (frac[1]>=100) then }
1910 mov dword ptr [edi],2 { places:=5; }
1911 mov eax, dword ptr number([edi]).frac+4
1912 mov edx,0
1913 mov ecx,1000000
1914 div ecx { r:=frac[5] mod 10;}
1915 sub dword ptr number([edi]).frac+4 ,edx {frac[5]:=frac[5]-r;}
1916 cmp edx,500000
1917 jb @exit0 {if r>= 5 then }
1918 add dword ptr number([edi]).frac+4 ,1000000 { frac[5]:=frac[5]+10; }
1919 jmp @L9
1920
1921 @L4:
1922
1923 cmp dword ptr number([edi]).frac , 10000
1924 jb @L5 { if (frac[1]>=100) then }
1925 mov dword ptr [edi],2 { places:=5; }
1926 mov eax, dword ptr number([edi]).frac+4
1927 mov edx,0
1928 mov ecx,100000
1929 div ecx { r:=frac[5] mod 10;}
1930 sub dword ptr number([edi]).frac+4 ,edx {frac[5]:=frac[5]-r;}
1931 cmp edx,50000
1932 jb @exit0 {if r>= 5 then }
1933 add dword ptr number([edi]).frac+4 ,100000 { frac[5]:=frac[5]+10; }
1934 jmp @L9
1935
1936 @L5:
1937
1938 cmp dword ptr number([edi]).frac , 1000
1939 jb @L6 { if (frac[1]>=100) then }
1940 mov dword ptr [edi],2 { places:=5; }
1941 mov eax, dword ptr number([edi]).frac+4
1942 mov edx,0
1943 mov ecx,10000
1944 div ecx { r:=frac[5] mod 10;}
1945 sub dword ptr number([edi]).frac+4 ,edx {frac[5]:=frac[5]-r;}
1946 cmp edx,5000
1947 jb @exit0 {if r>= 5 then }
1948 add dword ptr number([edi]).frac+4 ,10000 { frac[5]:=frac[5]+10; }
1949 jmp @L9
1950
1951 @L6:
1952
1953 cmp dword ptr number([edi]).frac , 100
1954 jb @L7 { if (frac[1]>=100) then }
1955 mov dword ptr [edi],2 { places:=2; }
1956 mov eax, dword ptr number([edi]).frac+4
1957 mov edx,0
1958 mov ecx,1000
1959 div ecx { r:=frac[2] mod 1000;}
1960 sub dword ptr number([edi]).frac+4 ,edx {frac[2]:=frac[2]-r;}
1961 cmp edx,500
1962 jb @exit0 {if r>= 500 then }
1963 add dword ptr number([edi]).frac+4 ,1000 { frac[2]:=frac[2]+1000; }
1964 jmp @L9
1965
1966 @L7:
1967 cmp dword ptr number([edi]).frac , 10
1968 jb @L8 { if (frac[1]>=10) then }
1969 mov dword ptr [edi],2 { places:=2; }
1970 mov eax, dword ptr number([edi]).frac+4
1971 mov edx,0
1972 mov ecx,100
1973 div ecx { r:=frac[2] mod 100;}
1974 sub dword ptr number([edi]).frac+4 ,edx {frac[2]:=frac[2]-r;}
1975 cmp edx,50
1976 jb @exit0 {if r>= 50 then }
1977 add dword ptr number([edi]).frac+4 ,100 { frac[2]:=frac[2]+100; }
1978 jmp @L9
1979
1980 @L8:
1981 mov dword ptr [edi],2 { places:=2; }
1982 mov eax, dword ptr number([edi]).frac+4
1983 mov edx,0
1984 mov ecx,10
1985 div ecx { r:=frac[2] mod 10;}
1986 sub dword ptr number([edi]).frac+4 ,edx {frac[2]:=frac[2]-r;}
1987 cmp edx,5
1988 jb @exit0 {if r>= 5 then }
1989 add dword ptr number([edi]).frac+4 ,10 { frac[2]:=frac[2]+10; }
1990 {jmp @L9 } {else}
1991
1992 @L9:
1993 mov eax,1
1994 jmp @exit
1995 @exit0:
1996 xor eax,eax
1997 @exit:
1998 pop edi
1999
2000 end;
2001
2002 procedure round9( var n:number);far;
2003 begin
2004 if round9sub(n) then
2005 carryuptail(n);
2006 shorten(n);
2007 end;
2008
2009
2010
2011 function round18sub(var n:number):boolean;assembler;
2012 asm
2013 push edi
2014 mov edi,n
2015
2016 cmp dword ptr [edi],2 {if n.places<=2 then goto @exit0; }
2017 jbe @exit0
2018
2019 cmp dword ptr number([edi]).frac , 100000000
2020 jb @L1 { if (frac[1]>=100000000) then }
2021 mov dword ptr [edi],2 { places:=2; }
2022 cmp dword ptr number([edi]).frac+8,500000000
2023 jb @exit0 {if frac[3]>=500000000 then }
2024 inc dword ptr number([edi]).frac+4 {inc(frac[2])}
2025 jmp @L9
2026
2027 @L1:
2028
2029 cmp dword ptr number([edi]).frac , 10000000
2030 jb @L2 { if (frac[1]>=100) then }
2031 mov dword ptr [edi],3 { places:=5; }
2032 mov eax, dword ptr number([edi]).frac+8
2033 mov edx,0
2034 mov ecx,100000000
2035 div ecx { r:=frac[5] mod 10;}
2036 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
2037 cmp edx,50000000
2038 jb @exit0 {if r>= 5 then }
2039 add dword ptr number([edi]).frac+8 ,100000000 { frac[5]:=frac[5]+10; }
2040 jmp @L9
2041
2042 @L2:
2043
2044 cmp dword ptr number([edi]).frac , 1000000
2045 jb @L3 { if (frac[1]>=100) then }
2046 mov dword ptr [edi],3 { places:=5; }
2047 mov eax, dword ptr number([edi]).frac+8
2048 mov edx,0
2049 mov ecx,10000000
2050 div ecx { r:=frac[5] mod 10;}
2051 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
2052 cmp edx,5000000
2053 jb @exit0 {if r>= 5 then }
2054 add dword ptr number([edi]).frac + 8 ,10000000 { frac[5]:=frac[5]+10; }
2055 jmp @L9
2056
2057 @L3:
2058
2059 cmp dword ptr number([edi]).frac , 100000
2060 jb @L4 { if (frac[1]>=100) then }
2061 mov dword ptr [edi],3 { places:=5; }
2062 mov eax, dword ptr number([edi]).frac+8
2063 mov edx,0
2064 mov ecx,1000000
2065 div ecx { r:=frac[5] mod 10;}
2066 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
2067 cmp edx,500000
2068 jb @exit0 {if r>= 5 then }
2069 add dword ptr number([edi]).frac+8 ,1000000 { frac[5]:=frac[5]+10; }
2070 jmp @L9
2071
2072 @L4:
2073
2074 cmp dword ptr number([edi]).frac , 10000
2075 jb @L5 { if (frac[1]>=100) then }
2076 mov dword ptr [edi],3 { places:=5; }
2077 mov eax, dword ptr number([edi]).frac+8
2078 mov edx,0
2079 mov ecx,100000
2080 div ecx { r:=frac[5] mod 10;}
2081 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
2082 cmp edx,50000
2083 jb @exit0 {if r>= 5 then }
2084 add dword ptr number([edi]).frac+8 ,100000 { frac[5]:=frac[5]+10; }
2085 jmp @L9
2086
2087 @L5:
2088
2089 cmp dword ptr number([edi]).frac , 1000
2090 jb @L6 { if (frac[1]>=100) then }
2091 mov dword ptr [edi],3 { places:=5; }
2092 mov eax, dword ptr number([edi]).frac+8
2093 mov edx,0
2094 mov ecx,10000
2095 div ecx { r:=frac[5] mod 10;}
2096 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
2097 cmp edx,5000
2098 jb @exit0 {if r>= 5 then }
2099 add dword ptr number([edi]).frac+8 ,10000 { frac[5]:=frac[5]+10; }
2100 jmp @L9
2101
2102 @L6:
2103
2104 cmp dword ptr number([edi]).frac , 100
2105 jb @L7 { if (frac[1]>=100) then }
2106 mov dword ptr [edi],3 { places:=5; }
2107 mov eax, dword ptr number([edi]).frac+8
2108 mov edx,0
2109 mov ecx,1000
2110 div ecx { r:=frac[5] mod 10;}
2111 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
2112 cmp edx,500
2113 jb @exit0 {if r>= 5 then }
2114 add dword ptr number([edi]).frac+8 ,1000 { frac[5]:=frac[5]+10; }
2115 jmp @L9
2116
2117 @L7:
2118 cmp dword ptr number([edi]).frac , 10
2119 jb @L8 { if (frac[1]>=100) then }
2120 mov dword ptr [edi],3 { places:=5; }
2121 mov eax, dword ptr number([edi]).frac+8
2122 mov edx,0
2123 mov ecx,100
2124 div ecx { r:=frac[5] mod 10;}
2125 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
2126 cmp edx,50
2127 jb @exit0 {if r>= 5 then }
2128 add dword ptr number([edi]).frac+8 ,100 { frac[5]:=frac[5]+10; }
2129 jmp @L9
2130
2131 @L8:
2132 mov dword ptr [edi],3 { places:=5; }
2133 mov eax, dword ptr number([edi]).frac+8
2134 mov edx,0
2135 mov ecx,10
2136 div ecx { r:=frac[5] mod 10;}
2137 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
2138 cmp edx,5
2139 jb @exit0 {if r>= 5 then }
2140 add dword ptr number([edi]).frac+8 ,10 { frac[5]:=frac[5]+10; }
2141 {jmp @L9 } {else}
2142
2143 @L9:
2144 mov eax,1
2145 jmp @exit
2146 @exit0:
2147 xor eax,eax
2148 @exit:
2149 pop edi
2150
2151 end;
2152
2153
2154
2155 procedure round18( var n:number);far;
2156 begin
2157 if round18sub(n) then
2158 carryuptail(n);
2159 shorten(n);
2160 end;
2161
2162 function round18msub(var n:number):boolean;assembler;
2163 asm
2164 push edi
2165 mov edi,n
2166
2167 cmp dword ptr [edi],1 {if n.places<=2 then goto @exit0; }
2168 jbe @exit0
2169
2170 cmp dword ptr number([edi]).frac , 100000000
2171 jb @L1 { if (frac[1]>=100000000) then }
2172 mov dword ptr [edi],2 { places:=2; }
2173 mov eax, dword ptr number([edi]).frac+4
2174 mov edx,0
2175 mov ecx,2
2176 div ecx { r:=frac[5] mod 10;}
2177 sub dword ptr number([edi]).frac+4 ,edx {frac[5]:=frac[5]-r;}
2178 cmp edx,1
2179 jb @exit0 {if r>= 5 then }
2180 add dword ptr number([edi]).frac+4 ,2 { frac[5]:=frac[5]+10; }
2181 jmp @L9
2182
2183 @L1:
2184
2185 cmp dword ptr [edi],2 {if n.places<=2 then goto @exit0; }
2186 jbe @exit0
2187
2188 cmp dword ptr number([edi]).frac , 10000000
2189 jb @L2 { if (frac[1]>=100) then }
2190 mov dword ptr [edi],3 { places:=5; }
2191 mov eax, dword ptr number([edi]).frac+8
2192 mov edx,0
2193 mov ecx,200000000
2194 div ecx { r:=frac[5] mod 10;}
2195 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
2196 cmp edx,100000000
2197 jb @exit0 {if r>= 5 then }
2198 add dword ptr number([edi]).frac+8 ,200000000 { frac[5]:=frac[5]+10; }
2199 jmp @L9
2200
2201 @L2:
2202
2203 cmp dword ptr number([edi]).frac , 1000000
2204 jb @L3 { if (frac[1]>=100) then }
2205 mov dword ptr [edi],3 { places:=5; }
2206 mov eax, dword ptr number([edi]).frac+8
2207 mov edx,0
2208 mov ecx,20000000
2209 div ecx { r:=frac[5] mod 10;}
2210 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
2211 cmp edx,10000000
2212 jb @exit0 {if r>= 5 then }
2213 add dword ptr number([edi]).frac + 8 ,20000000 { frac[5]:=frac[5]+10; }
2214 jmp @L9
2215
2216 @L3:
2217
2218 cmp dword ptr number([edi]).frac , 100000
2219 jb @L4 { if (frac[1]>=100) then }
2220 mov dword ptr [edi],3 { places:=5; }
2221 mov eax, dword ptr number([edi]).frac+8
2222 mov edx,0
2223 mov ecx,2000000
2224 div ecx { r:=frac[5] mod 10;}
2225 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
2226 cmp edx,1000000
2227 jb @exit0 {if r>= 5 then }
2228 add dword ptr number([edi]).frac+8 ,2000000 { frac[5]:=frac[5]+10; }
2229 jmp @L9
2230
2231 @L4:
2232
2233 cmp dword ptr number([edi]).frac , 10000
2234 jb @L5 { if (frac[1]>=100) then }
2235 mov dword ptr [edi],3 { places:=5; }
2236 mov eax, dword ptr number([edi]).frac+8
2237 mov edx,0
2238 mov ecx,200000
2239 div ecx { r:=frac[5] mod 10;}
2240 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
2241 cmp edx,100000
2242 jb @exit0 {if r>= 5 then }
2243 add dword ptr number([edi]).frac+8 ,200000 { frac[5]:=frac[5]+10; }
2244 jmp @L9
2245
2246 @L5:
2247
2248 cmp dword ptr number([edi]).frac , 1000
2249 jb @L6 { if (frac[1]>=100) then }
2250 mov dword ptr [edi],3 { places:=5; }
2251 mov eax, dword ptr number([edi]).frac+8
2252 mov edx,0
2253 mov ecx,20000
2254 div ecx { r:=frac[5] mod 10;}
2255 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
2256 cmp edx,10000
2257 jb @exit0 {if r>= 5 then }
2258 add dword ptr number([edi]).frac+8 ,20000 { frac[5]:=frac[5]+10; }
2259 jmp @L9
2260
2261 @L6:
2262
2263 cmp dword ptr number([edi]).frac , 100
2264 jb @L7 { if (frac[1]>=100) then }
2265 mov dword ptr [edi],3 { places:=5; }
2266 mov eax, dword ptr number([edi]).frac+8
2267 mov edx,0
2268 mov ecx,2000
2269 div ecx { r:=frac[5] mod 10;}
2270 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
2271 cmp edx,1000
2272 jb @exit0 {if r>= 5 then }
2273 add dword ptr number([edi]).frac+8 ,2000 { frac[5]:=frac[5]+10; }
2274 jmp @L9
2275
2276 @L7:
2277 cmp dword ptr number([edi]).frac , 10
2278 jb @L8 { if (frac[1]>=100) then }
2279 mov dword ptr [edi],3 { places:=5; }
2280 mov eax, dword ptr number([edi]).frac+8
2281 mov edx,0
2282 mov ecx,200
2283 div ecx { r:=frac[5] mod 10;}
2284 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
2285 cmp edx,100
2286 jb @exit0 {if r>= 5 then }
2287 add dword ptr number([edi]).frac+8 ,200 { frac[5]:=frac[5]+10; }
2288 jmp @L9
2289
2290 @L8:
2291 mov dword ptr [edi],3 { places:=5; }
2292 mov eax, dword ptr number([edi]).frac+8
2293 mov edx,0
2294 mov ecx,20
2295 div ecx { r:=frac[5] mod 10;}
2296 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
2297 cmp edx,10
2298 jb @exit0 {if r>= 5 then }
2299 add dword ptr number([edi]).frac+8 ,20 { frac[5]:=frac[5]+10; }
2300 {jmp @L9 } {else}
2301
2302 @L9:
2303 mov eax,1
2304 jmp @exit
2305 @exit0:
2306 xor eax,eax
2307 @exit:
2308 pop edi
2309
2310 end;
2311
2312
2313
2314 procedure round18m( var n:number);far;
2315 begin
2316 if round18msub(n) then
2317 carryuptail(n);
2318 shorten(n);
2319 end;
2320
2321 function round17msub(var n:number):boolean;assembler;
2322 asm
2323 push edi
2324 mov edi,n
2325
2326 cmp dword ptr [edi],1 {if n.places<=2 then goto @exit0; }
2327 jbe @exit0
2328
2329 cmp dword ptr number([edi]).frac , 100000000
2330 jb @L1 { if (frac[1]>=100000000) then }
2331 mov dword ptr [edi],2 { places:=2; }
2332 mov eax, dword ptr number([edi]).frac+4
2333 mov edx,0
2334 mov ecx,20
2335 div ecx { r:=frac[5] mod 10;}
2336 sub dword ptr number([edi]).frac+4 ,edx {frac[5]:=frac[5]-r;}
2337 cmp edx,10
2338 jb @exit0 {if r>= 5 then }
2339 add dword ptr number([edi]).frac+4 ,20 { frac[5]:=frac[5]+10; }
2340 jmp @L9
2341
2342 @L1:
2343
2344 cmp dword ptr number([edi]).frac , 10000000
2345 jb @L2 { if (frac[1]>=100000000) then }
2346 mov dword ptr [edi],2 { places:=2; }
2347 mov eax, dword ptr number([edi]).frac+4
2348 mov edx,0
2349 mov ecx,2
2350 div ecx { r:=frac[5] mod 10;}
2351 sub dword ptr number([edi]).frac+4 ,edx {frac[5]:=frac[5]-r;}
2352 cmp edx,1
2353 jb @exit0 {if r>= 5 then }
2354 add dword ptr number([edi]).frac+4 ,2 { frac[5]:=frac[5]+10; }
2355 jmp @L9
2356
2357 @L2:
2358 cmp dword ptr [edi],2 {if n.places<=2 then goto @exit0; }
2359 jbe @exit0
2360
2361
2362 cmp dword ptr number([edi]).frac , 1000000
2363 jb @L3 { if (frac[1]>=100) then }
2364 mov dword ptr [edi],3 { places:=5; }
2365 mov eax, dword ptr number([edi]).frac+8
2366 mov edx,0
2367 mov ecx,200000000
2368 div ecx { r:=frac[5] mod 10;}
2369 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
2370 cmp edx,100000000
2371 jb @exit0 {if r>= 5 then }
2372 add dword ptr number([edi]).frac + 8 ,200000000 { frac[5]:=frac[5]+10; }
2373 jmp @L9
2374
2375 @L3:
2376
2377 cmp dword ptr number([edi]).frac , 100000
2378 jb @L4 { if (frac[1]>=100) then }
2379 mov dword ptr [edi],3 { places:=5; }
2380 mov eax, dword ptr number([edi]).frac+8
2381 mov edx,0
2382 mov ecx,20000000
2383 div ecx { r:=frac[5] mod 10;}
2384 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
2385 cmp edx,10000000
2386 jb @exit0 {if r>= 5 then }
2387 add dword ptr number([edi]).frac+8 ,20000000 { frac[5]:=frac[5]+10; }
2388 jmp @L9
2389
2390 @L4:
2391
2392 cmp dword ptr number([edi]).frac , 10000
2393 jb @L5 { if (frac[1]>=100) then }
2394 mov dword ptr [edi],3 { places:=5; }
2395 mov eax, dword ptr number([edi]).frac+8
2396 mov edx,0
2397 mov ecx,2000000
2398 div ecx { r:=frac[5] mod 10;}
2399 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
2400 cmp edx,1000000
2401 jb @exit0 {if r>= 5 then }
2402 add dword ptr number([edi]).frac+8 ,2000000 { frac[5]:=frac[5]+10; }
2403 jmp @L9
2404
2405 @L5:
2406
2407 cmp dword ptr number([edi]).frac , 1000
2408 jb @L6 { if (frac[1]>=100) then }
2409 mov dword ptr [edi],3 { places:=5; }
2410 mov eax, dword ptr number([edi]).frac+8
2411 mov edx,0
2412 mov ecx,200000
2413 div ecx { r:=frac[5] mod 10;}
2414 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
2415 cmp edx,100000
2416 jb @exit0 {if r>= 5 then }
2417 add dword ptr number([edi]).frac+8 ,200000 { frac[5]:=frac[5]+10; }
2418 jmp @L9
2419
2420 @L6:
2421
2422 cmp dword ptr number([edi]).frac , 100
2423 jb @L7 { if (frac[1]>=100) then }
2424 mov dword ptr [edi],3 { places:=5; }
2425 mov eax, dword ptr number([edi]).frac+8
2426 mov edx,0
2427 mov ecx,20000
2428 div ecx { r:=frac[5] mod 10;}
2429 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
2430 cmp edx,10000
2431 jb @exit0 {if r>= 5 then }
2432 add dword ptr number([edi]).frac+8 ,20000 { frac[5]:=frac[5]+10; }
2433 jmp @L9
2434
2435 @L7:
2436 cmp dword ptr number([edi]).frac , 10
2437 jb @L8 { if (frac[1]>=100) then }
2438 mov dword ptr [edi],3 { places:=5; }
2439 mov eax, dword ptr number([edi]).frac+8
2440 mov edx,0
2441 mov ecx,2000
2442 div ecx { r:=frac[5] mod 10;}
2443 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
2444 cmp edx,1000
2445 jb @exit0 {if r>= 5 then }
2446 add dword ptr number([edi]).frac+8 ,2000 { frac[5]:=frac[5]+10; }
2447 jmp @L9
2448
2449 @L8:
2450 mov dword ptr [edi],3 { places:=5; }
2451 mov eax, dword ptr number([edi]).frac+8
2452 mov edx,0
2453 mov ecx,200
2454 div ecx { r:=frac[5] mod 10;}
2455 sub dword ptr number([edi]).frac+8 ,edx {frac[5]:=frac[5]-r;}
2456 cmp edx,100
2457 jb @exit0 {if r>= 5 then }
2458 add dword ptr number([edi]).frac+8 ,200 { frac[5]:=frac[5]+10; }
2459 {jmp @L9 } {else}
2460
2461 @L9:
2462 mov eax,1
2463 jmp @exit
2464 @exit0:
2465 xor eax,eax
2466 @exit:
2467 pop edi
2468
2469 end;
2470
2471 procedure round17m( var n:number);far;
2472 begin
2473 if round17msub(n) then
2474 carryuptail(n);
2475 shorten(n);
2476 end;
2477
2478
2479 procedure roundprecision(var n:number);
2480 begin
2481 with n do
2482 if places<=precision then
2483 exit
2484 else
2485 begin
2486 n.places:=precision;
2487 if frac[precision+1]>=500000000 then
2488 RoundUp(n);
2489 end;
2490 end;
2491
2492 procedure NoRound(var n:number);far;
2493 begin
2494 end;
2495
2496
2497 procedure checkRangeDecimal(var n:number; extyp:integer);
2498 var
2499 sign:shortint;
2500 begin
2501 sign:=n.sign;
2502 if sign=0 then exit;
2503 if (n.expn>=maxexpndecimal) and (compareabs(n,MAXNUM^)>0) then
2504 begin
2505 setexception(extyp);
2506 n.init(MAXNUM);
2507 n.sign:=sign;
2508 end
2509 else if (n.expn<minExpnDecimal) then
2510 n.initzero;
2511 end;
2512
2513 var
2514 RoundConv,RoundVari:roundprocedure;
2515
2516 procedure RoundVariable(var n:number);
2517 begin
2518 Roundvari(n);
2519 checkrangedecimal(n,1002);
2520 end;
2521
2522 procedure RoundConvert(var n:number; extyp:integer);
2523 begin
2524 Roundconv(n);
2525 checkrangedecimal(n,extyp);
2526 end;
2527
2528 {********}
2529 {Integers}
2530 {********}
2531
2532 procedure intround(var n:number); {round to integer}
2533 begin
2534 if n.sign=0 then exit;
2535 with n do
2536 begin
2537 if expn<0 then
2538 n.initzero
2539 else if expn=0 then
2540 if n.sign>0 then
2541 if frac[1]<500000000 then
2542 n.initzero
2543 else
2544 n.init(one)
2545 else
2546 if frac[1]<=500000000 then
2547 n.initzero
2548 else
2549 begin n.init(one);n.sign:=-1 end
2550 else if expn<places then
2551 begin
2552 places:=expn;
2553 if n.sign>0 then
2554 begin
2555 if frac[expn+1]>=500000000 then
2556 RoundUp(n);
2557 end
2558 else
2559 begin
2560 if frac[expn+1]>500000000 then
2561 RoundUp(n);
2562 end;
2563 shorten(n);
2564 end;
2565 end;
2566 end;
2567
2568
2569 function LongintVal(var a:number; var c:integer):longint; //c���������������������
2570 var
2571 a1 :number;
2572 e :smallint;
2573 x :longint;
2574
2575 begin
2576 a1.init(@a);
2577 intround(a1);
2578 with a1 do
2579 begin
2580 c:=0;
2581 x:=0;
2582 case sign of
2583 0: ;
2584 1: for e:=1 to expn do
2585 begin
2586 if (x>0) and (x<=2) then
2587 x:=x*1000000000
2588 else if x<>0 then
2589 c:=sign;
2590 if e<=places then
2591 x:=x+frac[e];
2592 if x<0 then
2593 c:=sign;
2594 end;
2595 -1: for e:=1 to expn do
2596 begin
2597 if (x<0) and (x>=-2) then
2598 x:=x*1000000000
2599 else if x<>0 then
2600 c:=sign;
2601 if e<=places then
2602 x:=x-frac[e];
2603 if x>=0 then
2604 c:=sign;
2605 end;
2606 end;
2607 longintval:=x;
2608 end;
2609 end;
2610
2611 function wordVal(var a:number; var c:integer):word;
2612 var
2613 x :longint;
2614 begin
2615 x:=LongintVal(a,c);
2616 if x<0 then
2617 c:=-1
2618 else if x>$FFFF then
2619 c:=1
2620 else
2621 wordval:=x;
2622 end;
2623
2624 {***********}
2625 {type Number}
2626 {***********}
2627
2628 function isZero(n:PNumber):boolean;
2629 begin
2630 iszero:=(n^.sign=0)
2631 end;
2632
2633 function sgn(n:Pnumber):shortint;
2634 begin
2635 sgn:=n^.sign
2636 end;
2637
2638 procedure opposite(var n:Number);
2639 begin
2640 with n do sign:=-sign;
2641 end;
2642
2643 procedure oppose(var n:Number);
2644 begin
2645 with n do sign:=-sign;
2646 end;
2647
2648 procedure absolute(var n:number);
2649 begin
2650 with n do if sign<>0 then sign:=1;
2651 end;
2652
2653
2654 procedure intpart(var n:number);
2655 begin
2656 with n do
2657 begin
2658 if sign<>0 then
2659 if expn<=0 then
2660 initzero
2661 else if expn<places then
2662 places:=expn;
2663 end;
2664 end;
2665 (*
2666 procedure fractpart(var n:number);
2667 var
2668 m:number;
2669 begin
2670 m:=n;
2671 intpart(m);
2672 sbt(n,m,n);
2673 end;
2674 *)
2675 procedure BasicInt(var n:number);
2676 var
2677 m:number;
2678 begin
2679 if n.sign>=0 then
2680 intpart(n)
2681 else
2682 begin
2683 m:=n;
2684 intpart(m);
2685 if compare(m,n)=0 then
2686 n:=m
2687 else
2688 sbt(m,one^,n)
2689 end;
2690 end;
2691 (*
2692 procedure ceil(var n:number);
2693 begin
2694 oppose(n);
2695 BasicInt(n);
2696 oppose(n);
2697 end;
2698
2699 procedure BasicMod(var a,b:Number; var x:Number);
2700 begin
2701 remainder(a,b,x);
2702 if (a.sign=b.sign) or (x.sign=0) then
2703 else
2704 add(x,b,x)
2705 end;
2706 *)
2707
2708 function isinteger(var n:number):boolean;
2709 begin
2710 with n do
2711 if (sign=0) or (places<=expn) then
2712 isinteger:=true
2713 else
2714 isinteger:=false
2715 end;
2716
2717 (*
2718 function nearly1(var n:number):boolean;
2719 begin
2720 nearly1:=
2721 ((n.expn=1) and (n.frac[1]=1) and ((n.places=1)or(n.frac[2]<100000000))
2722 or (n.expn=0) and (n.frac[1]>900000000))
2723 end;
2724 *)
2725 {
2726 function nearly1(var n:number):boolean;
2727 begin
2728 nearly1:=
2729 ((n.expn=1) and (n.frac[1]=1) and ((n.places=1)or(n.frac[2]<=100000000))
2730 or (n.expn=0) and (n.frac[1]>=900000000))
2731 end;
2732 }
2733 {
2734 function nearly1(var n:number):boolean;
2735 begin
2736 nearly1:=
2737 ((n.expn=1) and (n.frac[1]=1) and ((n.places=1)or(n.frac[2]<=292893218))
2738 or (n.expn=0) and (n.frac[1]>=707106782 ))
2739 end;
2740 }
2741
2742 {*****}
2743 {power}
2744 {*****}
2745 (*
2746 procedure IncremPowerLongint(var a:Number; b:longint; var x:Number); //2010.3.28
2747 var
2748 svlimit:LongInt;
2749 bb:longint;
2750 y,xx:number;
2751 label
2752 L1;
2753 begin
2754 svlimit:=limit;
2755 limit:=mini(limit + 2 ,maxplace-1);
2756 try
2757 xx.initone;
2758 if b=0 then goto L1;
2759 y.init(@a);
2760 if b>0 then
2761 begin
2762 while b<>0 do
2763 begin
2764 if b mod 2<>0 then mlt(xx,y,xx);
2765 b:=b div 2;
2766 if b<>0 then mlt(y,y,y);
2767 end;
2768 end
2769 else
2770 if iszero(@a) then
2771 setexception(3003)
2772 else
2773 try
2774 while b<>0 do
2775 begin
2776 if b mod 2<>0 then mlt(xx,y,xx);
2777 b:=b div 2;
2778 if b<>0 then mlt(y,y,y);
2779 end;
2780 qtt(one^,xx,xx); {y:=1/y}
2781 except
2782 on E:EExtype do
2783 if extype=1002 then
2784 begin
2785 extype:=0;
2786 xx.initzero;
2787 end
2788 else if extype=3001 then
2789 setexception(1002)
2790 else
2791 raise E;
2792 end;
2793 L1:
2794 x.init(@xx);
2795 finally
2796 limit:=svlimit;
2797 end;
2798 end;
2799
2800
2801
2802 procedure IncremPowerComp(var a:Number; b:comp; var x:Number); //2010.3.28
2803 var
2804 svlimit:LongInt;
2805 y,xx:number;
2806 c:comp;
2807 begin
2808 svlimit:=limit;
2809 limit:=mini(limit + 2 ,maxplace-1);
2810 try
2811 xx.initone;
2812 y.init(@a);
2813 if b>0 then
2814 begin
2815 while b<>0 do
2816 begin
2817 c:=system.int(b/2);
2818 if b-2*c<>0 then mlt(xx,y,xx);
2819 b:=c;
2820 if b<>0 then mlt(y,y,y);
2821 end;
2822 end
2823 else if b<0 then
2824 try
2825 while b<>0 do
2826 begin
2827 c:=system.int(b/2);
2828 if b-2*c<>0 then mlt(xx,y,xx);
2829 b:=c;
2830 if b<>0 then mlt(y,y,y);
2831 end;
2832 qtt(one^,xx,xx); {y:=1/y}
2833 except
2834 on E:EExtype do
2835 if extype=1002 then
2836 begin
2837 extype:=0;
2838 xx.initzero;
2839 end
2840 else if extype=3001 then
2841 setexception(1002)
2842 else
2843 raise E;
2844 end;
2845 x.init(@xx);
2846 finally
2847 limit:=svlimit;
2848 end;
2849 end;
2850
2851
2852
2853
2854 procedure intpower(var a,b:number; var n:number);
2855 var
2856 i:longint;
2857 c:integer;
2858 ii:comp;
2859 begin
2860
2861
2862 if isinteger(b) then
2863 begin
2864 i:=LongintVal(b,c);
2865 if c=0 then
2866 begin
2867 IncremPowerLongint(a,i,n);
2868 exit
2869 end
2870 else
2871 begin
2872 c:=0;
2873 try
2874 ii:=extendedVal(b);
2875 except
2876 c:=1
2877 end;
2878 if c=0 then
2879 begin
2880 IncremPowerComp(a,ii,n);
2881 exit
2882 end;
2883 end;
2884 end;
2885
2886 if UseTranscendentalFunction then
2887 power(a,b,n)
2888 else
2889 setexceptionwith(s_PowerIndex,1000); //2010.3.28
2890 end;
2891 *)
2892 procedure incrempower(var a:Number; b:LongInt; var x:Number);
2893 {assume b>=0}
2894 var
2895 n:number;
2896 z:number;
2897 begin
2898 z.initone;
2899 n.init(@a);
2900 while b<>0 do
2901 begin
2902 if b mod 2 <>0 then mlt(z,n,z);
2903 b:=b div 2;
2904 if b<>0 then mlt(n,n,n);
2905 end;
2906 x.init(@z);
2907 end;
2908
2909
2910 {***********}
2911 {type Number}
2912 {***********}
2913
2914
2915
2916
2917
2918 {**********}
2919 {arithmetic}
2920 {**********}
2921
2922 (*
2923 procedure initinteger(var n:number; i:smallint);
2924 begin
2925 n.initzero;
2926 if i=0 then exit;
2927 if i>0 then
2928 n.sign:=1
2929 else if i<0 then
2930 begin
2931 i:=-i;
2932 n.sign:=-1
2933 end;
2934 n.places:=1;
2935 n.expn:=1;
2936 n.frac[1]:=i;
2937 end;
2938 *)
2939
2940 procedure div1000000000(i:longint; var a,b:longint);assembler;
2941 // eax, edx,ecx
2942 asm
2943 push edx
2944 push ecx
2945 mov edx,0
2946 mov ecx,1000000000
2947 div ecx
2948 pop ecx
2949 mov [ecx], edx
2950 pop edx
2951 mov [edx] ,eax
2952 end;
2953
2954
2955 procedure initlongint(var n:number; i:longint);
2956 var
2957 a,b:longint;
2958 begin
2959 n.initzero;
2960 if i=0 then exit;
2961 if i>0 then
2962 n.sign:=1
2963 else if i<0 then
2964 begin
2965 i:=-i;
2966 n.sign:=-1
2967 end;
2968
2969 Div1000000000(i,a,b);
2970 // a:=i div 1000000000;
2971 // b:=i mod 1000000000;
2972
2973 if a>0 then
2974 begin
2975 n.places:=2;
2976 n.expn:=2;
2977 n.frac[1]:=a;
2978 n.frac[2]:=b;
2979 end
2980 else
2981 begin
2982 n.places:=1;
2983 n.expn:=1;
2984 n.frac[1]:=b;
2985 end
2986 end;
2987
2988 {*************}
2989 { EPS function}
2990 {*************}
2991 (*
2992 procedure EpsNative(var n:number);
2993 begin
2994 with n do
2995 begin
2996 if iszero(@n) then
2997 begin frac[1]:=1 ; expn:=minExpnDecimal end
2998 else
2999 begin
3000 frac[1]:=1;
3001 dec(expn,precision-1);
3002 end;
3003 places:=1;
3004 sign:=1;
3005 if expn<minexpnDecimal then
3006 begin
3007 n.initzero;
3008 EpsNative(n);
3009 end;
3010 end;
3011 end;
3012
3013 procedure EpsDecimal(var n:number); {15digits}
3014 begin
3015 with n do
3016 begin
3017 if iszero(@n) then
3018 begin frac[1]:=1 ; expn:=minExpnDecimal end
3019 else
3020 begin
3021 roundvariable(n);
3022 if frac[1]>=100000000 then
3023 begin
3024 frac[1]:=1000;
3025 dec(expn,1)
3026 end
3027 else if frac[1]>=10000000 then
3028 begin
3029 frac[1]:=100;
3030 dec(expn,1)
3031 end
3032 else if frac[1]>=1000000 then
3033 begin
3034 frac[1]:=10;
3035 dec(expn,1)
3036 end
3037 else if frac[1]>=100000 then
3038 begin
3039 frac[1]:=1;
3040 dec(expn,1)
3041 end
3042 else if frac[1]>=10000 then
3043 begin
3044 frac[1]:=100000000;
3045 dec(expn,2)
3046 end
3047 else if frac[1]>=1000 then
3048 begin
3049 frac[1]:=10000000;
3050 dec(expn,2)
3051 end
3052 else if frac[1]>=100 then
3053 begin
3054 frac[1]:=1000000;
3055 dec(expn,2)
3056 end
3057 else if frac[1]>=10 then
3058 begin
3059 frac[1]:=100000;
3060 dec(expn,2)
3061 end
3062 else
3063 begin
3064 frac[1]:=10000;
3065 dec(expn,2)
3066 end;
3067 end ;
3068 places:=1;
3069 sign:=1;
3070 if expn<minexpnDecimal then
3071 begin
3072 n.initzero;
3073 EpsDecimal(n);
3074 end;
3075 end;
3076 end;
3077
3078 procedure min(var a,b:number; var n:number);
3079 begin
3080 if compare(a,b)<=0 then n:=a else n:=b;
3081 end;
3082
3083 procedure max(var a,b:number; var n:number);
3084 begin
3085 if compare(a,b)>=0 then n:=a else n:=b ;
3086 end;
3087 *)
3088
3089 procedure tenfold(var x:number ; n:integer);
3090 var
3091 i:integer;
3092 begin
3093 if n>0 then
3094 for i:=1 to n do mlt(x,ten^,x)
3095 else if n<0 then
3096 for i:=-1 downto n do qtt(x,ten^,x)
3097 end;
3098
3099
3100
3101 procedure round(var x,n:number; var y:number);
3102 var
3103 i:integer;
3104 c:integer;
3105 t:number;
3106 begin
3107 i:=longintval(n,c);
3108 t.init(@x);
3109 tenfold(t,i);
3110 add(t,half^,y);
3111 BasicInt(y);
3112 tenfold(y,-i);
3113 end;
3114
3115 (*
3116 procedure truncate(var x,n:number; var y:number);
3117 var
3118 i:integer;
3119 c:integer;
3120 t:number;
3121 begin
3122 i:=longintval(n,c);
3123 t.init(@x);
3124 tenfold(t,i);
3125 y:=t;
3126 IntPart(y);
3127 tenfold(y,-i);
3128 end;
3129 *)
3130
3131 {***********}
3132 {square root}
3133 {***********}
3134 (*
3135 procedure sqrsub(var a:number);
3136 var
3137 x,y,z:number;
3138 e:integer;
3139 limitsave:LongInt;
3140 begin
3141 limitsave:=limit;
3142 convert(sqrt(extendedval(a)),y);
3143 limit:=4;
3144 repeat
3145 x.init(@y);
3146 qtt(a,x,y);
3147 add(y,x,y);
3148 qtt2(y);
3149 sbt(x,y,z);
3150 e:=y.expn-z.expn;
3151 limit:=mini(2*e+3,maxplace-1);
3152 until (z.sign=0) or (e>precision) ;
3153 limit:=maxplace-1;
3154 repeat
3155 x.init(@y);
3156 qtt(a,x,y);
3157 add(y,x,y);
3158 qtt2(y);
3159 sbt(x,y,z);
3160 e:=y.expn-z.expn;
3161 until (z.sign=0) or (e>precision) ;
3162 a.init(@y);
3163 limit:=limitsave;
3164 end;
3165
3166 procedure sqrlong(var a:number);
3167 var
3168 e:smallint;
3169 begin
3170 if a.sign<0 then
3171 setexceptionwith(s_InvalidArgInSQR,3005)
3172 else if a.sign=0 then
3173 else
3174 begin
3175 e:=a.expn;
3176 a.expn:=e and 1;
3177 asm
3178 sar e,1
3179 end;
3180 sqrsub(a);
3181 a.expn:=a.expn+e;
3182 end;
3183 end;
3184
3185 procedure square(var n:number);
3186 begin
3187 mlt(n,n,n)
3188 end;
3189 *)
3190
3191 {**********************}
3192 {numeric representation}
3193 {**********************}
3194
3195 {**********************}
3196 {numeric representation}
3197 {**********************}
3198
3199 procedure NumericRep(var n:number;var code:integer;var line:ansistring;
3200 var cp:integer);
3201
3202 var
3203 cpintpart,cpfractpart,cpexrad:integer;
3204 intpartlen,fractpartlen,exradlen:integer;
3205 scaledrep:boolean;
3206
3207 procedure giveValue(var n:number; var code:integer);
3208 var
3209 intpart :ansistring;
3210 fractpart :ansistring;
3211 exrad :ansistring;
3212 {i:smallint; }
3213 x:LongInt;
3214 m:number;
3215 c:integer;
3216 begin
3217 extype:=0; {this routine is used on phase 0, so extype may <>0}
3218
3219 intpart :=copy(line,cpintpart, intpartlen);
3220 fractpart:=copy(line,cpfractpart,fractpartlen);
3221 exrad :=copy(line,cpexrad, exradlen);
3222
3223 if (intpartlen=0) and (fractpartlen=0) then code:=8101;
3224
3225 {give a value}
3226
3227 {eliminate and append leading zeros}
3228
3229 while (length(intpart)>0)and (intpart[1]='0') do
3230 delete(intpart,1,1){intpart:=copy(intpart,2,255)};
3231 if length(intpart) mod 9 <>0 then
3232 intpart:=copy('00000000',1,(9 - length(intpart) mod 9)) + intpart;
3233 if length(fractpart) mod 9 <>0 then
3234 fractpart:=fractpart + copy('00000000',1,(9-length(fractpart) mod 9));
3235 if length(intpart)>0 then
3236 n.expn:=length(intpart) div 9
3237 else
3238 begin
3239 n.expn:=0;
3240 while copy(fractpart,1,9)='000000000' do
3241 begin
3242 delete(fractpart,1,9){fractpart:=copy(fractpart,10,255)};
3243 dec(n.expn);
3244 end;
3245 end;
3246
3247 fractpart:=intpart + fractpart; {fractpart means efficient digits.}
3248
3249 if fractpart='' then
3250 n.sign:=0
3251 else
3252 n.sign:=1;
3253
3254 n.places:=0;
3255 while (fractpart<>'') and (n.places<limit)do
3256 begin
3257 inc(n.places);
3258 intpart:=copy(fractpart,1,9); {intpart is used as temporary string.}
3259 delete(fractpart,1,9){fractpart:=copy(fractpart,10,255)};
3260 val(intpart,x,c);
3261 if c<>0 then code:=1001;
3262 n.frac[n.places]:=x
3263 end;
3264
3265 if length(exrad)>0 then
3266 begin
3267 val(exrad,x,c);
3268 if (c<>0) or (x>maxExpn*9+1) then
3269 code:=1001
3270 else if (x<minExpn*9) then
3271 begin
3272 //code:=1501; {������������������}
3273 n.initzero
3274 end
3275 else
3276 if x>0 then
3277 begin
3278 incrempower(ten^,x,m);
3279 mlt(n,m,n)
3280 end
3281 else
3282 begin
3283 incrempower(ten^,-x,m) ;
3284 qtt(n,m,n)
3285 end;
3286 end;
3287
3288 end;
3289
3290
3291 function isDigit:boolean;
3292 begin
3293 case line[cp] of
3294 '0'..'9':
3295 isDigit:=true
3296 else
3297 isDigit:=false
3298 end
3299 end;
3300
3301 var
3302 numrep:ansistring{string[31]};
3303
3304 begin
3305 code:=0;
3306
3307 while (cp<=length(line)) and (line[cp]=' ') do inc(cp); {spacecut}
3308
3309 {intPart}
3310 cpintpart:=cp;
3311 while (cp<=length(line)) and isDigit do inc(cp);
3312 intpartlen:=cp-cpintpart;
3313
3314 {fractpart}
3315 if (cp<=length(line)) and (line[cp]='.') then inc(cp);
3316 cpfractpart:=cp;
3317 while (cp<=length(line)) and isDigit do inc(cp);
3318 fractpartlen:=cp-cpfractpart;
3319
3320 {exrad}
3321 if (cp+1<=length(line)) and (line[cp] in ['E','e'])
3322 and (line[cp+1] in ['+','-','0'..'9']) then
3323 begin
3324 inc(cp);
3325 cpExrad:=cp;
3326 if (cp<=length(line)) and((line[cp]='+') or (line[cp]='-')) then
3327 inc(cp);
3328 while (cp<=length(line)) and isDigit do inc(cp);
3329 exradlen:=cp-cpexrad;
3330 scaledrep:=true;
3331 end
3332 else
3333 begin
3334 cpExrad:=cp;
3335 exradlen:=0;
3336 scaledrep:=false;
3337 end;
3338
3339
3340 numrep:=copy(line,cpintpart,cp-cpintpart);
3341
3342 givevalue(n,code);
3343 shorten(n);
3344 end;
3345
3346
3347 procedure NVal(s:ansistring; var n:number);
3348 var
3349 c,cp:integer;
3350 m:boolean;
3351 begin
3352 cp:=1;
3353 while (cp<=length(s)) and (s[cp]=' ') do inc(cp);
3354 m:=false;
3355 if (cp<=length(s)) then
3356 begin
3357 if s[cp]='+' then
3358 inc(cp)
3359 else if (s[cp]='-') then
3360 begin
3361 m:=true;
3362 inc(cp)
3363 end;
3364 end;
3365 NumericRep(n,c,s,cp) ;
3366 if c<>0 then setexception(c);
3367 if m then oppose(n);
3368 while (cp<=length(s)) and (s[cp]=' ') do inc(cp);
3369 if cp<=length(s) then setexception(4001);
3370 end;
3371
3372 (*
3373 procedure disposenumber(var p:PNumber);
3374 begin
3375 if p<>nil then MemoryFree(pointer(p),(p^.places)*4+8);
3376 p:=nil
3377 end;
3378
3379 procedure subst(var p:PNumber; var n:number);
3380 begin
3381 if p=nil then
3382 MemoryGet(pointer(p), (n.places)*4+8)
3383 else if (p^.places<>n.places) then
3384 begin
3385 disposeNumber(p);
3386 MemoryGet(pointer(p), (n.places)*4+8);
3387 end;
3388 p^.init(@n)
3389
3390 end;
3391 *)
3392
3393
3394
3395 procedure ConvertToString(const n:number;var digits:ansistring;var exp:integer);
3396 var
3397 s:string[9];
3398 i:integer;
3399 begin
3400 digits:='';
3401 i:=1;
3402 while i<=n.places do
3403 begin
3404 str(n.frac[i],s);
3405 while length(s)<9 do s:='0' + s;
3406 digits:=digits + s;
3407 inc(i);
3408 end;
3409
3410 if n.sign=0 then
3411 exp:=0
3412 else
3413 exp:=9*n.expn;
3414 i:=1;
3415 while (i<=length(digits)) and (digits[i]='0') do
3416 begin inc(i); dec(exp) end;
3417 delete(digits,1,i-1) {digits:=copy(digits,i,255)} ;
3418 while (length(digits)>0) and (digits[length(digits)]='0') do
3419 setlength(digits,length(digits)-1);
3420 end;
3421
3422 procedure roundstring(var s:ansistring; n:integer; var exp:integer);
3423 var
3424 carry:boolean;
3425 t:char;
3426 begin
3427 if n<0 then begin s:=''; exit end;
3428
3429 if length(s)>n then
3430 begin
3431 t:=s[n+1];
3432 setlength(s,n);
3433 if t>='5' then
3434 begin
3435 carry:=true;
3436 while carry and (length(s)>0) do
3437 begin
3438 s[length(s)]:=succ(s[length(s)]);
3439 if s[length(s)]<='9' then
3440 carry:=false
3441 else
3442 setlength(s,length(s)-1);
3443 end;
3444 if length(s)=0 then
3445 begin
3446 s:='1';
3447 inc(exp)
3448 end;
3449 end;
3450 end;
3451
3452 while (length(s)>0) and (s[length(s)]='0') do
3453 setlength(s,length(s)-1);
3454 end;
3455
3456
3457 function DStr(var n:Number):ansistring;
3458 var
3459 sign :string[1];
3460 digits :ansistring;
3461 exp :integer;
3462 exrad :ansistring;
3463 e :integer;
3464 begin
3465 {roundvariable(n);}
3466 if n.sign=0 then begin Dstr:=' 0' ; exit end;
3467 if n.sign>=0 then sign:=' ' else sign:='-';
3468 ConvertToString(n,digits,exp);
3469 roundstring(digits,signiwidth,exp);
3470
3471 if (exp>0) and (exp<=signiwidth) then
3472 begin
3473 if exp>=length(digits) then {wothout fraction part}
3474 begin