Browse Source

Switch to C++14.

Branimir Karadžić 7 years ago
parent
commit
ac47b863b0
5 changed files with 162 additions and 151 deletions
  1. 25 25
      include/bx/inline/math.inl
  2. 37 37
      include/bx/math.h
  3. 14 14
      scripts/toolchain.lua
  4. 33 47
      src/math.cpp
  5. 53 28
      tests/string_test.cpp

+ 25 - 25
include/bx/inline/math.inl

@@ -23,25 +23,25 @@ namespace bx
 		return _rad * 180.0f / kPi;
 	}
 
-	inline BX_CONST_FUNC uint32_t floatToBits(float _a)
+	inline constexpr BX_CONST_FUNC uint32_t floatToBits(float _a)
 	{
 		union { float f; uint32_t ui; } u = { _a };
 		return u.ui;
 	}
 
-	inline BX_CONST_FUNC float bitsToFloat(uint32_t _a)
+	inline constexpr BX_CONST_FUNC float bitsToFloat(uint32_t _a)
 	{
 		union { uint32_t ui; float f; } u = { _a };
 		return u.f;
 	}
 
-	inline BX_CONST_FUNC uint64_t doubleToBits(double _a)
+	inline constexpr BX_CONST_FUNC uint64_t doubleToBits(double _a)
 	{
 		union { double f; uint64_t ui; } u = { _a };
 		return u.ui;
 	}
 
-	inline BX_CONST_FUNC double bitsToDouble(uint64_t _a)
+	inline constexpr BX_CONST_FUNC double bitsToDouble(uint64_t _a)
 	{
 		union { uint64_t ui; double f; } u = { _a };
 		return u.f;
@@ -58,37 +58,37 @@ namespace bx
 		return result;
 	}
 
-	inline BX_CONST_FUNC bool isNan(float _f)
+	inline constexpr BX_CONST_FUNC bool isNan(float _f)
 	{
 		const uint32_t tmp = floatToBits(_f) & INT32_MAX;
 		return tmp > UINT32_C(0x7f800000);
 	}
 
-	inline BX_CONST_FUNC bool isNan(double _f)
+	inline constexpr BX_CONST_FUNC bool isNan(double _f)
 	{
 		const uint64_t tmp = doubleToBits(_f) & INT64_MAX;
 		return tmp > UINT64_C(0x7ff0000000000000);
 	}
 
-	inline BX_CONST_FUNC bool isFinite(float _f)
+	inline constexpr BX_CONST_FUNC bool isFinite(float _f)
 	{
 		const uint32_t tmp = floatToBits(_f) & INT32_MAX;
 		return tmp < UINT32_C(0x7f800000);
 	}
 
-	inline BX_CONST_FUNC bool isFinite(double _f)
+	inline constexpr BX_CONST_FUNC bool isFinite(double _f)
 	{
 		const uint64_t tmp = doubleToBits(_f) & INT64_MAX;
 		return tmp < UINT64_C(0x7ff0000000000000);
 	}
 
-	inline BX_CONST_FUNC bool isInfinite(float _f)
+	inline constexpr BX_CONST_FUNC bool isInfinite(float _f)
 	{
 		const uint32_t tmp = floatToBits(_f) & INT32_MAX;
 		return tmp == UINT32_C(0x7f800000);
 	}
 
-	inline BX_CONST_FUNC bool isInfinite(double _f)
+	inline constexpr BX_CONST_FUNC bool isInfinite(double _f)
 	{
 		const uint64_t tmp = doubleToBits(_f) & INT64_MAX;
 		return tmp == UINT64_C(0x7ff0000000000000);
@@ -104,22 +104,22 @@ namespace bx
 		return -floor(-_a);
 	}
 
-	inline BX_CONST_FUNC float lerp(float _a, float _b, float _t)
+	inline constexpr BX_CONST_FUNC float lerp(float _a, float _b, float _t)
 	{
 		return _a + (_b - _a) * _t;
 	}
 
