123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081 |
- #include "tommath_private.h"
- #ifdef BN_S_MP_BALANCE_MUL_C
- /* LibTomMath, multiple-precision integer library -- Tom St Denis */
- /* SPDX-License-Identifier: Unlicense */
- /* single-digit multiplication with the smaller number as the single-digit */
- mp_err s_mp_balance_mul(const mp_int *a, const mp_int *b, mp_int *c)
- {
- int count, len_a, len_b, nblocks, i, j, bsize;
- mp_int a0, tmp, A, B, r;
- mp_err err;
- len_a = a->used;
- len_b = b->used;
- nblocks = MP_MAX(a->used, b->used) / MP_MIN(a->used, b->used);
- bsize = MP_MIN(a->used, b->used) ;
- if ((err = mp_init_size(&a0, bsize + 2)) != MP_OKAY) {
- return err;
- }
- if ((err = mp_init_multi(&tmp, &r, NULL)) != MP_OKAY) {
- mp_clear(&a0);
- return err;
- }
- /* Make sure that A is the larger one*/
- if (len_a < len_b) {
- B = *a;
- A = *b;
- } else {
- A = *a;
- B = *b;
- }
- for (i = 0, j=0; i < nblocks; i++) {
- /* Cut a slice off of a */
- a0.used = 0;
- for (count = 0; count < bsize; count++) {
- a0.dp[count] = A.dp[ j++ ];
- a0.used++;
- }
- mp_clamp(&a0);
- /* Multiply with b */
- if ((err = mp_mul(&a0, &B, &tmp)) != MP_OKAY) {
- goto LBL_ERR;
- }
- /* Shift tmp to the correct position */
- if ((err = mp_lshd(&tmp, bsize * i)) != MP_OKAY) {
- goto LBL_ERR;
- }
- /* Add to output. No carry needed */
- if ((err = mp_add(&r, &tmp, &r)) != MP_OKAY) {
- goto LBL_ERR;
- }
- }
- /* The left-overs; there are always left-overs */
- if (j < A.used) {
- a0.used = 0;
- for (count = 0; j < A.used; count++) {
- a0.dp[count] = A.dp[ j++ ];
- a0.used++;
- }
- mp_clamp(&a0);
- if ((err = mp_mul(&a0, &B, &tmp)) != MP_OKAY) {
- goto LBL_ERR;
- }
- if ((err = mp_lshd(&tmp, bsize * i)) != MP_OKAY) {
- goto LBL_ERR;
- }
- if ((err = mp_add(&r, &tmp, &r)) != MP_OKAY) {
- goto LBL_ERR;
- }
- }
- mp_exch(&r,c);
- LBL_ERR:
- mp_clear_multi(&a0, &tmp, &r,NULL);
- return err;
- }
- #endif
|