不韋 呂
/
SDR_AM_Rx_CIC
AM中波放送用SDR.CICフィルタのみを使用.CQ出版社「トランジスタ技術」誌,2021年4月号に掲載
SDR_Library/FastATan.hpp@1:30d9fb51dec1, 2019-09-23 (annotated)
- Committer:
- MikamiUitOpen
- Date:
- Mon Sep 23 07:32:10 2019 +0000
- Revision:
- 1:30d9fb51dec1
- Child:
- 2:4bec6b2be809
2
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
MikamiUitOpen | 1:30d9fb51dec1 | 1 | //-------------------------------------------------------------- |
MikamiUitOpen | 1:30d9fb51dec1 | 2 | // 高速低精度 arctan 計算 |
MikamiUitOpen | 1:30d9fb51dec1 | 3 | // 係数はミニマックス近似で求めたもの |
MikamiUitOpen | 1:30d9fb51dec1 | 4 | // ただし,誤差は絶対誤差で評価した |
MikamiUitOpen | 1:30d9fb51dec1 | 5 | // |
MikamiUitOpen | 1:30d9fb51dec1 | 6 | // 2019/09/18, Copyright (c) 2019 MIKAMI, Naoki |
MikamiUitOpen | 1:30d9fb51dec1 | 7 | //-------------------------------------------------------------- |
MikamiUitOpen | 1:30d9fb51dec1 | 8 | |
MikamiUitOpen | 1:30d9fb51dec1 | 9 | #include "mbed.h" |
MikamiUitOpen | 1:30d9fb51dec1 | 10 | |
MikamiUitOpen | 1:30d9fb51dec1 | 11 | #ifndef FAST_ARCTAN_LOW_PRECISION_HPP |
MikamiUitOpen | 1:30d9fb51dec1 | 12 | #define FAST_ARCTAN_LOW_PRECISION_HPP |
MikamiUitOpen | 1:30d9fb51dec1 | 13 | |
MikamiUitOpen | 1:30d9fb51dec1 | 14 | namespace Mikami |
MikamiUitOpen | 1:30d9fb51dec1 | 15 | { |
MikamiUitOpen | 1:30d9fb51dec1 | 16 | inline float ATanPoly(float x); |
MikamiUitOpen | 1:30d9fb51dec1 | 17 | |
MikamiUitOpen | 1:30d9fb51dec1 | 18 | // 引数の与え方は,atan2() と同じ |
MikamiUitOpen | 1:30d9fb51dec1 | 19 | float FastATan(float y, float x) |
MikamiUitOpen | 1:30d9fb51dec1 | 20 | { |
MikamiUitOpen | 1:30d9fb51dec1 | 21 | static const float PI = 3.1415926536f; // π |
MikamiUitOpen | 1:30d9fb51dec1 | 22 | static const float PI_4 = PI/4.0f; // π/4 |
MikamiUitOpen | 1:30d9fb51dec1 | 23 | static const float PI3_4 = 3.0f*PI/4.0f; // 3π/4 |
MikamiUitOpen | 1:30d9fb51dec1 | 24 | static const float PI_2 = PI/2.0f; // π/2 |
MikamiUitOpen | 1:30d9fb51dec1 | 25 | |
MikamiUitOpen | 1:30d9fb51dec1 | 26 | if ( (x == 0.0f) && (y == 0.0f) ) return 0.0f; |
MikamiUitOpen | 1:30d9fb51dec1 | 27 | if (y == 0.0f) |
MikamiUitOpen | 1:30d9fb51dec1 | 28 | { |
MikamiUitOpen | 1:30d9fb51dec1 | 29 | if (x > 0.0f) return 0.0f; // 0 |
MikamiUitOpen | 1:30d9fb51dec1 | 30 | else return PI; // π |
MikamiUitOpen | 1:30d9fb51dec1 | 31 | } |
MikamiUitOpen | 1:30d9fb51dec1 | 32 | float abs_x = fabsf(x); |
MikamiUitOpen | 1:30d9fb51dec1 | 33 | float abs_y = fabsf(y); |
MikamiUitOpen | 1:30d9fb51dec1 | 34 | |
MikamiUitOpen | 1:30d9fb51dec1 | 35 | if (abs_x == abs_y) |
MikamiUitOpen | 1:30d9fb51dec1 | 36 | { |
MikamiUitOpen | 1:30d9fb51dec1 | 37 | if (x > 0.0f) |
MikamiUitOpen | 1:30d9fb51dec1 | 38 | { |
MikamiUitOpen | 1:30d9fb51dec1 | 39 | if (y > 0.0f) return PI_4; // π/4 |
MikamiUitOpen | 1:30d9fb51dec1 | 40 | else return -PI_4; // -π/4 |
MikamiUitOpen | 1:30d9fb51dec1 | 41 | } |
MikamiUitOpen | 1:30d9fb51dec1 | 42 | else |
MikamiUitOpen | 1:30d9fb51dec1 | 43 | { |
MikamiUitOpen | 1:30d9fb51dec1 | 44 | if (y > 0.0f) return PI3_4; // 3π/4 |
MikamiUitOpen | 1:30d9fb51dec1 | 45 | else return -PI3_4; // -3π/4 |
MikamiUitOpen | 1:30d9fb51dec1 | 46 | } |
MikamiUitOpen | 1:30d9fb51dec1 | 47 | } |
MikamiUitOpen | 1:30d9fb51dec1 | 48 | |
MikamiUitOpen | 1:30d9fb51dec1 | 49 | if (abs_x > abs_y) // |θ|< π/4,3π/4<|θ|<π |
MikamiUitOpen | 1:30d9fb51dec1 | 50 | { |
MikamiUitOpen | 1:30d9fb51dec1 | 51 | float u = ATanPoly(y/x); |
MikamiUitOpen | 1:30d9fb51dec1 | 52 | if (x > 0.0f) return u; |
MikamiUitOpen | 1:30d9fb51dec1 | 53 | if (y > 0.0f) return u + PI; |
MikamiUitOpen | 1:30d9fb51dec1 | 54 | else return u - PI; |
MikamiUitOpen | 1:30d9fb51dec1 | 55 | } |
MikamiUitOpen | 1:30d9fb51dec1 | 56 | else // π/4 <|θ|<3π/4 |
MikamiUitOpen | 1:30d9fb51dec1 | 57 | { |
MikamiUitOpen | 1:30d9fb51dec1 | 58 | float u = ATanPoly(x/y); |
MikamiUitOpen | 1:30d9fb51dec1 | 59 | if (y > 0.0f) return -u + PI_2; |
MikamiUitOpen | 1:30d9fb51dec1 | 60 | else return -u - PI_2; |
MikamiUitOpen | 1:30d9fb51dec1 | 61 | } |
MikamiUitOpen | 1:30d9fb51dec1 | 62 | } |
MikamiUitOpen | 1:30d9fb51dec1 | 63 | |
MikamiUitOpen | 1:30d9fb51dec1 | 64 | inline float ATanPoly(float x) |
MikamiUitOpen | 1:30d9fb51dec1 | 65 | { |
MikamiUitOpen | 1:30d9fb51dec1 | 66 | static const float A1 = 0.9992138f; // a1 |
MikamiUitOpen | 1:30d9fb51dec1 | 67 | static const float A3 = -0.3211750f; // a3 |
MikamiUitOpen | 1:30d9fb51dec1 | 68 | static const float A5 = 0.1462645f; // a5 |
MikamiUitOpen | 1:30d9fb51dec1 | 69 | static const float A7 = -0.03898651f; // a7 |
MikamiUitOpen | 1:30d9fb51dec1 | 70 | |
MikamiUitOpen | 1:30d9fb51dec1 | 71 | float x2 = x*x; |
MikamiUitOpen | 1:30d9fb51dec1 | 72 | float atanx = (((A7*x2 + A5)*x2 + A3)*x2 + A1)*x; |
MikamiUitOpen | 1:30d9fb51dec1 | 73 | |
MikamiUitOpen | 1:30d9fb51dec1 | 74 | return atanx; |
MikamiUitOpen | 1:30d9fb51dec1 | 75 | } |
MikamiUitOpen | 1:30d9fb51dec1 | 76 | } |
MikamiUitOpen | 1:30d9fb51dec1 | 77 | #endif // FAST_ARCTAN_LOW_PRECISION_HPP |