File indexing completed on 2024-04-06 12:04:41
0001 #ifndef DataFormatsMathAPPROX_ATAN2_H
0002 #define DataFormatsMathAPPROX_ATAN2_H
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030 #include <cstdint>
0031 #include <cmath>
0032 #include <limits>
0033 #include <algorithm>
0034
0035
0036
0037 template <int DEGREE>
0038 constexpr float approx_atan2f_P(float x);
0039
0040
0041 template <>
0042 constexpr float approx_atan2f_P<3>(float x) {
0043 return x * (float(-0xf.8eed2p-4) + x * x * float(0x3.1238p-4));
0044 }
0045
0046
0047 template <>
0048 constexpr float approx_atan2f_P<5>(float x) {
0049 auto z = x * x;
0050 return x * (float(-0xf.ecfc8p-4) + z * (float(0x4.9e79dp-4) + z * float(-0x1.44f924p-4)));
0051 }
0052
0053
0054 template <>
0055 constexpr float approx_atan2f_P<7>(float x) {
0056 auto z = x * x;
0057 return x * (float(-0xf.fcc7ap-4) + z * (float(0x5.23886p-4) + z * (float(-0x2.571968p-4) + z * float(0x9.fb05p-8))));
0058 }
0059
0060
0061 template <>
0062 constexpr float approx_atan2f_P<9>(float x) {
0063 auto z = x * x;
0064 return x * (float(-0xf.ff73ep-4) +
0065 z * (float(0x5.48ee1p-4) +
0066 z * (float(-0x2.e1efe8p-4) + z * (float(0x1.5cce54p-4) + z * float(-0x5.56245p-8)))));
0067 }
0068
0069
0070 template <>
0071 constexpr float approx_atan2f_P<11>(float x) {
0072 auto z = x * x;
0073 return x * (float(-0xf.ffe82p-4) +
0074 z * (float(0x5.526c8p-4) +
0075 z * (float(-0x3.18bea8p-4) +
0076 z * (float(0x1.dce3bcp-4) + z * (float(-0xd.7a64ap-8) + z * float(0x3.000eap-8))))));
0077 }
0078
0079
0080 template <>
0081 constexpr float approx_atan2f_P<13>(float x) {
0082 auto z = x * x;
0083 return x * (float(-0xf.fffbep-4) +
0084 z * (float(0x5.54adp-4) +
0085 z * (float(-0x3.2b4df8p-4) +
0086 z * (float(0x2.1df79p-4) +
0087 z * (float(-0x1.46081p-4) + z * (float(0x8.99028p-8) + z * float(-0x1.be0bc4p-8)))))));
0088 }
0089
0090
0091 template <>
0092 constexpr float approx_atan2f_P<15>(float x) {
0093 auto z = x * x;
0094 return x * (float(-0xf.ffff4p-4) +
0095 z * (float(0x5.552f9p-4 + z * (float(-0x3.30f728p-4) +
0096 z * (float(0x2.39826p-4) +
0097 z * (float(-0x1.8a880cp-4) +
0098 z * (float(0xe.484d6p-8) +
0099 z * (float(-0x5.93d5p-8) + z * float(0x1.0875dcp-8)))))))));
0100 }
0101
0102 template <int DEGREE>
0103 constexpr float unsafe_atan2f_impl(float y, float x) {
0104 constexpr float pi4f = 3.1415926535897932384626434 / 4;
0105 constexpr float pi34f = 3.1415926535897932384626434 * 3 / 4;
0106
0107 auto r = (std::abs(x) - std::abs(y)) / (std::abs(x) + std::abs(y));
0108 if (x < 0)
0109 r = -r;
0110
0111 auto angle = (x >= 0) ? pi4f : pi34f;
0112 angle += approx_atan2f_P<DEGREE>(r);
0113
0114 return ((y < 0)) ? -angle : angle;
0115 }
0116
0117 template <int DEGREE>
0118 constexpr float unsafe_atan2f(float y, float x) {
0119 return unsafe_atan2f_impl<DEGREE>(y, x);
0120 }
0121
0122 template <int DEGREE>
0123 constexpr float safe_atan2f(float y, float x) {
0124 return unsafe_atan2f_impl<DEGREE>(y, ((y == 0.f) & (x == 0.f)) ? 0.2f : x);
0125
0126 }
0127
0128
0129
0130
0131
0132
0133
0134
0135 template <int DEGREE>
0136 constexpr float approx_atan2i_P(float x);
0137
0138
0139 template <>
0140 constexpr float approx_atan2i_P<3>(float x) {
0141 auto z = x * x;
0142 return x * (-664694912.f + z * 131209024.f);
0143 }
0144
0145
0146 template <>
0147 constexpr float approx_atan2i_P<5>(float x) {
0148 auto z = x * x;
0149 return x * (-680392064.f + z * (197338400.f + z * (-54233256.f)));
0150 }
0151
0152
0153 template <>
0154 constexpr float approx_atan2i_P<7>(float x) {
0155 auto z = x * x;
0156 return x * (-683027840.f + z * (219543904.f + z * (-99981040.f + z * 26649684.f)));
0157 }
0158
0159
0160 template <>
0161 constexpr float approx_atan2i_P<9>(float x) {
0162 auto z = x * x;
0163 return x * (-683473920.f + z * (225785056.f + z * (-123151184.f + z * (58210592.f + z * (-14249276.f)))));
0164 }
0165
0166
0167 template <>
0168 constexpr float approx_atan2i_P<11>(float x) {
0169 auto z = x * x;
0170 return x *
0171 (-683549696.f + z * (227369312.f + z * (-132297008.f + z * (79584144.f + z * (-35987016.f + z * 8010488.f)))));
0172 }
0173
0174
0175 template <>
0176 constexpr float approx_atan2i_P<13>(float x) {
0177 auto z = x * x;
0178 return x * (-683562624.f +
0179 z * (227746080.f +
0180 z * (-135400128.f + z * (90460848.f + z * (-54431464.f + z * (22973256.f + z * (-4657049.f)))))));
0181 }
0182
0183 template <>
0184 constexpr float approx_atan2i_P<15>(float x) {
0185 auto z = x * x;
0186 return x * (-683562624.f +
0187 z * (227746080.f +
0188 z * (-135400128.f + z * (90460848.f + z * (-54431464.f + z * (22973256.f + z * (-4657049.f)))))));
0189 }
0190
0191 template <int DEGREE>
0192 constexpr int unsafe_atan2i_impl(float y, float x) {
0193 constexpr long long maxint = (long long)(std::numeric_limits<int>::max()) + 1LL;
0194 constexpr int pi4 = int(maxint / 4LL);
0195 constexpr int pi34 = int(3LL * maxint / 4LL);
0196
0197 auto r = (std::abs(x) - std::abs(y)) / (std::abs(x) + std::abs(y));
0198 if (x < 0)
0199 r = -r;
0200
0201 auto angle = (x >= 0) ? pi4 : pi34;
0202 angle += int(approx_atan2i_P<DEGREE>(r));
0203
0204
0205 return (y < 0) ? -angle : angle;
0206 }
0207
0208 template <int DEGREE>
0209 constexpr int unsafe_atan2i(float y, float x) {
0210 return unsafe_atan2i_impl<DEGREE>(y, x);
0211 }
0212
0213
0214
0215 template <int DEGREE>
0216 constexpr float approx_atan2s_P(float x);
0217
0218
0219 template <>
0220 constexpr float approx_atan2s_P<3>(float x) {
0221 auto z = x * x;
0222 return x * ((-10142.439453125f) + z * 2002.0908203125f);
0223 }
0224
0225 template <>
0226 constexpr float approx_atan2s_P<5>(float x) {
0227 auto z = x * x;
0228 return x * ((-10381.9609375f) + z * ((3011.1513671875f) + z * (-827.538330078125f)));
0229 }
0230
0231 template <>
0232 constexpr float approx_atan2s_P<7>(float x) {
0233 auto z = x * x;
0234 return x * ((-10422.177734375f) + z * (3349.97412109375f + z * ((-1525.589599609375f) + z * 406.64190673828125f)));
0235 }
0236
0237 template <>
0238 constexpr float approx_atan2s_P<9>(float x) {
0239 auto z = x * x;
0240 return x * ((-10428.984375f) + z * (3445.20654296875f + z * ((-1879.137939453125f) +
0241 z * (888.22314453125f + z * (-217.42669677734375f)))));
0242 }
0243
0244 template <int DEGREE>
0245 constexpr short unsafe_atan2s_impl(float y, float x) {
0246 constexpr int maxshort = (int)(std::numeric_limits<short>::max()) + 1;
0247 constexpr short pi4 = short(maxshort / 4);
0248 constexpr short pi34 = short(3 * maxshort / 4);
0249
0250 auto r = (std::abs(x) - std::abs(y)) / (std::abs(x) + std::abs(y));
0251 if (x < 0)
0252 r = -r;
0253
0254 auto angle = (x >= 0) ? pi4 : pi34;
0255 angle += short(approx_atan2s_P<DEGREE>(r));
0256
0257 return (y < 0) ? -angle : angle;
0258 }
0259
0260 template <int DEGREE>
0261 constexpr short unsafe_atan2s(float y, float x) {
0262 return unsafe_atan2s_impl<DEGREE>(y, x);
0263 }
0264
0265 constexpr int phi2int(float x) {
0266 constexpr float p2i = ((long long)(std::numeric_limits<int>::max()) + 1LL) / M_PI;
0267 return std::round(x * p2i);
0268 }
0269
0270 constexpr float int2phi(int x) {
0271 constexpr float i2p = M_PI / ((long long)(std::numeric_limits<int>::max()) + 1LL);
0272 return float(x) * i2p;
0273 }
0274
0275 constexpr double int2dphi(int x) {
0276 constexpr double i2p = M_PI / ((long long)(std::numeric_limits<int>::max()) + 1LL);
0277 return x * i2p;
0278 }
0279
0280 constexpr short phi2short(float x) {
0281 constexpr float p2i = ((int)(std::numeric_limits<short>::max()) + 1) / M_PI;
0282 return std::round(x * p2i);
0283 }
0284
0285 constexpr float short2phi(short x) {
0286 constexpr float i2p = M_PI / ((int)(std::numeric_limits<short>::max()) + 1);
0287 return float(x) * i2p;
0288 }
0289
0290 #endif