/ src / ref / floor.c
floor.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 "fn_macros.h"
29  #include "libm_util_amd.h"
30  #include "libm_special.h"
31  
32  double FN_PROTOTYPE_REF(floor)(double x)
33  {
34    double r;
35    long long rexp, xneg;
36  
37  
38    unsigned long long ux, ax, ur, mask;
39  
40    GET_BITS_DP64(x, ux);
41    ax = ux & (~SIGNBIT_DP64);
42    xneg = (ux != ax);
43  
44    if (ax >= 0x4340000000000000)
45      {
46        /* abs(x) is either NaN, infinity, or >= 2^53 */
47        if (ax > 0x7ff0000000000000)
48        {
49          /* x is NaN */
50         #ifdef WINDOWS
51              return __amd_handle_error("floor", __amd_floor, ux|0x0008000000000000, _DOMAIN, 0, EDOM, x, 0.0, 1);
52         #else
53              if(!(ax & 0x0008000000000000)) //x is snan
54                    return __amd_handle_error("floor", __amd_floor, ux|0x0008000000000000, _DOMAIN, AMD_F_INVALID, EDOM, x, 0.0, 1);
55              else // x is qnan or inf
56                    return x;
57         #endif
58        }
59        else
60          return x;
61      }
62    else if (ax < 0x3ff0000000000000) /* abs(x) < 1.0 */
63      {
64        if (ax == 0x0000000000000000)
65          /* x is +zero or -zero; return the same zero */
66          return x;
67        else if (xneg) /* x < 0.0 */
68          return -1.0;
69        else
70          return 0.0;
71      }
72    else
73      {
74        r = x;
75        rexp = ((ux & EXPBITS_DP64) >> EXPSHIFTBITS_DP64) - EXPBIAS_DP64;
76        /* Mask out the bits of r that we don't want */
77        mask = 1;
78        mask = (mask << (EXPSHIFTBITS_DP64 - rexp)) - 1;
79        ur = (ux & ~mask);
80        PUT_BITS_DP64(ur, r);
81        if (xneg && (ur != ux))
82          /* We threw some bits away and x was negative */
83          return r - 1.0;
84        else
85          return r;
86      }
87  
88  }
89  
90