• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef _FENV_PORTABLE_H_
18 #define _FENV_PORTABLE_H_
19 
20 #include <fenv.h>
21 #include <portability.h>
22 #include <stdint.h>
23 #include <stdlib.h>
24 
25 typedef struct {
26   unsigned char a[128];
27 } fenv_t_portable;
28 typedef uint32_t fexcept_t_portable;
29 
30 /* Exception flags. */
31 #define FE_INVALID_PORTABLE    0x01
32 #define FE_DIVBYZERO_PORTABLE  0x02
33 #define FE_OVERFLOW_PORTABLE   0x04
34 #define FE_UNDERFLOW_PORTABLE  0x08
35 #define FE_INEXACT_PORTABLE    0x10
36 #define FE_ALL_EXCEPT_PORTABLE (FE_DIVBYZERO_PORTABLE | FE_INEXACT_PORTABLE | FE_INVALID_PORTABLE |\
37                                 FE_OVERFLOW_PORTABLE | FE_UNDERFLOW_PORTABLE)
38 
39 /* Rounding modes. */
40 #define FE_TONEAREST_PORTABLE  0x0
41 #define FE_UPWARD_PORTABLE     0x1
42 #define FE_DOWNWARD_PORTABLE   0x2
43 #define FE_TOWARDZERO_PORTABLE 0x3
44 
45 
target_change_except(int flags)46 static inline int target_change_except(int flags)
47 {
48     int targetflags = 0;
49 
50     if (flags & FE_INVALID_PORTABLE)
51         targetflags |= FE_INVALID;
52     if (flags & FE_DIVBYZERO_PORTABLE)
53         targetflags |= FE_DIVBYZERO;
54     if (flags & FE_OVERFLOW_PORTABLE)
55         targetflags |= FE_OVERFLOW;
56     if (flags & FE_UNDERFLOW_PORTABLE)
57         targetflags |= FE_UNDERFLOW;
58     if (flags & FE_INEXACT_PORTABLE)
59         targetflags |= FE_INEXACT;
60 
61     return targetflags;
62 }
63 
target_change_rounding(int flags)64 static inline int target_change_rounding(int flags)
65 {
66     int targetflags = 0;
67 
68     switch(flags)
69     {
70       case FE_TONEAREST_PORTABLE:
71         targetflags = FE_TONEAREST;
72         break;
73       case FE_DOWNWARD_PORTABLE:
74         targetflags = FE_DOWNWARD;
75         break;
76       case FE_UPWARD_PORTABLE:
77         targetflags = FE_UPWARD;
78         break;
79       case FE_TOWARDZERO_PORTABLE:
80         targetflags = FE_TOWARDZERO;
81         break;
82     }
83     return targetflags;
84 }
85 
target_get_except(int targetflags)86 static inline int target_get_except(int targetflags)
87 {
88     int flags = 0;
89 
90     if (targetflags & FE_INVALID)
91         flags |= FE_INVALID_PORTABLE;
92     if (targetflags & FE_DIVBYZERO)
93         flags |= FE_DIVBYZERO_PORTABLE;
94     if (targetflags & FE_OVERFLOW)
95         flags |= FE_OVERFLOW_PORTABLE;
96     if (targetflags & FE_UNDERFLOW)
97         flags |= FE_UNDERFLOW_PORTABLE;
98     if (targetflags & FE_INEXACT)
99         flags |= FE_INEXACT_PORTABLE;
100     return flags;
101 }
102 
target_get_rounding(int targetflags)103 static inline int target_get_rounding(int targetflags)
104 {
105     int flags = 0;
106 
107     switch(targetflags)
108     {
109       case FE_TONEAREST:
110         flags = FE_TONEAREST_PORTABLE;
111         break;
112       case FE_DOWNWARD:
113         flags = FE_DOWNWARD_PORTABLE;
114         break;
115       case FE_UPWARD:
116         flags = FE_UPWARD_PORTABLE;
117         break;
118       case FE_TOWARDZERO:
119         flags = FE_TOWARDZERO_PORTABLE;
120         break;
121     }
122     return flags;
123 }
124 
125 
WRAP(fegetenv)126 int WRAP(fegetenv)(fenv_t_portable* __envp) {
127   return REAL(fegetenv)((fenv_t*) __envp);
128 }
129 
WRAP(fesetenv)130 int WRAP(fesetenv)(const fenv_t_portable* __envp) {
131   return REAL(fesetenv)((fenv_t*) __envp);
132 }
133 
WRAP(feclearexcept)134 int WRAP(feclearexcept)(int __excepts) {
135   __excepts = target_change_except(__excepts);
136   return REAL(feclearexcept)(__excepts);
137 }
138 
WRAP(fegetexceptflag)139 int WRAP(fegetexceptflag)(fexcept_t_portable* __flagp, int __excepts) {
140   __excepts = target_change_except(__excepts);
141   int ret = REAL(fegetexceptflag)((fexcept_t*) __flagp, __excepts);
142   *__flagp = target_get_except(*__flagp);
143   return ret;
144 }
145 
WRAP(fesetexceptflag)146 int WRAP(fesetexceptflag)(const fexcept_t_portable* __flagp, int __excepts) {
147   __excepts = target_change_except(__excepts);
148   return REAL(fesetexceptflag)((const fexcept_t*) __flagp, __excepts);
149 }
150 
WRAP(feraiseexcept)151 int WRAP(feraiseexcept)(int __excepts) {
152   __excepts = target_change_except(__excepts);
153   return REAL(feraiseexcept)(__excepts);
154 }
155 
WRAP(fetestexcept)156 int WRAP(fetestexcept)(int __excepts) {
157   __excepts = target_change_except(__excepts);
158   return target_get_except(REAL(fetestexcept)(__excepts));
159 }
160 
WRAP(fegetround)161 int WRAP(fegetround)(void) {
162   int rounding = REAL(fegetround)();
163   return target_get_rounding(rounding);
164 }
165 
WRAP(fesetround)166 int WRAP(fesetround)(int __round) {
167   __round = target_change_rounding(__round);
168   return REAL(fesetround)(__round);
169 }
170 
WRAP(feholdexcept)171 int WRAP(feholdexcept)(fenv_t_portable* __envp) {
172   memset(__envp, '\0', sizeof(fenv_t_portable));
173   fenv_t env;
174   int ret = REAL(feholdexcept)(&env);
175   memcpy(__envp, &env, sizeof(env));
176   return ret;
177 }
178 
WRAP(feupdateenv)179 int WRAP(feupdateenv)(const fenv_t_portable* __envp) {
180   fenv_t env;
181   memcpy(&env, __envp, sizeof(env));
182   return REAL(feupdateenv)(&env);
183 }
184 
WRAP(feenableexcept)185 int WRAP(feenableexcept)(int __excepts) {
186   __excepts = target_change_except(__excepts);
187   return REAL(feenableexcept)(__excepts);
188 }
189 
WRAP(fedisableexcept)190 int WRAP(fedisableexcept)(int __excepts) {
191   __excepts = target_change_except(__excepts);
192   return REAL(fedisableexcept)(__excepts);
193 }
194 
195 #endif /* _FENV_PORTABLE_H_ */
196