259286cb5cf311cb3ca620c18c22c8a15724c105
[platform/upstream/VK-GL-CTS.git] / framework / delibs / debase / deMath.c
1 /*-------------------------------------------------------------------------
2  * drawElements Base Portability Library
3  * -------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Basic mathematical operations.
22  *//*--------------------------------------------------------------------*/
23
24 #include "deMath.h"
25
26 #if (DE_COMPILER == DE_COMPILER_MSC)
27 #       include <float.h>
28 #endif
29
30 #if (DE_COMPILER == DE_COMPILER_GCC) || (DE_COMPILER == DE_COMPILER_CLANG)
31 #       include <fenv.h>
32 #endif
33
34 deRoundingMode deGetRoundingMode (void)
35 {
36 #if (DE_COMPILER == DE_COMPILER_MSC)
37         unsigned int status = 0;
38         int ret;
39
40         ret = _controlfp_s(&status, 0, 0);
41         DE_ASSERT(ret == 0);
42
43         switch (status & _MCW_RC)
44         {
45                 case _RC_CHOP:  return DE_ROUNDINGMODE_TO_ZERO;
46                 case _RC_UP:    return DE_ROUNDINGMODE_TO_POSITIVE_INF;
47                 case _RC_DOWN:  return DE_ROUNDINGMODE_TO_NEGATIVE_INF;
48                 case _RC_NEAR:  return DE_ROUNDINGMODE_TO_NEAREST;
49                 default:                return DE_ROUNDINGMODE_LAST;
50         }
51 #elif (DE_COMPILER == DE_COMPILER_GCC) || (DE_COMPILER == DE_COMPILER_CLANG)
52         int mode = fegetround();
53         switch (mode)
54         {
55                 case FE_TOWARDZERO:     return DE_ROUNDINGMODE_TO_ZERO;
56                 case FE_UPWARD:         return DE_ROUNDINGMODE_TO_POSITIVE_INF;
57                 case FE_DOWNWARD:       return DE_ROUNDINGMODE_TO_NEGATIVE_INF;
58                 case FE_TONEAREST:      return DE_ROUNDINGMODE_TO_NEAREST;
59                 default:                        return DE_ROUNDINGMODE_LAST;
60         }
61 #else
62 #       error Implement deGetRoundingMode().
63 #endif
64 }
65
66 deBool deSetRoundingMode (deRoundingMode mode)
67 {
68 #if (DE_COMPILER == DE_COMPILER_MSC)
69         unsigned int flag = 0;
70         unsigned int oldState;
71         int ret;
72
73         switch (mode)
74         {
75                 case DE_ROUNDINGMODE_TO_ZERO:                   flag = _RC_CHOP;        break;
76                 case DE_ROUNDINGMODE_TO_POSITIVE_INF:   flag = _RC_UP;          break;
77                 case DE_ROUNDINGMODE_TO_NEGATIVE_INF:   flag = _RC_DOWN;        break;
78                 case DE_ROUNDINGMODE_TO_NEAREST:                flag = _RC_NEAR;        break;
79                 default:
80                         DE_ASSERT(DE_FALSE);
81         }
82
83         ret = _controlfp_s(&oldState, flag, _MCW_RC);
84         return ret == 0;
85 #elif (DE_COMPILER == DE_COMPILER_GCC) || (DE_COMPILER == DE_COMPILER_CLANG)
86         int flag = 0;
87         int ret;
88
89         switch (mode)
90         {
91                 case DE_ROUNDINGMODE_TO_ZERO:                   flag = FE_TOWARDZERO;   break;
92                 case DE_ROUNDINGMODE_TO_POSITIVE_INF:   flag = FE_UPWARD;               break;
93                 case DE_ROUNDINGMODE_TO_NEGATIVE_INF:   flag = FE_DOWNWARD;             break;
94                 case DE_ROUNDINGMODE_TO_NEAREST:                flag = FE_TONEAREST;    break;
95                 default:
96                         DE_ASSERT(DE_FALSE);
97         }
98
99         ret = fesetround(flag);
100         return ret == 0;
101 #else
102 #       error Implement deSetRoundingMode().
103 #endif
104 }
105
106 double deFractExp (double x, int* exponent)
107 {
108         if (deIsInf(x))
109         {
110                 *exponent = 0;
111                 return x;
112         }
113         else
114         {
115                 int             tmpExp  = 0;
116                 double  fract   = frexp(x, &tmpExp);
117                 *exponent = tmpExp - 1;
118                 return fract * 2.0;
119         }
120 }
121
122 /* We could use frexpf, if available. */
123 float deFloatFractExp (float x, int* exponent)
124 {
125         return (float)deFractExp(x, exponent);
126 }
127
128 double deRoundEven (double a)
129 {
130         double integer;
131         double fract = modf(a, &integer);
132         if (fabs(fract) == 0.5)
133                 return 2.0 * deRound(a / 2.0);
134         return deRound(a);
135 }