1b8e80941Smrg/**************************************************************************
2b8e80941Smrg *
3b8e80941Smrg * Copyright 2007-2015 VMware, Inc.
4b8e80941Smrg * All Rights Reserved.
5b8e80941Smrg *
6b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7b8e80941Smrg * copy of this software and associated documentation files (the
8b8e80941Smrg * "Software"), to deal in the Software without restriction, including
9b8e80941Smrg * without limitation the rights to use, copy, modify, merge, publish,
10b8e80941Smrg * distribute, sub license, and/or sell copies of the Software, and to
11b8e80941Smrg * permit persons to whom the Software is furnished to do so, subject to
12b8e80941Smrg * the following conditions:
13b8e80941Smrg *
14b8e80941Smrg * The above copyright notice and this permission notice (including the
15b8e80941Smrg * next paragraph) shall be included in all copies or substantial portions
16b8e80941Smrg * of the Software.
17b8e80941Smrg *
18b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19b8e80941Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20b8e80941Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21b8e80941Smrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22b8e80941Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23b8e80941Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24b8e80941Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25b8e80941Smrg *
26b8e80941Smrg **************************************************************************/
27b8e80941Smrg
28b8e80941Smrg/**
29b8e80941Smrg * Wrapper for math.h which makes sure we have definitions of all the c99
30b8e80941Smrg * functions.
31b8e80941Smrg */
32b8e80941Smrg
33b8e80941Smrg
34b8e80941Smrg#ifndef _C99_MATH_H_
35b8e80941Smrg#define _C99_MATH_H_
36b8e80941Smrg
37b8e80941Smrg#include <math.h>
38b8e80941Smrg#include "c99_compat.h"
39b8e80941Smrg
40b8e80941Smrg
41b8e80941Smrg/* This is to ensure that we get M_PI, etc. definitions */
42b8e80941Smrg#if defined(_MSC_VER) && !defined(_USE_MATH_DEFINES)
43b8e80941Smrg#error _USE_MATH_DEFINES define required when building with MSVC
44b8e80941Smrg#endif
45b8e80941Smrg
46b8e80941Smrg
47b8e80941Smrg#if !defined(_MSC_VER) && \
48b8e80941Smrg    __STDC_VERSION__ < 199901L && \
49b8e80941Smrg    (!defined(_XOPEN_SOURCE) || _XOPEN_SOURCE < 600) && \
50b8e80941Smrg    !defined(__cplusplus)
51b8e80941Smrg
52b8e80941Smrgstatic inline long int
53b8e80941Smrglrint(double d)
54b8e80941Smrg{
55b8e80941Smrg   long int rounded = (long int)(d + 0.5);
56b8e80941Smrg
57b8e80941Smrg   if (d - floor(d) == 0.5) {
58b8e80941Smrg      if (rounded % 2 != 0)
59b8e80941Smrg         rounded += (d > 0) ? -1 : 1;
60b8e80941Smrg   }
61b8e80941Smrg
62b8e80941Smrg   return rounded;
63b8e80941Smrg}
64b8e80941Smrg
65b8e80941Smrgstatic inline long int
66b8e80941Smrglrintf(float f)
67b8e80941Smrg{
68b8e80941Smrg   long int rounded = (long int)(f + 0.5f);
69b8e80941Smrg
70b8e80941Smrg   if (f - floorf(f) == 0.5f) {
71b8e80941Smrg      if (rounded % 2 != 0)
72b8e80941Smrg         rounded += (f > 0) ? -1 : 1;
73b8e80941Smrg   }
74b8e80941Smrg
75b8e80941Smrg   return rounded;
76b8e80941Smrg}
77b8e80941Smrg
78b8e80941Smrgstatic inline long long int
79b8e80941Smrgllrint(double d)
80b8e80941Smrg{
81b8e80941Smrg   long long int rounded = (long long int)(d + 0.5);
82b8e80941Smrg
83b8e80941Smrg   if (d - floor(d) == 0.5) {
84b8e80941Smrg      if (rounded % 2 != 0)
85b8e80941Smrg         rounded += (d > 0) ? -1 : 1;
86b8e80941Smrg   }
87b8e80941Smrg
88b8e80941Smrg   return rounded;
89b8e80941Smrg}
90b8e80941Smrg
91b8e80941Smrgstatic inline long long int
92b8e80941Smrgllrintf(float f)
93b8e80941Smrg{
94b8e80941Smrg   long long int rounded = (long long int)(f + 0.5f);
95b8e80941Smrg
96b8e80941Smrg   if (f - floorf(f) == 0.5f) {
97b8e80941Smrg      if (rounded % 2 != 0)
98b8e80941Smrg         rounded += (f > 0) ? -1 : 1;
99b8e80941Smrg   }
100b8e80941Smrg
101b8e80941Smrg   return rounded;
102b8e80941Smrg}
103b8e80941Smrg
104b8e80941Smrgstatic inline float
105b8e80941Smrgexp2f(float f)
106b8e80941Smrg{
107b8e80941Smrg   return powf(2.0f, f);
108b8e80941Smrg}
109b8e80941Smrg
110b8e80941Smrgstatic inline double
111b8e80941Smrgexp2(double d)
112b8e80941Smrg{
113b8e80941Smrg   return pow(2.0, d);
114b8e80941Smrg}
115b8e80941Smrg
116b8e80941Smrg#endif /* C99 */
117b8e80941Smrg
118b8e80941Smrg
119b8e80941Smrg/*
120b8e80941Smrg * signbit() is a macro on Linux.  Not available on Windows.
121b8e80941Smrg */
122b8e80941Smrg#ifndef signbit
123b8e80941Smrg#define signbit(x) ((x) < 0.0f)
124b8e80941Smrg#endif
125b8e80941Smrg
126b8e80941Smrg
127b8e80941Smrg#ifndef M_PI
128b8e80941Smrg#define M_PI (3.14159265358979323846)
129b8e80941Smrg#endif
130b8e80941Smrg
131b8e80941Smrg#ifndef M_E
132b8e80941Smrg#define M_E (2.7182818284590452354)
133b8e80941Smrg#endif
134b8e80941Smrg
135b8e80941Smrg#ifndef M_LOG2E
136b8e80941Smrg#define M_LOG2E (1.4426950408889634074)
137b8e80941Smrg#endif
138b8e80941Smrg
139b8e80941Smrg#ifndef FLT_MAX_EXP
140b8e80941Smrg#define FLT_MAX_EXP 128
141b8e80941Smrg#endif
142b8e80941Smrg
143b8e80941Smrg
144b8e80941Smrg#if defined(fpclassify)
145b8e80941Smrg/* ISO C99 says that fpclassify is a macro.  Assume that any implementation
146b8e80941Smrg * of fpclassify, whether it's in a C99 compiler or not, will be a macro.
147b8e80941Smrg */
148b8e80941Smrg#elif defined(__cplusplus)
149b8e80941Smrg/* For C++, fpclassify() should be defined in <cmath> */
150b8e80941Smrg#elif defined(_MSC_VER)
151b8e80941Smrg/* Not required on VS2013 and above.  Oddly, the fpclassify() function
152b8e80941Smrg * doesn't exist in such a form on MSVC.  This is an implementation using
153b8e80941Smrg * slightly different lower-level Windows functions.
154b8e80941Smrg */
155b8e80941Smrg#include <float.h>
156b8e80941Smrg
157b8e80941Smrgstatic inline enum {FP_NAN, FP_INFINITE, FP_ZERO, FP_SUBNORMAL, FP_NORMAL}
158b8e80941Smrgfpclassify(double x)
159b8e80941Smrg{
160b8e80941Smrg   switch(_fpclass(x)) {
161b8e80941Smrg   case _FPCLASS_SNAN: /* signaling NaN */
162b8e80941Smrg   case _FPCLASS_QNAN: /* quiet NaN */
163b8e80941Smrg      return FP_NAN;
164b8e80941Smrg   case _FPCLASS_NINF: /* negative infinity */
165b8e80941Smrg   case _FPCLASS_PINF: /* positive infinity */
166b8e80941Smrg      return FP_INFINITE;
167b8e80941Smrg   case _FPCLASS_NN:   /* negative normal */
168b8e80941Smrg   case _FPCLASS_PN:   /* positive normal */
169b8e80941Smrg      return FP_NORMAL;
170b8e80941Smrg   case _FPCLASS_ND:   /* negative denormalized */
171b8e80941Smrg   case _FPCLASS_PD:   /* positive denormalized */
172b8e80941Smrg      return FP_SUBNORMAL;
173b8e80941Smrg   case _FPCLASS_NZ:   /* negative zero */
174b8e80941Smrg   case _FPCLASS_PZ:   /* positive zero */
175b8e80941Smrg      return FP_ZERO;
176b8e80941Smrg   default:
177b8e80941Smrg      /* Should never get here; but if we do, this will guarantee
178b8e80941Smrg       * that the pattern is not treated like a number.
179b8e80941Smrg       */
180b8e80941Smrg      return FP_NAN;
181b8e80941Smrg   }
182b8e80941Smrg}
183b8e80941Smrg#else
184b8e80941Smrg#error "Need to include or define an fpclassify function"
185b8e80941Smrg#endif
186b8e80941Smrg
187b8e80941Smrg
188b8e80941Smrg/* Since C++11, the following functions are part of the std namespace. Their C
189b8e80941Smrg * counteparts should still exist in the global namespace, however cmath
190b8e80941Smrg * undefines those functions, which in glibc 2.23, are defined as macros rather
191b8e80941Smrg * than functions as in glibc 2.22.
192b8e80941Smrg */
193b8e80941Smrg#if __cplusplus >= 201103L && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 23))
194b8e80941Smrg#include <cmath>
195b8e80941Smrg
196b8e80941Smrgusing std::fpclassify;
197b8e80941Smrgusing std::isfinite;
198b8e80941Smrgusing std::isinf;
199b8e80941Smrgusing std::isnan;
200b8e80941Smrgusing std::isnormal;
201b8e80941Smrgusing std::signbit;
202b8e80941Smrgusing std::isgreater;
203b8e80941Smrgusing std::isgreaterequal;
204b8e80941Smrgusing std::isless;
205b8e80941Smrgusing std::islessequal;
206b8e80941Smrgusing std::islessgreater;
207b8e80941Smrgusing std::isunordered;
208b8e80941Smrg#endif
209b8e80941Smrg
210b8e80941Smrg
211b8e80941Smrg#endif /* #define _C99_MATH_H_ */
212