FixMath
FixMath_Autotests.h
1 /*
2  * FixMath_Autotests.h
3  *
4  * Copyright 2024, Thomas Combriat, Thomas Friedrichsmeier and the Mozzi team
5  *
6  *
7  * FixMath is licensed under a GNU Lesser General Public Licence
8  *
9  */
10 
11 
14 namespace FixMathPrivate {
15  /* This function is never called, and has no effect, but simply encapsulates a bunch of static asserts */
16  inline void static_autotests() {
17  {
18  constexpr auto a = UFix<8,1>(64, true); // 32
19  constexpr auto b = UFix<8,2>(130, true); // 32.5
20  constexpr auto c = UFix<8,0>(33); // 33
21 
22  // basics
23  static_assert(a < b && b < c);
24  static_assert(a.getNF() == 1 && b.getNF() == 2);
25 
26  // addition
27  constexpr auto d = a + b;
28  static_assert(d.getNI() == 9);
29  static_assert(d.getNF() == 2); // NF is always max in addition
30  static_assert((a + c).getNF() == 1);
31  static_assert(d.asRaw() == 258);
32  constexpr auto e = d + b + c; // addition of one 9 (NI) bit and two 8 (NI) bit numbers needs promotion to 10 bits, not 11, only.
33  static_assert(e.getNI() == 10);
34  static_assert(e.getNF() == 2);
35  e.assertSize<12>();
36  static_assert((d + d).getNI() == 10);
37  static_assert((e + e).getNF() == 2);
38  static_assert((d + e).getNI() == 11);
39 
40  // the point of this block is to ascertain that addtion does not overflow, internally, where the internal_type of the operands is too small to hold the result
41  constexpr auto large = UFix<32,0>(1LL << 31, true);
42  static_assert(sizeof(decltype(large.asRaw())) == 4);
43  static_assert((large+large).asRaw() == (1LL << 32));
44  static_assert(sizeof(decltype((large+large).asRaw())) > 4);
45 
46  // subtraction
47  static_assert(b - a == c - b);
48  static_assert(c - UFix<17,8>(1) == a);
49  static_assert(c - SFix<13,9>(1) == a);
50  static_assert(b + a - b == a);
51  static_assert(b + a + (-b) == a); // same with unary minus
52  static_assert(-(-a) == a);
53 #if __cplusplus >= 202002L
54  // These here involve shifts of negative numbers, which used to be "implementation defined" before C++-20.
55  // It doesn't cause a real-world problem, but the compiler won't accept it in a constexpr
56  static_assert(UFix<43,9>(0) - b - a == -(a+b));
57  static_assert(SFix<4, 3>(-1) == SFix<4, 5>(-1)); // NOTE This is a simpler test case for the above problem. Note the difference in NF, which prompts shifting
58 #endif
59  // here's a variant that avoids the problem by using only positive numbers
60  static_assert(UFix<12,1>(999) - UFix<43,9>(0) - b - a == UFix<19,3>(999) + (-(a+b)));
61  static_assert(-SFix<4, 3>(-8, true) == -SFix<4, 5>(-32, true));
62 
63  // multiplication
64  static_assert(c * UFix<36, 5>(3ll << 31) == UFix<58,0>(33ll*(3ll << 31))); // NOTE: The exact values are aribrary, but we want something that would overflow the initial type range
65  static_assert(a * UFix<0, 2>(3, true) == UFix<17, 8>(24)); // 32 * .75 == 24
66  static_assert(a * UFix<5, 0>(4).invAccurate() == UFix<17, 8>(8)); // 32 * (1/4) == 8
67  static_assert(a * toUFraction((int8_t) 16) == UFix<3, 9>(2)); // 32 * (16/256) == 2
68 
69  // type conversions
70  static_assert(a.getNI() == a.asSFix().getNI());
71  static_assert(a.getNF() == a.asSFix().getNF());
72  }
73  }
74 }
75 
76 
constexpr UFix< 0, sizeof(T) *8 > toUFraction(T val)
Definition: FixMath.h:685
Definition: FixMath.h:714
Definition: FixMath.h:156
Definition: FixMath.h:127