• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
deGetRoundingMode(void)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 
deSetRoundingMode(deRoundingMode mode)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 
deFractExp(double x,int * exponent)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. */
deFloatFractExp(float x,int * exponent)123 float deFloatFractExp (float x, int* exponent)
124 {
125 	return (float)deFractExp(x, exponent);
126 }
127 
deRoundEven(double a)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 }
136