summaryrefslogtreecommitdiffstats
path: root/libtommath/bn_mp_mul.c
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2019-06-14 21:48:00 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2019-06-14 21:48:00 (GMT)
commit15e17d01d57f28aa3ccb9adcc344937c4b5a34e0 (patch)
tree80050a4af1fcd9e60dbc7cf57462a7ed505974c9 /libtommath/bn_mp_mul.c
parente69d76af16939ec4327b1793f8a2cb358a141972 (diff)
parentdb7fa65dce753b80d5f2a87799aabd481e9144a2 (diff)
downloadtcl-15e17d01d57f28aa3ccb9adcc344937c4b5a34e0.zip
tcl-15e17d01d57f28aa3ccb9adcc344937c4b5a34e0.tar.gz
tcl-15e17d01d57f28aa3ccb9adcc344937c4b5a34e0.tar.bz2
Latest libtommath's "develop" branch adapted for Tcl 8.6. And Tcl 8.6 adapted for changes in libtommath
Diffstat (limited to 'libtommath/bn_mp_mul.c')
-rw-r--r--libtommath/bn_mp_mul.c84
1 files changed, 53 insertions, 31 deletions
diff --git a/libtommath/bn_mp_mul.c b/libtommath/bn_mp_mul.c
index f83b1b7..f0ca04a 100644
--- a/libtommath/bn_mp_mul.c
+++ b/libtommath/bn_mp_mul.c
@@ -1,33 +1,59 @@
#include "tommath_private.h"
#ifdef BN_MP_MUL_C
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * SPDX-License-Identifier: Unlicense
- */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
/* high level multiplication (handles sign) */
-int mp_mul(const mp_int *a, const mp_int *b, mp_int *c)
+mp_err mp_mul(const mp_int *a, const mp_int *b, mp_int *c)
{
- int res, neg;
+ mp_err err;
+ mp_sign neg;
+#ifdef BN_S_MP_BALANCE_MUL_C
+ int len_b, len_a;
+#endif
neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
+#ifdef BN_S_MP_BALANCE_MUL_C
+ len_a = a->used;
+ len_b = b->used;
+
+ if (len_a == len_b) {
+ goto GO_ON;
+ }
+ /*
+ * Check sizes. The smaller one needs to be larger than the Karatsuba cut-off.
+ * The bigger one needs to be at least about one KARATSUBA_MUL_CUTOFF bigger
+ * to make some sense, but it depends on architecture, OS, position of the
+ * stars... so YMMV.
+ * Using it to cut the input into slices small enough for fast_s_mp_mul_digs
+ * was actually slower on the author's machine, but YMMV.
+ */
+ if ((MP_MIN(len_a, len_b) < MP_KARATSUBA_MUL_CUTOFF)
+ || ((MP_MAX(len_a, len_b) / 2) < MP_KARATSUBA_MUL_CUTOFF)) {
+ goto GO_ON;
+ }
+ /*
+ * Not much effect was observed below a ratio of 1:2, but again: YMMV.
+ */
+ if ((MP_MAX(len_a, len_b) / MP_MIN(len_a, len_b)) < 2) {
+ goto GO_ON;
+ }
+
+ err = s_mp_balance_mul(a,b,c);
+ goto END;
+
+GO_ON:
+#endif
/* use Toom-Cook? */
-#ifdef BN_MP_TOOM_MUL_C
- if (MIN(a->used, b->used) >= TOOM_MUL_CUTOFF) {
- res = mp_toom_mul(a, b, c);
+#ifdef BN_S_MP_TOOM_MUL_C
+ if (MP_MIN(a->used, b->used) >= MP_TOOM_MUL_CUTOFF) {
+ err = s_mp_toom_mul(a, b, c);
} else
#endif
-#ifdef BN_MP_KARATSUBA_MUL_C
+#ifdef BN_S_MP_KARATSUBA_MUL_C
/* use Karatsuba? */
- if (MIN(a->used, b->used) >= KARATSUBA_MUL_CUTOFF) {
- res = mp_karatsuba_mul(a, b, c);
+ if (MP_MIN(a->used, b->used) >= MP_KARATSUBA_MUL_CUTOFF) {
+ err = s_mp_karatsuba_mul(a, b, c);
} else
#endif
{
@@ -39,26 +65,22 @@ int mp_mul(const mp_int *a, const mp_int *b, mp_int *c)
*/
int digs = a->used + b->used + 1;
-#ifdef BN_FAST_S_MP_MUL_DIGS_C
- if ((digs < (int)MP_WARRAY) &&
- (MIN(a->used, b->used) <=
- (int)(1u << (((size_t)CHAR_BIT * sizeof(mp_word)) - (2u * (size_t)DIGIT_BIT))))) {
- res = fast_s_mp_mul_digs(a, b, c, digs);
+#ifdef BN_S_MP_MUL_DIGS_FAST_C
+ if ((digs < MP_WARRAY) &&
+ (MP_MIN(a->used, b->used) <= MP_MAXFAST)) {
+ err = s_mp_mul_digs_fast(a, b, c, digs);
} else
#endif
{
#ifdef BN_S_MP_MUL_DIGS_C
- res = s_mp_mul(a, b, c); /* uses s_mp_mul_digs */
+ err = s_mp_mul_digs(a, b, c, a->used + b->used + 1);
#else
- res = MP_VAL;
+ err = MP_VAL;
#endif
}
}
+END:
c->sign = (c->used > 0) ? neg : MP_ZPOS;
- return res;
+ return err;
}
#endif
-
-/* ref: $Format:%D$ */
-/* git commit: $Format:%H$ */
-/* commit time: $Format:%ai$ */