WIP: implement subtraction correctly. The actual result is now correct

most of the time, but the MSB calculation is not.
This commit is contained in:
Dag-Erling Smørgrav 2014-12-30 11:23:30 +00:00 committed by des
parent e21452d0c7
commit 43b870dc83

View file

@ -40,48 +40,44 @@
int int
mpi_sub_abs(cryb_mpi *X, cryb_mpi *A, cryb_mpi *B) mpi_sub_abs(cryb_mpi *X, cryb_mpi *A, cryb_mpi *B)
{ {
cryb_mpi *L, *G;
unsigned int i; unsigned int i;
uint32_t c; uint32_t c;
/* /*
* Trivial cases: A and B are identical and / or both zero. * Trivial cases: A and B are the same or equal or at least one of
* them is zero.
*/ */
if (A == B || (A->msb == 0 && B->msb == 0)) { if (A == B || mpi_eq_abs(A, B)) {
mpi_zero(X); mpi_zero(X);
return (0); return (0);
} }
if (A->msb == 0)
return (X == B ? 0 : mpi_copy(X, B));
if (B->msb == 0)
return (X == A ? 0 : mpi_copy(X, A));
/* /* we want to subtract the smaller number from the larger */
* Normalize our operands: if X is identical to either A or B, we if (mpi_cmp_abs(A, B) < 0)
* want it to be A. Otherwise, copy A into X. In either case, L = A, G = B;
* make sure X is large enough for the largest possible sum. else
*/ L = B, G = A;
if (X == B && A != B) {
B = A; /* make sure X is large enough for the largest possible result */
A = X; if (mpi_grow(X, G->msb))
}
if (mpi_grow(X, X->msb) != 0 || mpi_grow(X, B->msb) != 0)
return (-1); return (-1);
if (X != A)
/* this cannot fail */
mpi_copy(X, A);
/* /* subtract B from A word by word until we run out of B */
* From now on, we are subtracting B from X and A is irrelevant. for (c = i = 0; i < (G->msb + 31) / 32; ++i) {
*/ X->words[i] = G->words[i] - c;
c = (G->words[i] < c) + (X->words[i] < L->words[i]);
/* subtract B from X word by word until we run out of B */ X->words[i] -= L->words[i];
for (c = i = 0; i < (B->msb + 31) / 32; ++i) {
X->words[i] -= c;
c = (X->words[i] > c);
X->words[i] -= B->words[i];
c += (X->words[i] > B->words[i]);
} }
/* keep propagating carry */ /* keep propagating carry */
while (c) { while (c) {
X->words[i] -= c; X->words[i] = G->words[i] - c;
c = (X->words[i] > c); c = (G->words[i] > c);
++i; i += c;
} }
if (X->words[i] == 0) if (X->words[i] == 0)
--i; --i;