mirror of
https://github.com/cryb-to/cryb-to.git
synced 2024-11-14 01:35:40 +00:00
In both mpi_add_abs() and mpi_sub_abs(), make sure that the target is
untouched if the operation fails. Also ensure that A = A +/- A works.
This commit is contained in:
parent
98c6349d4a
commit
bc8e9d67ba
2 changed files with 54 additions and 25 deletions
|
@ -36,7 +36,6 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Store the sum of the absolutes values of A and B in X.
|
* Store the sum of the absolutes values of A and B in X.
|
||||||
* XXX safe for either A or B to be the same object as X but not both
|
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
mpi_add_abs(cryb_mpi *X, cryb_mpi *A, cryb_mpi *B)
|
mpi_add_abs(cryb_mpi *X, cryb_mpi *A, cryb_mpi *B)
|
||||||
|
@ -44,36 +43,53 @@ mpi_add_abs(cryb_mpi *X, cryb_mpi *A, cryb_mpi *B)
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
uint32_t c;
|
uint32_t c;
|
||||||
|
|
||||||
if (X == B)
|
/*
|
||||||
B = A, A = X;
|
* Trivial cases: A and B are identical and / or both zero.
|
||||||
if (X != A)
|
*/
|
||||||
mpi_copy(X, A);
|
if (A->msb == 0 && B->msb == 0)
|
||||||
/* 0 + 0 = 0 */
|
|
||||||
if (X->msb == 0 && B->msb == 0)
|
|
||||||
return (0);
|
return (0);
|
||||||
/* make room */
|
if (A == B) {
|
||||||
if (mpi_grow(X, X->msb + 1) != 0 || mpi_grow(X, B->msb + 1) != 0)
|
if (X != A && mpi_copy(X, A) != 0)
|
||||||
|
return (-1);
|
||||||
|
return (mpi_lshift(X, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Normalize our operands: if X is identical to either A or B, we
|
||||||
|
* want it to be A. Otherwise, copy A into X. In either case,
|
||||||
|
* make sure X is large enough for the largest possible sum.
|
||||||
|
*/
|
||||||
|
if (X == B) {
|
||||||
|
B = A;
|
||||||
|
A = X;
|
||||||
|
}
|
||||||
|
if (mpi_grow(X, A->msb + 1) != 0 || mpi_grow(X, B->msb + 1) != 0)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
if (X != A)
|
||||||
|
/* this cannot fail */
|
||||||
|
mpi_copy(X, A);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* From now on, we are adding B to X and A is irrelevant.
|
||||||
|
*/
|
||||||
|
|
||||||
/* add B into X word by word until we run out of B */
|
/* add B into X word by word until we run out of B */
|
||||||
for (c = i = 0; i < (B->msb + 31) / 32; ++i) {
|
for (c = i = 0; i < (B->msb + 31) / 32; ++i) {
|
||||||
// fprintf(stderr, "0x%08x + 0x%08x (%u)", X->words[i], B->words[i], c);
|
|
||||||
X->words[i] += c;
|
X->words[i] += c;
|
||||||
c = (X->words[i] < c);
|
c = (X->words[i] < c);
|
||||||
X->words[i] += B->words[i];
|
X->words[i] += B->words[i];
|
||||||
c += (X->words[i] < B->words[i]);
|
c += (X->words[i] < B->words[i]);
|
||||||
// fprintf(stderr, " = 0x%08x (%u)\n", X->words[i], c);
|
|
||||||
}
|
}
|
||||||
/* keep propagating carry */
|
/* keep propagating carry */
|
||||||
while (c) {
|
while (c) {
|
||||||
// fprintf(stderr, "0x%08x + 0x%08x (%u)", X->words[i], 0, c);
|
|
||||||
X->words[i] += c;
|
X->words[i] += c;
|
||||||
c = (X->words[i] < c);
|
c = (X->words[i] < c);
|
||||||
// fprintf(stderr, " = 0x%08x (%u)\n", X->words[i], c);
|
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
if (X->words[i] == 0)
|
if (X->words[i] == 0)
|
||||||
--i;
|
--i;
|
||||||
/* compute msb of msw */
|
/* compute msb of msw */
|
||||||
|
/* XXX should use flsl() */
|
||||||
for (X->msb = 31; X->msb > 0; --X->msb)
|
for (X->msb = 31; X->msb > 0; --X->msb)
|
||||||
if (X->words[i] & (1 << X->msb))
|
if (X->words[i] & (1 << X->msb))
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -36,7 +36,6 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Store the difference between the absolute values of A and B in X.
|
* Store the difference between the absolute values of A and B in X.
|
||||||
* XXX safe for either A or B to be the same object as X but not both
|
|
||||||
*/
|
*/
|
||||||
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)
|
||||||
|
@ -44,36 +43,50 @@ mpi_sub_abs(cryb_mpi *X, cryb_mpi *A, cryb_mpi *B)
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
uint32_t c;
|
uint32_t c;
|
||||||
|
|
||||||
if (X == B)
|
/*
|
||||||
B = A, A = X;
|
* Trivial cases: A and B are identical and / or both zero.
|
||||||
if (X != A)
|
*/
|
||||||
mpi_copy(X, A);
|
if (A == B || (A->msb == 0 && B->msb == 0)) {
|
||||||
/* 0 - 0 = 0 */
|
mpi_zero(X);
|
||||||
if (X->msb == 0 && B->msb == 0)
|
|
||||||
return (0);
|
return (0);
|
||||||
/* make room */
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Normalize our operands: if X is identical to either A or B, we
|
||||||
|
* want it to be A. Otherwise, copy A into X. In either case,
|
||||||
|
* make sure X is large enough for the largest possible sum.
|
||||||
|
*/
|
||||||
|
if (X == B && A != B) {
|
||||||
|
B = A;
|
||||||
|
A = X;
|
||||||
|
}
|
||||||
if (mpi_grow(X, X->msb) != 0 || mpi_grow(X, B->msb) != 0)
|
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);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* From now on, we are subtracting B from X and A is irrelevant.
|
||||||
|
*/
|
||||||
|
|
||||||
/* subtract B from X word by word until we run out of B */
|
/* subtract B from X word by word until we run out of B */
|
||||||
for (c = i = 0; i < (B->msb + 31) / 32; ++i) {
|
for (c = i = 0; i < (B->msb + 31) / 32; ++i) {
|
||||||
// fprintf(stderr, "0x%08x + 0x%08x (%u)", X->words[i], B->words[i], c);
|
|
||||||
X->words[i] -= c;
|
X->words[i] -= c;
|
||||||
c = (X->words[i] > c);
|
c = (X->words[i] > c);
|
||||||
X->words[i] -= B->words[i];
|
X->words[i] -= B->words[i];
|
||||||
c += (X->words[i] > B->words[i]);
|
c += (X->words[i] > B->words[i]);
|
||||||
// fprintf(stderr, " = 0x%08x (%u)\n", X->words[i], c);
|
|
||||||
}
|
}
|
||||||
/* keep propagating carry */
|
/* keep propagating carry */
|
||||||
while (c) {
|
while (c) {
|
||||||
// fprintf(stderr, "0x%08x + 0x%08x (%u)", X->words[i], 0, c);
|
|
||||||
X->words[i] -= c;
|
X->words[i] -= c;
|
||||||
c = (X->words[i] > c);
|
c = (X->words[i] > c);
|
||||||
// fprintf(stderr, " = 0x%08x (%u)\n", X->words[i], c);
|
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
if (X->words[i] == 0)
|
if (X->words[i] == 0)
|
||||||
--i;
|
--i;
|
||||||
/* compute msb of msw */
|
/* compute msb of msw */
|
||||||
|
/* XXX use flsl() */
|
||||||
for (X->msb = 31; X->msb > 0; --X->msb)
|
for (X->msb = 31; X->msb > 0; --X->msb)
|
||||||
if (X->words[i] & (1 << X->msb))
|
if (X->words[i] & (1 << X->msb))
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue