[BACK]Return to t-mul.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gmp / mpz / tests

Annotation of OpenXM_contrib/gmp/mpz/tests/t-mul.c, Revision 1.1.1.2

1.1       maekawa     1: /* Test mpz_add, mpz_cmp, mpz_cmp_ui, mpz_divmod, mpz_mul.
                      2:
1.1.1.2 ! maekawa     3: Copyright (C) 1991, 1993, 1994, 1996, 1997, 2000 Free Software Foundation, Inc.
1.1       maekawa     4:
                      5: This file is part of the GNU MP Library.
                      6:
                      7: The GNU MP Library is free software; you can redistribute it and/or modify
1.1.1.2 ! maekawa     8: it under the terms of the GNU Lesser General Public License as published by
        !             9: the Free Software Foundation; either version 2.1 of the License, or (at your
1.1       maekawa    10: option) any later version.
                     11:
                     12: The GNU MP Library is distributed in the hope that it will be useful, but
                     13: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1.1.1.2 ! maekawa    14: or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
1.1       maekawa    15: License for more details.
                     16:
1.1.1.2 ! maekawa    17: You should have received a copy of the GNU Lesser General Public License
1.1       maekawa    18: along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
                     19: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
                     20: MA 02111-1307, USA. */
                     21:
                     22: #include <stdio.h>
                     23: #include "gmp.h"
                     24: #include "gmp-impl.h"
                     25: #include "longlong.h"
                     26: #include "urandom.h"
                     27:
                     28: void debug_mp ();
                     29: mp_size_t _mpn_mul_classic ();
                     30: void mpz_refmul ();
                     31:
                     32: #ifndef SIZE
