Home | History | Annotate | Download | only in debase
      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 }
    136