[BACK]Return to mul_1.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gmp / mpn / cray / ieee

Annotation of OpenXM_contrib/gmp/mpn/cray/ieee/mul_1.c, Revision 1.1

1.1     ! ohara       1: /* Cray PVP/IEEE mpn_mul_1 -- multiply a limb vector with a limb and store the
        !             2:    result in a second limb vector.
        !             3:
        !             4: Copyright 2000, 2001 Free Software Foundation, Inc.
        !             5:
        !             6: This file is part of the GNU MP Library.
        !             7:
        !             8: The GNU MP Library is free software; you can redistribute it and/or modify
        !             9: it under the terms of the GNU Lesser General Public License as published by
        !            10: the Free Software Foundation; either version 2.1 of the License, or (at your
        !            11: option) any later version.
        !            12:
        !            13: The GNU MP Library is distributed in the hope that it will be useful, but
        !            14: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            15: or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
        !            16: License for more details.
        !            17:
        !            18: You should have received a copy of the GNU Lesser General Public License
        !            19: along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
        !            20: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
        !            21: MA 02111-1307, USA.  */
        !            22:
        !            23: /* This code runs at 5 cycles/limb on a T90.  That would probably
        !            24:    be hard to improve upon, even with assembly code.  */
        !            25:
        !            26: #include <intrinsics.h>
        !            27: #include "gmp.h"
        !            28: #include "gmp-impl.h"
        !            29:
        !            30: mp_limb_t
        !            31: mpn_mul_1 (mp_ptr rp, mp_srcptr up, mp_size_t n, mp_limb_t vl)
        !            32: {
        !            33:   mp_limb_t cy[n];
        !            34:   mp_limb_t a, b, r, s0, s1, c0, c1;
        !            35:   mp_size_t i;
        !            36:   int more_carries;
        !            37:
        !            38:   if (up == rp)
        !            39:     {
        !            40:       /* The algorithm used below cannot handle overlap.  Handle it here by
        !            41:         making a temporary copy of the source vector, then call ourselves.  */
        !            42:       mp_limb_t xp[n];
        !            43:       MPN_COPY (xp, up, n);
        !            44:       return mpn_mul_1 (rp, xp, n, vl);
        !            45:     }
        !            46:
        !            47:   a = up[0] * vl;
        !            48:   rp[0] = a;
        !            49:   cy[0] = 0;
        !            50:
        !            51:   /* Main multiply loop.  Generate a raw accumulated output product in rp[]
        !            52:      and a carry vector in cy[].  */
        !            53: #pragma _CRI ivdep
        !            54:   for (i = 1; i < n; i++)
        !            55:     {
        !            56:       a = up[i] * vl;
        !            57:       b = _int_mult_upper (up[i - 1], vl);
        !            58:       s0 = a + b;
        !            59:       c0 = ((a & b) | ((a | b) & ~s0)) >> 63;
        !            60:       rp[i] = s0;
        !            61:       cy[i] = c0;
        !            62:     }
        !            63:   /* Carry add loop.  Add the carry vector cy[] to the raw sum rp[] and
        !            64:      store the new sum back to rp[0].  */
        !            65:   more_carries = 0;
        !            66: #pragma _CRI ivdep
        !            67:   for (i = 2; i < n; i++)
        !            68:     {
        !            69:       r = rp[i];
        !            70:       c0 = cy[i - 1];
        !            71:       s0 = r + c0;
        !            72:       rp[i] = s0;
        !            73:       c0 = (r & ~s0) >> 63;
        !            74:       more_carries += c0;
        !            75:     }
        !            76:   /* If that second loop generated carry, handle that in scalar loop.  */
        !            77:   if (more_carries)
        !            78:     {
        !            79:       mp_limb_t cyrec = 0;
        !            80:       /* Look for places where rp[k] is zero and cy[k-1] is non-zero.
        !            81:         These are where we got a recurrency carry.  */
        !            82:       for (i = 2; i < n; i++)
        !            83:        {
        !            84:          r = rp[i];
        !            85:          c0 = (r == 0 && cy[i - 1] != 0);
        !            86:          s0 = r + cyrec;
        !            87:          rp[i] = s0;
        !            88:          c1 = (r & ~s0) >> 63;
        !            89:          cyrec = c0 | c1;
        !            90:        }
        !            91:       return _int_mult_upper (up[n - 1], vl) + cyrec + cy[n - 1];
        !            92:     }
        !            93:
        !            94:   return _int_mult_upper (up[n - 1], vl) + cy[n - 1];
        !            95: }

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