| 1 | module math |
| 2 | |
| 3 | import math.internal |
| 4 | |
| 5 | const sin_data = [ |
| 6 | -0.3295190160663511504173, |
| 7 | 0.0025374284671667991990, |
| 8 | 0.0006261928782647355874, |
| 9 | -4.6495547521854042157541e-06, |
| 10 | -5.6917531549379706526677e-07, |
| 11 | 3.7283335140973803627866e-09, |
| 12 | 3.0267376484747473727186e-10, |
| 13 | -1.7400875016436622322022e-12, |
| 14 | -1.0554678305790849834462e-13, |
| 15 | 5.3701981409132410797062e-16, |
| 16 | 2.5984137983099020336115e-17, |
| 17 | -1.1821555255364833468288e-19, |
| 18 | ] |
| 19 | const sin_cs = ChebSeries{ |
| 20 | c: sin_data |
| 21 | order: 11 |
| 22 | a: -1 |
| 23 | b: 1 |
| 24 | } |
| 25 | const cos_data = [ |
| 26 | 0.165391825637921473505668118136, |
| 27 | -0.00084852883845000173671196530195, |
| 28 | -0.000210086507222940730213625768083, |
| 29 | 1.16582269619760204299639757584e-6, |
| 30 | 1.43319375856259870334412701165e-7, |
| 31 | -7.4770883429007141617951330184e-10, |
| 32 | -6.0969994944584252706997438007e-11, |
| 33 | 2.90748249201909353949854872638e-13, |
| 34 | 1.77126739876261435667156490461e-14, |
| 35 | -7.6896421502815579078577263149e-17, |
| 36 | -3.7363121133079412079201377318e-18, |
| 37 | ] |
| 38 | const cos_cs = ChebSeries{ |
| 39 | c: cos_data |
| 40 | order: 10 |
| 41 | a: -1 |
| 42 | b: 1 |
| 43 | } |
| 44 | |
| 45 | // sin calculates the sine of the angle in radians |
| 46 | pub fn sin(x f64) f64 { |
| 47 | p1 := 7.85398125648498535156e-1 |
| 48 | p2 := 3.77489470793079817668e-8 |
| 49 | p3 := 2.69515142907905952645e-15 |
| 50 | sgn_x := if x < 0 { -1 } else { 1 } |
| 51 | abs_x := abs(x) |
| 52 | if abs_x < internal.root4_f64_epsilon { |
| 53 | x2 := x * x |
| 54 | return x * (1.0 - x2 / 6.0) |
| 55 | } else { |
| 56 | mut sgn_result := sgn_x |
| 57 | mut y := floor(abs_x / (0.25 * pi)) |
| 58 | mut octant := int(y - ldexp(floor(ldexp(y, -3)), 3)) |
| 59 | if (octant & 1) == 1 { |
| 60 | octant++ |
| 61 | octant &= 7 |
| 62 | y += 1.0 |
| 63 | } |
| 64 | if octant > 3 { |
| 65 | octant -= 4 |
| 66 | sgn_result = -sgn_result |
| 67 | } |
| 68 | z := ((abs_x - y * p1) - y * p2) - y * p3 |
| 69 | mut result := 0.0 |
| 70 | if octant == 0 { |
| 71 | t := 8.0 * abs(z) / pi - 1.0 |
| 72 | sin_cs_val, _ := sin_cs.eval_e(t) |
| 73 | result = z * (1.0 + z * z * sin_cs_val) |
| 74 | } else { |
| 75 | t := 8.0 * abs(z) / pi - 1.0 |
| 76 | cos_cs_val, _ := cos_cs.eval_e(t) |
| 77 | result = 1.0 - 0.5 * z * z * (1.0 - z * z * cos_cs_val) |
| 78 | } |
| 79 | result *= sgn_result |
| 80 | return result |
| 81 | } |
| 82 | } |
| 83 | |
| 84 | // cos calculates the cosine of the angle in radians |
| 85 | pub fn cos(x f64) f64 { |
| 86 | p1 := 7.85398125648498535156e-1 |
| 87 | p2 := 3.77489470793079817668e-8 |
| 88 | p3 := 2.69515142907905952645e-15 |
| 89 | abs_x := abs(x) |
| 90 | if abs_x < internal.root4_f64_epsilon { |
| 91 | x2 := x * x |
| 92 | return 1.0 - 0.5 * x2 |
| 93 | } else { |
| 94 | mut sgn_result := 1 |
| 95 | mut y := floor(abs_x / (0.25 * pi)) |
| 96 | mut octant := int(y - ldexp(floor(ldexp(y, -3)), 3)) |
| 97 | if (octant & 1) == 1 { |
| 98 | octant++ |
| 99 | octant &= 7 |
| 100 | y += 1.0 |
| 101 | } |
| 102 | if octant > 3 { |
| 103 | octant -= 4 |
| 104 | sgn_result = -sgn_result |
| 105 | } |
| 106 | if octant > 1 { |
| 107 | sgn_result = -sgn_result |
| 108 | } |
| 109 | z := ((abs_x - y * p1) - y * p2) - y * p3 |
| 110 | mut result := 0.0 |
| 111 | if octant == 0 { |
| 112 | t := 8.0 * abs(z) / pi - 1.0 |
| 113 | cos_cs_val, _ := cos_cs.eval_e(t) |
| 114 | result = 1.0 - 0.5 * z * z * (1.0 - z * z * cos_cs_val) |
| 115 | } else { |
| 116 | t := 8.0 * abs(z) / pi - 1.0 |
| 117 | sin_cs_val, _ := sin_cs.eval_e(t) |
| 118 | result = z * (1.0 + z * z * sin_cs_val) |
| 119 | } |
| 120 | result *= sgn_result |
| 121 | return result |
| 122 | } |
| 123 | } |
| 124 | |
| 125 | // cosf calculates cosine in radians (float32). |
| 126 | @[inline] |
| 127 | pub fn cosf(a f32) f32 { |
| 128 | return f32(cos(a)) |
| 129 | } |
| 130 | |
| 131 | // sinf calculates sine in radians (float32) |
| 132 | @[inline] |
| 133 | pub fn sinf(a f32) f32 { |
| 134 | return f32(sin(a)) |
| 135 | } |
| 136 | |
| 137 | // sincos calculates the sine and cosine of the angle in radians |
| 138 | pub fn sincos(x f64) (f64, f64) { |
| 139 | if is_nan(x) { |
| 140 | return x, x |
| 141 | } |
| 142 | p1 := 7.85398125648498535156e-1 |
| 143 | p2 := 3.77489470793079817668e-8 |
| 144 | p3 := 2.69515142907905952645e-15 |
| 145 | sgn_x := if x < 0 { -1 } else { 1 } |
| 146 | abs_x := abs(x) |
| 147 | if is_inf(x, sgn_x) { |
| 148 | return nan(), nan() |
| 149 | } |
| 150 | if abs_x < internal.root4_f64_epsilon { |
| 151 | x2 := x * x |
| 152 | return x * (1.0 - x2 / 6.0), 1.0 - 0.5 * x2 |
| 153 | } else { |
| 154 | mut sgn_result_sin := sgn_x |
| 155 | mut sgn_result_cos := 1 |
| 156 | mut y := floor(abs_x / (0.25 * pi)) |
| 157 | mut octant := int(y - ldexp(floor(ldexp(y, -3)), 3)) |
| 158 | if (octant & 1) == 1 { |
| 159 | octant++ |
| 160 | octant &= 7 |
| 161 | y += 1.0 |
| 162 | } |
| 163 | if octant > 3 { |
| 164 | octant -= 4 |
| 165 | sgn_result_sin = -sgn_result_sin |
| 166 | sgn_result_cos = -sgn_result_cos |
| 167 | } |
| 168 | sgn_result_cos = if octant > 1 { -sgn_result_cos } else { sgn_result_cos } |
| 169 | z := ((abs_x - y * p1) - y * p2) - y * p3 |
| 170 | t := 8.0 * abs(z) / pi - 1.0 |
| 171 | sin_cs_val, _ := sin_cs.eval_e(t) |
| 172 | cos_cs_val, _ := cos_cs.eval_e(t) |
| 173 | mut result_sin := 0.0 |
| 174 | mut result_cos := 0.0 |
| 175 | if octant == 0 { |
| 176 | result_sin = z * (1.0 + z * z * sin_cs_val) |
| 177 | result_cos = 1.0 - 0.5 * z * z * (1.0 - z * z * cos_cs_val) |
| 178 | } else { |
| 179 | result_sin = 1.0 - 0.5 * z * z * (1.0 - z * z * cos_cs_val) |
| 180 | result_cos = z * (1.0 + z * z * sin_cs_val) |
| 181 | } |
| 182 | result_sin *= sgn_result_sin |
| 183 | result_cos *= sgn_result_cos |
| 184 | return result_sin, result_cos |
| 185 | } |
| 186 | } |
| 187 | |