1 /*----------------------------------------------------------------------------
2 ChucK Concurrent, On-the-fly Audio Programming Language
3 Compiler and Virtual Machine
5 Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6 http://chuck.cs.princeton.edu/
7 http://soundlab.cs.princeton.edu/
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 -----------------------------------------------------------------------------*/
25 //-----------------------------------------------------------------------------
26 // file: ulib_math.cpp
29 // author: Ge Wang (gewang@cs.princeton.edu)
30 // Perry R. Cook (prc@cs.princeton.edu)
32 //-----------------------------------------------------------------------------
33 #include "chuck_type.h"
34 #include "ulib_math.h"
35 #include "util_math.h"
38 #ifdef __PLATFORM_WIN32__
43 static double g_pi
= ONE_PI
;
44 static double g_twopi
= TWO_PI
;
45 static double g_e
= ::exp( 1.0 );
46 static t_CKCOMPLEX g_i
= { 0.0, 1.0 };
50 DLL_QUERY
libmath_query( Chuck_DL_Query
* QUERY
)
53 Chuck_Env
* env
= Chuck_Env::instance();
55 QUERY
->setname( QUERY
, "Math" );
58 math.sin( math.pi /2.0 ) => stdout;
62 type_engine_register_deprecate( env
, "math", "Math" );
65 QUERY
->begin_class( QUERY
, "Math", "Object" );
68 QUERY
->add_sfun( QUERY
, abs_impl
, "int", "abs" );
69 QUERY
->add_arg( QUERY
, "int", "value" );
72 QUERY
->add_sfun( QUERY
, fabs_impl
, "float", "fabs" );
73 QUERY
->add_arg( QUERY
, "float", "value" );
76 QUERY
->add_sfun( QUERY
, sgn_impl
, "float", "sgn" );
77 QUERY
->add_arg( QUERY
, "float", "value" );
80 QUERY
->add_sfun( QUERY
, sin_impl
, "float", "sin" );
81 QUERY
->add_arg( QUERY
, "float", "x" );
84 QUERY
->add_sfun( QUERY
, cos_impl
, "float", "cos" );
85 QUERY
->add_arg( QUERY
, "float", "x" );
88 QUERY
->add_sfun( QUERY
, tan_impl
, "float", "tan" );
89 QUERY
->add_arg( QUERY
, "float", "x" );
92 QUERY
->add_sfun( QUERY
, asin_impl
, "float", "asin" );
93 QUERY
->add_arg( QUERY
, "float", "x" );
96 QUERY
->add_sfun( QUERY
, acos_impl
, "float", "acos" );
97 QUERY
->add_arg( QUERY
, "float", "x" );
100 QUERY
->add_sfun( QUERY
, atan_impl
, "float", "atan" );
101 QUERY
->add_arg( QUERY
, "float", "x" );
104 QUERY
->add_sfun( QUERY
, atan2_impl
, "float", "atan2" );
105 QUERY
->add_arg( QUERY
, "float", "y" );
106 QUERY
->add_arg( QUERY
, "float", "x" );
109 QUERY
->add_sfun( QUERY
, sinh_impl
, "float", "sinh" );
110 QUERY
->add_arg( QUERY
, "float", "x" );
113 QUERY
->add_sfun( QUERY
, cosh_impl
, "float", "cosh" );
114 QUERY
->add_arg( QUERY
, "float", "x" );
117 QUERY
->add_sfun( QUERY
, tanh_impl
, "float", "tanh" );
118 QUERY
->add_arg( QUERY
, "float", "x" );
121 QUERY
->add_sfun( QUERY
, hypot_impl
, "float", "hypot" );
122 QUERY
->add_arg( QUERY
, "float", "x" );
123 QUERY
->add_arg( QUERY
, "float", "y" );
126 QUERY
->add_sfun( QUERY
, pow_impl
, "float", "pow" );
127 QUERY
->add_arg( QUERY
, "float", "x" );
128 QUERY
->add_arg( QUERY
, "float", "y" );
131 QUERY
->add_sfun( QUERY
, sqrt_impl
, "float", "sqrt" );
132 QUERY
->add_arg( QUERY
, "float", "x" );
135 QUERY
->add_sfun( QUERY
, exp_impl
, "float", "exp" );
136 QUERY
->add_arg( QUERY
, "float", "x" );
139 QUERY
->add_sfun( QUERY
, log_impl
, "float", "log" );
140 QUERY
->add_arg( QUERY
, "float", "x" );
143 QUERY
->add_sfun( QUERY
, log2_impl
, "float", "log2" );
144 QUERY
->add_arg( QUERY
, "float", "x" );
147 QUERY
->add_sfun( QUERY
, log10_impl
, "float", "log10" );
148 QUERY
->add_arg( QUERY
, "float", "x" );
151 QUERY
->add_sfun( QUERY
, floor_impl
, "float", "floor" );
152 QUERY
->add_arg( QUERY
, "float", "x" );
155 QUERY
->add_sfun( QUERY
, ceil_impl
, "float", "ceil" );
156 QUERY
->add_arg( QUERY
, "float", "x" );
159 QUERY
->add_sfun( QUERY
, round_impl
, "float", "round" );
160 QUERY
->add_arg( QUERY
, "float", "x" );
163 QUERY
->add_sfun( QUERY
, trunc_impl
, "float", "trunc" );
164 QUERY
->add_arg( QUERY
, "float", "x" );
167 QUERY
->add_sfun( QUERY
, fmod_impl
, "float", "fmod" );
168 QUERY
->add_arg( QUERY
, "float", "x" );
169 QUERY
->add_arg( QUERY
, "float", "y" );
172 QUERY
->add_sfun( QUERY
, remainder_impl
, "float", "remainder" );
173 QUERY
->add_arg( QUERY
, "float", "x" );
174 QUERY
->add_arg( QUERY
, "float", "y" );
177 QUERY
->add_sfun( QUERY
, min_impl
, "float", "min" );
178 QUERY
->add_arg( QUERY
, "float", "x" );
179 QUERY
->add_arg( QUERY
, "float", "y" );
182 //! see \example powerup.ck
183 QUERY
->add_sfun( QUERY
, max_impl
, "float", "max" );
184 QUERY
->add_arg( QUERY
, "float", "x" );
185 QUERY
->add_arg( QUERY
, "float", "y" );
188 QUERY
->add_sfun( QUERY
, isinf_impl
, "int", "isinf" );
189 QUERY
->add_arg( QUERY
, "float", "x" );
192 QUERY
->add_sfun( QUERY
, isnan_impl
, "int", "isnan" );
193 QUERY
->add_arg( QUERY
, "float", "x" );
196 QUERY
->add_sfun( QUERY
, nextpow2_impl
, "int", "nextpow2" );
197 QUERY
->add_arg( QUERY
, "int", "n" );
200 QUERY
->add_sfun( QUERY
, rand_impl
, "int", "rand" ); //! return int between 0 and RAND_MAX
203 QUERY
->add_sfun( QUERY
, rand2_impl
, "int", "rand2" ); //! integer between [min,max]
204 QUERY
->add_arg( QUERY
, "int", "min" );
205 QUERY
->add_arg( QUERY
, "int", "max" );
208 QUERY
->add_sfun( QUERY
, randf_impl
, "float", "randf" ); //! rand between -1.0,1.0
211 QUERY
->add_sfun( QUERY
, rand2f_impl
, "float", "rand2f" ); //! rand between min and max
212 QUERY
->add_arg( QUERY
, "float", "min" );
213 QUERY
->add_arg( QUERY
, "float", "max" );
216 //! see \example mand-o-matic.ck
217 QUERY
->add_sfun( QUERY
, mtof_impl
, "float", "mtof" ); //! midi note to frequency
218 QUERY
->add_arg( QUERY
, "float", "value" );
221 QUERY
->add_sfun( QUERY
, ftom_impl
, "float", "ftom" ); //! frequency to midi note
222 QUERY
->add_arg( QUERY
, "float", "value" );
225 QUERY
->add_sfun( QUERY
, powtodb_impl
, "float", "powtodb" ); //! linear power to decibel
226 QUERY
->add_arg( QUERY
, "float", "value" );
229 QUERY
->add_sfun( QUERY
, rmstodb_impl
, "float", "rmstodb" ); //! rms to decibel
230 QUERY
->add_arg( QUERY
, "float", "value" );
233 QUERY
->add_sfun( QUERY
, dbtopow_impl
, "float", "dbtopow" ); //! decibel to linear
234 QUERY
->add_arg( QUERY
, "float", "value" );
237 QUERY
->add_sfun( QUERY
, dbtorms_impl
, "float", "dbtorms" ); //! decibel to rms
238 QUERY
->add_arg( QUERY
, "float", "value" );
241 QUERY
->add_sfun( QUERY
, re_impl
, "float", "re" ); //! real component of complex
242 QUERY
->add_arg( QUERY
, "complex", "value" );
245 QUERY
->add_sfun( QUERY
, im_impl
, "float", "im" ); //! imaginary component of complex
246 QUERY
->add_arg( QUERY
, "complex", "value" );
249 QUERY
->add_sfun( QUERY
, modulus_impl
, "float", "mag" ); //! mag
250 QUERY
->add_arg( QUERY
, "polar", "value" );
253 QUERY
->add_sfun( QUERY
, phase_impl
, "float", "phase" ); //! phase
254 QUERY
->add_arg( QUERY
, "polar", "value" );
257 QUERY
->add_sfun( QUERY
, rtop_impl
, "int", "rtop" ); // rect to polar
258 QUERY
->add_arg( QUERY
, "complex[]", "from" );
259 QUERY
->add_arg( QUERY
, "polar[]", "to" );
262 QUERY
->add_sfun( QUERY
, ptor_impl
, "int", "ptor" ); // polar to rect
263 QUERY
->add_arg( QUERY
, "polar[]", "from" );
264 QUERY
->add_arg( QUERY
, "complex[]", "to" );
267 //! see \example math.ck
268 QUERY
->add_svar( QUERY
, "float", "PI", TRUE
, &g_pi
);
271 QUERY
->add_svar( QUERY
, "float", "TWO_PI", TRUE
, &g_twopi
);
274 QUERY
->add_svar( QUERY
, "float", "E", TRUE
, &g_e
);
276 QUERY
->add_svar( QUERY
, "float", "e", TRUE
, &g_e
);
279 QUERY
->add_svar( QUERY
, "complex", "I", TRUE
, &g_i
);
280 QUERY
->add_svar( QUERY
, "complex", "i", TRUE
, &g_i
);
283 QUERY
->add_svar( QUERY
, "complex", "J", TRUE
, &g_i
);
284 QUERY
->add_svar( QUERY
, "complex", "j", TRUE
, &g_i
);
287 QUERY
->end_class( QUERY
);
293 CK_DLL_SFUN( sin_impl
)
295 RETURN
->v_float
= ::sin( GET_CK_FLOAT(ARGS
) );
299 CK_DLL_SFUN( cos_impl
)
301 RETURN
->v_float
= ::cos( GET_CK_FLOAT(ARGS
) );
305 CK_DLL_SFUN( tan_impl
)
307 RETURN
->v_float
= ::tan( GET_CK_FLOAT(ARGS
) );
311 CK_DLL_SFUN( asin_impl
)
313 RETURN
->v_float
= ::asin( GET_CK_FLOAT(ARGS
) );
317 CK_DLL_SFUN( acos_impl
)
319 RETURN
->v_float
= ::acos( GET_CK_FLOAT(ARGS
) );
323 CK_DLL_SFUN( atan_impl
)
325 RETURN
->v_float
= ::atan( GET_CK_FLOAT(ARGS
) );
329 CK_DLL_SFUN( atan2_impl
)
331 t_CKFLOAT x
= GET_CK_FLOAT(ARGS
);
332 t_CKFLOAT y
= *((t_CKFLOAT
*)ARGS
+ 1 );
333 RETURN
->v_float
= ::atan2( x
, y
);
337 CK_DLL_SFUN( sinh_impl
)
339 RETURN
->v_float
= ::sinh( GET_CK_FLOAT(ARGS
) );
343 CK_DLL_SFUN( cosh_impl
)
345 RETURN
->v_float
= ::cosh( GET_CK_FLOAT(ARGS
) );
349 CK_DLL_SFUN( tanh_impl
)
351 RETURN
->v_float
= ::tanh( GET_CK_FLOAT(ARGS
) );
355 CK_DLL_SFUN( hypot_impl
)
357 t_CKFLOAT x
= GET_CK_FLOAT(ARGS
);
358 t_CKFLOAT y
= *((t_CKFLOAT
*)ARGS
+ 1);
359 RETURN
->v_float
= ::hypot( x
, y
);
363 CK_DLL_SFUN( pow_impl
)
365 t_CKFLOAT x
= GET_CK_FLOAT(ARGS
);
366 t_CKFLOAT y
= *((t_CKFLOAT
*)ARGS
+ 1);
367 RETURN
->v_float
= ::pow( x
, y
);
371 CK_DLL_SFUN( sqrt_impl
)
373 RETURN
->v_float
= ::sqrt( GET_CK_FLOAT(ARGS
) );
377 CK_DLL_SFUN( exp_impl
)
379 RETURN
->v_float
= ::exp( GET_CK_FLOAT(ARGS
) );
383 CK_DLL_SFUN( log_impl
)
385 RETURN
->v_float
= ::log( GET_CK_FLOAT(ARGS
) );
389 CK_DLL_SFUN( log2_impl
)
391 RETURN
->v_float
= ::log( GET_CK_FLOAT(ARGS
) )/::log( 2.0 );
395 CK_DLL_SFUN( log10_impl
)
397 RETURN
->v_float
= ::log10( GET_CK_FLOAT(ARGS
) );
401 CK_DLL_SFUN( floor_impl
)
403 RETURN
->v_float
= ::floor( GET_CK_FLOAT(ARGS
) );
407 CK_DLL_SFUN( ceil_impl
)
409 RETURN
->v_float
= ::ceil( GET_CK_FLOAT(ARGS
) );
413 CK_DLL_SFUN( round_impl
)
415 RETURN
->v_float
= round( GET_CK_FLOAT(ARGS
) );
419 CK_DLL_SFUN( trunc_impl
)
421 RETURN
->v_float
= trunc( GET_CK_FLOAT(ARGS
) );
425 CK_DLL_SFUN( fmod_impl
)
427 t_CKFLOAT x
= GET_CK_FLOAT(ARGS
);
428 t_CKFLOAT y
= *((t_CKFLOAT
*)ARGS
+ 1);
429 RETURN
->v_float
= fmod( x
, y
);
433 CK_DLL_SFUN( remainder_impl
)
435 t_CKFLOAT x
= GET_CK_FLOAT(ARGS
);
436 t_CKFLOAT y
= *((t_CKFLOAT
*)ARGS
+ 1);
437 RETURN
->v_float
= remainder( x
, y
);
441 CK_DLL_SFUN( min_impl
)
443 t_CKFLOAT x
= GET_CK_FLOAT(ARGS
);
444 t_CKFLOAT y
= *((t_CKFLOAT
*)ARGS
+ 1);
445 RETURN
->v_float
= x
< y
? x
: y
;
449 CK_DLL_SFUN( max_impl
)
451 t_CKFLOAT x
= GET_CK_FLOAT(ARGS
);
452 t_CKFLOAT y
= *((t_CKFLOAT
*)ARGS
+ 1);
453 RETURN
->v_float
= x
> y
? x
: y
;
457 CK_DLL_SFUN( isinf_impl
)
459 t_CKFLOAT x
= GET_CK_FLOAT(ARGS
);
460 #ifdef __PLATFORM_WIN32__
461 RETURN
->v_int
= !_finite( x
);
463 RETURN
->v_int
= isinf( x
);
468 CK_DLL_SFUN( isnan_impl
)
470 t_CKFLOAT x
= GET_CK_FLOAT(ARGS
);
471 #ifdef __PLATFORM_WIN32__
472 RETURN
->v_int
= _isnan( x
);
474 RETURN
->v_int
= isnan( x
);
478 // nextpow2 - thanks to Niklas Werner, via music-dsp
479 CK_DLL_SFUN( nextpow2_impl
)
481 t_CKINT x
= GET_CK_INT(ARGS
);
483 for( ; x
&= x
-1; xx
= x
);
484 RETURN
->v_int
= xx
* 2;
488 CK_DLL_SFUN( re_impl
)
490 t_CKCOMPLEX x
= GET_NEXT_COMPLEX(ARGS
);
491 RETURN
->v_float
= x
.re
;
495 CK_DLL_SFUN( im_impl
)
497 t_CKCOMPLEX x
= GET_NEXT_COMPLEX(ARGS
);
498 RETURN
->v_float
= x
.im
;
502 CK_DLL_SFUN( modulus_impl
)
504 t_CKPOLAR x
= GET_NEXT_POLAR(ARGS
);
505 RETURN
->v_float
= x
.modulus
;
509 CK_DLL_SFUN( phase_impl
)
511 t_CKPOLAR x
= GET_NEXT_POLAR(ARGS
);
512 RETURN
->v_float
= x
.phase
;
517 CK_DLL_SFUN( rtop_impl
)
520 Chuck_Array16
* from
= (Chuck_Array16
*)GET_NEXT_OBJECT(ARGS
);
521 Chuck_Array16
* to
= (Chuck_Array16
*)GET_NEXT_OBJECT(ARGS
);
523 // make sure not null
527 EM_log( CK_LOG_WARNING
, "Math.rtop( ... ) was given one or more NULL arrays..." );
531 // find how much to copy
532 t_CKUINT count
= ck_min( from
->size(), to
->size() );
537 for( t_CKUINT i
= 0; i
< count
; i
++ )
541 p
.re
= ::hypot( c
.re
, c
.im
);
542 p
.im
= ::atan2( c
.im
, c
.re
);
547 // if( count < to->size() ) to->zero( count, to->size() );
548 if( count
< to
->size() ) to
->set_size( count
);
550 // return number of elements done
551 RETURN
->v_int
= count
;
556 CK_DLL_SFUN( ptor_impl
)
559 Chuck_Array16
* from
= (Chuck_Array16
*)GET_NEXT_OBJECT(ARGS
);
560 Chuck_Array16
* to
= (Chuck_Array16
*)GET_NEXT_OBJECT(ARGS
);
562 // make sure not null
566 EM_log( CK_LOG_WARNING
, "Math.ptor( ... ) was given one or more NULL arrays..." );
570 // find how much to copy
571 t_CKUINT count
= ck_min( from
->size(), to
->size() );
576 for( t_CKUINT i
= 0; i
< count
; i
++ )
579 from
->get( i
, (t_CKCOMPLEX
*)&p
);
580 c
.re
= p
.modulus
* ::cos( p
.phase
);
581 c
.im
= p
.modulus
* ::sin( p
.phase
);
586 // if( count < to->capacity() ) to->zero( count, to->size() );
587 if( count
< to
->size() ) to
->set_size( count
);
589 // return number of elements done
590 RETURN
->v_int
= count
;