diff options
author | Kevin Ryde <user42@zip.com.au> | 2001-03-29 00:45:25 +0200 |
---|---|---|
committer | Kevin Ryde <user42@zip.com.au> | 2001-03-29 00:45:25 +0200 |
commit | a344eaf9cac01b77dade879bf87057ea8066b48a (patch) | |
tree | 0e70dedbf6325f8fdd998f461f3a698e58a4b071 /mpf/ceilfloor.c | |
parent | 75f33bfb3964dcc18c390fb6bba3a4245527c38e (diff) | |
download | gmp-a344eaf9cac01b77dade879bf87057ea8066b48a.tar.gz |
* mpf/trunc.c: New file, rewrite of integer.c, preserve prec+1 in
copy, don't copy if unnecessary.
* mpf/ceilfloor.c: New file likewise, and use common subroutine for
ceil and floor.
Diffstat (limited to 'mpf/ceilfloor.c')
-rw-r--r-- | mpf/ceilfloor.c | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/mpf/ceilfloor.c b/mpf/ceilfloor.c new file mode 100644 index 000000000..ac32dc495 --- /dev/null +++ b/mpf/ceilfloor.c @@ -0,0 +1,114 @@ +/* mpf_ceil, mpf_floor -- round an mpf to an integer. + +Copyright 2001 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + + +/* dir==1 for ceil, dir==-1 for floor + + Notice the use of prec+1 ensures mpf_ceil and mpf_floor are equivalent to + mpf_set if u is already an integer. */ + +static void __gmpf_ceil_or_floor _PROTO ((REGPARM_2_1 (mpf_ptr r, mpf_srcptr u, int dir))) REGPARM_ATTR (1); +#define mpf_ceil_or_floor(r,u,dir) __gmpf_ceil_or_floor (REGPARM_2_1 (r, u, dir)) + +static void +mpf_ceil_or_floor (mpf_ptr r, mpf_srcptr u, int dir) +{ + mp_ptr rp, up, p; + mp_size_t size, asize, prec; + mp_exp_t exp; + + size = SIZ(u); + if (size == 0) + { + SIZ(r) = 0; + return; + } + + rp = PTR(r); + exp = EXP(u); + if (exp <= 0) + { + /* u is only a fraction */ + rp[0] = 1; + EXP(r) = 1; + dir = ((size ^ dir) >= 0 ? dir : 0); + SIZ(r) = (size != 0 ? dir : 0); + return; + } + EXP(r) = exp; + + up = PTR(u); + asize = ABS (size); + up += asize; + + /* skip fraction part of u */ + asize = MIN (asize, exp); + + /* don't lose precision in the copy */ + prec = PREC (r) + 1; + + /* skip excess over target precision */ + asize = MIN (asize, prec); + + up -= asize; + + if ((size ^ dir) >= 0) + { + /* rounding direction matches sign, must increment if ignored part is + non-zero */ + for (p = PTR(u); p != up; p++) + { + if (*p != 0) + { + if (mpn_add_1 (rp, up, asize, CNST_LIMB(1))) + { + /* was all 0xFF..FFs, which have become zeros, giving just + a carry */ + rp[0] = 1; + asize = 1; + EXP(r)++; + } + SIZ(r) = (size >= 0 ? asize : -asize); + return; + } + } + } + + SIZ(r) = (size >= 0 ? asize : -asize); + if (rp != up) + MPN_COPY_INCR (rp, up, asize); +} + + +void +mpf_ceil (mpf_ptr r, mpf_srcptr u) +{ + mpf_ceil_or_floor (r, u, 1); +} + +void +mpf_floor (mpf_ptr r, mpf_srcptr u) +{ + mpf_ceil_or_floor (r, u, -1); +} |