Skip to content

Commit 103c964

Browse files
better trigonometric functions' implementation (#1559)
* better trigonometric functions' implementation * better asin, acos, atan, atan2 implementation * add sin, cos, tan, asin, acos, atan, atan2 for floating-point --------- Co-authored-by: 东灯 <[email protected]>
1 parent 44c3412 commit 103c964

10 files changed

+1904
-571
lines changed

double/double.mbti

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@ let not_a_number : Double
1818
// Types and methods
1919
impl Double {
2020
abs(Double) -> Double
21+
acos(Double) -> Double
22+
asin(Double) -> Double
23+
atan(Double) -> Double
24+
atan2(Double, Double) -> Double
2125
ceil(Double) -> Double
26+
cos(Double) -> Double
2227
exp(Double) -> Double
2328
floor(Double) -> Double
2429
from_int(Int) -> Double
@@ -37,6 +42,8 @@ impl Double {
3742
pow(Double, Double) -> Double
3843
round(Double) -> Double
3944
signum(Double) -> Double
45+
sin(Double) -> Double
46+
tan(Double) -> Double
4047
to_be_bytes(Double) -> Bytes
4148
to_le_bytes(Double) -> Bytes
4249
to_string(Double) -> String

double/moon.pkg.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
"mod_nonjs.mbt": ["not", "js"],
1515
"pow_js.mbt": ["js"],
1616
"pow_nonjs.mbt": ["not", "js"],
17+
"trig_js.mbt" : ["js"],
18+
"trig_nonjs.mbt" : ["not", "js"],
1719
"round_js.mbt": ["js"],
1820
"round_wasm.mbt": ["wasm", "wasm-gc"],
1921
"round.mbt": ["not", "js", "wasm", "wasm-gc"],

double/trig_js.mbt

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
// Copyright 2025 International Digital Economy Academy
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
///|
16+
/// Calculates the sine of a number in radians. Handles special cases and edge
17+
/// conditions according to IEEE 754 standards.
18+
///
19+
/// Parameters:
20+
///
21+
/// * `x` : The angle in radians for which to calculate the sine.
22+
///
23+
/// Returns the sine of the angle `x`.
24+
///
25+
/// Example:
26+
///
27+
/// ```moonbit
28+
/// test "sin" {
29+
/// inspect!(0.0.sin(), content="0")
30+
/// inspect!(1.570796326794897.sin(), content="1") // pi / 2
31+
/// inspect!(2.0.sin(), content="0.9092974268256817")
32+
/// inspect!(-5.0.sin(), content="0.9589242746631385")
33+
/// inspect!(31415926535897.9323846.sin(), content="0.0012091232715481885")
34+
/// inspect!(@double.not_a_number.sin(), content="NaN")
35+
/// inspect!(@double.infinity.sin(), content="NaN")
36+
/// inspect!(@double.neg_infinity.sin(), content="NaN")
37+
/// }
38+
/// ```
39+
pub fn sin(self : Double) -> Double = "Math" "sin"
40+
41+
///|
42+
/// Calculates the cosine of a number in radians. Handles special cases and edge
43+
/// conditions according to IEEE 754 standards.
44+
///
45+
/// Parameters:
46+
///
47+
/// * `x` : The angle in radians for which to calculate the cosine.
48+
///
49+
/// Returns the cosine of the angle `x`.
50+
///
51+
/// Example:
52+
///
53+
/// ```moonbit
54+
/// test "cos" {
55+
/// inspect!(0.0.cos(), content="1")
56+
/// inspect!(2.5.cos(), content="-0.8011436155469337")
57+
/// inspect!((-3.141592653589793).cos(), content="-1") // -pi
58+
/// inspect!((-5.0).cos(), content="0.28366218546322625")
59+
/// inspect!(31415926535897.9323846.cos(), content="0.9999992690101899")
60+
/// inspect!(@double.not_a_number.cos(), content="NaN")
61+
/// inspect!(@double.infinity.cos(), content="NaN")
62+
/// inspect!(@double.neg_infinity.cos(), content="NaN")
63+
/// }
64+
/// ```
65+
pub fn cos(self : Double) -> Double = "Math" "cos"
66+
67+
///|
68+
/// Calculates the tangent of a number in radians. Handles special cases and edge
69+
/// conditions according to IEEE 754 standards.
70+
///
71+
/// Parameters:
72+
///
73+
/// * `x` : The angle in radians for which to calculate the tangent.
74+
///
75+
/// Returns the tangent of the angle `x`.
76+
///
77+
/// Example:
78+
///
79+
/// ```moonbit
80+
/// test "tan" {
81+
/// inspect!(0.0.tan(), content="0")
82+
/// inspect!(0.7853981633974483.tan(), content="0.9999999999999999")
83+
/// inspect!(4.0.tan(), content="1.1578212823495777")
84+
/// inspect!(5.0.tan(), content="-3.380515006246586")
85+
/// inspect!(31415926535897.9323846.tan(), content="0.0012091241554056254")
86+
/// inspect!(@double.not_a_number.tan(), content="NaN")
87+
/// inspect!(@double.infinity.tan(), content="NaN")
88+
/// inspect!(@double.neg_infinity.tan(), content="NaN")
89+
/// }
90+
/// ```
91+
pub fn tan(self : Double) -> Double = "Math" "tan"
92+
93+
///|
94+
/// Calculates the arcsine of a number. Handles special cases and edge conditions
95+
/// according to IEEE 754 standards.
96+
///
97+
/// Parameters:
98+
///
99+
/// * `x` : The number for which to calculate the arcsine.
100+
///
101+
/// Returns the arcsine of the number `x`.
102+
///
103+
/// * Returns NaN if the input is NaN.
104+
/// * Returns NaN if the input is less than -1 or greater than 1.
105+
///
106+
/// Example:
107+
///
108+
/// ```moonbit
109+
/// test "asin" {
110+
/// inspect!(0.0.asin(), content="0")
111+
/// inspect!(1.0.asin(), content="1.5707963267948966")
112+
/// inspect!((-1.0).asin(), content="-1.5707963267948966")
113+
/// inspect!(@double.not_a_number.asin(), content="NaN")
114+
/// inspect!(@double.infinity.asin(), content="NaN")
115+
/// inspect!(@double.neg_infinity.asin(), content="NaN")
116+
/// }
117+
/// ```
118+
pub fn asin(self : Double) -> Double = "Math" "asin"
119+
120+
///|
121+
/// Calculates the arccosine of a number.
122+
///
123+
/// Parameters:
124+
///
125+
/// * `x` : The number for which to calculate the arccosine.
126+
///
127+
/// Returns the arccosine of the number `x`.
128+
///
129+
/// * Returns NaN if the input is NaN.
130+
/// * Returns NaN if the input is less than -1 or greater than 1.
131+
///
132+
/// Example:
133+
///
134+
/// ```moonbit
135+
/// test "acos" {
136+
/// inspect!(0.0.acos(), content="1.5707963267948966")
137+
/// inspect!(1.0.acos(), content="0")
138+
/// inspect!((-1.0).acos(), content="3.141592653589793")
139+
/// inspect!(@double.not_a_number.acos(), content="NaN")
140+
/// inspect!(@double.infinity.acos(), content="NaN")
141+
/// inspect!(@double.neg_infinity.acos(), content="NaN")
142+
/// inspect!(0.0.acos(), content="1.5707963267948966")
143+
/// }
144+
/// ```
145+
pub fn acos(self : Double) -> Double = "Math" "acos"
146+
147+
///|
148+
/// Calculates the arctangent of a number.
149+
///
150+
/// Parameters:
151+
///
152+
/// * `x` : The number for which to calculate the arctangent.
153+
///
154+
/// Returns the arctangent of the number `x`.
155+
///
156+
/// Example:
157+
///
158+
/// * Returns NaN if the input is NaN.
159+
///
160+
/// ```moonbit
161+
/// test "atan" {
162+
/// inspect!(0.0.atan(), content="0")
163+
/// inspect!(1.0.atan(), content="0.7853981633974483")
164+
/// inspect!((-1.0).atan(), content="-0.7853981633974483")
165+
/// inspect!(@double.not_a_number.atan(), content="NaN")
166+
/// inspect!(@double.infinity.atan(), content="1.5707963267948966")
167+
/// inspect!(@double.neg_infinity.atan(), content="-1.5707963267948966")
168+
/// }
169+
/// ```
170+
pub fn atan(self : Double) -> Double = "Math" "atan"
171+
172+
///|
173+
/// Calculates the arctangent of the quotient of two numbers.
174+
///
175+
/// Parameters:
176+
///
177+
/// * `self` : The numerator of the quotient.
178+
/// * `x` : The denominator of the quotient.
179+
///
180+
/// Returns the arctangent of the quotient `self / x`.
181+
///
182+
/// * Returns NaN if self or x is NaN.
183+
///
184+
/// Example:
185+
///
186+
/// ```moonbit
187+
/// test "atan2" {
188+
/// inspect!(0.0.atan2(-1.0), content="3.141592653589793")
189+
/// inspect!(1.0.atan2(0.0), content="1.5707963267948966")
190+
/// inspect!(1.0.atan2(1.0), content="0.7853981633974483")
191+
/// inspect!(not_a_number.atan2(1.0), content="NaN")
192+
/// inspect!(1.0.atan2(not_a_number), content="NaN")
193+
/// inspect!(infinity.atan2(1.0), content="1.5707963267948966")
194+
/// inspect!(1.0.atan2(infinity), content="0")
195+
/// inspect!(neg_infinity.atan2(1.0), content="-1.5707963267948966")
196+
/// inspect!(1.0.atan2(neg_infinity), content="3.141592653589793")
197+
/// inspect!(infinity.atan2(infinity), content="0.7853981633974483")
198+
/// inspect!(neg_infinity.atan2(neg_infinity), content="-2.356194490192345")
199+
/// inspect!(infinity.atan2(neg_infinity), content="2.356194490192345")
200+
/// inspect!(neg_infinity.atan2(infinity), content="-0.7853981633974483")
201+
/// }
202+
/// ```
203+
pub fn atan2(self : Double, x : Double) -> Double = "Math" "atan2"

0 commit comments

Comments
 (0)