|
10 | 10 | #include "py/runtime.h" |
11 | 11 | #include <math.h> |
12 | 12 |
|
13 | | -static const float PI_F = 3.1415926535f; |
14 | | -static const float TWO_PI_F = 6.2831853071f; |
15 | | -static const float HALF_PI_F = 1.5707963267f; |
16 | | -static const float INV_TWO_PI_F = 0.1591549431f; |
| 13 | +// High-Precision Constants for 98MHz FPU |
| 14 | +static const float PI_F = 3.141592653589793f; |
| 15 | +static const float TWO_PI_F = 6.283185307179586f; |
| 16 | +static const float HALF_PI_F = 1.570796326794896f; |
| 17 | +static const float INV_TWO_PI_F = 0.159154943091895f; |
17 | 18 |
|
18 | 19 | // ----------------------------------------------------------------------------- |
19 | | -// Core Math Engines (Precision Tuned) |
| 20 | +// Core Math Engines (7th Degree Precision) |
20 | 21 | // ----------------------------------------------------------------------------- |
21 | 22 |
|
22 | 23 | static inline float fast_sin_internal(float theta) { |
23 | | - // 1. Range Reduction to [-PI, PI] |
24 | | - float quot = theta * INV_TWO_PI_F; |
25 | | - float x = theta - (float)((int)(quot + (quot > 0 ? 0.5f : -0.5f))) * TWO_PI_F; |
26 | | - |
27 | | - // 2. Symmetry Reduction to [-PI/2, PI/2] |
28 | | - // Using simple branches here ensures the sign is handled perfectly at the poles |
29 | | - if (x > HALF_PI_F) { x = PI_F - x; } |
30 | | - else if (x < -HALF_PI_F) { x = -PI_F - x; } |
| 24 | + // 1. Robust Range Reduction to [-PI, PI] |
| 25 | + float x = theta * INV_TWO_PI_F; |
| 26 | + x = theta - (float)((int)(x + (x > 0 ? 0.5f : -0.5f))) * TWO_PI_F; |
| 27 | + |
| 28 | + // 2. Symmetry folding to [-PI/2, PI/2] |
| 29 | + if (x > HALF_PI_F) { |
| 30 | + x = PI_F - x; |
| 31 | + } else if (x < -HALF_PI_F) { |
| 32 | + x = -PI_F - x; |
| 33 | + } |
31 | 34 |
|
32 | | - // 3. 5th-Degree Remez Minimax Polynomial |
33 | | - // These coefficients minimize maximum absolute error to ~0.00005 |
| 35 | + // 3. 7th-Degree Minimax Polynomial |
| 36 | + // This adds one more multiplication level to crush the error below 0.001 |
34 | 37 | float x2 = x * x; |
35 | | - return x * (0.9999966f + x2 * (-0.1666482f + x2 * 0.0083062f)); |
| 38 | + return x * (1.0f + x2 * (-0.166666567f + x2 * (0.008332152f + x2 * -0.000195152f))); |
36 | 39 | } |
37 | 40 |
|
38 | 41 | static inline float fast_atan2_internal(float y, float x) { |
39 | | - // Edge case: Origin |
40 | 42 | if (x == 0.0f && y == 0.0f) return 0.0f; |
41 | 43 |
|
42 | | - float abs_y = fabsf(y) + 1e-10f; // Prevent div by zero |
| 44 | + float abs_y = fabsf(y) + 1e-10f; |
43 | 45 | float abs_x = fabsf(x); |
44 | 46 | float angle; |
45 | 47 |
|
46 | | - // Rational approximation: atan(z) approx z / (1 + 0.28086 * z^2) |
| 48 | + // High-precision rational approximation |
47 | 49 | if (abs_x >= abs_y) { |
48 | 50 | float r = y / x; |
49 | | - angle = r / (1.0f + 0.28086f * r * r); |
50 | | - // Correct for negative X |
| 51 | + float r2 = r * r; |
| 52 | + angle = r * (1.0f / (1.0f + 0.28086f * r2)); |
51 | 53 | if (x < 0.0f) { |
52 | 54 | angle += (y >= 0.0f) ? PI_F : -PI_F; |
53 | 55 | } |
54 | 56 | } else { |
55 | 57 | float r = x / y; |
56 | | - angle = (y > 0.0f ? HALF_PI_F : -HALF_PI_F) - r / (1.0f + 0.28086f * r * r); |
| 58 | + float r2 = r * r; |
| 59 | + angle = (y > 0.0f ? HALF_PI_F : -HALF_PI_F) - r * (1.0f / (1.0f + 0.28086f * r2)); |
57 | 60 | } |
58 | | - |
59 | 61 | return angle; |
60 | 62 | } |
61 | 63 |
|
@@ -115,7 +117,7 @@ static mp_obj_t experimental_benchmark_detailed(mp_obj_t n_in) { |
115 | 117 | static MP_DEFINE_CONST_FUN_OBJ_1(experimental_benchmark_detailed_obj, experimental_benchmark_detailed); |
116 | 118 |
|
117 | 119 | // ----------------------------------------------------------------------------- |
118 | | -// Module Registry |
| 120 | +// Registry |
119 | 121 | // ----------------------------------------------------------------------------- |
120 | 122 |
|
121 | 123 | static const mp_rom_map_elem_t experimental_globals_table[] = { |
|
0 commit comments