xref: /reactos/sdk/lib/crt/math/libm_sse2/ldexp.c (revision 144e984b)
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.h"
29 #include "libm_util.h"
30 #include "libm_new.h"
31 
32 #define FN_PROTOTYPE_REF FN_PROTOTYPE
33 #define __amd_handle_error _handle_error
34 #define __amd_ldexp OP_LDEXP
35 
36 //#include "fn_macros.h"
37 //#include "libm_util.h"
38 //#include "libm_special.h"
39 
40 double FN_PROTOTYPE_REF(ldexp)(double x, int n)
41 {
42     UT64 val,val_x;
43     unsigned int sign;
44     int exponent;
45     val.f64 = x;
46 	val_x.f64 = x;
47     sign = val.u32[1] & 0x80000000;
48     val.u32[1] = val.u32[1] & 0x7fffffff; /* remove the sign bit */
49 
50     if (val.u64 > 0x7ff0000000000000)     /* x is NaN */
51         #ifdef WINDOWS
52         return __amd_handle_error("ldexp", __amd_ldexp, val_x.u64|0x0008000000000000, _DOMAIN, 0, EDOM, x, n, 2);
53         #else
54         {
55         if(!(val.u64 & 0x0008000000000000))// x is snan
56            return __amd_handle_error("ldexp", __amd_ldexp, val_x.u64|0x0008000000000000, _DOMAIN, AMD_F_INVALID, EDOM, x, n, 2);
57         else
58            return x;
59 	    }
60         #endif
61 
62     if(val.u64 == 0x7ff0000000000000)/* x = +-inf*/
63         return x;
64 
65     if((val.u64 == 0x0000000000000000) || (n==0))
66         return x; /* x= +-0 or n= 0*/
67 
68     exponent = val.u32[1] >> 20; /* get the exponent */
69 
70     if(exponent == 0)/*x is denormal*/
71     {
72 		val.f64 = val.f64 * VAL_2PMULTIPLIER_DP;/*multiply by 2^53 to bring it to the normal range*/
73         exponent = val.u32[1] >> 20; /* get the exponent */
74 		exponent = exponent + n - MULTIPLIER_DP;
75 		if(exponent < -MULTIPLIER_DP)/*underflow*/
76 		{
77 			val.u32[1] = sign | 0x00000000;
78 			val.u32[0] = 0x00000000;
79             return __amd_handle_error("ldexp", __amd_ldexp, val.u64, _UNDERFLOW, AMD_F_INEXACT|AMD_F_UNDERFLOW, ERANGE, x, (double)n, 2);
80 		}
81 		if(exponent > 2046)/*overflow*/
82 		{
83 			val.u32[1] = sign | 0x7ff00000;
84 			val.u32[0] = 0x00000000;
85 			return __amd_handle_error("ldexp", __amd_ldexp, val.u64, _OVERFLOW, AMD_F_INEXACT|AMD_F_OVERFLOW, ERANGE ,x, (double)n, 2);
86 		}
87 
88 		exponent += MULTIPLIER_DP;
89 		val.u32[1] = sign | (exponent << 20) | (val.u32[1] & 0x000fffff);
90 		val.f64 = val.f64 * VAL_2PMMULTIPLIER_DP;
91         return val.f64;
92     }
93 
94     exponent += n;
95 
96     if(exponent < -MULTIPLIER_DP)/*underflow*/
97 	{
98 		val.u32[1] = sign | 0x00000000;
99 		val.u32[0] = 0x00000000;
100         return __amd_handle_error("ldexp", __amd_ldexp, val.u64, _UNDERFLOW, AMD_F_INEXACT|AMD_F_UNDERFLOW, ERANGE, x, (double)n, 2);
101 	}
102 
103     if(exponent < 1)/*x is normal but output is debnormal*/
104     {
105 		exponent += MULTIPLIER_DP;
106 		val.u32[1] = sign | (exponent << 20) | (val.u32[1] & 0x000fffff);
107 		val.f64 = val.f64 * VAL_2PMMULTIPLIER_DP;
108         return val.f64;
109     }
110 
111     if(exponent > 2046)/*overflow*/
112 	{
113 		val.u32[1] = sign | 0x7ff00000;
114 		val.u32[0] = 0x00000000;
115 	return __amd_handle_error("ldexp", __amd_ldexp, val.u64, _OVERFLOW, AMD_F_INEXACT|AMD_F_OVERFLOW, ERANGE ,x, (double)n, 2);
116 	}
117 
118     val.u32[1] = sign | (exponent << 20) | (val.u32[1] & 0x000fffff);
119     return val.f64;
120 }
121 
122 
123 
124 
125