-
Notifications
You must be signed in to change notification settings - Fork 12
/
pb_div.c
135 lines (110 loc) · 3.68 KB
/
pb_div.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/* LibTomPoly, Polynomial Basis Math -- Tom St Denis
*
* LibTomPoly is a public domain library that provides
* polynomial basis arithmetic support. It relies on
* LibTomMath for large integer support.
*
* This library is free for all purposes without any
* express guarantee that it works.
*
* Tom St Denis, [email protected], http://poly.libtomcrypt.org
*/
#include <tompoly.h>
/* Divides a by b (uses the char of b as the char of the result) only for
* polynomials over GF(p^k)[x]
*/
int pb_div(pb_poly *a, pb_poly *b, pb_poly *c, pb_poly *d)
{
int err, x;
pb_poly p, q, r;
mp_int tmp, tmp2;
/* if ||b|| > ||a|| it's a simple copy over */
if (b->used > a->used) {
if (d != NULL) {
pb_copy(a, d);
}
if (c != NULL) {
pb_zero(c);
}
}
/* zero divisor */
if (b->used == 0) {
return MP_VAL;
}
/* compare chars */
if (mp_cmp(&(a->characteristic), &(b->characteristic)) != MP_EQ) {
return MP_VAL;
}
/* we don't support char zero! */
if (mp_iszero(&(b->characteristic)) == MP_YES) {
return MP_VAL;
}
/* get a copy of "a" to work with */
if ((err = pb_init_copy(&p, a)) != MP_OKAY) {
return err;
}
/* init a temp quotient */
if ((err = pb_init_size(&q, &(b->characteristic), a->used - b->used + 1)) != MP_OKAY) {
goto __P;
}
/* init a temp polynomial we can work with */
if ((err = pb_init_size(&r, &(b->characteristic), a->used)) != MP_OKAY) {
goto __Q;
}
/* now init an mp_int we can work with */
if ((err = mp_init(&tmp)) != MP_OKAY) {
goto __R;
}
/* and the inverse of the leading digit of b(x) */
if ((err = mp_init(&tmp2)) != MP_OKAY) {
goto __TMP;
}
if ((err = mp_invmod(&(b->terms[b->used - 1]), &(b->characteristic), &tmp2)) != MP_OKAY) {
goto __TMP2;
}
/* now let's reduce us some digits */
for (x = a->used - 1; x >= b->used-1; x--) {
/* skip zero digits */
if (mp_iszero(&(p.terms[x])) == MP_YES) {
continue;
}
/* now we have a leading digit of p(x), call it A
and a leading digit of b(x), call it B
Now we want to reduce it so we need A + CB = 0 which turns into
A + CB = 0
CB = -A
C = -A/B
So we multiply b(x) by C * x^k [where k = ||p(x)|| - ||b(x)||], add that to p(x) and
we must reduced one digit
*/
/* multiply 1/B [tmp2] by A */
if ((err = mp_mulmod(&tmp2, &(p.terms[x]), &(b->characteristic), &tmp)) != MP_OKAY) { goto __TMP2; }
/* tmp is now a term of the quotient */
if ((err = mp_copy(&tmp, &(q.terms[x - b->used + 1]))) != MP_OKAY) { goto __TMP2; }
/* create r(x) = C */
pb_zero(&r);
if ((err = mp_copy(&tmp, &(r.terms[0]))) != MP_OKAY) { goto __TMP2; }
r.used = 1;
/* now multiply r(x) by b(x)*x^k and subtract from p(x) */
if ((err = pb_mul(b, &r, &r)) != MP_OKAY) { goto __TMP2; }
if ((err = pb_lshd(&r, x - b->used + 1)) != MP_OKAY) { goto __TMP2; }
if ((err = pb_sub(&p, &r, &p)) != MP_OKAY) { goto __TMP2; }
}
/* setup q properly (so q.used is valid) */
q.used = a->used;
pb_clamp(&q);
/* ok so now p(x) is the remainder and q(x) is the quotient */
if (c != NULL) {
pb_exch(&q, c);
}
if (d != NULL) {
pb_exch(&p, d);
}
err = MP_OKAY;
__TMP2: mp_clear(&tmp2);
__TMP : mp_clear(&tmp);
__R : pb_clear(&r);
__Q : pb_clear(&q);
__P : pb_clear(&p);
return err;
}