-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRATFUNC.ASM
965 lines (799 loc) · 11.9 KB
/
RATFUNC.ASM
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
;ratfunc.asm
;
; rational functions
code segment public
assume cs:code,ds:data
extrn print_calcsp_out:near
extrn fargcd_calcsp:far
;
; * memory allocation
;
; inp ax : number of variables
; out bx : base segment
memoryalloc1:
mov bx,unitseg
mul bx
mov bx,[arrayseg]
add ax,bx
cmp ax,[limitseg]
jae malloc1over
mov [arrayseg],ax
ret
malloc1over:
jmp calcsperr
;
; * memory free
;
; inp ax : number of variables
memoryfree1:
mov bx,unitseg
mul bx
sub [arrayseg],ax
ret
xputsub1:
push es
add ax,bx
xor di,di
mov es,ax
mov cx,[si]
add si,2
mov es:[di],cx
add di,2
and cx,lenmask
rep movsw
pop es
ret
xgetsub1:
push ds
add ax,bx
xor si,si
mov ds,ax
mov cx,[si]
add si,2
mov es:[di],cx
add di,2
and cx,lenmask
rep movsw
pop ds
ret
code ends
code2 segment public
assume cs:code2,ds:data
public printratpoly
public add_rf,sub_rf
public mul_rf,div_rf,ratdiv_rf
public add_numrf,sub_numrf,mul_numrf,div_numrf
public farcompare_any
public memoryalloc,memoryfree,xputsub
;
;* compare any data
; non destructive
; si ,di : addresses
farcompareilg:
jmp far ptr systemerr
farcompare_any:
add [calcsp],unitbyte
cmp di,[calcsp]
jne farcompareilg
lea bx,[di-unitbyte]
cmp bx,si
jne farcompareilg
mov ax,2
call memoryalloc
xput xa,0 ;reserve
xput xb,1 ;
xsub
mov si,[calcsp]
cmp word ptr [si],0
pushf
xget 0,xa
xget 1,xb
mov ax,2
call memoryfree
sub [calcsp],unitbyte
popf
retf
;
; * check calcsp = const
;
isconst_calcsp:
mov si,[calcsp]
mov ax,[si]
and ah,attribmaskhigh
jz yesconst
cmp ah,polymaskhigh
je checkdegreepoly
cmp ah,modpolymaskhigh
je checkdegreemodpoly
test ah,nonnumericmaskhigh
jnz notconst
yesconst:
xor ax,ax ;set ZF
ret
notconst:
xor ax,ax
dec ax ;reset ZF
ret
checkdegreepoly:
cmp word ptr [si+2],1 ;check degree = 0?
ret
checkdegreemodpoly:
cmp word ptr [si],modpolymask+2 ;check degree = 0?
ret
;
; * memory allocation
;
; inp ax : number of variables
; out bx : base segment
memoryalloc:
mov bx,unitseg
mul bx
mov bx,[arrayseg]
add ax,bx
cmp ax,[limitseg]
jae mallocover
mov [arrayseg],ax
ret
mallocover:
jmp far ptr calcsperr
;
; * memory free
;
; inp ax : number of variables
memoryfree:
mov bx,unitseg
mul bx
sub [arrayseg],ax
ret
xreducesub:
push bp
mov bp,sp
push dx
push cx
push ax
mov di,[calcsp]
call xgetsub ;xget 0,xa
mov di,[calcsp]
mov ax,[bp-4]
sub di,unitbyte
call xgetsub ;xget 1,xb
push bx
call far ptr fargcd_calcsp
pop bx
call isconst_calcsp
je xreducegcd1 ;if gcd is constant
; call integerpoly_calcsp
; call normalizepoly_calcsp
mov si,[calcsp]
mov ax,[bp-2]
call xputsub ;xput xg,0
mov di,[calcsp]
mov ax,[bp-6]
call xgetsub ;xget 0,xa
mov di,[calcsp]
mov ax,[bp-2]
sub di,unitbyte
call xgetsub ;xget 1,xg
xidiv
mov si,[calcsp]
mov ax,[bp-6]
call xputsub ;xput xa,0
mov di,[calcsp]
mov ax,[bp-4]
call xgetsub ;xget 0,xb
mov di,[calcsp]
mov ax,[bp-2]
sub di,unitbyte
call xgetsub ;xget 1,xg
xidiv
mov si,[calcsp]
mov ax,[bp-4]
call xputsub ;xput xb,0
xreduce100:
mov sp,bp
pop bp
ret
xreducegcd1: ;set gcd = 1
push ds
mov ax,[bp-2]
add ax,bx
mov ds,ax
xor si,si
mov ax,1
mov [si],ax
mov [si+2],ax
pop ds
jmp xreduce100
xputbothsub:
push es
add ax,bx
xor di,di
mov es,ax
add si,2
mov cx,[si]
add si,2
mov es:[di],cx
add di,2
and cx,lenmask
rep movsw
add dx,bx
xor di,di
mov es,dx
mov cx,[si]
add si,2
mov es:[di],cx
add di,2
and cx,lenmask
rep movsw
pop es
ret
xputsub:
push es
add ax,bx
xor di,di
mov es,ax
mov cx,[si]
add si,2
mov es:[di],cx
add di,2
and cx,lenmask
rep movsw
pop es
ret
xgetsub:
push ds
add ax,bx
xor si,si
mov ds,ax
mov cx,[si]
add si,2
mov es:[di],cx
add di,2
and cx,lenmask
rep movsw
pop ds
ret
neg_rfsi:
add si,2
mov ax,[si]
and ax,attribmask
cmp ax,polymask
jne neg_rf_mpl
neg_rf_pl:
jmp neg_polysi ;call & ret
neg_rf_mpl:
jmp neg_modpolysi ;call & ret
sub_rfrf:
mov si,[calcsp]
sub si,unitbyte
mov [calcsp],si
call neg_rfsi
add [calcsp],unitbyte
add_rfrf:
; a//b + c//d = (ad+bc)//bd
mov ax,5
call memoryalloc
xputboth xa,xb,0
xputboth xc,xd,1
xreduce xb,xd,xg
xget 0,xa
xget 1,xd
xmul
xput xa,0 ;xa = ad'
xget 0,xb
xget 1,xc
xmul
xget 1,xa
xadd
xput xa,0 ;xa = ad'+b'c
xget 0,xb
xget 1,xd
xmul
xget 1,xg
xmul
cmove 1,0 ;sp1 = b'd'g
xget 0,xa ;sp0 = ad'+bc'
mov ax,5
call memoryfree
jmp setratfunc
; add rational functions entry
sub_rf:
cmp ah,ratpolymaskhigh
jne sub_rfnum
jmp sub_rfrf
sub_rfnum:
mov si,[calcsp]
sub si,unitbyte
mov [calcsp],si
call neg_numpl2
add [calcsp],unitbyte
jmps add_rfpl
add_rf:
cmp ah,ratpolymaskhigh
je add_rfrf
add_rfpl:
; a//b + c = (a+bc)//b
mov ax,2
call memoryalloc
xputboth xa,xb,0
xget 0,xb
add_rfplin:
xmul ;bc
xget 1,xa
xadd ;a+bc
xget 1,xb
mov ax,2
call memoryfree
jmp setratf_nogetgcd
;*
sub_numrf:
mov si,[calcsp]
sub si,unitbyte
mov [calcsp],si
call neg_rfsi
add [calcsp],unitbyte
add_numrf:
; c + a//b = (a+bc)//b
mov ax,2
call memoryalloc
xputboth xa,xb,1
xget 1,xb
jmp add_rfplin
div_numrf:
; c / a//b = c * b//a = bc//a
mov ax,4
call memoryalloc
xputboth xb,xa,1
xput xc,0
jmp mul_rfplin
;*
div_rfpl:
; a//b / c = a//bc
mov ax,4
call memoryalloc
xputboth xa,xb,0
xput xc,1
xreduce xa,xc,xd
xget 0,xb
xget 1,xc
xmul ;bc
cmove 1,0
xget 0,xa
mov ax,4
call memoryfree
jmp setratf_nogetgcd
ratdiv_rf:
div_rf:
cmp ah,ratpolymaskhigh
je div_rfrf
jmp div_rfpl
;*
div_rfrf:
; a//b / c//d = a//b * d//c = ad//bc
mov ax,5
call memoryalloc
xputboth xa,xb,0
xputboth xd,xc,1
jmp mul_rfrfin
;*
mul_rfpl:
; a//b * c = ac//b
mov ax,4
call memoryalloc
xputboth xa,xb,0
xput xc,1
mul_rfplin:
xreduce xb,xc,xd
xget 0,xa
xget 1,xc
xmul ;ac
xget 1,xb
mov ax,4
call memoryfree
jmp setratf_nogetgcd
mul_numrf:
; c * a//b = ac//b
mov ax,4
call memoryalloc
xputboth xa,xb,1
xput xc,0
jmp mul_rfplin
;*
mul_rf:
cmp ah,ratpolymaskhigh
jne mul_rfpl
; je mul_rfrf
mul_rfrf:
; a//b * c//d = ac//bd
mov ax,5
call memoryalloc
xputboth xa,xb,0
xputboth xc,xd,1
mul_rfrfin:
xreduce xa,xd,xg
xreduce xb,xc,xg
xget 0,xb
xget 1,xd
xmul ;bd
xput xg,0
xget 0,xa
xget 1,xc
xmul ;ac
xget 1,xg
mov ax,5
call memoryfree
jmp setratf_nogetgcd
ratdiv_intmpl:
div_intmpl:
mov bx,di
call int2modpoly2
jmps div_mplmpl
ratdiv_numpl:
div_numpl:
mov bx,di
call numer2poly2
div_mplmpl:
div_plpl:
; call reducedisi
jmps setratfunc
setratfunc2:
add [calcsp],2*unitbyte
setratfunc:
mov ax,3
call memoryalloc
xput xa,0
xput xb,1
push bx
call far ptr fargcd_calcsp
pop bx
call isconst_calcsp
je setratf20 ;if gcd = const
; call integerpoly_calcsp
; call normalizepoly_calcsp
xput xc,0 ;xc = g
xget 0,xb
xget 1,xc
push bx
call far ptr faridiv_calcsp
pop bx
xput xb,0
xget 0,xa
xget 1,xc
push bx
call far ptr faridiv_calcsp
pop bx
jmps setratf30
setratf20:
xget 0,xa
setratf30:
xget 1,xb
mov ax,3
call memoryfree
setratf_nogetgcd:
mov bx,[calcsp]
mov ax,[bx]
or ax,ax
jz gosetratfret ;if 0
and ah,attribmaskhigh
cmp ah,polymaskhigh
je setratf_poly
jmp setratf_modpoly
setratf_poly:
cmp word ptr [bx+2],1
jne setratf40 ;not const
cmp word ptr [bx-unitbyte+2],1
jne setratf40 ;not const
;if both const then divide rationally
mov di,bx
lea si,[bx+4]
mov cx,[si]
and cx,lenmask
inc cx
rep movsw
sub bx,unitbyte
mov di,bx
lea si,[bx+4]
mov cx,[si]
and cx,lenmask
inc cx
rep movsw
call far ptr farratdiv_calcsp
gosetratfret:
jmp setratfret
setratf40:
;let the leadcoef of den be positive
mov bx,[calcsp]
sub bx,unitbyte
call getleadcoeffadr
mov ax,[bx]
test ah,signmaskhigh
jz setratf48 ;if highest > 0
mov si,[calcsp]
call neg_polysi ;neg num
mov si,[calcsp]
sub si,unitbyte
call neg_polysi ;neg den
setratf48:
;check GCD of coeffs
mov bx,[calcsp]
lea di,[bx-2*unitbyte]
mov [calcsp],di
lea si,[bx+4]
copy_si2di
mov cx,[bx+2] ;number of terms
dec cx
jz setratf52
setratf50:
mov di,[calcsp]
mov ax,1
cmp [di],ax
jne setratf51
cmp [di+2],ax
je setratf60 ;if GCD=1 then end
setratf51:
push cx
push si
mov di,[calcsp]
call far ptr farGETGCD
mov si,WORK3 ;GCDADR
mov di,[calcsp]
copy_si2di
pop si
mov ax,[si]
and ax,lenmask
inc ax
add ax,ax
add si,ax
pop cx
loop setratf50
setratf52:
mov bx,[calcsp]
add bx,unitbyte
lea si,[bx+4]
mov cx,[bx+2] ;number of terms
setratf55:
mov di,[calcsp]
mov ax,1
cmp [di],ax
jne setratf56
cmp [di+2],ax
je setratf60 ;if GCD=1 then end
setratf56:
push cx
push si
mov di,[calcsp]
call far ptr farGETGCD
mov si,WORK3 ;GCDADR
mov di,[calcsp]
copy_si2di
pop si
mov ax,[si]
and ax,lenmask
inc ax
add ax,ax
add si,ax
pop cx
loop setratf55
;connect them
setratf60:
mov si,[calcsp]
mov ax,1
cmp [si],ax
jne setratf62
cmp [si+2],ax
jne setratf62
add si,2*unitbyte
mov [calcsp],si
jmps setratf65
setratf62:
;divide by GCD of coefs
mov ax,2
call memoryalloc
xput xa,0 ;reserve GCD of coefs
add [calcsp],unitbyte
push bx
call far ptr faridiv_calcsp
pop bx
xput xb,0 ;reserve result
xget 0,xa
add [calcsp],unitbyte
push bx
call far ptr faridiv_calcsp
pop bx
xget 1,xb
mov ax,2
call memoryfree
setratf65:
mov di,[calcsp]
lea si,[di-unitbyte]
mov cx,[si]
and cx,lenmask
cmp cx,1
jne setratf68
cmp word ptr [si+2],1
je setratfret ;if den=1
setratf68:
inc cx
mov bx,[di]
and bx,lenmask
jz setratfret ;if num=0
inc bx
mov ax,bx
add ax,cx
cmp ax,limitword
ja setratfovr
add di,ax
add si,cx
add di,ax ;highest word adr
add si,cx
sub si,2
std
rep movsw
lea si,[di-2]
mov cx,bx
rep movsw
or ah,ratpolymaskhigh
stosw
cld
setratfret:
jmp far ptr returnadr
setratfovr:
jmp far ptr ovrerr
getleadcoeffadr:
mov cx,[bx+2] ;number of terms
add bx,4
getleadca10:
dec cx
jz getleadcaret
mov ax,[bx]
and ax,lenmask
inc ax
add ax,ax
add bx,ax
jmp getleadca10
getleadcaret:
ret
setratf_modpoly:
mov ax,modpolymask+4
cmp [bx],ax
jne setratf_mp40 ;not const
cmp word ptr [bx-unitbyte],ax
jne setratf_mp40 ;not const
;if both const then divide them
set32
mov ax,[bx-unitbyte+6] ;den
call modinvdword
set32
mov dx,[bx+6]
set32
mul dx
set32
mov di,word ptr [polymodulus]
set32
div di
set32
mov [bx+6],dx
gosetratf_mpret:
jmp setratfret
setratf_mp40:
;let the leadcoef of den be 1
mov bx,[calcsp]
lea si,[bx-unitbyte]
mov cx,[si]
and cx,lenmask
add cx,cx
add si,cx
set32
mov ax,[si-2] ;lead coeff
set32
dec ax
jz setratf_mp50
set32
inc ax
set32
mov di,[bx+2] ;=[polymodulus]
call modinvdword
set32
mov si,ax
mov bx,[calcsp]
mov cx,[bx]
and cx,lenmask
shr cx,1
dec cx
add bx,6
setratf_mplp1:
set32
mov ax,[bx]
set32
mul si
set32
div di
set32
mov [bx],dx
add bx,4
loop setratf_mplp1
mov bx,[calcsp]
sub bx,unitbyte
mov cx,[bx]
and cx,lenmask
shr cx,1
dec cx
add bx,6
setratf_mplp2:
set32
mov ax,[bx]
set32
mul si
set32
div di
set32
mov [bx],dx
add bx,4
loop setratf_mplp2
setratf_mp50: ;connect them
mov di,[calcsp]
lea si,[di-unitbyte]
mov cx,[si]
and cx,lenmask
cmp cx,4
je setratf_mpret ;if den=1
setratf_mp60:
inc cx
mov bx,[di]
and bx,lenmask
jz setratf_mpret ;if num=0
inc bx
mov ax,bx
add ax,cx
cmp ax,limitword
ja setratf_mpovr
add di,ax
add si,cx
add di,ax ;highest word adr
add si,cx
sub si,2
std
rep movsw
lea si,[di-2]
mov cx,bx
rep movsw
or ah,ratpolymaskhigh
stosw
cld
setratf_mpret:
jmp far ptr returnadr
setratf_mpovr:
jmp far ptr ovrerr
printratpoly:
call ahedsp2
cmovereal 0,-1
mov al,'('
call prchr2
call printpolyboth
mov al,')'
call prchr2
mov al,'/'
call prchr2
cmoveimag 0,-1
mov al,'('
call prchr2
call printpolyboth
mov al,')'
call prchr2
add [calcsp],unitbyte
jmp far ptr print_calcsp_out
printpolyboth:
mov si,[calcsp]
mov ax,[si]
and ax,attribmask
cmp ax,polymask
je go_printpoly
cmp ax,modpolymask
je go_printmodpoly
jmp polyilgerr
go_printpoly:
jmp printpolysub
go_printmodpoly:
jmp printmodpolysub
code2 ends