|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 /* This file contains routines that perform vector multiplication. */ |
|
6 |
|
7 #include "mpi-priv.h" |
|
8 #include <unistd.h> |
|
9 |
|
10 #include <stddef.h> |
|
11 /* #include <sys/systeminfo.h> */ |
|
12 #include <strings.h> |
|
13 |
|
14 extern void multacc512( |
|
15 int length, /* doublewords in multiplicand vector. */ |
|
16 const mp_digit *scalaraddr, /* Address of scalar. */ |
|
17 const mp_digit *multiplicand, /* The multiplicand vector. */ |
|
18 mp_digit * result); /* Where to accumulate the result. */ |
|
19 |
|
20 extern void maxpy_little( |
|
21 int length, /* doublewords in multiplicand vector. */ |
|
22 const mp_digit *scalaraddr, /* Address of scalar. */ |
|
23 const mp_digit *multiplicand, /* The multiplicand vector. */ |
|
24 mp_digit * result); /* Where to accumulate the result. */ |
|
25 |
|
26 extern void add_diag_little( |
|
27 int length, /* doublewords in input vector. */ |
|
28 const mp_digit *root, /* The vector to square. */ |
|
29 mp_digit * result); /* Where to accumulate the result. */ |
|
30 |
|
31 void |
|
32 s_mpv_sqr_add_prop(const mp_digit *pa, mp_size a_len, mp_digit *ps) |
|
33 { |
|
34 add_diag_little(a_len, pa, ps); |
|
35 } |
|
36 |
|
37 #define MAX_STACK_DIGITS 258 |
|
38 #define MULTACC512_LEN (512 / MP_DIGIT_BIT) |
|
39 #define HP_MPY_ADD_FN (a_len == MULTACC512_LEN ? multacc512 : maxpy_little) |
|
40 |
|
41 /* c = a * b */ |
|
42 void |
|
43 s_mpv_mul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c) |
|
44 { |
|
45 mp_digit x[MAX_STACK_DIGITS]; |
|
46 mp_digit *px = x; |
|
47 size_t xSize = 0; |
|
48 |
|
49 if (a == c) { |
|
50 if (a_len > MAX_STACK_DIGITS) { |
|
51 xSize = sizeof(mp_digit) * (a_len + 2); |
|
52 px = malloc(xSize); |
|
53 if (!px) |
|
54 return; |
|
55 } |
|
56 memcpy(px, a, a_len * sizeof(*a)); |
|
57 a = px; |
|
58 } |
|
59 s_mp_setz(c, a_len + 1); |
|
60 HP_MPY_ADD_FN(a_len, &b, a, c); |
|
61 if (px != x && px) { |
|
62 memset(px, 0, xSize); |
|
63 free(px); |
|
64 } |
|
65 } |
|
66 |
|
67 /* c += a * b, where a is a_len words long. */ |
|
68 void |
|
69 s_mpv_mul_d_add(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c) |
|
70 { |
|
71 c[a_len] = 0; /* so carry propagation stops here. */ |
|
72 HP_MPY_ADD_FN(a_len, &b, a, c); |
|
73 } |
|
74 |
|
75 /* c += a * b, where a is y words long. */ |
|
76 void |
|
77 s_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len, mp_digit b, |
|
78 mp_digit *c) |
|
79 { |
|
80 HP_MPY_ADD_FN(a_len, &b, a, c); |
|
81 } |
|
82 |