31 #include <type_traits>
40 template <
typename T,
typename SignedT = std::
int64_t>
49 discontinuityOffset = 0;
54 static_assert(std::is_signed_v<SignedT>);
56 if constexpr(std::is_unsigned_v<T>)
58 static_assert(
sizeof(SignedT) >
sizeof(
T));
61 if constexpr(std::is_signed_v<T>)
63 static_assert(
sizeof(SignedT) >=
sizeof(
T));
70 const char* nameForDebugging =
"")
83 float discontinuityOffset,
86 const char* nameForDebugging =
"")
89 const auto rawAsInt =
reinterpret_cast<std::uint64_t
>(raw);
91 <<
"\nThe alignment is wrong!"
92 <<
"\nIt has to be " <<
alignof(
T) <<
", but the data is aligned with "
93 << rawAsInt %
alignof(std::max_align_t) <<
"!"
94 <<
"\nThis is an offset of " << (rawAsInt %
alignof(
T)) <<
" bytes!"
95 <<
"\nThe datatype is " << GetTypeString<T>() <<
"\nIts size is " <<
sizeof(
T)
96 <<
"\nraw = " << raw <<
" bytes"
97 <<
"\nThe name is '" << nameForDebugging <<
"'";
100 <<
"max value must not be zero (cannot divide/modulo by 0).";
103 <<
"max value is greater than the maximum value of the datatype, "
104 <<
"the datatype is " << GetTypeString<T>();
106 this->rawValue = raw;
107 this->zeroOffset =
static_cast<SignedT
>(zeroOffset);
108 this->discontinuityOffset =
static_cast<SignedT
>(discontinuityOffset);
109 this->maxValue =
static_cast<SignedT
>(maxValue);
110 this->factor = 2 * M_PIf64 / maxValue;
111 this->isInverted = isInverted;
121 auto actual_real_modulo = [](SignedT dividend, SignedT divisor) -> SignedT
123 const SignedT result = dividend % divisor;
124 return result >= 0 ? result : result + divisor;
127 const SignedT rawValueSigned =
static_cast<SignedT
>(*rawValue);
128 const SignedT maxValueSigned =
static_cast<SignedT
>(maxValue);
132 const SignedT
sign = isInverted ? -1 : 1;
133 const SignedT dirnorm = actual_real_modulo((
sign * rawValueSigned), maxValueSigned);
137 const SignedT monotonic_dirnorm =
138 actual_real_modulo((dirnorm + discontinuityOffset), maxValueSigned);
141 const SignedT zeroshift_monotonic_dirnorm = monotonic_dirnorm - zeroOffset;
144 const double zeroshift_monotonic_dirnorm_rad =
145 static_cast<double>(zeroshift_monotonic_dirnorm) * factor;
147 value = zeroshift_monotonic_dirnorm_rad;
167 SignedT discontinuityOffset;