-	inline BX_CONST_FUNC float abs(float _a)
+	inline constexpr BX_CONST_FUNC float sign(float _a)
 	{
-		return _a < 0.0f ? -_a : _a;
+		return _a < 0.0f ? -1.0f : 1.0f;
 	}
 
-	inline BX_CONST_FUNC float sign(float _a)
+	inline constexpr BX_CONST_FUNC float abs(float _a)
 	{
-		return _a < 0.0f ? -1.0f : 1.0f;
+		return _a < 0.0f ? -_a : _a;
 	}
 
-	inline BX_CONST_FUNC float square(float _a)
+	inline constexpr BX_CONST_FUNC float square(float _a)
 	{
 		return _a * _a;
 	}
@@ -237,17 +237,17 @@ namespace bx
 #endif // BX_CONFIG_SUPPORTS_SIMD
 	}
 
-	inline BX_CONST_FUNC float trunc(float _a)
+	inline constexpr BX_CONST_FUNC float trunc(float _a)
 	{
 		return float(int(_a) );
 	}
 
-	inline BX_CONST_FUNC float fract(float _a)
+	inline constexpr BX_CONST_FUNC float fract(float _a)
 	{
 		return _a - trunc(_a);
 	}
 
-	inline BX_CONST_FUNC float mad(float _a, float _b, float _c)
+	inline constexpr BX_CONST_FUNC float mad(float _a, float _b, float _c)
 	{
 		return _a * _b + _c;
 	}
@@ -257,7 +257,7 @@ namespace bx
 		return _a - _b * floor(_a / _b);
 	}
 
-	inline BX_CONST_FUNC bool equal(float _a, float _b, float _epsilon)
+	inline constexpr BX_CONST_FUNC bool equal(float _a, float _b, float _epsilon)
 	{
 		// Reference:
 		// https://web.archive.org/web/20181103180318/http://realtimecollisiondetection.net/blog/?p=89
@@ -283,27 +283,27 @@ namespace bx
 		return result;
 	}
 
-	inline BX_CONST_FUNC float step(float _edge, float _a)
+	inline constexpr BX_CONST_FUNC float step(float _edge, float _a)
 	{
 		return _a < _edge ? 0.0f : 1.0f;
 	}
 
-	inline BX_CONST_FUNC float pulse(float _a, float _start, float _end)
+	inline constexpr BX_CONST_FUNC float pulse(float _a, float _start, float _end)
 	{
 		return step(_a, _start) - step(_a, _end);
 	}
 
-	inline BX_CONST_FUNC float smoothStep(float _a)
+	inline constexpr BX_CONST_FUNC float smoothStep(float _a)
 	{
 		return square(_a)*(3.0f - 2.0f*_a);
 	}
 
-	inline BX_CONST_FUNC float bias(float _time, float _bias)
+	inline constexpr BX_CONST_FUNC float bias(float _time, float _bias)
 	{
 		return _time / ( ( (1.0f/_bias - 2.0f)*(1.0f - _time) ) + 1.0f);
 	}
 
