Austin Schuh | bb1338c | 2024-06-15 19:31:16 -0700 | [diff] [blame] | 1 | /* mpf_get_ui -- mpf to ulong conversion |
| 2 | |
| 3 | Copyright 2001, 2002, 2004 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 either: |
| 9 | |
| 10 | * the GNU Lesser General Public License as published by the Free |
| 11 | Software Foundation; either version 3 of the License, or (at your |
| 12 | option) any later version. |
| 13 | |
| 14 | or |
| 15 | |
| 16 | * the GNU General Public License as published by the Free Software |
| 17 | Foundation; either version 2 of the License, or (at your option) any |
| 18 | later version. |
| 19 | |
| 20 | or both in parallel, as here. |
| 21 | |
| 22 | The GNU MP Library is distributed in the hope that it will be useful, but |
| 23 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
| 24 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| 25 | for more details. |
| 26 | |
| 27 | You should have received copies of the GNU General Public License and the |
| 28 | GNU Lesser General Public License along with the GNU MP Library. If not, |
| 29 | see https://www.gnu.org/licenses/. */ |
| 30 | |
| 31 | #include "gmp-impl.h" |
| 32 | |
| 33 | |
| 34 | /* Any fraction bits are truncated, meaning simply discarded. |
| 35 | |
| 36 | For values bigger than a ulong, the low bits are returned (the low |
| 37 | absolute value bits actually), like mpz_get_ui, but this isn't |
| 38 | documented. |
| 39 | |
| 40 | Notice this is equivalent to mpz_set_f + mpz_get_ui. |
| 41 | |
| 42 | |
| 43 | Implementation: |
| 44 | |
| 45 | The limb just above the radix point for us to extract is ptr[size-exp]. |
| 46 | |
| 47 | We need to check that the size-exp index falls in our available data |
| 48 | range, 0 to size-1 inclusive. We test this without risk of an overflow |
| 49 | involving exp by requiring size>=exp (giving size-exp >= 0) and exp>0 |
| 50 | (giving size-exp <= size-1). |
| 51 | |
| 52 | Notice if size==0 there's no fetch, since of course size>=exp and exp>0 |
| 53 | can only be true if size>0. So there's no special handling for size==0, |
| 54 | it comes out as 0 the same as any other time we have no data at our |
| 55 | target index. |
| 56 | |
| 57 | For nails, the second limb above the radix point is also required, this |
| 58 | is ptr[size-exp+1]. |
| 59 | |
| 60 | Again we need to check that size-exp+1 falls in our data range, 0 to |
| 61 | size-1 inclusive. We test without risk of overflow by requiring |
| 62 | size+1>=exp (giving size-exp+1 >= 0) and exp>1 (giving size-exp+1 <= |
| 63 | size-1). |
| 64 | |
| 65 | And again if size==0 these second fetch conditions are not satisfied |
| 66 | either since size+1>=exp and exp>1 are only true if size>0. |
| 67 | |
| 68 | The code is arranged with exp>0 wrapping the exp>1 test since exp>1 is |
| 69 | mis-compiled by alpha gcc prior to version 3.4. It re-writes it as |
| 70 | exp-1>0, which is incorrect when exp==MP_EXP_T_MIN. By having exp>0 |
| 71 | tested first we ensure MP_EXP_T_MIN doesn't reach exp>1. */ |
| 72 | |
| 73 | unsigned long |
| 74 | mpf_get_ui (mpf_srcptr f) __GMP_NOTHROW |
| 75 | { |
| 76 | mp_size_t size; |
| 77 | mp_exp_t exp; |
| 78 | mp_srcptr fp; |
| 79 | mp_limb_t fl; |
| 80 | |
| 81 | exp = EXP (f); |
| 82 | size = SIZ (f); |
| 83 | fp = PTR (f); |
| 84 | |
| 85 | fl = 0; |
| 86 | if (exp > 0) |
| 87 | { |
| 88 | /* there are some limbs above the radix point */ |
| 89 | |
| 90 | size = ABS (size); |
| 91 | if (size >= exp) |
| 92 | fl = fp[size-exp]; |
| 93 | |
| 94 | #if BITS_PER_ULONG > GMP_NUMB_BITS |
| 95 | if (exp > 1 && size+1 >= exp) |
| 96 | fl += (fp[size-exp+1] << GMP_NUMB_BITS); |
| 97 | #endif |
| 98 | } |
| 99 | |
| 100 | return (unsigned long) fl; |
| 101 | } |