gwnavruntime/math/almostequal.h Source File

almostequal.h
Go to the documentation of this file.
1 /*
2 * Copyright 2016 Autodesk, Inc. All rights reserved.
3 * Use of this software is subject to the terms of the Autodesk license agreement and any attachments or Appendices thereto provided at the time of installation or download,
4 * or which otherwise accompanies this software in either electronic or hard copy form, or which is signed by you and accepted by Autodesk.
5 */
6 
7 #pragma once
8 
10 
11 namespace Kaim
12 {
13 
14 namespace AlmostEqualImpl
15 {
16 
17 inline bool IsNan(KyUInt32 ui32)
18 {
19  const KyUInt32 ExponentMask = 0x7F800000;
20  const KyUInt32 FractionMask = 0x007FFFFF;
21  return (ui32 & ExponentMask) == ExponentMask && (ui32 & FractionMask) != 0;
22 }
23 
24 inline KyUInt32 Biased(const KyUInt32& ui32)
25 {
26  return (0x80000000 & ui32) ? ~ui32 + 1 : 0x80000000 | ui32;
27 }
28 
29 // ULP stands for Unit of Least precision
30 inline KyUInt32 DistanceULP(const KyUInt32& a, const KyUInt32& b)
31 {
32  const KyUInt32 biased_a = Biased(a);
33  const KyUInt32 biased_b = Biased(b);
34  return (biased_a >= biased_b) ? (biased_a - biased_b) : (biased_b - biased_a);
35 }
36 
37 // We use a Union to reinterpret a KyFloat32 into a KyUInt32.
38 // Using reinterpret_cast<KyUInt32*>(&float_variable) does NOT work because of strict_aliasing compiler optimizations.
39 // In theory, the C++ standard does not state that using a Union works, but the C99 standard does.
40 // The only C++ standard way of doing this seems to involve memcpy(), it also seems that the memcpy() call can be optimized aggressively by the compiler.
41 // We still use a Union there, because it's simpler and it just work with all the compilers we support.
42 union U
43 {
44  KyFloat32 f32;
45  KyUInt32 ui32;
46 };
47 
48 };
49 
52 {
53  AlmostEqualImpl::U ua;
54  ua.f32 = a;
55  AlmostEqualImpl::U ub;
56  ub.f32 = b;
57  return AlmostEqualImpl::DistanceULP(ua.ui32, ub.ui32);
58 }
59 
61 inline bool AlmostEqual(KyFloat32 a, KyFloat32 b)
62 {
63  return DistanceULP(a, b) <= 4;
64 }
65 
67 inline bool AlmostEqual(KyFloat32 a, KyFloat32 b, KyUInt32 maxUlps)
68 {
69  return DistanceULP(a, b) <= maxUlps;
70 }
71 
74 {
75  AlmostEqualImpl::U ua;
76  ua.f32 = a;
77  AlmostEqualImpl::U ub;
78  ub.f32 = b;
79 
80  if (AlmostEqualImpl::IsNan(ua.ui32) || AlmostEqualImpl::IsNan(ub.ui32))
81  return false;
82 
83  return DistanceULP(a, b) <= 4;
84 }
85 
86 
87 }
88 
KyUInt32 DistanceULP(KyFloat32 a, KyFloat32 b)
Does not check nan.
Definition: almostequal.h:51
std::uint32_t KyUInt32
uint32_t
Definition: types.h:29
bool AlmostEqual(KyFloat32 a, KyFloat32 b)
Does not check nan.
Definition: almostequal.h:61
The Autodesk Navigation namespace.
Definition: gamekitcrowddispersion.cpp:17
bool AlmostEqual_nan(KyFloat32 a, KyFloat32 b)
Does check nan.
Definition: almostequal.h:73
float KyFloat32
float
Definition: types.h:32