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

Annotation of OpenXM_contrib/gmp/mpz/cfdiv_r_2exp.c, Revision 1.1.1.1

1.1       ohara       1: /* mpz_cdiv_r_2exp, mpz_fdiv_r_2exp -- remainder from mpz divided by 2^n.
                      2:
                      3: Copyright 2001, 2002 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: /* Bit mask of "n" least significant bits of a limb. */
                     27: #define LOW_MASK(n)   ((CNST_LIMB(1) << (n)) - 1)
                     28:
                     29:
                     30: /* dir==1 for ceil, dir==-1 for floor */
                     31:
                     32: static void __gmpz_cfdiv_r_2exp _PROTO ((REGPARM_3_1 (mpz_ptr w, mpz_srcptr u, unsigned long cnt, int dir))) REGPARM_ATTR (1);
                     33: #define cfdiv_r_2exp(w,u,cnt,dir)  __gmpz_cfdiv_r_2exp (REGPARM_3_1 (w, u, cnt, dir))
                     34:
                     35: static void
                     36: cfdiv_r_2exp (mpz_ptr w, mpz_srcptr u, unsigned long cnt, int dir)
                     37: {
                     38:   mp_size_t  usize, abs_usize, limb_cnt, i;
                     39:   mp_srcptr  up;
                     40:   mp_ptr     wp;
                     41:   mp_limb_t  high;
                     42:
                     43:   usize = SIZ(u);
                     44:   if (usize == 0)
                     45:     {
                     46:       SIZ(w) = 0;
                     47:       return;
                     48:     }
                     49:
                     50:   limb_cnt = cnt / GMP_NUMB_BITS;
                     51:   cnt %= GMP_NUMB_BITS;
                     52:   abs_usize = ABS (usize);
                     53:
                     54:   /* MPZ_REALLOC(w) below is only when w!=u, so we can fetch PTR(u) here
                     55:      nice and early */
                     56:   up = PTR(u);
                     57:
                     58:   if ((usize ^ dir) < 0)
                     59:     {
                     60:       /* Round towards zero, means just truncate */
                     61:
                     62:       if (w == u)
                     63:         {
                     64:           /* if already smaller than limb_cnt then do nothing */
                     65:           if (abs_usize <= limb_cnt)
                     66:             return;
                     67:           wp = PTR(w);
                     68:         }
                     69:       else
                     70:         {
                     71:           i = MIN (abs_usize, limb_cnt+1);
                     72:           MPZ_REALLOC (w, i);
                     73:           wp = PTR(w);
                     74:           MPN_COPY (wp, up, i);
                     75:
                     76:           /* if smaller than limb_cnt then only the copy is needed */
                     77:           if (abs_usize <= limb_cnt)
                     78:             {
                     79:               SIZ(w) = usize;
                     80:               return;
                     81:             }
                     82:         }
                     83:     }
                     84:   else
                     85:     {
                     86:       /* Round away from zero, means twos complement if non-zero */
                     87:
                     88:       /* if u!=0 and smaller than divisor, then must negate */
                     89:       if (abs_usize <= limb_cnt)
                     90:         goto negate;
                     91:
                     92:       /* if non-zero low limb, then must negate */
                     93:       for (i = 0; i < limb_cnt; i++)
                     94:         if (up[i] != 0)
                     95:           goto negate;
                     96:
                     97:       /* if non-zero partial limb, then must negate */
                     98:       if ((up[limb_cnt] & LOW_MASK (cnt)) != 0)
                     99:         goto negate;
                    100:
                    101:       /* otherwise low bits of u are zero, so that's the result */
                    102:       SIZ(w) = 0;
                    103:       return;
                    104:
                    105:     negate:
                    106:       /* twos complement negation to get 2**cnt-u */
                    107:
                    108:       MPZ_REALLOC (w, limb_cnt+1);
                    109:       up = PTR(u);
                    110:       wp = PTR(w);
                    111:
                    112:       /* Ones complement */
                    113:       i = MIN (abs_usize, limb_cnt+1);
                    114:       mpn_com_n (wp, up, i);
                    115:       for ( ; i <= limb_cnt; i++)
                    116:         wp[i] = GMP_NUMB_MAX;
                    117:
                    118:       /* Twos complement.  Since u!=0 in the relevant part, the twos
                    119:          complement never gives 0 and a carry, so can use MPN_INCR_U. */
                    120:       MPN_INCR_U (wp, limb_cnt+1, CNST_LIMB(1));
                    121:
                    122:       usize = -usize;
                    123:     }
                    124:
                    125:   /* Mask the high limb */
                    126:   high = wp[limb_cnt];
                    127:   high &= LOW_MASK (cnt);
                    128:   wp[limb_cnt] = high;
                    129:
                    130:   /* Strip any consequent high zeros */
                    131:   while (high == 0)
                    132:     {
                    133:       limb_cnt--;
                    134:       if (limb_cnt < 0)
                    135:         {
                    136:           SIZ(w) = 0;
                    137:           return;
                    138:         }
                    139:       high = wp[limb_cnt];
                    140:     }
                    141:
                    142:   limb_cnt++;
                    143:   SIZ(w) = (usize >= 0 ? limb_cnt : -limb_cnt);
                    144: }
                    145:
                    146:
                    147: void
                    148: mpz_cdiv_r_2exp (mpz_ptr w, mpz_srcptr u, unsigned long cnt)
                    149: {
                    150:   cfdiv_r_2exp (w, u, cnt, 1);
                    151: }
                    152:
                    153: void
                    154: mpz_fdiv_r_2exp (mpz_ptr w, mpz_srcptr u, unsigned long cnt)
                    155: {
                    156:   cfdiv_r_2exp (w, u, cnt, -1);
                    157: }

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