2005-07-23 12:43:03 +02:00
|
|
|
/* TomsFastMath, a fast ISO C bignum library.
|
|
|
|
*
|
|
|
|
* This project is meant to fill in where LibTomMath
|
|
|
|
* falls short. That is speed ;-)
|
|
|
|
*
|
|
|
|
* This project is public domain and free for all purposes.
|
|
|
|
*
|
|
|
|
* Tom St Denis, tomstdenis@gmail.com
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Generates squaring comba code... it learns it knows our secrets! */
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
int x, y, z, N, f;
|
|
|
|
|
|
|
|
printf(
|
2011-09-20 11:36:41 +02:00
|
|
|
"#define TFM_DEFINES\n"
|
|
|
|
"#include \"fp_sqr_comba.c\"\n"
|
|
|
|
"\n"
|
|
|
|
"#if defined(TFM_SMALL_SET)\n"
|
2005-07-23 12:43:03 +02:00
|
|
|
"void fp_sqr_comba_small(fp_int *A, fp_int *B)\n"
|
|
|
|
"{\n"
|
|
|
|
" fp_digit *a, b[32], c0, c1, c2, sc0, sc1, sc2;\n"
|
2011-09-20 11:36:41 +02:00
|
|
|
"#ifdef TFM_ISO\n"
|
|
|
|
" fp_word tt;\n"
|
|
|
|
"#endif\n"
|
2005-07-23 12:43:03 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
printf(" switch (A->used) { \n");
|
|
|
|
|
|
|
|
for (N = 1; N <= 16; N++) {
|
|
|
|
printf(
|
|
|
|
" case %d:\n"
|
|
|
|
" a = A->dp;\n"
|
|
|
|
" COMBA_START; \n"
|
|
|
|
"\n"
|
|
|
|
" /* clear carries */\n"
|
|
|
|
" CLEAR_CARRY;\n"
|
|
|
|
"\n"
|
|
|
|
" /* output 0 */\n"
|
|
|
|
" SQRADD(a[0],a[0]);\n"
|
|
|
|
" COMBA_STORE(b[0]);\n", N);
|
|
|
|
|
|
|
|
for (x = 1; x < N+N-1; x++) {
|
|
|
|
printf(
|
|
|
|
"\n /* output %d */\n"
|
|
|
|
" CARRY_FORWARD;\n ", x);
|
|
|
|
|
|
|
|
for (f = y = 0; y < N; y++) {
|
|
|
|
for (z = 0; z < N; z++) {
|
|
|
|
if (z != y && z + y == x && y <= z) {
|
|
|
|
++f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (f <= 2) {
|
|
|
|
for (y = 0; y < N; y++) {
|
|
|
|
for (z = 0; z < N; z++) {
|
|
|
|
if (y<=z && (y+z)==x) {
|
|
|
|
if (y == z) {
|
|
|
|
printf(" SQRADD(a[%d], a[%d]); ", y, y);
|
|
|
|
} else {
|
|
|
|
printf(" SQRADD2(a[%d], a[%d]); ", y, z);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// new method
|
|
|
|
/* do evens first */
|
|
|
|
f = 0;
|
|
|
|
for (y = 0; y < N; y++) {
|
|
|
|
for (z = 0; z < N; z++) {
|
|
|
|
if (z != y && z + y == x && y <= z) {
|
|
|
|
if (f == 0) {
|
|
|
|
// first double
|
|
|
|
printf("SQRADDSC(a[%d], a[%d]); ", y, z);
|
|
|
|
f = 1;
|
|
|
|
} else {
|
|
|
|
printf("SQRADDAC(a[%d], a[%d]); ", y, z);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// forward the carry
|
|
|
|
printf("SQRADDDB; ");
|
|
|
|
if ((x&1) == 0) {
|
|
|
|
// add the square
|
|
|
|
printf("SQRADD(a[%d], a[%d]); ", x/2, x/2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
printf("\n COMBA_STORE(b[%d]);\n", x);
|
|
|
|
}
|
|
|
|
printf(" COMBA_STORE2(b[%d]);\n", N+N-1);
|
|
|
|
|
|
|
|
printf(
|
|
|
|
" COMBA_FINI;\n"
|
|
|
|
"\n"
|
|
|
|
" B->used = %d;\n"
|
|
|
|
" B->sign = FP_ZPOS;\n"
|
|
|
|
" memcpy(B->dp, b, %d * sizeof(fp_digit));\n"
|
Bugfix: clear the exceeding destination digits.
Currently, the fp_sqr_comba_* functions do not fully clear the destination
number, but only overwrites the digits they care about. Eg: if
you call a comba4, it will overwrite the first 8 digits and leave
the others unchanged.
On the other hand, fp_mul_comba_* functions do *not* check incoming
unused digits (relying on the guarantee that they must be zero),
so they will happily compute the wrong result if those digits
are not empty. Testcase for a 32-bit system:
char buf[64];
fp_int num, num2, d;
memset(buf, 0xFF, sizeof(buf);
fp_read_unsigned_bin(&num, buf);
fp_set(&d, 1);
fp_sqr_comba_3(&d, &num);
// now num is { 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
// 0xFFFFFFFF, 0xFFFFFFFF ... }
// only first 6 digits have been written, but even
// if num.used is correctly set to 6, this can trigger
// bugs.
// Create a number larger than 6 digits
fp_2expt(&num2, 8*32+4);
fp_mul_comba_8(&num, &num2, &num2);
// wrong result has been computed, because the first 8
// digits of num have been read and multiplied
// even if num->used == 6, relying on the fact that
// they should be zero.
2011-09-20 11:02:53 +02:00
|
|
|
" memset(B->dp + %d, 0, (FP_SIZE - %d) * sizeof(fp_digit));\n"
|
2005-07-23 12:43:03 +02:00
|
|
|
" fp_clamp(B);\n"
|
Bugfix: clear the exceeding destination digits.
Currently, the fp_sqr_comba_* functions do not fully clear the destination
number, but only overwrites the digits they care about. Eg: if
you call a comba4, it will overwrite the first 8 digits and leave
the others unchanged.
On the other hand, fp_mul_comba_* functions do *not* check incoming
unused digits (relying on the guarantee that they must be zero),
so they will happily compute the wrong result if those digits
are not empty. Testcase for a 32-bit system:
char buf[64];
fp_int num, num2, d;
memset(buf, 0xFF, sizeof(buf);
fp_read_unsigned_bin(&num, buf);
fp_set(&d, 1);
fp_sqr_comba_3(&d, &num);
// now num is { 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
// 0xFFFFFFFF, 0xFFFFFFFF ... }
// only first 6 digits have been written, but even
// if num.used is correctly set to 6, this can trigger
// bugs.
// Create a number larger than 6 digits
fp_2expt(&num2, 8*32+4);
fp_mul_comba_8(&num, &num2, &num2);
// wrong result has been computed, because the first 8
// digits of num have been read and multiplied
// even if num->used == 6, relying on the fact that
// they should be zero.
2011-09-20 11:02:53 +02:00
|
|
|
" break;\n\n", N+N, N+N, N+N, N+N);
|
2005-07-23 12:43:03 +02:00
|
|
|
}
|
|
|
|
|
2011-09-20 11:36:41 +02:00
|
|
|
printf("}\n}\n\n#endif /* TFM_SMALL_SET */\n");
|
2005-07-23 12:43:03 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* $Source$ */
|
|
|
|
/* $Revision$ */
|
|
|
|
/* $Date$ */
|