xref: /reactos/sdk/lib/crt/math/libm_sse2/ldexpf.c (revision 886670e9)
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_errorf _handle_errorf
34 #define __amd_ldexp OP_LDEXP
35 
36 //#include "fn_macros.h"
37 //#include "libm_util_amd.h"
38 //#include "libm_special.h"
39 
40 float FN_PROTOTYPE_REF(ldexpf)(float x, int n)
41 {
42     UT32 val,val_x;
43     unsigned int sign;
44     int exponent;
45     val.f32 = x;
46 	val_x.f32 = x;
47     sign = val.u32 & 0x80000000;
48     val.u32 = val.u32 & 0x7fffffff;/* remove the sign bit */
49 
50     if(val.u32 > 0x7f800000)/* x= nan */
51         #ifdef WINDOWS
52         return __amd_handle_errorf("ldexpf", __amd_ldexp, val_x.u32|0x00400000, _DOMAIN, 0, EDOM, x, (float)n, 2);
53         #else
54         {
55           if(!(val.u32 & 0x00400000)) //x is snan
56               return __amd_handle_errorf("ldexpf", __amd_ldexp, val_x.u32|0x00400000, _DOMAIN, AMD_F_INVALID, EDOM, x, (float)n, 2);
57           else
58               return x;
59 		}
60         #endif
61 
62     if(val.u32 == 0x7f800000)/* x = +-inf*/
63         return x;
64 
65     if((val.u32 == 0x00000000) || (n==0))/* x= +-0 or n= 0*/
66         return x;
67 
68     exponent = val.u32 >> 23; /* get the exponent */
69 
70 	if(exponent == 0)/*x is denormal*/
71 	{
72 		val.f32 = val.f32 * VAL_2PMULTIPLIER_SP;/*multiply by 2^24 to bring it to the normal range*/
73 		exponent = (val.u32 >> 23); /* get the exponent */
74 		exponent = exponent + n - MULTIPLIER_SP;
75 		if(exponent < -MULTIPLIER_SP)/*underflow*/
76 		{
77 			val.u32 = sign | 0x00000000;
78             return __amd_handle_errorf("ldexpf", __amd_ldexp, val.u32, _UNDERFLOW, AMD_F_INEXACT|AMD_F_UNDERFLOW, ERANGE, x, (float)n, 2);
79 		}
80 		if(exponent > 254)/*overflow*/
81 		{
82 			val.u32 = sign | 0x7f800000;
83             return __amd_handle_errorf("ldexpf", __amd_ldexp, val.u32, _OVERFLOW, AMD_F_INEXACT|AMD_F_OVERFLOW, ERANGE, x, (float)n, 2);
84 		}
85 
86 		exponent += MULTIPLIER_SP;
87 		val.u32 = sign | (exponent << 23) | (val.u32 & 0x007fffff);
88 		val.f32 = val.f32 * VAL_2PMMULTIPLIER_SP;
89         return val.f32;
90 	}
91 
92     exponent += n;
93 
94     if(exponent < -MULTIPLIER_SP)/*underflow*/
95 	{
96 		val.u32 = sign | 0x00000000;
97         return __amd_handle_errorf("ldexpf", __amd_ldexp, val.u32, _UNDERFLOW, AMD_F_INEXACT|AMD_F_UNDERFLOW, ERANGE, x, (float)n, 2);
98 	}
99 
100     if(exponent < 1)/*x is normal but output is debnormal*/
101     {
102 		exponent += MULTIPLIER_SP;
103 		val.u32 = sign | (exponent << 23) | (val.u32 & 0x007fffff);
104 		val.f32 = val.f32 * VAL_2PMMULTIPLIER_SP;
105         return val.f32;
106     }
107 
108     if(exponent > 254)/*overflow*/
109 	{
110         val.u32 = sign | 0x7f800000;
111         return __amd_handle_errorf("ldexpf", __amd_ldexp, val.u32, _OVERFLOW, AMD_F_INEXACT|AMD_F_OVERFLOW, ERANGE, x, (float)n, 2);
112 	}
113 
114     val.u32 = sign | (exponent << 23) | (val.u32 & 0x007fffff);/*x is normal and output is normal*/
115     return val.f32;
116 }
117 
118 
119