-	inline BX_CONST_FUNC float gain(float _time, float _gain)
+	inline constexpr BX_CONST_FUNC float gain(float _time, float _gain)
 	{
 		if (_time < 0.5f)
 		{

+ 37 - 37
include/bx/math.h

@@ -13,21 +13,21 @@
 
 namespace bx
 {
-	extern const float kPi;
-	extern const float kPi2;
-	extern const float kInvPi;
-	extern const float kPiHalf;
-	extern const float kPiQuarter;
-	extern const float kSqrt2;
-	extern const float kLogNat10;
-	extern const float kInvLogNat2;
-	extern const float kLogNat2Hi;
-	extern const float kLogNat2Lo;
-	extern const float kE;
-	extern const float kNearZero;
+	constexpr float kPi         = 3.1415926535897932384626433832795f;
+	constexpr float kPi2        = 6.2831853071795864769252867665590f;
+	constexpr float kInvPi      = 1.0f/kPi;
+	constexpr float kPiHalf     = 1.5707963267948966192313216916398f;
+	constexpr float kPiQuarter  = 0.7853981633974483096156608458199f;
+	constexpr float kSqrt2      = 1.4142135623730950488016887242097f;
+	constexpr float kLogNat10   = 2.3025850929940456840179914546844f;
+	constexpr float kInvLogNat2 = 1.4426950408889634073599246810019f;
+	constexpr float kLogNat2Hi  = 0.6931471805599453094172321214582f;
+	constexpr float kLogNat2Lo  = 1.90821492927058770002e-10f;
+	constexpr float kE          = 2.7182818284590452353602874713527f;
+	constexpr float kNearZero   = 1.0f/float(1 << 28);
+	constexpr float kFloatMin   = 1.175494e-38f;
+	constexpr float kFloatMax   = 3.402823e+38f;
 	extern const float kInfinity;
-	extern const float kFloatMin;
-	extern const float kFloatMax;
 
 	///
 	typedef float (*LerpFn)(float _a, float _b, float _t);
@@ -62,19 +62,19 @@ namespace bx
 
 	/// Reinterprets the bit pattern of _a as uint32_t.
 	///
-	BX_CONST_FUNC uint32_t floatToBits(float _a);
+	constexpr BX_CONST_FUNC uint32_t floatToBits(float _a);
 
 	/// Reinterprets the bit pattern of _a as float.
 	///
-	BX_CONST_FUNC float bitsToFloat(uint32_t _a);
+	constexpr BX_CONST_FUNC float bitsToFloat(uint32_t _a);
 
 	/// Reinterprets the bit pattern of _a as uint64_t.
 	///
-	BX_CONST_FUNC uint64_t doubleToBits(double _a);
+	constexpr BX_CONST_FUNC uint64_t doubleToBits(double _a);
 
 	/// Reinterprets the bit pattern of _a as double.
 	///
-	BX_CONST_FUNC double bitsToDouble(uint64_t _a);
+	constexpr BX_CONST_FUNC double bitsToDouble(uint64_t _a);
 
 	/// Returns sortable floating point value.
 	///
@@ -82,27 +82,27 @@ namespace bx
 
 	/// Returns true if _f is a number that is NaN.
 	///
-	BX_CONST_FUNC bool isNan(float _f);
+	constexpr BX_CONST_FUNC bool isNan(float _f);
 
 	/// Returns true if _f is a number that is NaN.
 	///
-	BX_CONST_FUNC bool isNan(double _f);
+	constexpr BX_CONST_FUNC bool isNan(double _f);
 
 	/// Returns true if _f is not infinite and is not a NaN.
 	///
-	BX_CONST_FUNC bool isFinite(float _f);
+	constexpr BX_CONST_FUNC bool isFinite(float _f);
 
 	/// Returns true if _f is not infinite and is not a NaN.
 	///
-	BX_CONST_FUNC bool isFinite(double _f);
+	constexpr BX_CONST_FUNC bool isFinite(double _f);
 
 	/// Returns true if _f is infinite and is not a NaN.
 	///
-	BX_CONST_FUNC bool isInfinite(float _f);
+	constexpr BX_CONST_FUNC bool isInfinite(float _f);
 
 	/// Returns true if _f is infinite and is not a NaN.
 	///
-	BX_CONST_FUNC bool isInfinite(double _f);
+	constexpr BX_CONST_FUNC bool isInfinite(double _f);
 
 	/// Returns the largest integer value not greater than _f.
 	///
@@ -118,19 +118,19 @@ namespace bx
 
 	/// Returns linear interpolation between two values _a and _b.
 	///
-	BX_CONST_FUNC float lerp(float _a, float _b, float _t);
+	constexpr BX_CONST_FUNC float lerp(float _a, float _b, float _t);
 
 	/// Returns the sign of _a.
 	///
-	BX_CONST_FUNC float sign(float _a);
+	constexpr BX_CONST_FUNC float sign(float _a);
 
 	/// Returns the absolute of _a.
 	///
-	BX_CONST_FUNC float abs(float _a);
+	constexpr BX_CONST_FUNC float abs(float _a);
 
 	/// Returns the square of _a.
 	///
-	BX_CONST_FUNC float square(float _a);
+	constexpr BX_CONST_FUNC float square(float _a);
 
 	/// Returns the cosine of the argument _a.
 	///
@@ -211,23 +211,23 @@ namespace bx
 
 	/// Returns the nearest integer not greater in magnitude than _a.
 	///
-	BX_CONST_FUNC float trunc(float _a);
+	constexpr BX_CONST_FUNC float trunc(float _a);
 
 	/// Returns the fractional (or decimal) part of _a, which is greater than or equal to 0
 	/// and less than 1.
 	///
-	BX_CONST_FUNC float fract(float _a);
+	constexpr BX_CONST_FUNC float fract(float _a);
 
 	/// Returns result of multipla and add (_a * _b + _c).
 	///
-	BX_CONST_FUNC float mad(float _a, float _b, float _c);
+	constexpr BX_CONST_FUNC float mad(float _a, float _b, float _c);
 
 	/// Returns the floating-point remainder of the division operation _a/_b.
 	///
 	BX_CONST_FUNC float mod(float _a, float _b);
 
 	///
-	BX_CONST_FUNC bool equal(float _a, float _b, float _epsilon);
+	constexpr BX_CONST_FUNC bool equal(float _a, float _b, float _epsilon);
 
 	///
 	BX_CONST_FUNC bool equal(const float* _a, const float* _b, uint32_t _num, float _epsilon);
@@ -236,23 +236,23 @@ namespace bx
 	BX_CONST_FUNC float wrap(float _a, float _wrap);
 
 	///
-	BX_CONST_FUNC float step(float _edge, float _a);
+	constexpr BX_CONST_FUNC float step(float _edge, float _a);
 
 	///
-	BX_CONST_FUNC float pulse(float _a, float _start, float _end);
+	constexpr BX_CONST_FUNC float pulse(float _a, float _start, float _end);
 
 	///
-	BX_CONST_FUNC float smoothStep(float _a);
+	constexpr BX_CONST_FUNC float smoothStep(float _a);
 
 	// References:
 	//  - Bias And Gain Are Your Friend
 	//    http://blog.demofox.org/2012/09/24/bias-and-gain-are-your-friend/
 	//  - http://demofox.org/biasgain.html
 	///
-	BX_CONST_FUNC float bias(float _time, float _bias);
+	constexpr BX_CONST_FUNC float bias(float _time, float _bias);
 
 	///
-	BX_CONST_FUNC float gain(float _time, float _gain);
+	constexpr BX_CONST_FUNC float gain(float _time, float _gain);
 
 	///
 	BX_CONST_FUNC float angleDiff(float _a, float _b);

+ 14 - 14
scripts/toolchain.lua

@@ -648,7 +648,7 @@ function toolchain(_buildDir, _libDir)
 			"-Wundef",
 		}
 		buildoptions_cpp {
-			"-std=c++11",
+			"-std=c++14",
 		}
 		linkoptions {
 			"-Wl,--gc-sections",
@@ -737,7 +737,7 @@ function toolchain(_buildDir, _libDir)
 --			"-Wuseless-cast",
 		}
 		buildoptions_cpp {
-			"-std=c++11",
+			"-std=c++14",
 		}
 		links {
 			"rt",
@@ -794,7 +794,7 @@ function toolchain(_buildDir, _libDir)
 			"-Wundef",
 		}
 		buildoptions_cpp {
-			"-std=c++11",
+			"-std=c++14",
 		}
 		links {
 			"rt",
@@ -813,7 +813,7 @@ function toolchain(_buildDir, _libDir)
 			"-Wundef",
 		}
 		buildoptions_cpp {
-			"-std=c++11",
+			"-std=c++14",
 		}
 		links {
 			"rt",
@@ -854,7 +854,7 @@ function toolchain(_buildDir, _libDir)
 			"-Wundef",
 		}
 		buildoptions_cpp {
-			"-std=c++11",
+			"-std=c++14",
 		}
 		linkoptions {
 			"-no-canonical-prefixes",
@@ -873,7 +873,7 @@ function toolchain(_buildDir, _libDir)
 			"__STEAMLINK__=1", -- There is no special prefedined compiler symbol to detect SteamLink, faking it.
 		}
 		buildoptions {
-			"-std=c++11",
+			"-std=c++14",
 			"-Wfatal-errors",
 			"-Wunused-value",
 			"-Wundef",
@@ -989,7 +989,7 @@ function toolchain(_buildDir, _libDir)
 			"-Wundef",
 		}
 		buildoptions_cpp {
-			"-std=c++11",
+			"-std=c++14",
 		}
 
 	configuration { "freebsd" }
@@ -1049,10 +1049,10 @@ function toolchain(_buildDir, _libDir)
 
 	configuration { "osx" }
 		buildoptions_cpp {
-			"-std=c++11",
+			"-std=c++14",
 		}
 		buildoptions_objcpp {
-			"-std=c++11",
+			"-std=c++14",
 		}
 		buildoptions {
 			"-Wfatal-errors",
@@ -1067,10 +1067,10 @@ function toolchain(_buildDir, _libDir)
 			"-lc++",
 		}
 		buildoptions_cpp {
-			"-std=c++11",
+			"-std=c++14",
 		}
 		buildoptions_objcpp {
-			"-std=c++11",
+			"-std=c++14",
 		}
 		buildoptions {
 			"-Wfatal-errors",
@@ -1215,7 +1215,7 @@ function toolchain(_buildDir, _libDir)
 			"$(SCE_ORBIS_SDK_DIR)/target/include_common",
 		}
 		buildoptions_cpp {
-			"-std=c++11",
+			"-std=c++14",
 		}
 
 	configuration { "rpi" }
@@ -1234,7 +1234,7 @@ function toolchain(_buildDir, _libDir)
 			"-Wundef",
 		}
 		buildoptions_cpp {
-			"-std=c++11",
+			"-std=c++14",
 		}
 		includedirs {
 			"/opt/vc/include",
@@ -1266,7 +1266,7 @@ function toolchain(_buildDir, _libDir)
 			"--sysroot=$(FREEDOM_E_SDK)/work/build/riscv-gnu-toolchain/riscv64-unknown-elf/prefix/riscv64-unknown-elf",
 		}
 		buildoptions_cpp {
-			"-std=c++11",
+			"-std=c++14",
 		}
 
 	configuration {} -- reset configuration

+ 33 - 47
src/math.cpp

@@ -9,35 +9,21 @@
 
 namespace bx
 {
-	const float kPi         = 3.1415926535897932384626433832795f;
-	const float kPi2        = 6.2831853071795864769252867665590f;
-	const float kInvPi      = 1.0f/kPi;
-	const float kPiHalf     = 1.5707963267948966192313216916398f;
-	const float kPiQuarter  = 0.7853981633974483096156608458199f;
-	const float kSqrt2      = 1.4142135623730950488016887242097f;
-	const float kLogNat10   = 2.3025850929940456840179914546844f;
-	const float kInvLogNat2 = 1.4426950408889634073599246810019f;
-	const float kLogNat2Hi  = 0.6931471805599453094172321214582f;
-	const float kLogNat2Lo  = 1.90821492927058770002e-10f;
-	const float kE          = 2.7182818284590452353602874713527f;
-	const float kNearZero   = 1.0f/float(1 << 28);
-	const float kFloatMin   = 1.175494e-38f;
-	const float kFloatMax   = 3.402823e+38f;
-	const float kInfinity   = bitsToFloat(UINT32_C(0x7f800000) );
+	const float kInfinity = bitsToFloat(UINT32_C(0x7f800000) );
 
 	namespace
 	{
-		static const float kSinC2  = -0.16666667163372039794921875f;
-		static const float kSinC4  =  8.333347737789154052734375e-3f;
-		static const float kSinC6  = -1.9842604524455964565277099609375e-4f;
-		static const float kSinC8  =  2.760012648650445044040679931640625e-6f;
-		static const float kSinC10 = -2.50293279435709337121807038784027099609375e-8f;
+		constexpr float kSinC2  = -0.16666667163372039794921875f;
+		constexpr float kSinC4  =  8.333347737789154052734375e-3f;
+		constexpr float kSinC6  = -1.9842604524455964565277099609375e-4f;
+		constexpr float kSinC8  =  2.760012648650445044040679931640625e-6f;
+		constexpr float kSinC10 = -2.50293279435709337121807038784027099609375e-8f;
 
-		static const float kCosC2  = -0.5f;
-		static const float kCosC4  =  4.166664183139801025390625e-2f;
-		static const float kCosC6  = -1.388833043165504932403564453125e-3f;
-		static const float kCosC8  =  2.47562347794882953166961669921875e-5f;
-		static const float kCosC10 = -2.59630184018533327616751194000244140625e-7f;
+		constexpr float kCosC2  = -0.5f;
+		constexpr float kCosC4  =  4.166664183139801025390625e-2f;
+		constexpr float kCosC6  = -1.388833043165504932403564453125e-3f;
+		constexpr float kCosC8  =  2.47562347794882953166961669921875e-5f;
+		constexpr float kCosC10 = -2.59630184018533327616751194000244140625e-7f;
 
 	} // namespace
 
@@ -86,10 +72,10 @@ namespace bx
 
 	namespace
 	{
-		static const float kAcosC0 =  1.5707288f;
-		static const float kAcosC1 = -0.2121144f;
-		static const float kAcosC2 =  0.0742610f;
-		static const float kAcosC3 = -0.0187293f;
+		constexpr float kAcosC0 =  1.5707288f;
+		constexpr float kAcosC1 = -0.2121144f;
+		constexpr float kAcosC2 =  0.0742610f;
+		constexpr float kAcosC3 = -0.0187293f;
 
 	} // namespace
 
@@ -109,12 +95,12 @@ namespace bx
 
 	namespace
 	{
-		static const float kAtan2C0 = -0.013480470f;
-		static const float kAtan2C1 =  0.057477314f;
-		static const float kAtan2C2 = -0.121239071f;
-		static const float kAtan2C3 =  0.195635925f;
-		static const float kAtan2C4 = -0.332994597f;
-		static const float kAtan2C5 =  0.999995630f;
+		constexpr float kAtan2C0 = -0.013480470f;
+		constexpr float kAtan2C1 =  0.057477314f;
+		constexpr float kAtan2C2 = -0.121239071f;
+		constexpr float kAtan2C3 =  0.195635925f;
+		constexpr float kAtan2C4 = -0.332994597f;
+		constexpr float kAtan2C5 =  0.999995630f;
 
 	} // namespace
 
@@ -175,11 +161,11 @@ namespace bx
 
 	namespace
 	{
-		static const float kExpC0  =  1.66666666666666019037e-01f;
-		static const float kExpC1  = -2.77777777770155933842e-03f;
-		static const float kExpC2  =  6.61375632143793436117e-05f;
-		static const float kExpC3  = -1.65339022054652515390e-06f;
-		static const float kExpC4  =  4.13813679705723846039e-08f;
+		constexpr float kExpC0  =  1.66666666666666019037e-01f;
+		constexpr float kExpC1  = -2.77777777770155933842e-03f;
+		constexpr float kExpC2  =  6.61375632143793436117e-05f;
+		constexpr float kExpC3  = -1.65339022054652515390e-06f;
+		constexpr float kExpC4  =  4.13813679705723846039e-08f;
 
 	} // namespace
 
@@ -209,13 +195,13 @@ namespace bx
 
 	namespace
 	{
-		static const float kLogC0 = 6.666666666666735130e-01f;
-		static const float kLogC1 = 3.999999999940941908e-01f;
-		static const float kLogC2 = 2.857142874366239149e-01f;
-		static const float kLogC3 = 2.222219843214978396e-01f;
-		static const float kLogC4 = 1.818357216161805012e-01f;
-		static const float kLogC5 = 1.531383769920937332e-01f;
-		static const float kLogC6 = 1.479819860511658591e-01f;
+		constexpr float kLogC0 = 6.666666666666735130e-01f;
+		constexpr float kLogC1 = 3.999999999940941908e-01f;
+		constexpr float kLogC2 = 2.857142874366239149e-01f;
+		constexpr float kLogC3 = 2.222219843214978396e-01f;
+		constexpr float kLogC4 = 1.818357216161805012e-01f;
+		constexpr float kLogC5 = 1.531383769920937332e-01f;
+		constexpr float kLogC6 = 1.479819860511658591e-01f;
 
 	} // namespace
 

+ 53 - 28
tests/string_test.cpp

@@ -318,15 +318,16 @@ TEST_CASE("toString double", "")
 	REQUIRE(testToString(-79.39773355813419,      "-79.39773355813419") );
 }
 
-static bool testFromString(double _value, const char* _input)
+template<typename Ty>
+static bool testFromString(Ty _value, const char* _input)
 {
 	char tmp[1024];
 	bx::toString(tmp, BX_COUNTOF(tmp), _value);
 
-	double lhs;
+	Ty lhs;
 	bx::fromString(&lhs, tmp);
 
-	double rhs;
+	Ty rhs;
 	bx::fromString(&rhs, _input);
 
 	if (lhs == rhs)
@@ -338,33 +339,57 @@ static bool testFromString(double _value, const char* _input)
 	return false;
 }
 
+TEST_CASE("fromString float", "")
+{
+	REQUIRE(testFromString<float>(std::numeric_limits<float>::min(),    "1.175494351e-38") );
+	REQUIRE(testFromString<float>(std::numeric_limits<float>::lowest(), "-3.402823466e+38") );
+	REQUIRE(testFromString<float>(std::numeric_limits<float>::max(),    "3.402823466e+38") );
+}
+
 TEST_CASE("fromString double", "")
 {
-	REQUIRE(testFromString(0.0,                     "0.0") );
-	REQUIRE(testFromString(-0.0,                    "-0.0") );
-	REQUIRE(testFromString(1.0,                     "1.0") );
-	REQUIRE(testFromString(-1.0,                    "-1.0") );
-	REQUIRE(testFromString(1.2345,                  "1.2345") );
-	REQUIRE(testFromString(1.2345678,               "1.2345678") );
-	REQUIRE(testFromString(0.123456789012,          "0.123456789012") );
-	REQUIRE(testFromString(1234567.8,               "1234567.8") );
-	REQUIRE(testFromString(-79.39773355813419,      "-79.39773355813419") );
-	REQUIRE(testFromString(0.000001,                "0.000001") );
-	REQUIRE(testFromString(0.0000001,               "1e-7") );
-	REQUIRE(testFromString(1e30,                    "1e30") );
-	REQUIRE(testFromString(1.234567890123456e30,    "1.234567890123456e30") );
-	REQUIRE(testFromString(-5e-324,                 "-5e-324") );
-	REQUIRE(testFromString(2.225073858507201e-308,  "2.225073858507201e-308") );
-	REQUIRE(testFromString(2.2250738585072014e-308, "2.2250738585072014e-308") );
-	REQUIRE(testFromString(1.7976931348623157e308,  "1.7976931348623157e308") );
-	REQUIRE(testFromString(0.00000123123123,        "0.00000123123123") );
-	REQUIRE(testFromString(0.000000123123123,       "1.23123123e-7") );
-	REQUIRE(testFromString(123123.123,              "123123.123") );
-	REQUIRE(testFromString(1231231.23,              "1231231.23") );
-	REQUIRE(testFromString(0.000000000123123,       "1.23123e-10") );
-	REQUIRE(testFromString(0.0000000001,            "1e-10") );
-	REQUIRE(testFromString(-270.000000,             "-270.0") );
-	REQUIRE(testFromString(2.2250738585072011e-308, "2.2250738585072011e-308") );
+	REQUIRE(testFromString<double>(0.0,                     "0.0") );
+	REQUIRE(testFromString<double>(-0.0,                    "-0.0") );
+	REQUIRE(testFromString<double>(1.0,                     "1.0") );
+	REQUIRE(testFromString<double>(-1.0,                    "-1.0") );
+	REQUIRE(testFromString<double>(1.2345,                  "1.2345") );
+	REQUIRE(testFromString<double>(1.2345678,               "1.2345678") );
+	REQUIRE(testFromString<double>(0.123456789012,          "0.123456789012") );
+	REQUIRE(testFromString<double>(123456.789,              "123456.789") );
+	REQUIRE(testFromString<double>(1234567.8,               "1234567.8") );
+	REQUIRE(testFromString<double>(-79.39773355813419,      "-79.39773355813419") );
+	REQUIRE(testFromString<double>(0.000001,                "0.000001") );
+	REQUIRE(testFromString<double>(0.0000001,               "1e-7") );
+	REQUIRE(testFromString<double>(1e30,                    "1e30") );
+	REQUIRE(testFromString<double>(1.234567890123456e30,    "1.234567890123456e30") );
+	REQUIRE(testFromString<double>(-5e-324,                 "-5e-324") );
+	REQUIRE(testFromString<double>(2.225073858507201e-308,  "2.225073858507201e-308") );
+	REQUIRE(testFromString<double>(2.2250738585072014e-308, "2.2250738585072014e-308") );
+	REQUIRE(testFromString<double>(1.7976931348623157e308,  "1.7976931348623157e308") );
+	REQUIRE(testFromString<double>(0.00000123123123,        "0.00000123123123") );
+	REQUIRE(testFromString<double>(0.000000123123123,       "1.23123123e-7") );
+	REQUIRE(testFromString<double>(123123.123,              "123123.123") );
+	REQUIRE(testFromString<double>(1231231.23,              "1231231.23") );
+	REQUIRE(testFromString<double>(0.000000000123123,       "1.23123e-10") );
+	REQUIRE(testFromString<double>(0.0000000001,            "1e-10") );
+	REQUIRE(testFromString<double>(-270.000000,             "-270.0") );
+	REQUIRE(testFromString<double>(2.2250738585072011e-308, "2.2250738585072011e-308") ); // https://web.archive.org/web/20181112222123/https://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
+	REQUIRE(testFromString<double>(2.2250738585072009e-308, "2.2250738585072009e-308") ); // Max subnormal double
+	REQUIRE(testFromString<double>(4.9406564584124654e-324, "4.9406564584124654e-324") ); // Min denormal
+	REQUIRE(testFromString<double>(1.7976931348623157e+308, "1.7976931348623157e+308") ); // Max double
+
+//  warning: magnitude of floating-point constant too small for type 'double'; minimum is 4.9406564584124654E-324
+//	REQUIRE(testFromString<double>(1e-10000,                "0.0") );                     // Must underflow
+//	integer literal is too large to be represented in any integer type
+//	REQUIRE(testFromString<double>(18446744073709551616,    "18446744073709551616.0") );  // 2^64 (max of uint64_t + 1, force to use double)
+//	REQUIRE(testFromString<double>(-9223372036854775809,    "-9223372036854775809.0") );  // -2^63 - 1(min of int64_t + 1, force to use double)
+
+	REQUIRE(testFromString<double>(0.9868011474609375,      "0.9868011474609375") );      // https://github.com/miloyip/rapidjson/issues/120
+	REQUIRE(testFromString<double>(123e34,                  "123e34") );
+	REQUIRE(testFromString<double>(45913141877270640000.0,  "45913141877270640000.0") );
+	REQUIRE(testFromString<double>(std::numeric_limits<double>::min(),    "2.2250738585072014e-308") );
+	REQUIRE(testFromString<double>(std::numeric_limits<double>::lowest(), "-1.7976931348623158e+308") );
+	REQUIRE(testFromString<double>(std::numeric_limits<double>::max(),    "1.7976931348623158e+308") );
 }
 
 static bool testFromString(int32_t _value, const char* _input)