1 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3 * LibTomMath is library that provides for multiple-precision
4 * integer arithmetic as well as number theoretic functionality.
6 * This file "poly.c" provides GF(p^k) functionality on top of the
9 * The library is designed directly after the MPI library by
10 * Michael Fromberger but has been written from scratch with
11 * additional optimizations in place.
13 * The library is free for all purposes without any express
16 * Tom St Denis, tomstdenis@iahu.ca, http://libtommath.iahu.ca
21 #define MIN(x,y) ((x)<(y)?(x):(y))
23 #define MAX(x,y) ((x)>(y)?(x):(y))
25 static void s_free(mp_poly *a)
28 for (k = 0; k < a->alloc; k++) {
29 mp_clear(&(a->co[k]));
33 static int s_setup(mp_poly *a, int low, int high)
36 for (k = low; k < high; k++) {
37 if ((res = mp_init(&(a->co[k]))) != MP_OKAY) {
38 for (j = low; j < k; j++) {
39 mp_clear(&(a->co[j]));
47 int mp_poly_init(mp_poly *a, mp_int *cha)
49 return mp_poly_init_size(a, cha, MP_POLY_PREC);
52 /* init a poly of a given (size) degree */
53 int mp_poly_init_size(mp_poly *a, mp_int *cha, int size)
57 /* allocate array of mp_ints for coefficients */
58 a->co = malloc(size * sizeof(mp_int));
65 /* now init the range */
66 if ((res = s_setup(a, 0, size)) != MP_OKAY) {
71 /* copy characteristic */
72 if ((res = mp_init_copy(&(a->cha), cha)) != MP_OKAY) {
78 /* return ok at this point */
82 /* grow the size of a poly */
83 static int mp_poly_grow(mp_poly *a, int size)
87 if (size > a->alloc) {
88 /* resize the array of coefficients */
89 a->co = realloc(a->co, sizeof(mp_int) * size);
94 /* now setup the coefficients */
95 if ((res = s_setup(a, a->alloc, a->alloc + size)) != MP_OKAY) {
105 int mp_poly_copy(mp_poly *a, mp_poly *b)
110 if ((res = mp_poly_grow(b, a->used)) != MP_OKAY) {
114 /* now copy the used part */
118 if ((res = mp_copy(&(a->cha), &(b->cha))) != MP_OKAY) {
122 /* now all the coefficients */
123 for (k = 0; k < b->used; k++) {
124 if ((res = mp_copy(&(a->co[k]), &(b->co[k]))) != MP_OKAY) {
129 /* now zero the top */
130 for (k = b->used; k < b->alloc; k++) {
131 mp_zero(&(b->co[k]));
137 /* init from a copy, a = b */
138 int mp_poly_init_copy(mp_poly *a, mp_poly *b)
142 if ((res = mp_poly_init(a, &(b->cha))) != MP_OKAY) {
145 return mp_poly_copy(b, a);
148 /* free a poly from ram */
149 void mp_poly_clear(mp_poly *a)
156 a->used = a->alloc = 0;
159 /* exchange two polys */
160 void mp_poly_exch(mp_poly *a, mp_poly *b)
163 t = *a; *a = *b; *b = t;
166 /* clamp the # of used digits */
167 static void mp_poly_clamp(mp_poly *a)
169 while (a->used > 0 && mp_cmp_d(&(a->co[a->used]), 0) == MP_EQ) --(a->used);
172 /* add two polynomials, c(x) = a(x) + b(x) */
173 int mp_poly_add(mp_poly *a, mp_poly *b, mp_poly *c)
178 /* ensure char's are the same */
179 if (mp_cmp(&(a->cha), &(b->cha)) != MP_EQ) {
183 /* now figure out the sizes such that x is the
184 largest degree poly and y is less or equal in degree
186 if (a->used > b->used) {
194 /* now init the result to be a copy of the largest */
195 if ((res = mp_poly_init_copy(&t, x)) != MP_OKAY) {
199 /* now add the coeffcients of the smaller one */
200 for (k = 0; k < y->used; k++) {
201 if ((res = mp_addmod(&(a->co[k]), &(b->co[k]), &(a->cha), &(t.co[k]))) != MP_OKAY) {
210 __T: mp_poly_clear(&t);
214 /* subtracts two polynomials, c(x) = a(x) - b(x) */
215 int mp_poly_sub(mp_poly *a, mp_poly *b, mp_poly *c)
220 /* ensure char's are the same */
221 if (mp_cmp(&(a->cha), &(b->cha)) != MP_EQ) {
225 /* now figure out the sizes such that x is the
226 largest degree poly and y is less or equal in degree
228 if (a->used > b->used) {
236 /* now init the result to be a copy of the largest */
237 if ((res = mp_poly_init_copy(&t, x)) != MP_OKAY) {
241 /* now add the coeffcients of the smaller one */
242 for (k = 0; k < y->used; k++) {
243 if ((res = mp_submod(&(a->co[k]), &(b->co[k]), &(a->cha), &(t.co[k]))) != MP_OKAY) {
252 __T: mp_poly_clear(&t);
256 /* multiplies two polynomials, c(x) = a(x) * b(x) */
257 int mp_poly_mul(mp_poly *a, mp_poly *b, mp_poly *c)
261 int res, pa, pb, ix, iy;
263 /* ensure char's are the same */
264 if (mp_cmp(&(a->cha), &(b->cha)) != MP_EQ) {
268 /* degrees of a and b */
272 /* now init the temp polynomial to be of degree pa+pb */
273 if ((res = mp_poly_init_size(&t, &(a->cha), pa+pb)) != MP_OKAY) {
277 /* now init our temp int */
278 if ((res = mp_init(&tt)) != MP_OKAY) {
282 /* now loop through all the digits */
283 for (ix = 0; ix < pa; ix++) {
284 for (iy = 0; iy < pb; iy++) {
285 if ((res = mp_mul(&(a->co[ix]), &(b->co[iy]), &tt)) != MP_OKAY) {
288 if ((res = mp_addmod(&tt, &(t.co[ix+iy]), &(a->cha), &(t.co[ix+iy]))) != MP_OKAY) {
299 __T: mp_poly_clear(&t);