1.1.1.2 ! maekawa    33: #define SIZE 2 * TOOM3_MUL_THRESHOLD
1.1       maekawa    34: #endif
                     35:
                     36: main (argc, argv)
                     37:      int argc;
                     38:      char **argv;
                     39: {
                     40:   mpz_t multiplier, multiplicand;
                     41:   mpz_t product, ref_product;
                     42:   mpz_t quotient, remainder;
                     43:   mp_size_t multiplier_size, multiplicand_size;
                     44:   int i;
1.1.1.2 ! maekawa    45:   int reps = 2000;
1.1       maekawa    46:
                     47:   if (argc == 2)
                     48:      reps = atoi (argv[1]);
                     49:
                     50:   mpz_init (multiplier);
                     51:   mpz_init (multiplicand);
                     52:   mpz_init (product);
                     53:   mpz_init (ref_product);
                     54:   mpz_init (quotient);
                     55:   mpz_init (remainder);
                     56:
                     57:   for (i = 0; i < reps; i++)
                     58:     {
1.1.1.2 ! maekawa    59:       multiplier_size = urandom () % 2 * SIZE - SIZE;
        !            60:       multiplicand_size = urandom () % 2 * SIZE - SIZE;
1.1       maekawa    61:
                     62:       mpz_random2 (multiplier, multiplier_size);
                     63:       mpz_random2 (multiplicand, multiplicand_size);
                     64:
                     65:       mpz_mul (product, multiplier, multiplicand);
                     66:       mpz_refmul (ref_product, multiplier, multiplicand);
                     67:       if (mpz_cmp_ui (multiplicand, 0) != 0)
                     68:        mpz_divmod (quotient, remainder, product, multiplicand);
                     69:
                     70:       if (mpz_cmp (product, ref_product))
1.1.1.2 ! maekawa    71:        dump_abort ("incorrect plain product",
        !            72:                    multiplier, multiplicand, product, ref_product);
1.1       maekawa    73:
                     74:       if (mpz_cmp_ui (multiplicand, 0) != 0)
                     75:       if (mpz_cmp_ui (remainder, 0) || mpz_cmp (quotient, multiplier))
1.1.1.2 ! maekawa    76:        {
        !            77:          debug_mp (quotient, -16);
        !            78:          debug_mp (remainder, -16);
        !            79:          dump_abort ("incorrect quotient or remainder",
        !            80:                      multiplier, multiplicand, product, ref_product);
        !            81:        }
        !            82:
        !            83:       /* Test squaring.  */
        !            84:       mpz_mul (product, multiplier, multiplier);
        !            85:       mpz_refmul (ref_product, multiplier, multiplier);
        !            86:
        !            87:       if (mpz_cmp (product, ref_product))
        !            88:        dump_abort ("incorrect square product",
        !            89:                    multiplier, multiplier, product, ref_product);
1.1       maekawa    90:     }
                     91:
                     92:   exit (0);
                     93: }
                     94:
                     95: void
                     96: mpz_refmul (w, u, v)
                     97:      mpz_t w;
                     98:      const mpz_t u;
                     99:      const mpz_t v;
                    100: {
                    101:   mp_size_t usize = u->_mp_size;
                    102:   mp_size_t vsize = v->_mp_size;
                    103:   mp_size_t wsize;
                    104:   mp_size_t sign_product;
                    105:   mp_ptr up, vp;
                    106:   mp_ptr wp;
                    107:   mp_ptr free_me = NULL;
                    108:   size_t free_me_size;
                    109:   TMP_DECL (marker);
                    110:
                    111:   TMP_MARK (marker);
                    112:   sign_product = usize ^ vsize;
                    113:   usize = ABS (usize);
                    114:   vsize = ABS (vsize);
                    115:
                    116:   if (usize < vsize)
                    117:     {
                    118:       /* Swap U and V.  */
                    119:       {const __mpz_struct *t = u; u = v; v = t;}
                    120:       {mp_size_t t = usize; usize = vsize; vsize = t;}
                    121:     }
                    122:
                    123:   up = u->_mp_d;
                    124:   vp = v->_mp_d;
                    125:   wp = w->_mp_d;
                    126:
                    127:   /* Ensure W has space enough to store the result.  */
                    128:   wsize = usize + vsize;
                    129:   if (w->_mp_alloc < wsize)
                    130:     {
                    131:       if (wp == up || wp == vp)
                    132:        {
                    133:          free_me = wp;
                    134:          free_me_size = w->_mp_alloc;
                    135:        }
                    136:       else
                    137:        (*_mp_free_func) (wp, w->_mp_alloc * BYTES_PER_MP_LIMB);
                    138:
                    139:       w->_mp_alloc = wsize;
                    140:       wp = (mp_ptr) (*_mp_allocate_func) (wsize * BYTES_PER_MP_LIMB);
                    141:       w->_mp_d = wp;
                    142:     }
                    143:   else
                    144:     {
                    145:       /* Make U and V not overlap with W.  */
                    146:       if (wp == up)
                    147:        {
                    148:          /* W and U are identical.  Allocate temporary space for U.  */
                    149:          up = (mp_ptr) TMP_ALLOC (usize * BYTES_PER_MP_LIMB);
                    150:          /* Is V identical too?  Keep it identical with U.  */
                    151:          if (wp == vp)
                    152:            vp = up;
                    153:          /* Copy to the temporary space.  */
                    154:          MPN_COPY (up, wp, usize);
                    155:        }
                    156:       else if (wp == vp)
                    157:        {
                    158:          /* W and V are identical.  Allocate temporary space for V.  */
                    159:          vp = (mp_ptr) TMP_ALLOC (vsize * BYTES_PER_MP_LIMB);
                    160:          /* Copy to the temporary space.  */
                    161:          MPN_COPY (vp, wp, vsize);
                    162:        }
                    163:     }
                    164:
                    165:   wsize = _mpn_mul_classic (wp, up, usize, vp, vsize);
                    166:   w->_mp_size = sign_product < 0 ? -wsize : wsize;
                    167:   if (free_me != NULL)
                    168:     (*_mp_free_func) (free_me, free_me_size * BYTES_PER_MP_LIMB);
                    169:
                    170:   TMP_FREE (marker);
                    171: }
                    172:
                    173: mp_size_t
                    174: _mpn_mul_classic (prodp, up, usize, vp, vsize)
                    175:      mp_ptr prodp;
                    176:      mp_srcptr up;
                    177:      mp_size_t usize;
                    178:      mp_srcptr vp;
                    179:      mp_size_t vsize;
                    180: {
                    181:   mp_size_t i, j;
                    182:   mp_limb_t prod_low, prod_high;
                    183:   mp_limb_t cy_dig;
                    184:   mp_limb_t v_limb, c;
                    185:
                    186:   if (vsize == 0)
                    187:     return 0;
                    188:
                    189:   /* Offset UP and PRODP so that the inner loop can be faster.  */
                    190:   up += usize;
                    191:   prodp += usize;
                    192:
                    193:   /* Multiply by the first limb in V separately, as the result can
                    194:      be stored (not added) to PROD.  We also avoid a loop for zeroing.  */
                    195:   v_limb = vp[0];
                    196:   cy_dig = 0;
                    197:   j = -usize;
                    198:   do
                    199:     {
                    200:       umul_ppmm (prod_high, prod_low, up[j], v_limb);
                    201:       add_ssaaaa (cy_dig, prodp[j], prod_high, prod_low, 0, cy_dig);
                    202:       j++;
                    203:     }
                    204:   while (j < 0);
                    205:
                    206:   prodp[j] = cy_dig;
                    207:   prodp++;
                    208:
                    209:   /* For each iteration in the outer loop, multiply one limb from
                    210:      U with one limb from V, and add it to PROD.  */
                    211:   for (i = 1; i < vsize; i++)
                    212:     {
                    213:       v_limb = vp[i];
                    214:       cy_dig = 0;
                    215:       j = -usize;
                    216:
                    217:       /* Inner loops.  Simulate the carry flag by jumping between
                    218:         these loops.  The first is used when there was no carry
                    219:         in the previois iteration; the second when there was carry.  */
                    220:
                    221:       do
                    222:        {
                    223:          umul_ppmm (prod_high, prod_low, up[j], v_limb);
                    224:          add_ssaaaa (cy_dig, prod_low, prod_high, prod_low, 0, cy_dig);
                    225:          c = prodp[j];
                    226:          prod_low += c;
                    227:          prodp[j] = prod_low;
                    228:          if (prod_low < c)
                    229:            goto cy_loop;
                    230:        ncy_loop:
                    231:          j++;
                    232:        }
                    233:       while (j < 0);
                    234:
                    235:       prodp[j] = cy_dig;
                    236:       prodp++;
                    237:       continue;
                    238:
                    239:       do
                    240:        {
                    241:          umul_ppmm (prod_high, prod_low, up[j], v_limb);
                    242:          add_ssaaaa (cy_dig, prod_low, prod_high, prod_low, 0, cy_dig);
                    243:          c = prodp[j];
                    244:          prod_low += c + 1;
                    245:          prodp[j] = prod_low;
                    246:          if (prod_low > c)
                    247:            goto ncy_loop;
                    248:        cy_loop:
                    249:          j++;
                    250:        }
                    251:       while (j < 0);
                    252:
                    253:       cy_dig += 1;
                    254:       prodp[j] = cy_dig;
                    255:       prodp++;
                    256:     }
                    257:
                    258:   return usize + vsize - (cy_dig == 0);
                    259: }
                    260:
1.1.1.2 ! maekawa   261: dump_abort (s, multiplier, multiplicand, product, ref_product)
        !           262:      char *s;
        !           263:      mpz_t multiplier, multiplicand, product, ref_product;
1.1       maekawa   264: {
1.1.1.2 ! maekawa   265:   fprintf (stderr, "ERROR: %s\n", s);
1.1       maekawa   266:   fprintf (stderr, "multiplier = "); debug_mp (multiplier, -16);
                    267:   fprintf (stderr, "multiplicand  = "); debug_mp (multiplicand, -16);
1.1.1.2 ! maekawa   268:   fprintf (stderr, "product  = "); debug_mp (product, -16);
        !           269:   fprintf (stderr, "ref_product  = "); debug_mp (ref_product, -16);
1.1       maekawa   270:   abort();
                    271: }
                    272:
                    273: void
                    274: debug_mp (x, base)
                    275:      mpz_t x;
                    276: {
                    277:   mpz_out_str (stderr, base, x); fputc ('\n', stderr);
                    278: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>