summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorNiels Möller <nisse@lysator.liu.se>2011-10-03 13:07:18 +0200
committerNiels Möller <nisse@lysator.liu.se>2011-10-03 13:07:18 +0200
commitab5d3c7f9553c3a3058813b7076d061794a57b33 (patch)
treeec6d7e8bc1bdd4ea213266eb5b0137a893276e6e /tests
parentbd0cba9593c4093444dd52aa65070c48366a8827 (diff)
downloadgmp-ab5d3c7f9553c3a3058813b7076d061794a57b33.tar.gz
mulmid testing.
Diffstat (limited to 'tests')
-rw-r--r--tests/devel/try.c171
-rw-r--r--tests/refmpn.c226
-rw-r--r--tests/tests.h27
3 files changed, 397 insertions, 27 deletions
diff --git a/tests/devel/try.c b/tests/devel/try.c
index caca7b9e1..5619ec26d 100644
--- a/tests/devel/try.c
+++ b/tests/devel/try.c
@@ -240,7 +240,7 @@ struct region_t {
int trap_location = TRAP_NOWHERE;
-#define NUM_SOURCES 2
+#define NUM_SOURCES 5
#define NUM_DESTS 2
struct source_t {
@@ -302,32 +302,36 @@ typedef mp_limb_t (*tryfun_t) __GMP_PROTO ((ANYARGS));
struct try_t {
char retval;
- char src[2];
- char dst[2];
+ char src[NUM_SOURCES];
+ char dst[NUM_DESTS];
#define SIZE_YES 1
#define SIZE_ALLOW_ZERO 2
#define SIZE_1 3 /* 1 limb */
#define SIZE_2 4 /* 2 limbs */
#define SIZE_3 5 /* 3 limbs */
-#define SIZE_FRACTION 6 /* size2 is fraction for divrem etc */
-#define SIZE_SIZE2 7
-#define SIZE_PLUS_1 8
-#define SIZE_SUM 9
-#define SIZE_DIFF 10
-#define SIZE_DIFF_PLUS_1 11
-#define SIZE_RETVAL 12
-#define SIZE_CEIL_HALF 13
-#define SIZE_GET_STR 14
-#define SIZE_PLUS_MSIZE_SUB_1 15 /* size+msize-1 */
+#define SIZE_4 6 /* 4 limbs */
+#define SIZE_6 7 /* 6 limbs */
+#define SIZE_FRACTION 8 /* size2 is fraction for divrem etc */
+#define SIZE_SIZE2 9
+#define SIZE_PLUS_1 10
+#define SIZE_SUM 11
+#define SIZE_DIFF 12
+#define SIZE_DIFF_PLUS_1 13
+#define SIZE_DIFF_PLUS_3 14
+#define SIZE_RETVAL 15
+#define SIZE_CEIL_HALF 16
+#define SIZE_GET_STR 17
+#define SIZE_PLUS_MSIZE_SUB_1 18 /* size+msize-1 */
+#define SIZE_ODD 19
char size;
char size2;
- char dst_size[2];
+ char dst_size[NUM_DESTS];
/* multiplier_N size in limbs */
mp_size_t msize;
- char dst_bytes[2];
+ char dst_bytes[NUM_DESTS];
char dst0_from_src1;
@@ -366,6 +370,7 @@ struct try_t {
#define OVERLAP_HIGH_TO_LOW 3
#define OVERLAP_NOT_SRCS 4
#define OVERLAP_NOT_SRC2 8
+#define OVERLAP_NOT_DST2 16
char overlap;
tryfun_t reference;
@@ -587,6 +592,9 @@ validate_sqrtrem (void)
enum {
TYPE_ADD = 1, TYPE_ADD_N, TYPE_ADD_NC, TYPE_SUB, TYPE_SUB_N, TYPE_SUB_NC,
+ TYPE_ADD_ERR1_N, TYPE_ADD_ERR2_N, TYPE_ADD_ERR3_N,
+ TYPE_SUB_ERR1_N, TYPE_SUB_ERR2_N, TYPE_SUB_ERR3_N,
+
TYPE_MUL_1, TYPE_MUL_1C,
TYPE_MUL_2, TYPE_MUL_3, TYPE_MUL_4, TYPE_MUL_5, TYPE_MUL_6,
@@ -631,7 +639,7 @@ enum {
TYPE_XOR_N, TYPE_XNOR_N,
TYPE_MUL_MN, TYPE_MUL_N, TYPE_SQR, TYPE_UMUL_PPMM, TYPE_UMUL_PPMM_R,
- TYPE_MULLO_N,
+ TYPE_MULLO_N, TYPE_MULMID_MN, TYPE_MULMID_N,
TYPE_SBPI1_DIV_QR, TYPE_TDIV_QR,
@@ -698,6 +706,43 @@ param_init (void)
REFERENCE (refmpn_sub);
+ p = &param[TYPE_ADD_ERR1_N];
+ p->retval = 1;
+ p->dst[0] = 1;
+ p->dst[1] = 1;
+ p->src[0] = 1;
+ p->src[1] = 1;
+ p->src[2] = 1;
+ p->dst_size[1] = SIZE_2;
+ p->carry = CARRY_BIT;
+ p->overlap = OVERLAP_NOT_DST2;
+ REFERENCE (refmpn_add_err1_n);
+
+ p = &param[TYPE_SUB_ERR1_N];
+ COPY (TYPE_ADD_ERR1_N);
+ REFERENCE (refmpn_sub_err1_n);
+
+ p = &param[TYPE_ADD_ERR2_N];
+ COPY (TYPE_ADD_ERR1_N);
+ p->src[3] = 1;
+ p->dst_size[1] = SIZE_4;
+ REFERENCE (refmpn_add_err2_n);
+
+ p = &param[TYPE_SUB_ERR2_N];
+ COPY (TYPE_ADD_ERR2_N);
+ REFERENCE (refmpn_sub_err2_n);
+
+ p = &param[TYPE_ADD_ERR3_N];
+ COPY (TYPE_ADD_ERR2_N);
+ p->src[4] = 1;
+ p->dst_size[1] = SIZE_6;
+ REFERENCE (refmpn_add_err3_n);
+
+ p = &param[TYPE_SUB_ERR3_N];
+ COPY (TYPE_ADD_ERR3_N);
+ REFERENCE (refmpn_sub_err3_n);
+
+
p = &param[TYPE_MUL_1];
p->retval = 1;
p->dst[0] = 1;
@@ -1210,6 +1255,18 @@ param_init (void)
p->size2 = 1;
REFERENCE (refmpn_mul_basecase);
+ p = &param[TYPE_MULMID_MN];
+ COPY (TYPE_MUL_MN);
+ p->dst_size[0] = SIZE_DIFF_PLUS_3;
+ REFERENCE (refmpn_mulmid_basecase);
+
+ p = &param[TYPE_MULMID_N];
+ COPY (TYPE_MUL_N);
+ p->size = SIZE_ODD;
+ p->size2 = SIZE_CEIL_HALF;
+ p->dst_size[0] = SIZE_DIFF_PLUS_3;
+ REFERENCE (refmpn_mulmid_n);
+
p = &param[TYPE_UMUL_PPMM];
p->retval = 1;
p->src[0] = 1;
@@ -1529,6 +1586,19 @@ mpn_toom4_sqr_fun (mp_ptr dst, mp_srcptr src, mp_size_t size)
TMP_FREE;
}
+void
+mpn_toom42_mulmid_fun (mp_ptr dst, mp_srcptr src1, mp_srcptr src2,
+ mp_size_t size)
+{
+ mp_ptr tspace;
+ mp_size_t n;
+ TMP_DECL;
+ TMP_MARK;
+ tspace = TMP_ALLOC_LIMBS (mpn_toom42_mulmid_itch (size));
+ mpn_toom42_mulmid (dst, src1, src2, size, tspace);
+ TMP_FREE;
+}
+
mp_limb_t
umul_ppmm_fun (mp_limb_t *lowptr, mp_limb_t m1, mp_limb_t m2)
{
@@ -1578,6 +1648,13 @@ const struct choice_t choice_array[] = {
{ TRY(mpn_add_n_sub_nc), TYPE_ADDSUB_NC },
#endif
+ { TRY(mpn_add_err1_n), TYPE_ADD_ERR1_N },
+ { TRY(mpn_sub_err1_n), TYPE_SUB_ERR1_N },
+ { TRY(mpn_add_err2_n), TYPE_ADD_ERR2_N },
+ { TRY(mpn_sub_err2_n), TYPE_SUB_ERR2_N },
+ { TRY(mpn_add_err3_n), TYPE_ADD_ERR3_N },
+ { TRY(mpn_sub_err3_n), TYPE_SUB_ERR3_N },
+
{ TRY(mpn_addmul_1), TYPE_ADDMUL_1 },
{ TRY(mpn_submul_1), TYPE_SUBMUL_1 },
#if HAVE_NATIVE_mpn_addmul_1c
@@ -1789,6 +1866,7 @@ const struct choice_t choice_array[] = {
{ TRY(mpn_mul_basecase), TYPE_MUL_MN },
+ { TRY(mpn_mulmid_basecase), TYPE_MULMID_MN },
{ TRY(mpn_mullo_basecase), TYPE_MULLO_N },
#if SQR_TOOM2_THRESHOLD > 0
{ TRY(mpn_sqr_basecase), TYPE_SQR },
@@ -1813,6 +1891,11 @@ const struct choice_t choice_array[] = {
{ TRY_FUNFUN(mpn_toom44_mul), TYPE_MUL_N, MPN_TOOM44_MUL_MINSIZE },
{ TRY_FUNFUN(mpn_toom4_sqr), TYPE_SQR, MPN_TOOM4_SQR_MINSIZE },
+ { TRY(mpn_mulmid_n), TYPE_MULMID_N, 1 },
+ { TRY(mpn_mulmid), TYPE_MULMID_MN, 1 },
+ { TRY_FUNFUN(mpn_toom42_mulmid), TYPE_MULMID_N,
+ (2 * MPN_TOOM42_MULMID_MINSIZE - 1) },
+
{ TRY(mpn_gcd_1), TYPE_GCD_1 },
{ TRY(mpn_gcd), TYPE_GCD },
{ TRY(mpz_legendre), TYPE_MPZ_LEGENDRE },
@@ -2032,15 +2115,15 @@ int divisor_index;
struct overlap_t {
int s[NUM_SOURCES];
} overlap_array[] = {
- { { -1, -1 } },
- { { 0, -1 } },
- { { -1, 0 } },
- { { 0, 0 } },
- { { 1, -1 } },
- { { -1, 1 } },
- { { 1, 1 } },
- { { 0, 1 } },
- { { 1, 0 } },
+ { { -1, -1, -1, -1, -1 } },
+ { { 0, -1, -1, -1, -1 } },
+ { { -1, 0, -1, -1, -1 } },
+ { { 0, 0, -1, -1, -1 } },
+ { { 1, -1, -1, -1, -1 } },
+ { { -1, 1, -1, -1, -1 } },
+ { { 1, 1, -1, -1, -1 } },
+ { { 0, 1, -1, -1, -1 } },
+ { { 1, 0, -1, -1, -1 } },
};
struct overlap_t *overlap, *overlap_limit;
@@ -2049,6 +2132,7 @@ struct overlap_t *overlap, *overlap_limit;
(tr->overlap & OVERLAP_NONE ? 1 \
: tr->overlap & OVERLAP_NOT_SRCS ? 3 \
: tr->overlap & OVERLAP_NOT_SRC2 ? 2 \
+ : tr->overlap & OVERLAP_NOT_DST2 ? 4 \
: tr->dst[1] ? 9 \
: tr->src[1] ? 4 \
: tr->dst[0] ? 2 \
@@ -2314,6 +2398,21 @@ call (struct each_t *e, tryfun_t function)
e->retval = CALLING_CONVENTIONS (function)
(e->d[0].p, e->s[0].p, e->s[1].p, size, carry);
break;
+ case TYPE_ADD_ERR1_N:
+ case TYPE_SUB_ERR1_N:
+ e->retval = CALLING_CONVENTIONS (function)
+ (e->d[0].p, e->s[0].p, e->s[1].p, e->d[1].p, e->s[2].p, size, carry);
+ break;
+ case TYPE_ADD_ERR2_N:
+ case TYPE_SUB_ERR2_N:
+ e->retval = CALLING_CONVENTIONS (function)
+ (e->d[0].p, e->s[0].p, e->s[1].p, e->d[1].p, e->s[2].p, e->s[3].p, size, carry);
+ break;
+ case TYPE_ADD_ERR3_N:
+ case TYPE_SUB_ERR3_N:
+ e->retval = CALLING_CONVENTIONS (function)
+ (e->d[0].p, e->s[0].p, e->s[1].p, e->d[1].p, e->s[2].p, e->s[3].p, e->s[4].p, size, carry);
+ break;
case TYPE_MUL_1:
case TYPE_ADDMUL_1:
@@ -2556,6 +2655,7 @@ call (struct each_t *e, tryfun_t function)
break;
case TYPE_MUL_MN:
+ case TYPE_MULMID_MN:
CALLING_CONVENTIONS (function)
(e->d[0].p, e->s[0].p, size, e->s[1].p, size2);
break;
@@ -2563,6 +2663,10 @@ call (struct each_t *e, tryfun_t function)
case TYPE_MULLO_N:
CALLING_CONVENTIONS (function) (e->d[0].p, e->s[0].p, e->s[1].p, size);
break;
+ case TYPE_MULMID_N:
+ CALLING_CONVENTIONS (function) (e->d[0].p, e->s[0].p, e->s[1].p,
+ (size + 1) / 2);
+ break;
case TYPE_SQR:
CALLING_CONVENTIONS (function) (e->d[0].p, e->s[0].p, size);
break;
@@ -2691,6 +2795,12 @@ pointer_setup (struct each_t *e)
case SIZE_3:
d[i].size = 3;
break;
+ case SIZE_4:
+ d[i].size = 4;
+ break;
+ case SIZE_6:
+ d[i].size = 6;
+ break;
case SIZE_PLUS_1:
d[i].size = size+1;
@@ -2718,6 +2828,10 @@ pointer_setup (struct each_t *e)
d[i].size = size - size2 + 1;
break;
+ case SIZE_DIFF_PLUS_3:
+ d[i].size = size - size2 + 3;
+ break;
+
case SIZE_CEIL_HALF:
d[i].size = (size+1)/2;
break;
@@ -3027,13 +3141,15 @@ try_one (void)
#define SIZE_ITERATION \
for (size = MAX3 (option_firstsize, \
choice->minsize, \
- (tr->size == SIZE_ALLOW_ZERO) ? 0 : 1); \
+ (tr->size == SIZE_ALLOW_ZERO) ? 0 : 1), \
+ size += (tr->size == SIZE_ODD) && !(size & 1); \
size <= option_lastsize; \
- size++)
+ size += (tr->size == SIZE_ODD) ? 2 : 1)
#define SIZE2_FIRST \
(tr->size2 == SIZE_2 ? 2 \
: tr->size2 == SIZE_FRACTION ? option_firstsize2 \
+ : tr->size2 == SIZE_CEIL_HALF ? ((size + 1) / 2) \
: tr->size2 ? \
MAX (choice->minsize, (option_firstsize2 != 0 \
? option_firstsize2 : 1)) \
@@ -3042,6 +3158,7 @@ try_one (void)
#define SIZE2_LAST \
(tr->size2 == SIZE_2 ? 2 \
: tr->size2 == SIZE_FRACTION ? FRACTION_COUNT-1 \
+ : tr->size2 == SIZE_CEIL_HALF ? ((size + 1) / 2) \
: tr->size2 ? size \
: 0)
diff --git a/tests/refmpn.c b/tests/refmpn.c
index 876ca078a..fbcc602d6 100644
--- a/tests/refmpn.c
+++ b/tests/refmpn.c
@@ -596,6 +596,178 @@ refmpn_sub_n (mp_ptr rp, mp_srcptr s1p, mp_srcptr s2p, mp_size_t size)
return refmpn_sub_nc (rp, s1p, s2p, size, CNST_LIMB(0));
}
+
+#define AORS_ERR1_N(operation) \
+ { \
+ mp_size_t i; \
+ mp_limb_t carry2; \
+ \
+ ASSERT (refmpn_overlap_fullonly_p (rp, s1p, size)); \
+ ASSERT (refmpn_overlap_fullonly_p (rp, s2p, size)); \
+ ASSERT (! refmpn_overlap_p (rp, size, yp, size)); \
+ ASSERT (! refmpn_overlap_p (ep, 2, s1p, size)); \
+ ASSERT (! refmpn_overlap_p (ep, 2, s2p, size)); \
+ ASSERT (! refmpn_overlap_p (ep, 2, yp, size)); \
+ ASSERT (! refmpn_overlap_p (ep, 2, rp, size)); \
+ \
+ ASSERT (carry == 0 || carry == 1); \
+ ASSERT (size >= 1); \
+ ASSERT_MPN (s1p, size); \
+ ASSERT_MPN (s2p, size); \
+ ASSERT_MPN (yp, size); \
+ \
+ ep[0] = ep[1] = CNST_LIMB(0); \
+ \
+ for (i = 0; i < size; i++) \
+ { \
+ carry = operation (&rp[i], s1p[i], s2p[i], carry); \
+ if (carry == 1) \
+ { \
+ carry2 = ref_addc_limb (&ep[0], ep[0], yp[size - 1 - i]); \
+ carry2 = ref_addc_limb (&ep[1], ep[1], carry2); \
+ ASSERT (carry2 == 0); \
+ } \
+ } \
+ return carry; \
+ }
+
+mp_limb_t
+refmpn_add_err1_n (mp_ptr rp, mp_srcptr s1p, mp_srcptr s2p,
+ mp_ptr ep, mp_srcptr yp,
+ mp_size_t size, mp_limb_t carry)
+{
+ AORS_ERR1_N (adc);
+}
+mp_limb_t
+refmpn_sub_err1_n (mp_ptr rp, mp_srcptr s1p, mp_srcptr s2p,
+ mp_ptr ep, mp_srcptr yp,
+ mp_size_t size, mp_limb_t carry)
+{
+ AORS_ERR1_N (sbb);
+}
+
+
+#define AORS_ERR2_N(operation) \
+ { \
+ mp_size_t i; \
+ mp_limb_t carry2; \
+ \
+ ASSERT (refmpn_overlap_fullonly_p (rp, s1p, size)); \
+ ASSERT (refmpn_overlap_fullonly_p (rp, s2p, size)); \
+ ASSERT (! refmpn_overlap_p (rp, size, y1p, size)); \
+ ASSERT (! refmpn_overlap_p (rp, size, y2p, size)); \
+ ASSERT (! refmpn_overlap_p (ep, 4, s1p, size)); \
+ ASSERT (! refmpn_overlap_p (ep, 4, s2p, size)); \
+ ASSERT (! refmpn_overlap_p (ep, 4, y1p, size)); \
+ ASSERT (! refmpn_overlap_p (ep, 4, y2p, size)); \
+ ASSERT (! refmpn_overlap_p (ep, 4, rp, size)); \
+ \
+ ASSERT (carry == 0 || carry == 1); \
+ ASSERT (size >= 1); \
+ ASSERT_MPN (s1p, size); \
+ ASSERT_MPN (s2p, size); \
+ ASSERT_MPN (y1p, size); \
+ ASSERT_MPN (y2p, size); \
+ \
+ ep[0] = ep[1] = CNST_LIMB(0); \
+ ep[2] = ep[3] = CNST_LIMB(0); \
+ \
+ for (i = 0; i < size; i++) \
+ { \
+ carry = operation (&rp[i], s1p[i], s2p[i], carry); \
+ if (carry == 1) \
+ { \
+ carry2 = ref_addc_limb (&ep[0], ep[0], y1p[size - 1 - i]); \
+ carry2 = ref_addc_limb (&ep[1], ep[1], carry2); \
+ ASSERT (carry2 == 0); \
+ carry2 = ref_addc_limb (&ep[2], ep[2], y2p[size - 1 - i]); \
+ carry2 = ref_addc_limb (&ep[3], ep[3], carry2); \
+ ASSERT (carry2 == 0); \
+ } \
+ } \
+ return carry; \
+ }
+
+mp_limb_t
+refmpn_add_err2_n (mp_ptr rp, mp_srcptr s1p, mp_srcptr s2p,
+ mp_ptr ep, mp_srcptr y1p, mp_srcptr y2p,
+ mp_size_t size, mp_limb_t carry)
+{
+ AORS_ERR2_N (adc);
+}
+mp_limb_t
+refmpn_sub_err2_n (mp_ptr rp, mp_srcptr s1p, mp_srcptr s2p,
+ mp_ptr ep, mp_srcptr y1p, mp_srcptr y2p,
+ mp_size_t size, mp_limb_t carry)
+{
+ AORS_ERR2_N (sbb);
+}
+
+
+#define AORS_ERR3_N(operation) \
+ { \
+ mp_size_t i; \
+ mp_limb_t carry2; \
+ \
+ ASSERT (refmpn_overlap_fullonly_p (rp, s1p, size)); \
+ ASSERT (refmpn_overlap_fullonly_p (rp, s2p, size)); \
+ ASSERT (! refmpn_overlap_p (rp, size, y1p, size)); \
+ ASSERT (! refmpn_overlap_p (rp, size, y2p, size)); \
+ ASSERT (! refmpn_overlap_p (rp, size, y3p, size)); \
+ ASSERT (! refmpn_overlap_p (ep, 6, s1p, size)); \
+ ASSERT (! refmpn_overlap_p (ep, 6, s2p, size)); \
+ ASSERT (! refmpn_overlap_p (ep, 6, y1p, size)); \
+ ASSERT (! refmpn_overlap_p (ep, 6, y2p, size)); \
+ ASSERT (! refmpn_overlap_p (ep, 6, y3p, size)); \
+ ASSERT (! refmpn_overlap_p (ep, 6, rp, size)); \
+ \
+ ASSERT (carry == 0 || carry == 1); \
+ ASSERT (size >= 1); \
+ ASSERT_MPN (s1p, size); \
+ ASSERT_MPN (s2p, size); \
+ ASSERT_MPN (y1p, size); \
+ ASSERT_MPN (y2p, size); \
+ ASSERT_MPN (y3p, size); \
+ \
+ ep[0] = ep[1] = CNST_LIMB(0); \
+ ep[2] = ep[3] = CNST_LIMB(0); \
+ ep[4] = ep[5] = CNST_LIMB(0); \
+ \
+ for (i = 0; i < size; i++) \
+ { \
+ carry = operation (&rp[i], s1p[i], s2p[i], carry); \
+ if (carry == 1) \
+ { \
+ carry2 = ref_addc_limb (&ep[0], ep[0], y1p[size - 1 - i]); \
+ carry2 = ref_addc_limb (&ep[1], ep[1], carry2); \
+ ASSERT (carry2 == 0); \
+ carry2 = ref_addc_limb (&ep[2], ep[2], y2p[size - 1 - i]); \
+ carry2 = ref_addc_limb (&ep[3], ep[3], carry2); \
+ ASSERT (carry2 == 0); \
+ carry2 = ref_addc_limb (&ep[4], ep[4], y3p[size - 1 - i]); \
+ carry2 = ref_addc_limb (&ep[5], ep[5], carry2); \
+ ASSERT (carry2 == 0); \
+ } \
+ } \
+ return carry; \
+ }
+
+mp_limb_t
+refmpn_add_err3_n (mp_ptr rp, mp_srcptr s1p, mp_srcptr s2p,
+ mp_ptr ep, mp_srcptr y1p, mp_srcptr y2p, mp_srcptr y3p,
+ mp_size_t size, mp_limb_t carry)
+{
+ AORS_ERR3_N (adc);
+}
+mp_limb_t
+refmpn_sub_err3_n (mp_ptr rp, mp_srcptr s1p, mp_srcptr s2p,
+ mp_ptr ep, mp_srcptr y1p, mp_srcptr y2p, mp_srcptr y3p,
+ mp_size_t size, mp_limb_t carry)
+{
+ AORS_ERR3_N (sbb);
+}
+
+
mp_limb_t
refmpn_addlsh_n (mp_ptr rp, mp_srcptr up, mp_srcptr vp,
mp_size_t n, unsigned int s)
@@ -1603,6 +1775,60 @@ refmpn_mul_basecase (mp_ptr prodp,
prodp[usize+i] = refmpn_addmul_1 (prodp+i, up, usize, vp[i]);
}
+
+/* The same as mpn/generic/mulmid_basecase.c, but using refmpn functions. */
+void
+refmpn_mulmid_basecase (mp_ptr rp,
+ mp_srcptr up, mp_size_t un,
+ mp_srcptr vp, mp_size_t vn)
+{
+ mp_limb_t cy;
+ mp_size_t i;
+
+ ASSERT (un >= vn);
+ ASSERT (vn >= 1);
+ ASSERT (! refmpn_overlap_p (rp, un - vn + 3, up, un));
+ ASSERT (! refmpn_overlap_p (rp, un - vn + 3, vp, vn));
+ ASSERT_MPN (up, un);
+ ASSERT_MPN (vp, vn);
+
+ rp[un - vn + 1] = refmpn_mul_1 (rp, up + vn - 1, un - vn + 1, vp[0]);
+ rp[un - vn + 2] = CNST_LIMB (0);
+ for (i = 1; i < vn; i++)
+ {
+ cy = refmpn_addmul_1 (rp, up + vn - i - 1, un - vn + 1, vp[i]);
+ cy = ref_addc_limb (&rp[un - vn + 1], rp[un - vn + 1], cy);
+ cy = ref_addc_limb (&rp[un - vn + 2], rp[un - vn + 2], cy);
+ ASSERT (cy == 0);
+ }
+}
+
+void
+refmpn_toom42_mulmid (mp_ptr rp, mp_srcptr up, mp_srcptr vp, mp_size_t n,
+ mp_ptr scratch)
+{
+ refmpn_mulmid_basecase (rp, up, 2*n - 1, vp, n);
+}
+
+void
+refmpn_mulmid_n (mp_ptr rp, mp_srcptr up, mp_srcptr vp, mp_size_t n)
+{
+ /* FIXME: this could be made faster by using refmpn_mul and then subtracting
+ off products near the middle product region boundary */
+ refmpn_mulmid_basecase (rp, up, 2*n - 1, vp, n);
+}
+
+void
+refmpn_mulmid (mp_ptr rp, mp_srcptr up, mp_size_t un,
+ mp_srcptr vp, mp_size_t vn)
+{
+ /* FIXME: this could be made faster by using refmpn_mul and then subtracting
+ off products near the middle product region boundary */
+ refmpn_mulmid_basecase (rp, up, un, vp, vn);
+}
+
+
+
#define TOOM3_THRESHOLD (MAX (MUL_TOOM33_THRESHOLD, SQR_TOOM3_THRESHOLD))
#define TOOM4_THRESHOLD (MAX (MUL_TOOM44_THRESHOLD, SQR_TOOM4_THRESHOLD))
#if WANT_FFT
diff --git a/tests/tests.h b/tests/tests.h
index c9e45d291..4086e5c5d 100644
--- a/tests/tests.h
+++ b/tests/tests.h
@@ -177,6 +177,15 @@ mp_limb_t refmpn_add __GMP_PROTO ((mp_ptr rp,
mp_srcptr s2p, mp_size_t s2size));
mp_limb_t refmpn_add_1 __GMP_PROTO ((mp_ptr rp, mp_srcptr sp, mp_size_t size,
mp_limb_t n));
+mp_limb_t refmpn_add_err1_n __GMP_PROTO ((mp_ptr rp, mp_srcptr s1p, mp_srcptr s2p,
+ mp_ptr ep, mp_srcptr yp,
+ mp_size_t size, mp_limb_t carry));
+mp_limb_t refmpn_add_err2_n __GMP_PROTO ((mp_ptr rp, mp_srcptr s1p, mp_srcptr s2p,
+ mp_ptr ep, mp_srcptr y1p, mp_srcptr y2p,
+ mp_size_t size, mp_limb_t carry));
+mp_limb_t refmpn_add_err3_n __GMP_PROTO ((mp_ptr rp, mp_srcptr s1p, mp_srcptr s2p,
+ mp_ptr ep, mp_srcptr y1p, mp_srcptr y2p, mp_srcptr y3p,
+ mp_size_t size, mp_limb_t carry));
mp_limb_t refmpn_add_n __GMP_PROTO ((mp_ptr wp, mp_srcptr xp, mp_srcptr yp,
mp_size_t size));
mp_limb_t refmpn_add_nc __GMP_PROTO ((mp_ptr wp, mp_srcptr xp, mp_srcptr yp,
@@ -304,6 +313,15 @@ mp_limb_t refmpn_mul_6 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr));
void refmpn_mul_basecase __GMP_PROTO ((mp_ptr prodp,
mp_srcptr up, mp_size_t usize,
mp_srcptr vp, mp_size_t vsize));
+void refmpn_mulmid_basecase __GMP_PROTO ((mp_ptr rp,
+ mp_srcptr up, mp_size_t un,
+ mp_srcptr vp, mp_size_t vn));
+void refmpn_toom42_mulmid __GMP_PROTO ((mp_ptr rp, mp_srcptr up, mp_srcptr vp,
+ mp_size_t n, mp_ptr scratch));
+void refmpn_mulmid_n __GMP_PROTO ((mp_ptr rp, mp_srcptr up, mp_srcptr vp,
+ mp_size_t n));
+void refmpn_mulmid __GMP_PROTO ((mp_ptr rp, mp_srcptr up, mp_size_t un,
+ mp_srcptr vp, mp_size_t vn));
void refmpn_mullo_n __GMP_PROTO ((mp_ptr prodp,
mp_srcptr up, mp_srcptr vp, mp_size_t vsize));
void refmpn_mul_any __GMP_PROTO ((mp_ptr prodp,
@@ -363,6 +381,15 @@ mp_limb_t refmpn_sub __GMP_PROTO ((mp_ptr rp,
mp_srcptr s2p, mp_size_t s2size));
mp_limb_t refmpn_sub_1 __GMP_PROTO ((mp_ptr rp, mp_srcptr sp, mp_size_t size,
mp_limb_t n));
+mp_limb_t refmpn_sub_err1_n __GMP_PROTO ((mp_ptr rp, mp_srcptr s1p, mp_srcptr s2p,
+ mp_ptr ep, mp_srcptr yp,
+ mp_size_t size, mp_limb_t carry));
+mp_limb_t refmpn_sub_err2_n __GMP_PROTO ((mp_ptr rp, mp_srcptr s1p, mp_srcptr s2p,
+ mp_ptr ep, mp_srcptr y1p, mp_srcptr y2p,
+ mp_size_t size, mp_limb_t carry));
+mp_limb_t refmpn_sub_err3_n __GMP_PROTO ((mp_ptr rp, mp_srcptr s1p, mp_srcptr s2p,
+ mp_ptr ep, mp_srcptr y1p, mp_srcptr y2p, mp_srcptr y3p,
+ mp_size_t size, mp_limb_t carry));
mp_limb_t refmpn_sub_n __GMP_PROTO ((mp_ptr wp, mp_srcptr xp, mp_srcptr yp,
mp_size_t size));
mp_limb_t refmpn_sub_nc __GMP_PROTO ((mp_ptr wp, mp_srcptr xp, mp_srcptr yp,