]> www.ginac.de Git - cln.git/blob - src/integer/elem/cl_I_plus.cc
* */*: Remove cl_boolean, cl_true, and cl_false in favor of built-in
[cln.git] / src / integer / elem / cl_I_plus.cc
1 // binary operator +
2
3 // General includes.
4 #include "cl_sysdep.h"
5
6 // Specification.
7 #include "cln/integer.h"
8
9
10 // Implementation.
11
12 #include "cl_I.h"
13 #include "cl_DS.h"
14
15 namespace cln {
16
17 const cl_I operator+ (const cl_I& x, const cl_I& y)
18 {
19     // Methode:
20     // x Fixnum ->
21     //   y Fixnum -> beide direkt addieren, mit L_to_I beenden
22     //   y Bignum -> falls x=0, y; sonst beide zu DS machen, addieren.
23     // x Bignum ->
24     //   y Fixnum -> falls y=0, x; sonst beide zu DS machen, addieren.
25     //   y Bignum -> beide zu DS machen, addieren.
26       var uintD* MSDptr;
27       var uintC len;
28       var uintD* LSDptr;
29       // MSDptr/len/LSDptr bilden die DS des Ergebnisses.
30       if (fixnump(x))
31         { // x ist Fixnum
32           if (fixnump(y))
33             { // x,y sind Fixnums
34               #if (cl_value_len < intVsize)
35               return V_to_I( FN_to_V(x) + FN_to_V(y) ); // als intVsize-Bit-Zahlen addieren
36               #elif (cl_word_size==64)
37               return Q_to_I( FN_to_Q(x) + FN_to_Q(y) ); // als 64-Bit-Zahlen addieren
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);
43               xhi += yhi;
44               xlo += ylo;
45               if (xlo < ylo) { xhi += 1; }
46               return L2_to_I(xhi,xlo);
47               #endif
48             }
49             else
50             { // x ist Fixnum, y ist Bignum, also y länger
51               #if (intDsize==64)
52               var sint64 x_ = FN_to_V(x); // Wert von x
53               #else
54               var sintV x_ = FN_to_V(x); // Wert von x
55               #endif
56               if (FN_V_zerop(x,x_)) { return y; } // bei x=0 Ergebnis y
57               CL_ALLOCA_STACK;
58               BN_to_NDS_1(y, MSDptr=,len=,LSDptr=); // NDS zu y bilden.
59               // len>=bn_minlength. len>pFN_maxlength erzwingen:
60               if ((bn_minlength==pFN_maxlength) && (len==pFN_maxlength))
61                 { var sintD sign = sign_of_sintD(mspref(MSDptr,0));
62                   lsprefnext(MSDptr) = sign; len++;
63                 }
64               // x_ zu den oberen pFN_maxlength Digits von y addieren:
65               {
66                 #if (intDsize==64)
67                 var uint64 y_ = lspref(LSDptr,0);
68                 var uint64 y_new = y_+(uint64)x_;
69                 lspref(LSDptr,0) = y_new;
70                 #else
71                 var uintV y_ = pFN_maxlength_digits_at(LSDptr);
72                 var uintV y_new = y_+(uintV)x_;
73                 set_pFN_maxlength_digits_at(LSDptr,y_new);
74                 #endif
75                 var uintD* midptr = LSDptr lspop pFN_maxlength;
76                 if (y_new < y_)
77                   { // Carry.
78                     if (!FN_V_minusp(x,x_)) // kürzerer Summand war positiv
79                       // Dann ist ein positiver Übertrag weiterzutragen
80                       // (Beispiel: 0002FFFC + 0007 = 00030003)
81                       { DS_1_plus(midptr,len-pFN_maxlength); }
82                   }
83                   else
84                   { // Kein Carry.
85                     if (FN_V_minusp(x,x_)) // kürzerer Summand war negativ
86                       // Dann ist ein negativer Übertrag weiterzutragen
87                       // (Beispiel: 00020003 + FFF5 = 0001FFF8)
88                       { DS_minus1_plus(midptr,len-pFN_maxlength); }
89               }   }
90               return DS_to_I(MSDptr,len); // DS wieder zum Integer machen
91             }
92         }
93         else
94         { // x ist Bignum
95           if (fixnump(y))
96             { // x ist Bignum, y ist Fixnum, also x länger
97               #if (intDsize==64)
98               var sint64 y_ = FN_to_V(y); // Wert von y
99               #else
100               var sintV y_ = FN_to_V(y); // Wert von y
101               #endif
102               if (FN_V_zerop(y,y_)) { return x; } // bei y=0 Ergebnis x
103               CL_ALLOCA_STACK;
104               BN_to_NDS_1(x, MSDptr=,len=,LSDptr=); // NDS zu x bilden.
105               // len>=bn_minlength. len>pFN_maxlength erzwingen:
106               if ((bn_minlength==pFN_maxlength) && (len==pFN_maxlength))
107                 { var sintD sign = sign_of_sintD(mspref(MSDptr,0));
108                   lsprefnext(MSDptr) = sign; len++;
109                 }
110               // y_ zu den oberen pFN_maxlength Digits von x addieren:
111               {
112                 #if (intDsize==64)
113                 var uint64 x_ = lspref(LSDptr,0);
114                 var uint64 x_new = x_+(uint64)y_;
115                 lspref(LSDptr,0) = x_new;
116                 #else
117                 var uintV x_ = pFN_maxlength_digits_at(LSDptr);
118                 var uintV x_new = x_+(uintV)y_;
119                 set_pFN_maxlength_digits_at(LSDptr,x_new);
120                 #endif
121                 var uintD* midptr = LSDptr lspop pFN_maxlength;
122                 if (x_new < x_)
123                   { // Carry.
124                     if (!FN_V_minusp(y,y_)) // kürzerer Summand war positiv
125                       // Dann ist ein positiver Übertrag weiterzutragen
126                       // (Beispiel: 0002FFFC + 0007 = 00030003)
127                       { DS_1_plus(midptr,len-pFN_maxlength); }
128                   }
129                   else
130                   { // Kein Carry.
131                     if (FN_V_minusp(y,y_)) // kürzerer Summand war negativ
132                       // Dann ist ein negativer Übertrag weiterzutragen
133                       // (Beispiel: 00020003 + FFF5 = 0001FFF8)
134                       { DS_minus1_plus(midptr,len-pFN_maxlength); }
135               }   }
136               return DS_to_I(MSDptr,len); // DS wieder zum Integer machen
137             }
138             else
139             { // x und y sind Bignums
140               CL_ALLOCA_STACK;
141               if (TheBignum(x)->length > TheBignum(y)->length)
142                 { // x das längere von beiden.
143                   BN_to_NDS_1(x, MSDptr=,len=,LSDptr=); // NDS zu x bilden.
144                   var const uintD* yMSDptr;
145                   var uintC ylen;
146                   var const uintD* yLSDptr;
147                   BN_to_NDS_nocopy(y, yMSDptr=,ylen=,yLSDptr=); // NDS zu y bilden.
148                   // yMSDptr/ylen/yLSDptr bilden die DS des kürzeren Arguments y.
149                   // Es ist len>ylen.
150                   // addieren:
151                   { var uintD* midptr = LSDptr lspop ylen;
152                     var uintD carry = addto_loop_lsp(yLSDptr,LSDptr,ylen);
153                     if (carry)
154                       { // Carry.
155                         if ((sintD)mspref(yMSDptr,0) >=0) // kürzerer Summand war positiv
156                           // Dann ist ein positiver Übertrag weiterzutragen
157                           // (Beispiel: 0002FFFC + 0007 = 00030003)
158                           { DS_1_plus(midptr,len-ylen); }
159                       }
160                       else
161                       { // Kein Carry.
162                         if ((sintD)mspref(yMSDptr,0) <0) // kürzerer Summand war negativ
163                           // Dann ist ein negativer Übertrag weiterzutragen
164                           // (Beispiel: 00020003 + FFF5 = 0001FFF8)
165                           { DS_minus1_plus(midptr,len-ylen); }
166                   }   }
167                   return DS_to_I(MSDptr,len); // DS wieder zum Integer machen
168                 }
169                 else
170                 { // y das längere von beiden.
171                   BN_to_NDS_1(y, MSDptr=,len=,LSDptr=); // NDS zu y bilden.
172                   var const uintD* xMSDptr;
173                   var uintC xlen;
174                   var const uintD* xLSDptr;
175                   BN_to_NDS_nocopy(x, xMSDptr=,xlen=,xLSDptr=); // NDS zu x bilden.
176                   // xMSDptr/xlen/xLSDptr bilden die DS des kürzeren Arguments x.
177                   // len>xlen erzwingen:
178                   if (len==xlen)
179                     { var sintD sign = sign_of_sintD(mspref(MSDptr,0));
180                       lsprefnext(MSDptr) = sign; len++;
181                     }
182                   // addieren:
183                   { var uintD* midptr = LSDptr lspop xlen;
184                     var uintD carry = addto_loop_lsp(xLSDptr,LSDptr,xlen);
185                     if (carry)
186                       { // Carry.
187                         if ((sintD)mspref(xMSDptr,0) >=0) // kürzerer Summand war positiv
188                           // Dann ist ein positiver Übertrag weiterzutragen
189                           // (Beispiel: 0002FFFC + 0007 = 00030003)
190                           { DS_1_plus(midptr,len-xlen); }
191                       }
192                       else
193                       { // Kein Carry.
194                         if ((sintD)mspref(xMSDptr,0) <0) // kürzerer Summand war negativ
195                           // Dann ist ein negativer Übertrag weiterzutragen
196                           // (Beispiel: 00020003 + FFF5 = 0001FFF8)
197                           { DS_minus1_plus(midptr,len-xlen); }
198                   }   }
199                   return DS_to_I(MSDptr,len); // DS wieder zum Integer machen
200                 }
201             }
202         }
203 }
204
205 }  // namespace cln