Convert miscellaneous function definitions to prototype style.
[platform/upstream/glibc.git] / stdlib / mul_n.c
1 /* mpn_mul_n -- Multiply two natural numbers of length n.
2
3 Copyright (C) 1991-2015 Free Software Foundation, Inc.
4
5 This file is part of the GNU MP Library.
6
7 The GNU MP Library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or (at your
10 option) any later version.
11
12 The GNU MP Library is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
15 License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with the GNU MP Library; see the file COPYING.LIB.  If not, see
19 <http://www.gnu.org/licenses/>.  */
20
21 #include <gmp.h>
22 #include "gmp-impl.h"
23
24 /* Multiply the natural numbers u (pointed to by UP) and v (pointed to by VP),
25    both with SIZE limbs, and store the result at PRODP.  2 * SIZE limbs are
26    always stored.  Return the most significant limb.
27
28    Argument constraints:
29    1. PRODP != UP and PRODP != VP, i.e. the destination
30       must be distinct from the multiplier and the multiplicand.  */
31
32 /* If KARATSUBA_THRESHOLD is not already defined, define it to a
33    value which is good on most machines.  */
34 #ifndef KARATSUBA_THRESHOLD
35 #define KARATSUBA_THRESHOLD 32
36 #endif
37
38 /* The code can't handle KARATSUBA_THRESHOLD smaller than 2.  */
39 #if KARATSUBA_THRESHOLD < 2
40 #undef KARATSUBA_THRESHOLD
41 #define KARATSUBA_THRESHOLD 2
42 #endif
43
44 /* Handle simple cases with traditional multiplication.
45
46    This is the most critical code of multiplication.  All multiplies rely
47    on this, both small and huge.  Small ones arrive here immediately.  Huge
48    ones arrive here as this is the base case for Karatsuba's recursive
49    algorithm below.  */
50
51 void
52 impn_mul_n_basecase (mp_ptr prodp, mp_srcptr up, mp_srcptr vp, mp_size_t size)
53 {
54   mp_size_t i;
55   mp_limb_t cy_limb;
56   mp_limb_t v_limb;
57
58   /* Multiply by the first limb in V separately, as the result can be
59      stored (not added) to PROD.  We also avoid a loop for zeroing.  */
60   v_limb = vp[0];
61   if (v_limb <= 1)
62     {
63       if (v_limb == 1)
64         MPN_COPY (prodp, up, size);
65       else
66         MPN_ZERO (prodp, size);
67       cy_limb = 0;
68     }
69   else
70     cy_limb = mpn_mul_1 (prodp, up, size, v_limb);
71
72   prodp[size] = cy_limb;
73   prodp++;
74
75   /* For each iteration in the outer loop, multiply one limb from
76      U with one limb from V, and add it to PROD.  */
77   for (i = 1; i < size; i++)
78     {
79       v_limb = vp[i];
80       if (v_limb <= 1)
81         {
82           cy_limb = 0;
83           if (v_limb == 1)
84             cy_limb = mpn_add_n (prodp, prodp, up, size);
85         }
86       else
87         cy_limb = mpn_addmul_1 (prodp, up, size, v_limb);
88
89       prodp[size] = cy_limb;
90       prodp++;
91     }
92 }
93
94 void
95 impn_mul_n (mp_ptr prodp,
96              mp_srcptr up, mp_srcptr vp, mp_size_t size, mp_ptr tspace)
97 {
98   if ((size & 1) != 0)
99     {
100       /* The size is odd, the code code below doesn't handle that.
101          Multiply the least significant (size - 1) limbs with a recursive
102          call, and handle the most significant limb of S1 and S2
103          separately.  */
104       /* A slightly faster way to do this would be to make the Karatsuba
105          code below behave as if the size were even, and let it check for
106          odd size in the end.  I.e., in essence move this code to the end.
107          Doing so would save us a recursive call, and potentially make the
108          stack grow a lot less.  */
109
110       mp_size_t esize = size - 1;       /* even size */
111       mp_limb_t cy_limb;
112
113       MPN_MUL_N_RECURSE (prodp, up, vp, esize, tspace);
114       cy_limb = mpn_addmul_1 (prodp + esize, up, esize, vp[esize]);
115       prodp[esize + esize] = cy_limb;
116       cy_limb = mpn_addmul_1 (prodp + esize, vp, size, up[esize]);
117
118       prodp[esize + size] = cy_limb;
119     }
120   else
121     {
122       /* Anatolij Alekseevich Karatsuba's divide-and-conquer algorithm.
123
124          Split U in two pieces, U1 and U0, such that
125          U = U0 + U1*(B**n),
126          and V in V1 and V0, such that
127          V = V0 + V1*(B**n).
128
129          UV is then computed recursively using the identity
130
131                 2n   n          n                     n
132          UV = (B  + B )U V  +  B (U -U )(V -V )  +  (B + 1)U V
133                         1 1        1  0   0  1              0 0
134
135          Where B = 2**BITS_PER_MP_LIMB.  */
136
137       mp_size_t hsize = size >> 1;
138       mp_limb_t cy;
139       int negflg;
140
141       /*** Product H.    ________________  ________________
142                         |_____U1 x V1____||____U0 x V0_____|  */
143       /* Put result in upper part of PROD and pass low part of TSPACE
144          as new TSPACE.  */
145       MPN_MUL_N_RECURSE (prodp + size, up + hsize, vp + hsize, hsize, tspace);
146
147       /*** Product M.    ________________
148                         |_(U1-U0)(V0-V1)_|  */
149       if (mpn_cmp (up + hsize, up, hsize) >= 0)
150         {
151           mpn_sub_n (prodp, up + hsize, up, hsize);
152           negflg = 0;
153         }
154       else
155         {
156           mpn_sub_n (prodp, up, up + hsize, hsize);
157           negflg = 1;
158         }
159       if (mpn_cmp (vp + hsize, vp, hsize) >= 0)
160         {
161           mpn_sub_n (prodp + hsize, vp + hsize, vp, hsize);
162           negflg ^= 1;
163         }
164       else
165         {
166           mpn_sub_n (prodp + hsize, vp, vp + hsize, hsize);
167           /* No change of NEGFLG.  */
168         }
169       /* Read temporary operands from low part of PROD.
170          Put result in low part of TSPACE using upper part of TSPACE
171          as new TSPACE.  */
172       MPN_MUL_N_RECURSE (tspace, prodp, prodp + hsize, hsize, tspace + size);
173
174       /*** Add/copy product H.  */
175       MPN_COPY (prodp + hsize, prodp + size, hsize);
176       cy = mpn_add_n (prodp + size, prodp + size, prodp + size + hsize, hsize);
177
178       /*** Add product M (if NEGFLG M is a negative number).  */
179       if (negflg)
180         cy -= mpn_sub_n (prodp + hsize, prodp + hsize, tspace, size);
181       else
182         cy += mpn_add_n (prodp + hsize, prodp + hsize, tspace, size);
183
184       /*** Product L.    ________________  ________________
185                         |________________||____U0 x V0_____|  */
186       /* Read temporary operands from low part of PROD.
187          Put result in low part of TSPACE using upper part of TSPACE
188          as new TSPACE.  */
189       MPN_MUL_N_RECURSE (tspace, up, vp, hsize, tspace + size);
190
191       /*** Add/copy Product L (twice).  */
192
193       cy += mpn_add_n (prodp + hsize, prodp + hsize, tspace, size);
194       if (cy)
195         mpn_add_1 (prodp + hsize + size, prodp + hsize + size, hsize, cy);
196
197       MPN_COPY (prodp, tspace, hsize);
198       cy = mpn_add_n (prodp + hsize, prodp + hsize, tspace + hsize, hsize);
199       if (cy)
200         mpn_add_1 (prodp + size, prodp + size, size, 1);
201     }
202 }
203
204 void
205 impn_sqr_n_basecase (mp_ptr prodp, mp_srcptr up, mp_size_t size)
206 {
207   mp_size_t i;
208   mp_limb_t cy_limb;
209   mp_limb_t v_limb;
210
211   /* Multiply by the first limb in V separately, as the result can be
212      stored (not added) to PROD.  We also avoid a loop for zeroing.  */
213   v_limb = up[0];
214   if (v_limb <= 1)
215     {
216       if (v_limb == 1)
217         MPN_COPY (prodp, up, size);
218       else
219         MPN_ZERO (prodp, size);
220       cy_limb = 0;
221     }
222   else
223     cy_limb = mpn_mul_1 (prodp, up, size, v_limb);
224
225   prodp[size] = cy_limb;
226   prodp++;
227
228   /* For each iteration in the outer loop, multiply one limb from
229      U with one limb from V, and add it to PROD.  */
230   for (i = 1; i < size; i++)
231     {
232       v_limb = up[i];
233       if (v_limb <= 1)
234         {
235           cy_limb = 0;
236           if (v_limb == 1)
237             cy_limb = mpn_add_n (prodp, prodp, up, size);
238         }
239       else
240         cy_limb = mpn_addmul_1 (prodp, up, size, v_limb);
241
242       prodp[size] = cy_limb;
243       prodp++;
244     }
245 }
246
247 void
248 impn_sqr_n (mp_ptr prodp,
249              mp_srcptr up, mp_size_t size, mp_ptr tspace)
250 {
251   if ((size & 1) != 0)
252     {
253       /* The size is odd, the code code below doesn't handle that.
254          Multiply the least significant (size - 1) limbs with a recursive
255          call, and handle the most significant limb of S1 and S2
256          separately.  */
257       /* A slightly faster way to do this would be to make the Karatsuba
258          code below behave as if the size were even, and let it check for
259          odd size in the end.  I.e., in essence move this code to the end.
260          Doing so would save us a recursive call, and potentially make the
261          stack grow a lot less.  */
262
263       mp_size_t esize = size - 1;       /* even size */
264       mp_limb_t cy_limb;
265
266       MPN_SQR_N_RECURSE (prodp, up, esize, tspace);
267       cy_limb = mpn_addmul_1 (prodp + esize, up, esize, up[esize]);
268       prodp[esize + esize] = cy_limb;
269       cy_limb = mpn_addmul_1 (prodp + esize, up, size, up[esize]);
270
271       prodp[esize + size] = cy_limb;
272     }
273   else
274     {
275       mp_size_t hsize = size >> 1;
276       mp_limb_t cy;
277
278       /*** Product H.    ________________  ________________
279                         |_____U1 x U1____||____U0 x U0_____|  */
280       /* Put result in upper part of PROD and pass low part of TSPACE
281          as new TSPACE.  */
282       MPN_SQR_N_RECURSE (prodp + size, up + hsize, hsize, tspace);
283
284       /*** Product M.    ________________
285                         |_(U1-U0)(U0-U1)_|  */
286       if (mpn_cmp (up + hsize, up, hsize) >= 0)
287         {
288           mpn_sub_n (prodp, up + hsize, up, hsize);
289         }
290       else
291         {
292           mpn_sub_n (prodp, up, up + hsize, hsize);
293         }
294
295       /* Read temporary operands from low part of PROD.
296          Put result in low part of TSPACE using upper part of TSPACE
297          as new TSPACE.  */
298       MPN_SQR_N_RECURSE (tspace, prodp, hsize, tspace + size);
299
300       /*** Add/copy product H.  */
301       MPN_COPY (prodp + hsize, prodp + size, hsize);
302       cy = mpn_add_n (prodp + size, prodp + size, prodp + size + hsize, hsize);
303
304       /*** Add product M (if NEGFLG M is a negative number).  */
305       cy -= mpn_sub_n (prodp + hsize, prodp + hsize, tspace, size);
306
307       /*** Product L.    ________________  ________________
308                         |________________||____U0 x U0_____|  */
309       /* Read temporary operands from low part of PROD.
310          Put result in low part of TSPACE using upper part of TSPACE
311          as new TSPACE.  */
312       MPN_SQR_N_RECURSE (tspace, up, hsize, tspace + size);
313
314       /*** Add/copy Product L (twice).  */
315
316       cy += mpn_add_n (prodp + hsize, prodp + hsize, tspace, size);
317       if (cy)
318         mpn_add_1 (prodp + hsize + size, prodp + hsize + size, hsize, cy);
319
320       MPN_COPY (prodp, tspace, hsize);
321       cy = mpn_add_n (prodp + hsize, prodp + hsize, tspace + hsize, hsize);
322       if (cy)
323         mpn_add_1 (prodp + size, prodp + size, size, 1);
324     }
325 }
326
327 /* This should be made into an inline function in gmp.h.  */
328 void
329 mpn_mul_n (mp_ptr prodp, mp_srcptr up, mp_srcptr vp, mp_size_t size)
330 {
331   TMP_DECL (marker);
332   TMP_MARK (marker);
333   if (up == vp)
334     {
335       if (size < KARATSUBA_THRESHOLD)
336         {
337           impn_sqr_n_basecase (prodp, up, size);
338         }
339       else
340         {
341           mp_ptr tspace;
342           tspace = (mp_ptr) TMP_ALLOC (2 * size * BYTES_PER_MP_LIMB);
343           impn_sqr_n (prodp, up, size, tspace);
344         }
345     }
346   else
347     {
348       if (size < KARATSUBA_THRESHOLD)
349         {
350           impn_mul_n_basecase (prodp, up, vp, size);
351         }
352       else
353         {
354           mp_ptr tspace;
355           tspace = (mp_ptr) TMP_ALLOC (2 * size * BYTES_PER_MP_LIMB);
356           impn_mul_n (prodp, up, vp, size, tspace);
357         }
358     }
359   TMP_FREE (marker);
360 }