7 #include "cln/integer.h"
17 const cl_I operator- (const cl_I& x, const cl_I& y)
21 // y Fixnum -> beide direkt subtrahieren, mit L_to_I beenden
22 // y Bignum -> falls x=0, (- y); sonst beide zu DS machen, subtrahieren.
24 // y Fixnum -> falls y=0, x; sonst beide zu DS machen, subtrahieren.
25 // y Bignum -> beide zu DS machen, subtrahieren.
29 // MSDptr/len/LSDptr bilden die DS des Ergebnisses.
34 #if (cl_value_len < intVsize)
35 return V_to_I( FN_to_V(x) - FN_to_V(y) ); // als intVsize-Bit-Zahlen subtrahieren
36 #elif (cl_word_size==64)
37 return Q_to_I( FN_to_Q(x) - FN_to_Q(y) ); // als 64-Bit-Zahlen subtrahieren
38 #elif (intVsize==32) // && (cl_value_len == intVsize)
39 var sint32 xhi = sign_of(FN_to_V(x));
40 var uint32 xlo = FN_to_V(x);
41 var sint32 yhi = sign_of(FN_to_V(y));
42 var uint32 ylo = FN_to_V(y);
44 if (xlo < ylo) { xhi -= 1; }
46 return L2_to_I(xhi,xlo);
50 { // x ist Fixnum, y ist Bignum, also y länger
52 var sint64 x_ = FN_to_V(x); // Wert von x
54 var sintV x_ = FN_to_V(x); // Wert von x
56 if (FN_V_zerop(x,x_)) { return -y; } // bei x=0 Ergebnis (- y)
58 BN_to_NDS_1(y, MSDptr=,len=,LSDptr=); // NDS zu y bilden.
59 // vorsorglich 1 Digit mehr belegen:
60 { var sintD sign = sign_of_sintD(mspref(MSDptr,0));
61 lsprefnext(MSDptr) = sign; len++;
64 neg_loop_lsp(LSDptr,len);
65 // MSDigit ist nun = 0x0000 oder = 0xFFFF
66 // x_ zu den oberen pFN_maxlength Digits von -y addieren:
69 var uint64 y_ = lspref(LSDptr,0);
70 var uint64 y_new = y_+(uint64)x_;
71 lspref(LSDptr,0) = y_new;
73 var uintV y_ = pFN_maxlength_digits_at(LSDptr);
74 var uintV y_new = y_+(uintV)x_;
75 set_pFN_maxlength_digits_at(LSDptr,y_new);
77 var uintD* midptr = LSDptr lspop pFN_maxlength;
80 if (!FN_V_minusp(x,x_)) // kürzerer Summand war positiv
81 // Dann ist ein positiver Übertrag weiterzutragen
82 // (Beispiel: 0002FFFC + 0007 = 00030003)
83 { DS_1_plus(midptr,len-pFN_maxlength); }
87 if (FN_V_minusp(x,x_)) // kürzerer Summand war negativ
88 // Dann ist ein negativer Übertrag weiterzutragen
89 // (Beispiel: 00020003 + FFF5 = 0001FFF8)
90 { DS_minus1_plus(midptr,len-pFN_maxlength); }
92 return DS_to_I(MSDptr,len); // DS wieder zum Integer machen
98 { // x ist Bignum, y ist Fixnum, also x länger
100 var sint64 y_ = FN_to_V(y); // Wert von y
102 var sintV y_ = FN_to_V(y); // Wert von y
104 if (FN_V_zerop(y,y_)) { return x; } // bei y=0 Ergebnis x
106 BN_to_NDS_1(x, MSDptr=,len=,LSDptr=); // NDS zu x bilden.
107 // len>=bn_minlength. len>pFN_maxlength erzwingen:
108 if ((bn_minlength==pFN_maxlength) && (len==pFN_maxlength))
109 { var sintD sign = sign_of_sintD(mspref(MSDptr,0));
110 lsprefnext(MSDptr) = sign; len++;
112 // y_ von den oberen pFN_maxlength Digits von x subtrahieren:
115 var uint64 x_ = lspref(LSDptr,0);
116 var uint64 x_new = x_-(uint64)y_;
117 lspref(LSDptr,0) = x_new;
119 var uintV x_ = pFN_maxlength_digits_at(LSDptr);
120 var uintV x_new = x_-(uintV)y_;
121 set_pFN_maxlength_digits_at(LSDptr,x_new);
123 var uintD* midptr = LSDptr lspop pFN_maxlength;
126 if (!FN_V_minusp(y,y_)) // kürzerer Summand war positiv
127 // Dann ist ein negativer Übertrag weiterzutragen
128 // (Beispiel: 00030003 - 0007 = 0002FFFC)
129 { DS_minus1_plus(midptr,len-pFN_maxlength); }
133 if (FN_V_minusp(y,y_)) // kürzerer Summand war negativ
134 // Dann ist ein positiver Übertrag weiterzutragen
135 // (Beispiel: 0002FFF8 - FFF5 = 00030003)
136 { DS_1_plus(midptr,len-pFN_maxlength); }
138 return DS_to_I(MSDptr,len); // DS wieder zum Integer machen
141 { // x und y sind Bignums
142 if (TheBignum(x)->length > TheBignum(y)->length)
143 { // x das längere von beiden.
145 BN_to_NDS_1(x, MSDptr=,len=,LSDptr=); // NDS zu x bilden.
146 var const uintD* yMSDptr;
148 var const uintD* yLSDptr;
149 BN_to_NDS_nocopy(y, yMSDptr=,ylen=,yLSDptr=); // NDS zu y bilden.
150 // yMSDptr/ylen/yLSDptr bilden die DS des kürzeren Arguments y.
153 { var uintD* midptr = LSDptr lspop ylen;
154 var uintD carry = subfrom_loop_lsp(yLSDptr,LSDptr,ylen);
157 if ((sintD)mspref(yMSDptr,0) >=0) // kürzerer Summand war positiv
158 // Dann ist ein negativer Übertrag weiterzutragen
159 // (Beispiel: 00030003 - 0007 = 0002FFFC)
160 { DS_minus1_plus(midptr,len-ylen); }
164 if ((sintD)mspref(yMSDptr,0) <0) // kürzerer Summand war negativ
165 // Dann ist ein positiver Übertrag weiterzutragen
166 // (Beispiel: 0002FFF8 - FFF5 = 00030003)
167 { DS_1_plus(midptr,len-ylen); }
169 return DS_to_I(MSDptr,len); // DS wieder zum Integer machen
172 { // y das längere von beiden.
174 BN_to_NDS_1(y, MSDptr=,len=,LSDptr=); // NDS zu y bilden.
175 // vorsorglich 1 Digit mehr belegen:
176 { var sintD sign = sign_of_sintD(mspref(MSDptr,0));
177 lsprefnext(MSDptr) = sign; len++;
180 neg_loop_lsp(LSDptr,len);
181 // MSDigit ist nun = 0x0000 oder = 0xFFFF
182 var const uintD* xMSDptr;
184 var const uintD* xLSDptr;
185 BN_to_NDS_nocopy(x, xMSDptr=,xlen=,xLSDptr=); // NDS zu x bilden.
186 // xMSDptr/xlen/xLSDptr bilden die DS des kürzeren Arguments x.
187 // Es ist jetzt len>xlen.
189 { var uintD* midptr = LSDptr lspop xlen;
190 var uintD carry = addto_loop_lsp(xLSDptr,LSDptr,xlen);
193 if ((sintD)mspref(xMSDptr,0) >=0) // kürzerer Summand war positiv
194 // Dann ist ein positiver Übertrag weiterzutragen
195 // (Beispiel: 0002FFFC + 0007 = 00030003)
196 { DS_1_plus(midptr,len-xlen); }
200 if ((sintD)mspref(xMSDptr,0) <0) // kürzerer Summand war negativ
201 // Dann ist ein negativer Übertrag weiterzutragen
202 // (Beispiel: 00020003 + FFF5 = 0001FFF8)
203 { DS_minus1_plus(midptr,len-xlen); }
205 return DS_to_I(MSDptr,len); // DS wieder zum Integer machen