Skip to main content

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}