xref: /dflybsd-src/contrib/gmp/mpf/get_ui.c (revision d365564473a20a528d07c59cad8ee2f4bea5546f)
14b6a78b7SSimon Schubert /* mpf_get_ui -- mpf to ulong conversion
24b6a78b7SSimon Schubert 
34b6a78b7SSimon Schubert Copyright 2001, 2002, 2004 Free Software Foundation, Inc.
44b6a78b7SSimon Schubert 
54b6a78b7SSimon Schubert This file is part of the GNU MP Library.
64b6a78b7SSimon Schubert 
74b6a78b7SSimon Schubert The GNU MP Library is free software; you can redistribute it and/or modify
84b6a78b7SSimon Schubert it under the terms of the GNU Lesser General Public License as published by
94b6a78b7SSimon Schubert the Free Software Foundation; either version 3 of the License, or (at your
104b6a78b7SSimon Schubert option) any later version.
114b6a78b7SSimon Schubert 
124b6a78b7SSimon Schubert The GNU MP Library is distributed in the hope that it will be useful, but
134b6a78b7SSimon Schubert WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
144b6a78b7SSimon Schubert or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
154b6a78b7SSimon Schubert License for more details.
164b6a78b7SSimon Schubert 
174b6a78b7SSimon Schubert You should have received a copy of the GNU Lesser General Public License
184b6a78b7SSimon Schubert along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
194b6a78b7SSimon Schubert 
204b6a78b7SSimon Schubert #include "gmp.h"
214b6a78b7SSimon Schubert #include "gmp-impl.h"
224b6a78b7SSimon Schubert 
234b6a78b7SSimon Schubert 
244b6a78b7SSimon Schubert /* Any fraction bits are truncated, meaning simply discarded.
254b6a78b7SSimon Schubert 
264b6a78b7SSimon Schubert    For values bigger than a ulong, the low bits are returned (the low
274b6a78b7SSimon Schubert    absolute value bits actually), like mpz_get_ui, but this isn't
284b6a78b7SSimon Schubert    documented.
294b6a78b7SSimon Schubert 
304b6a78b7SSimon Schubert    Notice this is equivalent to mpz_set_f + mpz_get_ui.
314b6a78b7SSimon Schubert 
324b6a78b7SSimon Schubert 
334b6a78b7SSimon Schubert    Implementation:
344b6a78b7SSimon Schubert 
354b6a78b7SSimon Schubert    The limb just above the radix point for us to extract is ptr[size-exp].
364b6a78b7SSimon Schubert 
374b6a78b7SSimon Schubert    We need to check that the size-exp index falls in our available data
384b6a78b7SSimon Schubert    range, 0 to size-1 inclusive.  We test this without risk of an overflow
394b6a78b7SSimon Schubert    involving exp by requiring size>=exp (giving size-exp >= 0) and exp>0
404b6a78b7SSimon Schubert    (giving size-exp <= size-1).
414b6a78b7SSimon Schubert 
424b6a78b7SSimon Schubert    Notice if size==0 there's no fetch, since of course size>=exp and exp>0
434b6a78b7SSimon Schubert    can only be true if size>0.  So there's no special handling for size==0,
444b6a78b7SSimon Schubert    it comes out as 0 the same as any other time we have no data at our
454b6a78b7SSimon Schubert    target index.
464b6a78b7SSimon Schubert 
474b6a78b7SSimon Schubert    For nails, the second limb above the radix point is also required, this
484b6a78b7SSimon Schubert    is ptr[size-exp+1].
494b6a78b7SSimon Schubert 
504b6a78b7SSimon Schubert    Again we need to check that size-exp+1 falls in our data range, 0 to
514b6a78b7SSimon Schubert    size-1 inclusive.  We test without risk of overflow by requiring
524b6a78b7SSimon Schubert    size+1>=exp (giving size-exp+1 >= 0) and exp>1 (giving size-exp+1 <=
534b6a78b7SSimon Schubert    size-1).
544b6a78b7SSimon Schubert 
554b6a78b7SSimon Schubert    And again if size==0 these second fetch conditions are not satisfied
564b6a78b7SSimon Schubert    either since size+1>=exp and exp>1 are only true if size>0.
574b6a78b7SSimon Schubert 
584b6a78b7SSimon Schubert    The code is arranged with exp>0 wrapping the exp>1 test since exp>1 is
594b6a78b7SSimon Schubert    mis-compiled by alpha gcc prior to version 3.4.  It re-writes it as
604b6a78b7SSimon Schubert    exp-1>0, which is incorrect when exp==MP_EXP_T_MIN.  By having exp>0
614b6a78b7SSimon Schubert    tested first we ensure MP_EXP_T_MIN doesn't reach exp>1.  */
624b6a78b7SSimon Schubert 
634b6a78b7SSimon Schubert unsigned long
mpf_get_ui(mpf_srcptr f)64*d2d4b659SJohn Marino mpf_get_ui (mpf_srcptr f) __GMP_NOTHROW
654b6a78b7SSimon Schubert {
664b6a78b7SSimon Schubert   mp_size_t size;
674b6a78b7SSimon Schubert   mp_exp_t exp;
684b6a78b7SSimon Schubert   mp_srcptr fp;
694b6a78b7SSimon Schubert   mp_limb_t fl;
704b6a78b7SSimon Schubert 
714b6a78b7SSimon Schubert   exp = EXP (f);
724b6a78b7SSimon Schubert   size = SIZ (f);
734b6a78b7SSimon Schubert   fp = PTR (f);
744b6a78b7SSimon Schubert 
754b6a78b7SSimon Schubert   fl = 0;
764b6a78b7SSimon Schubert   if (exp > 0)
774b6a78b7SSimon Schubert     {
784b6a78b7SSimon Schubert       /* there are some limbs above the radix point */
794b6a78b7SSimon Schubert 
804b6a78b7SSimon Schubert       size = ABS (size);
814b6a78b7SSimon Schubert       if (size >= exp)
824b6a78b7SSimon Schubert         fl = fp[size-exp];
834b6a78b7SSimon Schubert 
844b6a78b7SSimon Schubert #if BITS_PER_ULONG > GMP_NUMB_BITS
854b6a78b7SSimon Schubert       if (exp > 1 && size+1 >= exp)
864b6a78b7SSimon Schubert         fl += (fp[size-exp+1] << GMP_NUMB_BITS);
874b6a78b7SSimon Schubert #endif
884b6a78b7SSimon Schubert     }
894b6a78b7SSimon Schubert 
904b6a78b7SSimon Schubert   return (unsigned long) fl;
914b6a78b7SSimon Schubert }
92