rhai_sci/trig.rs
1use rhai::plugin::*;
2
3#[export_module]
4pub mod trig_functions {
5 use rhai::{Array, Dynamic, FLOAT};
6
7 /// Converts the argument from degrees to radians
8 /// ```typescript
9 /// assert_eq(deg2rad(180.0), pi);
10 /// ```
11 #[rhai_fn(name = "deg2rad")]
12 pub fn deg2rad(degrees: FLOAT) -> FLOAT {
13 degrees * std::f64::consts::PI / 180.0
14 }
15
16 /// Converts the argument from radians to degrees
17 /// ```typescript
18 /// assert_eq(rad2deg(pi), 180.0);
19 /// ```
20 #[rhai_fn(name = "rad2deg")]
21 pub fn rad2deg(radians: FLOAT) -> FLOAT {
22 radians * 180.0 / std::f64::consts::PI
23 }
24
25 /// Convert the argument from 3D Cartesian coordinates to polar coordinates.
26 /// ```typescript
27 /// assert_eq(cart2pol(1.0, 1.0, 1.0), [pi/4, sqrt(2.0), 1.0])
28 /// ```
29 #[rhai_fn(name = "cart2pol")]
30 pub fn cart2pol3d(x: FLOAT, y: FLOAT, z: FLOAT) -> Array {
31 vec![
32 Dynamic::from(y.atan2(x)),
33 Dynamic::from(y.hypot(x)),
34 Dynamic::from(z),
35 ]
36 }
37
38 /// Convert the argument from 2D Cartesian coordinates to polar coordinates.
39 /// ```typescript
40 /// assert_eq(cart2pol(1.0, 1.0), [pi/4, sqrt(2.0)])
41 /// ```
42 #[rhai_fn(name = "cart2pol")]
43 pub fn cart2pol2d(x: FLOAT, y: FLOAT) -> Array {
44 vec![Dynamic::from(y.atan2(x)), Dynamic::from(y.hypot(x))]
45 }
46
47 /// Convert the argument from 3D polar coordinates to Cartesian coordinates.
48 /// ```typescript
49 /// assert_approx_eq(pol2cart(pi/4, sqrt(2.0), 1.0), [1.0, 1.0, 1.0])
50 /// ```
51 #[rhai_fn(name = "pol2cart")]
52 pub fn pol2cart3d(theta: FLOAT, r: FLOAT, z: FLOAT) -> Array {
53 vec![
54 Dynamic::from(r * theta.cos()),
55 Dynamic::from(r * theta.sin()),
56 Dynamic::from(z),
57 ]
58 }
59
60 /// Convert the argument from 2D polar coordinates to Cartesian coordinates.
61 /// ```typescript
62 /// assert_approx_eq(pol2cart(pi/4, sqrt(2.0)), [1.0, 1.0])
63 /// ```
64 #[rhai_fn(name = "pol2cart")]
65 pub fn pol2cart2d(theta: FLOAT, r: FLOAT) -> Array {
66 vec![
67 Dynamic::from(r * theta.cos()),
68 Dynamic::from(r * theta.sin()),
69 ]
70 }
71
72 /// Convert the argument from 3D Cartesian coordinates to spherical coordinates.
73 /// ```typescript
74 /// assert_approx_eq(cart2sph(1.0, 0.0, 1.0), [0.0, pi/4, sqrt(2.0)])
75 /// ```
76 #[rhai_fn(name = "cart2sph")]
77 pub fn cart2sph(x: FLOAT, y: FLOAT, z: FLOAT) -> Array {
78 vec![
79 Dynamic::from(y.atan2(x)),
80 Dynamic::from(z.atan2(y.hypot(x))),
81 Dynamic::from(hypot3(x, y, z)),
82 ]
83 }
84
85 /// Convert the argument from spherical coordinates to 3D Cartesian coordinates.
86 /// ```typescript
87 /// assert_approx_eq(sph2cart(0.0, pi/4, sqrt(2.0)), [1.0, 0.0, 1.0])
88 /// ```
89 #[rhai_fn(name = "sph2cart")]
90 pub fn sph2cart(azimuth: FLOAT, elevation: FLOAT, r: FLOAT) -> Array {
91 vec![
92 Dynamic::from(r * elevation.cos() * azimuth.cos()),
93 Dynamic::from(r * elevation.cos() * azimuth.sin()),
94 Dynamic::from(r * elevation.sin()),
95 ]
96 }
97
98 /// Extends the built-in hypot function to compute distance in 3D cartesian space
99 /// ```typescript
100 /// assert_eq(hypot(2.0, 3.0, 6.0), 7.0);
101 /// ```
102 #[rhai_fn(name = "hypot")]
103 pub fn hypot3(x: FLOAT, y: FLOAT, z: FLOAT) -> FLOAT {
104 (x.powf(2.0) + y.powf(2.0) + z.powf(2.0)).sqrt()
105 }
106
107 /// Returns the sine of an argument given in degrees
108 /// ```typescript
109 /// assert_eq(sind(0.0), 0.0);
110 /// ```
111 /// ```typescript
112 /// assert_eq(sind(90.0), 1.0);
113 /// ```
114 /// ```typescript
115 /// assert_approx_eq(sind(180.0), 0.0);
116 /// ```
117 /// ```typescript
118 /// assert_eq(sind(270.0), -1.0);
119 /// ```
120 #[rhai_fn(name = "sind")]
121 pub fn sind(degrees: FLOAT) -> FLOAT {
122 FLOAT::sin(deg2rad(degrees))
123 }
124
125 /// Returns the inverse sine in degrees
126 /// ```typescript
127 /// assert_eq(asind(-1.0), -90.0);
128 /// ```
129 /// ```typescript
130 /// assert_eq(asind(0.0), 0.0);
131 /// ```
132 /// ```typescript
133 /// assert_eq(asind(1.0), 90.0);
134 /// ```
135 #[rhai_fn(name = "asind")]
136 pub fn asind(x: FLOAT) -> FLOAT {
137 rad2deg(FLOAT::asin(x))
138 }
139
140 /// Returns the hyperbolic sine of the argument given in degrees
141 /// ```typescript
142 /// assert_eq(sinhd(0.0), 0.0)
143 /// ```
144 /// ```typescript
145 /// assert_eq(sinhd(10.0), sinh(10.0*pi/180.0))
146 /// ```
147 #[rhai_fn(name = "sinhd")]
148 pub fn sinhd(degrees: FLOAT) -> FLOAT {
149 FLOAT::sinh(deg2rad(degrees))
150 }
151
152 /// Returns the inverse hyperbolic sine in degrees
153 /// ```typescript
154 /// assert_eq(asinhd(0.0), 0.0)
155 /// ```
156 /// ```typescript
157 /// assert_eq(asinhd(10.0), 180.0/pi*asinh(10.0))
158 /// ```
159 #[rhai_fn(name = "asinhd")]
160 pub fn asinhd(x: FLOAT) -> FLOAT {
161 rad2deg(FLOAT::asinh(x))
162 }
163
164 /// Returns the cosine of an argument given in degrees
165 /// ```typescript
166 /// assert_eq(cosd(0.0), 1.0);
167 /// ```
168 /// ```typescript
169 /// assert_approx_eq(cosd(90.0), 0.0);
170 /// ```
171 /// ```typescript
172 /// assert_eq(cosd(180.0), -1.0);
173 /// ```
174 /// ```typescript
175 /// assert_approx_eq(cosd(270.0), 0.0);
176 /// ```
177 #[rhai_fn(name = "cosd")]
178 pub fn cosd(degrees: FLOAT) -> FLOAT {
179 FLOAT::cos(deg2rad(degrees))
180 }
181
182 /// Returns the inverse cosine in degrees
183 /// ```typescript
184 /// assert_eq(acosd(-1.0), 180.0);
185 /// ```
186 /// ```typescript
187 /// assert_eq(acosd(0.0), 90.0);
188 /// ```
189 /// ```typescript
190 /// assert_eq(acosd(1.0), 0.0);
191 /// ```
192 #[rhai_fn(name = "acosd")]
193 pub fn acosd(x: FLOAT) -> FLOAT {
194 rad2deg(FLOAT::acos(x))
195 }
196
197 /// Returns the hyperbolic cosine of the argument given in degrees
198 /// ```typescript
199 /// assert_eq(coshd(0.0), 1.0)
200 /// ```
201 /// ```typescript
202 /// assert_eq(coshd(10.0), cosh(10.0*pi/180.0))
203 /// ```
204 #[rhai_fn(name = "coshd")]
205 pub fn coshd(degrees: FLOAT) -> FLOAT {
206 FLOAT::cosh(deg2rad(degrees))
207 }
208
209 /// Returns the inverse hyperbolic cosine in degrees
210 /// ```typescript
211 /// assert_eq(acoshd(1.0), 0.0)
212 /// ```
213 /// ```typescript
214 /// assert_eq(acoshd(10.0), 180.0/pi*acosh(10.0))
215 /// ```
216 #[rhai_fn(name = "acoshd")]
217 pub fn acoshd(x: FLOAT) -> FLOAT {
218 rad2deg(FLOAT::acosh(x))
219 }
220
221 /// Returns the tangent of an argument given in degrees
222 /// ```typescript
223 /// assert_approx_eq(tand(-45.0), -1.0);
224 /// ```
225 /// ```typescript
226 /// assert_eq(tand(0.0), 0.0);
227 /// ```
228 /// ```typescript
229 /// assert_approx_eq(tand(45.0), 1.0);
230 /// ```
231 #[rhai_fn(name = "tand")]
232 pub fn tand(degrees: FLOAT) -> FLOAT {
233 FLOAT::tan(deg2rad(degrees))
234 }
235
236 /// Returns the inverse tangent in degrees
237 /// ```typescript
238 /// assert_approx_eq(atand(-1.0), -45.0);
239 /// ```
240 /// ```typescript
241 /// assert_eq(atand(0.0), 0.0);
242 /// ```
243 /// ```typescript
244 /// assert_approx_eq(atand(1.0), 45.0);
245 /// ```
246 #[rhai_fn(name = "atand")]
247 pub fn atand(x: FLOAT) -> FLOAT {
248 rad2deg(FLOAT::atan(x))
249 }
250
251 /// Returns the inverse tangent in degrees , taking two arguments as input.
252 /// ```typescript
253 /// assert_approx_eq(atand(-1.0, 1.0), -45.0);
254 /// ```
255 /// ```typescript
256 /// assert_eq(atand(0.0, 1.0), 0.0);
257 /// ```
258 /// ```typescript
259 /// assert_approx_eq(atand(1.0, 1.0), 45.0);
260 /// ```
261 #[rhai_fn(name = "atand")]
262 pub fn atand2(x: FLOAT, y: FLOAT) -> FLOAT {
263 rad2deg(FLOAT::atan2(x, y))
264 }
265
266 /// Returns the hyperbolic tangent of the argument given in degrees
267 /// ```typescript
268 /// assert_eq(tanhd(0.0), 0.0)
269 /// ```
270 /// ```typescript
271 /// assert_eq(tanhd(10.0), tanh(10.0*pi/180.0))
272 /// ```
273 #[rhai_fn(name = "tanhd")]
274 pub fn tanhd(degrees: FLOAT) -> FLOAT {
275 FLOAT::tanh(deg2rad(degrees))
276 }
277
278 /// Returns the inverse hyperbolic tangent in degrees
279 /// ```typescript
280 /// assert_eq(atanhd(0.0), 0.0)
281 /// ```
282 /// ```typescript
283 /// assert_eq(atanhd(10.0), 180.0/pi*atanh(10.0))
284 /// ```
285 #[rhai_fn(name = "atanhd")]
286 pub fn atanhd(x: FLOAT) -> FLOAT {
287 rad2deg(FLOAT::atanh(x))
288 }
289
290 /// Returns the cosecant of the argument given in radians
291 /// ```typescript
292 /// assert_eq(csc(-pi/2), -1.0)
293 /// ```
294 /// ```typescript
295 /// assert_eq(csc(0.0), inf)
296 /// ```
297 /// ```typescript
298 /// assert_eq(csc(pi/2), 1.0)
299 /// ```
300 #[rhai_fn(name = "csc")]
301 pub fn csc(radians: FLOAT) -> FLOAT {
302 1.0 / FLOAT::sin(radians)
303 }
304
305 /// Returns the cosecant of the argument given in degrees
306 /// ```typescript
307 /// assert_eq(cscd(-90.0), -1.0)
308 /// ```
309 /// ```typescript
310 /// assert_eq(cscd(0.0), inf)
311 /// ```
312 /// ```typescript
313 /// assert_eq(cscd(90.0), 1.0)
314 /// ```
315 #[rhai_fn(name = "cscd")]
316 pub fn cscd(degrees: FLOAT) -> FLOAT {
317 1.0 / FLOAT::sin(deg2rad(degrees))
318 }
319
320 /// Returns the inverse cosecant in radians
321 /// ```typescript
322 /// assert_eq(acsc(-1.0), -pi/2)
323 /// ```
324 /// ```typescript
325 /// assert_eq(acsc(inf), 0.0)
326 /// ```
327 /// ```typescript
328 /// assert_eq(acsc(1.0), pi/2)
329 /// ```
330 #[rhai_fn(name = "acsc")]
331 pub fn acsc(x: FLOAT) -> FLOAT {
332 FLOAT::asin(1.0 / x)
333 }
334
335 /// Returns the inverse cosecant in degrees
336 /// ```typescript
337 /// assert_eq(acscd(-1.0), -90.0)
338 /// ```
339 /// ```typescript
340 /// assert_eq(acscd(inf), 0.0)
341 /// ```
342 /// ```typescript
343 /// assert_eq(acscd(1.0), 90.0)
344 /// ```
345 #[rhai_fn(name = "acscd")]
346 pub fn acscd(x: FLOAT) -> FLOAT {
347 rad2deg(FLOAT::asin(1.0 / x))
348 }
349
350 /// Returns the hyperbolic cosecant of the argument given in radians
351 /// ```typescript
352 /// assert_eq(csch(0.0), inf)
353 /// ```
354 /// ```typescript
355 /// assert_eq(csch(10.0), 1.0/sinh(10.0))
356 /// ```
357 /// ```typescript
358 /// assert_eq(csch(pi/2), 1.0/sinh(pi/2))
359 /// ```
360 #[rhai_fn(name = "csch")]
361 pub fn csch(radians: FLOAT) -> FLOAT {
362 1.0 / FLOAT::sinh(radians)
363 }
364
365 /// Returns the hyperbolic cosecant of the argument given in degrees
366 /// ```typescript
367 /// assert_eq(cschd(0.0), inf)
368 /// ```
369 /// ```typescript
370 /// assert_eq(cschd(10.0), 1.0/sinhd(10.0))
371 /// ```
372 /// ```typescript
373 /// assert_eq(cschd(90.0), 1.0/sinhd(90.0))
374 /// ```
375 #[rhai_fn(name = "cschd")]
376 pub fn cschd(degrees: FLOAT) -> FLOAT {
377 1.0 / FLOAT::sinh(deg2rad(degrees))
378 }
379
380 /// Returns the inverse hyperbolic cosecant in radians
381 /// ```typescript
382 /// assert_eq(acsch(inf), 0.0)
383 /// ```
384 /// ```typescript
385 /// assert_eq(acsch(1.0), asinh(1.0))
386 /// ```
387 /// ```typescript
388 /// assert_eq(acsch(-1.0), asinh(-1.0))
389 /// ```
390 #[rhai_fn(name = "acsch")]
391 pub fn acsch(x: FLOAT) -> FLOAT {
392 FLOAT::asinh(1.0 / x)
393 }
394
395 /// Returns the inverse hyperbolic cosecant in degrees
396 /// ```typescript
397 /// assert_eq(acschd(inf), 0.0)
398 /// ```
399 /// ```typescript
400 /// assert_eq(acschd(1.0), asinhd(1.0))
401 /// ```
402 /// ```typescript
403 /// assert_eq(acschd(-1.0), asinhd(-1.0))
404 /// ```
405 #[rhai_fn(name = "acschd")]
406 pub fn acschd(x: FLOAT) -> FLOAT {
407 rad2deg(FLOAT::asinh(1.0 / x))
408 }
409
410 /// Returns the secant of the argument given in radians
411 /// ```typescript
412 /// assert_eq(sec(0.0), 1.0);
413 /// ```
414 /// ```typescript
415 /// assert_eq(sec(pi/2), 1/cos(pi/2));
416 /// ```
417 /// ```typescript
418 /// assert_eq(sec(pi), -1.0);
419 #[rhai_fn(name = "sec")]
420 pub fn sec(radians: FLOAT) -> FLOAT {
421 1.0 / FLOAT::cos(radians)
422 }
423
424 /// Returns the secant of the argument given in degrees
425 /// ```typescript
426 /// assert_eq(secd(0.0), 1.0);
427 /// ```
428 /// ```typescript
429 /// assert_eq(secd(90.0), 1/cosd(90.0));
430 /// ```
431 /// ```typescript
432 /// assert_eq(secd(180.0), -1.0);
433 /// ```
434 #[rhai_fn(name = "secd")]
435 pub fn secd(degrees: FLOAT) -> FLOAT {
436 1.0 / FLOAT::cos(deg2rad(degrees))
437 }
438
439 /// Returns the inverse secant in radians
440 /// ```typescript
441 /// assert_eq(asec(1.0), 0.0);
442 /// ```
443 /// ```typescript
444 /// assert_eq(asec(-1.0), pi);
445 /// ```
446 /// ```typescript
447 /// assert_eq(asec(0.5), acos(2.0));
448 /// ```
449 #[rhai_fn(name = "asec")]
450 pub fn asec(x: FLOAT) -> FLOAT {
451 FLOAT::acos(1.0 / x)
452 }
453
454 /// Returns the inverse secant in degrees
455 /// ```typescript
456 /// assert_eq(asecd(1.0), 0.0);
457 /// ```
458 /// ```typescript
459 /// assert_eq(asecd(-1.0), 180.0);
460 /// ```
461 /// ```typescript
462 /// assert_eq(asecd(0.5), acosd(2.0));
463 /// ```
464 #[rhai_fn(name = "asecd")]
465 pub fn asecd(x: FLOAT) -> FLOAT {
466 rad2deg(FLOAT::acos(1.0 / x))
467 }
468
469 /// Returns the hyperbolic secant of the argument given in radians
470 /// ```typescript
471 /// assert_eq(sech(0.0), 1.0);
472 /// ```
473 /// ```typescript
474 /// assert_eq(sech(10.0), 1.0/cosh(10.0));
475 /// ```
476 /// ```typescript
477 /// assert_eq(sech(pi/2), 1.0/cosh(pi/2));
478 /// ```
479 #[rhai_fn(name = "sech")]
480 pub fn sech(radians: FLOAT) -> FLOAT {
481 1.0 / FLOAT::cosh(radians)
482 }
483 /// Returns the hyperbolic secant of the argument given in degrees
484 /// ```typescript
485 /// assert_eq(sechd(0.0), 1.0);
486 /// ```
487 /// ```typescript
488 /// assert_eq(sechd(10.0), 1.0/coshd(10.0));
489 /// ```
490 /// ```typescript
491 /// assert_eq(sechd(90.0), 1.0/coshd(90.0));
492 /// ```
493 #[rhai_fn(name = "sechd")]
494 pub fn sechd(degrees: FLOAT) -> FLOAT {
495 1.0 / FLOAT::cosh(deg2rad(degrees))
496 }
497
498 /// Returns the inverse hyperbolic secant in radians
499 /// ```typescript
500 /// assert_eq(asech(1.0), 0.0);
501 /// ```
502 /// ```typescript
503 /// assert_eq(asech(0.5), acosh(2.0));
504 /// ```
505 /// ```typescript
506 /// assert_eq(asech(0.1), acosh(10.0));
507 /// ```
508 #[rhai_fn(name = "asech")]
509 pub fn asech(x: FLOAT) -> FLOAT {
510 FLOAT::acosh(1.0 / x)
511 }
512
513 /// Returns the inverse hyperbolic secant of the argument in degrees
514 /// ```typescript
515 /// assert_eq(asechd(1.0), 0.0);
516 /// ```
517 #[rhai_fn(name = "asechd")]
518 pub fn asechd(x: FLOAT) -> FLOAT {
519 rad2deg(FLOAT::acosh(1.0 / x))
520 }
521
522 /// Returns the cotangent of the argument given in radians
523 /// ```typescript
524 /// assert_approx_eq(cot(pi/4), 1.0, 1e-10);
525 /// ```
526 /// ```typescript
527 /// assert_approx_eq(cot(pi/2), 0.0, 1e-10);
528 /// ```
529 /// ```typescript
530 /// assert_approx_eq(cot(3*pi/4), -1.0, 1e-10);
531 /// ```
532 #[rhai_fn(name = "cot")]
533 pub fn cot(radians: FLOAT) -> FLOAT {
534 1.0 / FLOAT::tan(radians)
535 }
536
537 /// Returns the cotangent of the argument given in degrees
538 /// ```typescript
539 /// assert_approx_eq(cotd(45.0), 1.0, 1e-10);
540 /// ```
541 /// ```typescript
542 /// assert_approx_eq(cotd(90.0), 0.0, 1e-10);
543 /// ```
544 /// ```typescript
545 /// assert_approx_eq(cotd(135.0), -1.0, 1e-10);
546 /// ```
547 #[rhai_fn(name = "cotd")]
548 pub fn cotd(degrees: FLOAT) -> FLOAT {
549 1.0 / FLOAT::tan(deg2rad(degrees))
550 }
551
552 /// Returns the inverse of the cotangent in radians
553 /// ```typescript
554 /// assert_eq(acot(1.0), pi/4);
555 /// ```
556 /// ```typescript
557 /// assert_eq(acot(-1.0), -pi/4);
558 /// ```
559 /// ```typescript
560 /// assert_eq(acot(0.0), pi/2);
561 /// ```
562 #[rhai_fn(name = "acot")]
563 pub fn acot(x: FLOAT) -> FLOAT {
564 FLOAT::atan(1.0 / x)
565 }
566
567 /// Returns the inverse of the cotangent in degrees
568 /// ```typescript
569 /// assert_eq(acotd(1.0), 45.0);
570 /// ```
571 /// ```typescript
572 /// assert_eq(acotd(-1.0), -45.0);
573 /// ```
574 /// ```typescript
575 /// assert_eq(acotd(0.0), 90.0);
576 /// ```
577 #[rhai_fn(name = "acotd")]
578 pub fn acotd(x: FLOAT) -> FLOAT {
579 rad2deg(FLOAT::atan(1.0 / x))
580 }
581
582 /// Returns the hyperbolic cotangent of the argument given in radians
583 /// ```typescript
584 /// assert_approx_eq(coth(1.0), cosh(1.0)/sinh(1.0), 1e-10);
585 /// ```
586 /// ```typescript
587 /// assert_approx_eq(coth(0.5), cosh(0.5)/sinh(0.5), 1e-10);
588 /// ```
589 /// ```typescript
590 /// assert_approx_eq(coth(0.1), cosh(0.1)/sinh(0.1), 1e-10);
591 /// ```
592 #[rhai_fn(name = "coth")]
593 pub fn coth(radians: FLOAT) -> FLOAT {
594 1.0 / FLOAT::tanh(radians)
595 }
596
597 /// Returns the hyperbolic cotangent of the argument given in degrees
598 /// ```typescript
599 /// assert_approx_eq(cothd(1.0), coshd(1.0)/sinhd(1.0), 1e-10);
600 /// ```
601 /// ```typescript
602 /// assert_approx_eq(cothd(0.5), coshd(0.5)/sinhd(0.5), 1e-10);
603 /// ```
604 /// ```typescript
605 /// assert_approx_eq(cothd(0.1), coshd(0.1)/sinhd(0.1), 1e-10);
606 /// ```
607 #[rhai_fn(name = "cothd")]
608 pub fn cothd(degrees: FLOAT) -> FLOAT {
609 1.0 / FLOAT::tanh(deg2rad(degrees))
610 }
611
612 /// Returns the inverse hyperbolic cotangent of the argument in radians
613 /// ```typescript
614 /// assert_eq(acoth(1.0), atanh(1.0));
615 /// ```
616 /// ```typescript
617 /// assert_eq(acoth(-1.0), atanh(-1.0));
618 /// ```
619 #[rhai_fn(name = "acoth")]
620 pub fn acoth(x: FLOAT) -> FLOAT {
621 FLOAT::atanh(1.0 / x)
622 }
623
624 /// Returns the inverse hyperbolic cotangent of the argument in degrees
625 /// ```typescript
626 /// assert_eq(acothd(1.0), atanhd(1.0));
627 /// ```
628 /// ```typescript
629 /// assert_eq(acothd(-1.0), atanhd(-1.0));
630 /// ```
631 #[rhai_fn(name = "acothd")]
632 pub fn acothd(x: FLOAT) -> FLOAT {
633 rad2deg(FLOAT::atanh(1.0 / x))
634 }
635}