/ src / ref / modf.c
modf.c
 1  /*
 2   * Copyright (C) 2008-2020 Advanced Micro Devices, Inc. All rights reserved.
 3   *
 4   * Redistribution and use in source and binary forms, with or without modification,
 5   * are permitted provided that the following conditions are met:
 6   * 1. Redistributions of source code must retain the above copyright notice,
 7   *    this list of conditions and the following disclaimer.
 8   * 2. Redistributions in binary form must reproduce the above copyright notice,
 9   *    this list of conditions and the following disclaimer in the documentation
10   *    and/or other materials provided with the distribution.
11   * 3. Neither the name of the copyright holder nor the names of its contributors
12   *    may be used to endorse or promote products derived from this software without
13   *    specific prior written permission.
14   *
15   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18   * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
19   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
20   * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
21   * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24   * POSSIBILITY OF SUCH DAMAGE.
25   *
26   */
27  
28  #include "libm_amd.h"
29  #include "libm_util_amd.h"
30  #include "libm_special.h"
31  #include "libm_errno_amd.h"
32  
33  double FN_PROTOTYPE_REF(modf)(double x, double *iptr)
34  {
35    /* modf splits the argument x into integer and fraction parts,
36       each with the same sign as x. */
37  
38  
39    long long xexp;
40    unsigned long long ux, ax, mask;
41  
42    GET_BITS_DP64(x, ux);
43    ax = ux & (~SIGNBIT_DP64);
44  
45    if (ax >= 0x4340000000000000)
46      {
47        /* abs(x) is either NaN, infinity, or >= 2^53 */
48        if (ax > 0x7ff0000000000000)
49          {
50            /* x is NaN */
51            *iptr = x;
52  #ifdef WINDOWS
53            return __amd_handle_error("modf", __amd_modf, ux|0x0008000000000000, _DOMAIN, AMD_F_NONE, EDOM, x, 0.0, 1);
54  #else
55            return x+x;
56  #endif
57          }
58        else
59          {
60            /* x is infinity or large. Return zero with the sign of x */
61            *iptr = x;
62            PUT_BITS_DP64(ux & SIGNBIT_DP64, x);
63            return x;
64          }
65      }
66    else if (ax < 0x3ff0000000000000)
67      {
68        /* abs(x) < 1.0. Set iptr to zero with the sign of x
69           and return x. */
70        PUT_BITS_DP64(ux & SIGNBIT_DP64, *iptr);
71        return x;
72      }
73    else
74      {
75        double r;
76        unsigned long long ur;
77        xexp = ((ux & EXPBITS_DP64) >> EXPSHIFTBITS_DP64) - EXPBIAS_DP64;
78        /* Mask out the bits of x that we don't want */
79        mask = 1;
80        mask = (mask << (EXPSHIFTBITS_DP64 - xexp)) - 1;
81        PUT_BITS_DP64(ux & ~mask, *iptr);
82        r = x - *iptr;
83        GET_BITS_DP64(r, ur);
84        PUT_BITS_DP64(((ux & SIGNBIT_DP64)|ur), r);
85        return r;
86      }
87  
88  }
89  
90