xref: /netbsd-src/external/lgpl3/mpfr/dist/src/ui_div.c (revision ec6772edaf0cdcb5f52a48f4aca5e33a8fb8ecfd)
1d59437c0Smrg /* mpfr_ui_div -- divide a machine integer by a floating-point number
2d59437c0Smrg 
3ba125506Smrg Copyright 2000-2023 Free Software Foundation, Inc.
4efdec83bSmrg Contributed by the AriC and Caramba projects, INRIA.
5d59437c0Smrg 
6d59437c0Smrg This file is part of the GNU MPFR Library.
7d59437c0Smrg 
8d59437c0Smrg The GNU MPFR Library is free software; you can redistribute it and/or modify
9d59437c0Smrg it under the terms of the GNU Lesser General Public License as published by
10d59437c0Smrg the Free Software Foundation; either version 3 of the License, or (at your
11d59437c0Smrg option) any later version.
12d59437c0Smrg 
13d59437c0Smrg The GNU MPFR Library is distributed in the hope that it will be useful, but
14d59437c0Smrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15d59437c0Smrg or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16d59437c0Smrg License for more details.
17d59437c0Smrg 
18d59437c0Smrg You should have received a copy of the GNU Lesser General Public License
19d59437c0Smrg along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
202ba2404bSmrg https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
21d59437c0Smrg 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
22d59437c0Smrg 
23d59437c0Smrg 
24d59437c0Smrg #define MPFR_NEED_LONGLONG_H
25d59437c0Smrg #include "mpfr-impl.h"
26d59437c0Smrg 
27d59437c0Smrg int
mpfr_ui_div(mpfr_ptr y,unsigned long int u,mpfr_srcptr x,mpfr_rnd_t rnd_mode)28d59437c0Smrg mpfr_ui_div (mpfr_ptr y, unsigned long int u, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
29d59437c0Smrg {
30d59437c0Smrg   MPFR_LOG_FUNC
31*ec6772edSmrg     (("u=%lu x[%Pd]=%.*Rg rnd=%d",
32d59437c0Smrg       u, mpfr_get_prec(x), mpfr_log_prec, x, rnd_mode),
33*ec6772edSmrg      ("y[%Pd]=%.*Rg", mpfr_get_prec(y), mpfr_log_prec, y));
34d59437c0Smrg 
35d59437c0Smrg   if (MPFR_UNLIKELY(MPFR_IS_SINGULAR(x)))
36d59437c0Smrg     {
37d59437c0Smrg       if (MPFR_IS_NAN(x))
38d59437c0Smrg         {
39d59437c0Smrg           MPFR_SET_NAN(y);
40d59437c0Smrg           MPFR_RET_NAN;
41d59437c0Smrg         }
42d59437c0Smrg       else if (MPFR_IS_INF(x)) /* u/Inf = 0 */
43d59437c0Smrg         {
44d59437c0Smrg           MPFR_SET_ZERO(y);
45d59437c0Smrg           MPFR_SET_SAME_SIGN(y,x);
46d59437c0Smrg           MPFR_RET(0);
47d59437c0Smrg         }
48d59437c0Smrg       else /* u / 0 */
49d59437c0Smrg         {
50d59437c0Smrg           MPFR_ASSERTD(MPFR_IS_ZERO(x));
51d59437c0Smrg           if (u)
52d59437c0Smrg             {
53d59437c0Smrg               /* u > 0, so y = sign(x) * Inf */
54d59437c0Smrg               MPFR_SET_SAME_SIGN(y, x);
55d59437c0Smrg               MPFR_SET_INF(y);
56299c6f0cSmrg               MPFR_SET_DIVBY0 ();
57d59437c0Smrg               MPFR_RET(0);
58d59437c0Smrg             }
59d59437c0Smrg           else
60d59437c0Smrg             {
61d59437c0Smrg               /* 0 / 0 */
62d59437c0Smrg               MPFR_SET_NAN(y);
63d59437c0Smrg               MPFR_RET_NAN;
64d59437c0Smrg             }
65d59437c0Smrg         }
66d59437c0Smrg     }
67d59437c0Smrg   else if (MPFR_LIKELY(u != 0))
68d59437c0Smrg     {
692ba2404bSmrg       int inex;
702ba2404bSmrg       MPFR_SAVE_EXPO_DECL (expo);
712ba2404bSmrg 
722ba2404bSmrg       /* Optimization note: Exponent save/restore operations may be
732ba2404bSmrg          removed if mpfr_div works even when uu is out-of-range. */
742ba2404bSmrg       MPFR_SAVE_EXPO_MARK (expo);
752ba2404bSmrg 
762ba2404bSmrg #ifdef MPFR_LONG_WITHIN_LIMB
772ba2404bSmrg       {
78efdec83bSmrg         mpfr_t uu;
79efdec83bSmrg         mp_limb_t up[1];
80efdec83bSmrg         int cnt;
81efdec83bSmrg 
82d59437c0Smrg         MPFR_TMP_INIT1(up, uu, GMP_NUMB_BITS);
83d59437c0Smrg         MPFR_ASSERTN(u == (mp_limb_t) u);
84d59437c0Smrg         count_leading_zeros(cnt, (mp_limb_t) u);
85d59437c0Smrg         up[0] = (mp_limb_t) u << cnt;
86efdec83bSmrg 
87d59437c0Smrg         MPFR_SET_EXP (uu, GMP_NUMB_BITS - cnt);
88efdec83bSmrg         inex = mpfr_div (y, uu, x, rnd_mode);
892ba2404bSmrg       }
902ba2404bSmrg #else
912ba2404bSmrg       {
922ba2404bSmrg       mpfr_t uu;
932ba2404bSmrg 
942ba2404bSmrg       mpfr_init2 (uu, sizeof (unsigned long) * CHAR_BIT);
952ba2404bSmrg       mpfr_set_ui (uu, u, MPFR_RNDZ);
962ba2404bSmrg       inex = mpfr_div (y, uu, x, rnd_mode);
972ba2404bSmrg       mpfr_clear (uu);
982ba2404bSmrg       }
992ba2404bSmrg #endif
1002ba2404bSmrg 
101efdec83bSmrg       MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags);
102efdec83bSmrg       MPFR_SAVE_EXPO_FREE (expo);
103efdec83bSmrg       return mpfr_check_range (y, inex, rnd_mode);
104d59437c0Smrg     }
105d59437c0Smrg   else /* u = 0, and x != 0 */
106d59437c0Smrg     {
107d59437c0Smrg       MPFR_SET_ZERO(y);         /* if u=0, then set y to 0 */
108d59437c0Smrg       MPFR_SET_SAME_SIGN(y, x); /* u considered as +0: sign(+0/x) = sign(x) */
109d59437c0Smrg       MPFR_RET(0);
110d59437c0Smrg     }
111d59437c0Smrg }
112