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

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

1.1     ! ohara       1: /* Cray PVP/IEEE mpn_addmul_1 -- multiply a limb vector with a limb and add the
        !             2:    result to a second limb vector.
        !             3:
        !             4: Copyright 2000, 2001, 2002 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 just under 9 cycles/limb on a T90.  That is not perfect,
        !            24:    mainly due to vector register shortage in the main loop.  Assembly code
        !            25:    should bring it down to perhaps 7 cycles/limb.  */
        !            26:
        !            27: #include <intrinsics.h>
        !            28: #include "gmp.h"
        !            29: #include "gmp-impl.h"
        !            30:
        !            31: mp_limb_t
        !            32: mpn_addmul_1 (mp_ptr rp, mp_srcptr up, mp_size_t n, mp_limb_t vl)
        !            33: {
        !            34:   mp_limb_t cy[n];
        !            35:   mp_limb_t a, b, r, s0, s1, c0, c1;
        !            36:   mp_size_t i;
        !            37:   int more_carries;
        !            38:
        !            39:   if (up == rp)
        !            40:     {
        !            41:       /* The algorithm used below cannot handle overlap.  Handle it here by
        !            42:         making a temporary copy of the source vector, then call ourselves.  */
        !            43:       mp_limb_t xp[n];
        !            44:       MPN_COPY (xp, up, n);
        !            45:       return mpn_addmul_1 (rp, xp, n, vl);
        !            46:     }
        !            47:
        !            48:   a = up[0] * vl;
        !            49:   r = rp[0];
        !            50:   s0 = a + r;
        !            51:   rp[0] = s0;
        !            52:   c0 = ((a & r) | ((a | r) & ~s0)) >> 63;
        !            53:   cy[0] = c0;
        !            54:
        !            55:   /* Main multiply loop.  Generate a raw accumulated output product in rp[]
        !            56:      and a carry vector in cy[].  */
        !            57: #pragma _CRI ivdep
        !            58:   for (i = 1; i < n; i++)
        !            59:     {
        !            60:       a = up[i] * vl;
        !            61:       b = _int_mult_upper (up[i - 1], vl);
        !            62:       s0 = a + b;
        !            63:       c0 = ((a & b) | ((a | b) & ~s0)) >> 63;
        !            64:       r = rp[i];
        !            65:       s1 = s0 + r;
        !            66:       rp[i] = s1;
        !            67:       c1 = ((s0 & r) | ((s0 | r) & ~s1)) >> 63;
        !            68:       cy[i] = c0 + c1;
        !            69:     }
        !            70:   /* Carry add loop.  Add the carry vector cy[] to the raw result rp[] and
        !            71:      store the new result back to rp[].  */
        !            72:   more_carries = 0;
        !            73: #pragma _CRI ivdep
        !            74:   for (i = 1; i < n; i++)
        !            75:     {
        !            76:       r = rp[i];
        !            77:       c0 = cy[i - 1];
        !            78:       s0 = r + c0;
        !            79:       rp[i] = s0;
        !            80:       c0 = (r & ~s0) >> 63;
        !            81:       more_carries += c0;
        !            82:     }
        !            83:   /* If that second loop generated carry, handle that in scalar loop.  */
        !            84:   if (more_carries)
        !            85:     {
        !            86:       mp_limb_t cyrec = 0;
        !            87:       /* Look for places where rp[k] == 0 and cy[k-1] == 1 or
        !            88:         rp[k] == 1 and cy[k-1] == 2.
        !            89:         These are where we got a recurrency carry.  */
        !            90:       for (i = 1; i < n; i++)
        !            91:        {
        !            92:          r = rp[i];
        !            93:          c0 = r < cy[i - 1];
        !            94:          s0 = r + cyrec;
        !            95:          rp[i] = s0;
        !            96:          c1 = (r & ~s0) >> 63;
        !            97:          cyrec = c0 | c1;
        !            98:        }
        !            99:       return _int_mult_upper (up[n - 1], vl) + cyrec + cy[n - 1];
        !           100:     }
        !           101:
        !           102:   return _int_mult_upper (up[n - 1], vl) + cy[n - 1];
        !           103: }

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