2018-05-02 19:43:17 +00:00
|
|
|
#include "tommath_private.h"
|
2019-10-19 14:24:39 +00:00
|
|
|
#ifdef S_MP_TOOM_SQR_C
|
2019-04-07 13:29:11 +00:00
|
|
|
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
|
|
|
|
/* SPDX-License-Identifier: Unlicense */
|
2003-08-05 01:24:44 +00:00
|
|
|
|
|
|
|
/* squaring using Toom-Cook 3-way algorithm */
|
2019-05-16 21:51:02 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
This file contains code from J. Arndt's book "Matters Computational"
|
|
|
|
and the accompanying FXT-library with permission of the author.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* squaring using Toom-Cook 3-way algorithm */
|
|
|
|
/*
|
|
|
|
Setup and interpolation from algorithm SQR_3 in
|
|
|
|
|
|
|
|
Chung, Jaewook, and M. Anwar Hasan. "Asymmetric squaring formulae."
|
|
|
|
18th IEEE Symposium on Computer Arithmetic (ARITH'07). IEEE, 2007.
|
|
|
|
|
|
|
|
*/
|
2019-05-12 22:22:18 +00:00
|
|
|
mp_err s_mp_toom_sqr(const mp_int *a, mp_int *b)
|
2003-08-05 01:24:44 +00:00
|
|
|
{
|
2019-05-16 21:51:02 +00:00
|
|
|
mp_int S0, a0, a1, a2;
|
|
|
|
mp_digit *tmpa, *tmpc;
|
2019-10-19 15:14:46 +00:00
|
|
|
int B, count;
|
|
|
|
mp_err err;
|
2019-05-16 21:51:02 +00:00
|
|
|
|
2017-08-30 17:15:27 +00:00
|
|
|
|
|
|
|
/* init temps */
|
2019-05-16 21:51:02 +00:00
|
|
|
if ((err = mp_init(&S0)) != MP_OKAY) {
|
2019-05-19 15:16:13 +00:00
|
|
|
return err;
|
2017-08-30 17:15:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* B */
|
|
|
|
B = a->used / 3;
|
|
|
|
|
2019-05-16 21:51:02 +00:00
|
|
|
/** a = a2 * x^2 + a1 * x + a0; */
|
2019-09-04 06:40:39 +00:00
|
|
|
if ((err = mp_init_size(&a0, B)) != MP_OKAY) goto LBL_ERRa0;
|
|
|
|
|
2019-05-16 21:51:02 +00:00
|
|
|
a0.used = B;
|
2019-09-04 06:40:39 +00:00
|
|
|
if ((err = mp_init_size(&a1, B)) != MP_OKAY) goto LBL_ERRa1;
|
2019-05-16 21:51:02 +00:00
|
|
|
a1.used = B;
|
2019-09-04 06:40:39 +00:00
|
|
|
if ((err = mp_init_size(&a2, B + (a->used - (3 * B)))) != MP_OKAY) goto LBL_ERRa2;
|
|
|
|
|
2019-05-16 21:51:02 +00:00
|
|
|
tmpa = a->dp;
|
|
|
|
tmpc = a0.dp;
|
|
|
|
for (count = 0; count < B; count++) {
|
|
|
|
*tmpc++ = *tmpa++;
|
2017-08-30 17:15:27 +00:00
|
|
|
}
|
2019-05-16 21:51:02 +00:00
|
|
|
tmpc = a1.dp;
|
|
|
|
for (; count < (2 * B); count++) {
|
|
|
|
*tmpc++ = *tmpa++;
|
2017-08-30 17:15:27 +00:00
|
|
|
}
|
2019-05-16 21:51:02 +00:00
|
|
|
tmpc = a2.dp;
|
|
|
|
for (; count < a->used; count++) {
|
|
|
|
*tmpc++ = *tmpa++;
|
|
|
|
a2.used++;
|
2017-08-30 17:15:27 +00:00
|
|
|
}
|
2019-05-16 21:51:02 +00:00
|
|
|
mp_clamp(&a0);
|
|
|
|
mp_clamp(&a1);
|
2019-10-02 03:47:04 +00:00
|
|
|
mp_clamp(&a2);
|
2017-08-30 17:15:27 +00:00
|
|
|
|
2019-05-16 21:51:02 +00:00
|
|
|
/** S0 = a0^2; */
|
2019-09-04 06:40:39 +00:00
|
|
|
if ((err = mp_sqr(&a0, &S0)) != MP_OKAY) goto LBL_ERR;
|
|
|
|
|
2019-05-16 21:51:02 +00:00
|
|
|
/** \\S1 = (a2 + a1 + a0)^2 */
|
|
|
|
/** \\S2 = (a2 - a1 + a0)^2 */
|
|
|
|
/** \\S1 = a0 + a2; */
|
|
|
|
/** a0 = a0 + a2; */
|
2019-09-04 06:40:39 +00:00
|
|
|
if ((err = mp_add(&a0, &a2, &a0)) != MP_OKAY) goto LBL_ERR;
|
2019-05-16 21:51:02 +00:00
|
|
|
/** \\S2 = S1 - a1; */
|
|
|
|
/** b = a0 - a1; */
|
2019-09-04 06:40:39 +00:00
|
|
|
if ((err = mp_sub(&a0, &a1, b)) != MP_OKAY) goto LBL_ERR;
|
2019-05-16 21:51:02 +00:00
|
|
|
/** \\S1 = S1 + a1; */
|
|
|
|
/** a0 = a0 + a1; */
|
2019-09-04 06:40:39 +00:00
|
|
|
if ((err = mp_add(&a0, &a1, &a0)) != MP_OKAY) goto LBL_ERR;
|
2019-05-16 21:51:02 +00:00
|
|
|
/** \\S1 = S1^2; */
|
|
|
|
/** a0 = a0^2; */
|
2019-09-04 06:40:39 +00:00
|
|
|
if ((err = mp_sqr(&a0, &a0)) != MP_OKAY) goto LBL_ERR;
|
2019-05-16 21:51:02 +00:00
|
|
|
/** \\S2 = S2^2; */
|
|
|
|
/** b = b^2; */
|
2019-09-04 06:40:39 +00:00
|
|
|
if ((err = mp_sqr(b, b)) != MP_OKAY) goto LBL_ERR;
|
2017-08-30 17:15:27 +00:00
|
|
|
|
2019-05-16 21:51:02 +00:00
|
|
|
/** \\ S3 = 2 * a1 * a2 */
|
|
|
|
/** \\S3 = a1 * a2; */
|
|
|
|
/** a1 = a1 * a2; */
|
2019-09-04 06:40:39 +00:00
|
|
|
if ((err = mp_mul(&a1, &a2, &a1)) != MP_OKAY) goto LBL_ERR;
|
2019-05-16 21:51:02 +00:00
|
|
|
/** \\S3 = S3 << 1; */
|
|
|
|
/** a1 = a1 << 1; */
|
2019-09-04 06:40:39 +00:00
|
|
|
if ((err = mp_mul_2(&a1, &a1)) != MP_OKAY) goto LBL_ERR;
|
2019-05-16 21:51:02 +00:00
|
|
|
|
|
|
|
/** \\S4 = a2^2; */
|
|
|
|
/** a2 = a2^2; */
|
2019-09-04 06:40:39 +00:00
|
|
|
if ((err = mp_sqr(&a2, &a2)) != MP_OKAY) goto LBL_ERR;
|
2019-05-16 21:51:02 +00:00
|
|
|
|
|
|
|
/** \\ tmp = (S1 + S2)/2 */
|
|
|
|
/** \\tmp = S1 + S2; */
|
|
|
|
/** b = a0 + b; */
|
2019-09-04 06:40:39 +00:00
|
|
|
if ((err = mp_add(&a0, b, b)) != MP_OKAY) goto LBL_ERR;
|
2019-05-16 21:51:02 +00:00
|
|
|
/** \\tmp = tmp >> 1; */
|
|
|
|
/** b = b >> 1; */
|
2019-09-04 06:40:39 +00:00
|
|
|
if ((err = mp_div_2(b, b)) != MP_OKAY) goto LBL_ERR;
|
2017-08-30 17:15:27 +00:00
|
|
|
|
2019-05-16 21:51:02 +00:00
|
|
|
/** \\ S1 = S1 - tmp - S3 */
|
|
|
|
/** \\S1 = S1 - tmp; */
|
|
|
|
/** a0 = a0 - b; */
|
2019-09-04 06:40:39 +00:00
|
|
|
if ((err = mp_sub(&a0, b, &a0)) != MP_OKAY) goto LBL_ERR;
|
2019-05-16 21:51:02 +00:00
|
|
|
/** \\S1 = S1 - S3; */
|
|
|
|
/** a0 = a0 - a1; */
|
2019-09-04 06:40:39 +00:00
|
|
|
if ((err = mp_sub(&a0, &a1, &a0)) != MP_OKAY) goto LBL_ERR;
|
2019-05-16 21:51:02 +00:00
|
|
|
|
|
|
|
/** \\S2 = tmp - S4 -S0 */
|
|
|
|
/** \\S2 = tmp - S4; */
|
|
|
|
/** b = b - a2; */
|
2019-09-04 06:40:39 +00:00
|
|
|
if ((err = mp_sub(b, &a2, b)) != MP_OKAY) goto LBL_ERR;
|
2019-05-16 21:51:02 +00:00
|
|
|
/** \\S2 = S2 - S0; */
|
|
|
|
/** b = b - S0; */
|
2019-09-04 06:40:39 +00:00
|
|
|
if ((err = mp_sub(b, &S0, b)) != MP_OKAY) goto LBL_ERR;
|
2017-08-30 17:15:27 +00:00
|
|
|
|
|
|
|
|
2019-05-16 21:51:02 +00:00
|
|
|
/** \\P = S4*x^4 + S3*x^3 + S2*x^2 + S1*x + S0; */
|
|
|
|
/** P = a2*x^4 + a1*x^3 + b*x^2 + a0*x + S0; */
|
2017-08-30 17:15:27 +00:00
|
|
|
|
2019-09-04 06:40:39 +00:00
|
|
|
if ((err = mp_lshd(&a2, 4 * B)) != MP_OKAY) goto LBL_ERR;
|
|
|
|
if ((err = mp_lshd(&a1, 3 * B)) != MP_OKAY) goto LBL_ERR;
|
|
|
|
if ((err = mp_lshd(b, 2 * B)) != MP_OKAY) goto LBL_ERR;
|
|
|
|
if ((err = mp_lshd(&a0, 1 * B)) != MP_OKAY) goto LBL_ERR;
|
|
|
|
if ((err = mp_add(&a2, &a1, &a2)) != MP_OKAY) goto LBL_ERR;
|
|
|
|
if ((err = mp_add(&a2, b, b)) != MP_OKAY) goto LBL_ERR;
|
|
|
|
if ((err = mp_add(b, &a0, b)) != MP_OKAY) goto LBL_ERR;
|
|
|
|
if ((err = mp_add(b, &S0, b)) != MP_OKAY) goto LBL_ERR;
|
2019-05-16 21:51:02 +00:00
|
|
|
/** a^2 - P */
|
2017-08-30 17:15:27 +00:00
|
|
|
|
|
|
|
|
2019-09-03 03:51:56 +00:00
|
|
|
LBL_ERR:
|
2019-05-16 21:51:02 +00:00
|
|
|
mp_clear(&a2);
|
2019-09-03 03:51:56 +00:00
|
|
|
LBL_ERRa2:
|
2019-05-16 21:51:02 +00:00
|
|
|
mp_clear(&a1);
|
2019-09-03 03:51:56 +00:00
|
|
|
LBL_ERRa1:
|
2019-05-16 21:51:02 +00:00
|
|
|
mp_clear(&a0);
|
2019-09-03 03:51:56 +00:00
|
|
|
LBL_ERRa0:
|
2019-05-16 21:51:02 +00:00
|
|
|
mp_clear(&S0);
|
2003-09-19 22:43:07 +00:00
|
|
|
|
2019-05-19 15:16:13 +00:00
|
|
|
return err;
|
2003-09-19 22:43:07 +00:00
|
|
|
}
|
|
|
|
|
2004-10-29 22:07:18 +00:00
|
|
|
#endif
|