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