[BACK]Return to aorsmul.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gmp / mpz

Annotation of OpenXM_contrib/gmp/mpz/aorsmul.c, Revision 1.1

1.1     ! ohara       1: /* mpz_addmul, mpz_submul -- add or subtract multiple.
        !             2:
        !             3: Copyright 2001 Free Software Foundation, Inc.
        !             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
        !             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
        !            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
        !            14: or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
        !            15: License for more details.
        !            16:
        !            17: You should have received a copy of the GNU Lesser General Public License
        !            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 "gmp.h"
        !            23: #include "gmp-impl.h"
        !            24:
        !            25:
        !            26: /* expecting x and y both with non-zero high limbs */
        !            27: #define mpn_cmp_twosizes_lt(xp,xsize, yp,ysize)                 \
        !            28:   ((xsize) < (ysize)                                            \
        !            29:    || ((xsize) == (ysize) && mpn_cmp (xp, yp, xsize) < 0))
        !            30:
        !            31:
        !            32: /* sub>=0 means an addmul w += x*y, sub<0 means a submul w -= x*y.
        !            33:
        !            34:    The signs of w, x and y are fully accounted for by each flipping "sub".
        !            35:
        !            36:    The sign of w is retained for the result, unless the absolute value
        !            37:    submul underflows, in which case it flips.  */
        !            38:
        !            39: static void __gmpz_aorsmul _PROTO ((REGPARM_3_1 (mpz_ptr w, mpz_srcptr x, mpz_srcptr y, mp_size_t sub))) REGPARM_ATTR (1);
        !            40: #define mpz_aorsmul(w,x,y,sub)  __gmpz_aorsmul (REGPARM_3_1 (w, x, y, sub))
        !            41:
        !            42: static void
        !            43: mpz_aorsmul (mpz_ptr w, mpz_srcptr x, mpz_srcptr y, mp_size_t sub)
        !            44: {
        !            45:   mp_size_t  xsize, ysize, tsize, wsize, wsize_signed;
        !            46:   mp_ptr     wp, tp;
        !            47:   mp_limb_t  c, high;
        !            48:   TMP_DECL (marker);
        !            49:
        !            50:   /* w unaffected if x==0 or y==0 */
        !            51:   xsize = SIZ(x);
        !            52:   ysize = SIZ(y);
        !            53:   if (xsize == 0 || ysize == 0)
        !            54:     return;
        !            55:
        !            56:   /* make x the bigger of the two */
        !            57:   if (ABS(ysize) > ABS(xsize))
        !            58:     {
        !            59:       MPZ_SRCPTR_SWAP (x, y);
        !            60:       MP_SIZE_T_SWAP (xsize, ysize);
        !            61:     }
        !            62:
        !            63:   sub ^= ysize;
        !            64:   ysize = ABS(ysize);
        !            65:
        !            66:   /* use mpn_addmul_1/mpn_submul_1 if possible */
        !            67:   if (ysize == 1)
        !            68:     {
        !            69:       mpz_aorsmul_1 (w, x, PTR(y)[0], sub);
        !            70:       return;
        !            71:     }
        !            72:
        !            73:   sub ^= xsize;
        !            74:   xsize = ABS(xsize);
        !            75:
        !            76:   wsize_signed = SIZ(w);
        !            77:   sub ^= wsize_signed;
        !            78:   wsize = ABS(wsize_signed);
        !            79:
        !            80:   tsize = xsize + ysize;
        !            81:   MPZ_REALLOC (w, MAX (wsize, tsize) + 1);
        !            82:   wp = PTR(w);
        !            83:
        !            84:   if (wsize_signed == 0)
        !            85:     {
        !            86:       /* Nothing to add to, just set w=x*y.  No w==x or w==y overlap here,
        !            87:          since we know x,y!=0 but w==0.  */
        !            88:       high = mpn_mul (wp, PTR(x),xsize, PTR(y),ysize);
        !            89:       tsize -= (high == 0);
        !            90:       SIZ(w) = (sub >= 0 ? tsize : -tsize);
        !            91:       return;
        !            92:     }
        !            93:
        !            94:   TMP_MARK (marker);
        !            95:   tp = TMP_ALLOC_LIMBS (tsize);
        !            96:
        !            97:   high = mpn_mul (tp, PTR(x),xsize, PTR(y),ysize);
        !            98:   tsize -= (high == 0);
        !            99:   ASSERT (tp[tsize-1] != 0);
        !           100:   if (sub >= 0)
        !           101:     {
        !           102:       mp_srcptr up    = wp;
        !           103:       mp_size_t usize = wsize;
        !           104:
        !           105:       if (usize < tsize)
        !           106:         {
        !           107:           up    = tp;
        !           108:           usize = tsize;
        !           109:           tp    = wp;
        !           110:           tsize = wsize;
        !           111:
        !           112:           wsize = usize;
        !           113:         }
        !           114:
        !           115:       c = mpn_add (wp, up,usize, tp,tsize);
        !           116:       wp[wsize] = c;
        !           117:       wsize += (c != 0);
        !           118:     }
        !           119:   else
        !           120:     {
        !           121:       mp_srcptr up    = wp;
        !           122:       mp_size_t usize = wsize;
        !           123:
        !           124:       if (mpn_cmp_twosizes_lt (up,usize, tp,tsize))
        !           125:         {
        !           126:           up    = tp;
        !           127:           usize = tsize;
        !           128:           tp    = wp;
        !           129:           tsize = wsize;
        !           130:
        !           131:           wsize = usize;
        !           132:           wsize_signed = -wsize_signed;
        !           133:         }
        !           134:
        !           135:       ASSERT_NOCARRY (mpn_sub (wp, up,usize, tp,tsize));
        !           136:       wsize = usize;
        !           137:       MPN_NORMALIZE (wp, wsize);
        !           138:     }
        !           139:
        !           140:   SIZ(w) = (wsize_signed >= 0 ? wsize : -wsize);
        !           141:
        !           142:   TMP_FREE (marker);
        !           143: }
        !           144:
        !           145:
        !           146: void
        !           147: mpz_addmul (mpz_ptr w, mpz_srcptr u, mpz_srcptr v)
        !           148: {
        !           149:   mpz_aorsmul (w, u, v, (mp_size_t) 0);
        !           150: }
        !           151:
        !           152: void
        !           153: mpz_submul (mpz_ptr w, mpz_srcptr u, mpz_srcptr v)
        !           154: {
        !           155:   mpz_aorsmul (w, u, v, (mp_size_t) -1);
        !           156: }

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