*** empty log message ***
[chuck-blob.git] / v2 / ulib_math.cpp
blobe6ae674710defa676dc3023d17b4fff7294a2fa3
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
22 U.S.A.
23 -----------------------------------------------------------------------------*/
25 //-----------------------------------------------------------------------------
26 // file: ulib_math.cpp
27 // desc: ...
29 // author: Ge Wang (gewang@cs.princeton.edu)
30 // Perry R. Cook (prc@cs.princeton.edu)
31 // date: Spring 2004
32 //-----------------------------------------------------------------------------
33 #include "chuck_type.h"
34 #include "ulib_math.h"
35 #include "util_math.h"
36 #include "ulib_std.h"
38 #ifdef __PLATFORM_WIN32__
39 #include <float.h>
40 #endif
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 };
49 // query
50 DLL_QUERY libmath_query( Chuck_DL_Query * QUERY )
52 // get global
53 Chuck_Env * env = Chuck_Env::instance();
54 // name
55 QUERY->setname( QUERY, "Math" );
57 /*! \example
58 math.sin( math.pi /2.0 ) => stdout;
61 // register deprecate
62 type_engine_register_deprecate( env, "math", "Math" );
64 // add class
65 QUERY->begin_class( QUERY, "Math", "Object" );
67 // add abs
68 QUERY->add_sfun( QUERY, abs_impl, "int", "abs" );
69 QUERY->add_arg( QUERY, "int", "value" );
71 // add fabs
72 QUERY->add_sfun( QUERY, fabs_impl, "float", "fabs" );
73 QUERY->add_arg( QUERY, "float", "value" );
75 // add sgn
76 QUERY->add_sfun( QUERY, sgn_impl, "float", "sgn" );
77 QUERY->add_arg( QUERY, "float", "value" );
79 // sin
80 QUERY->add_sfun( QUERY, sin_impl, "float", "sin" );
81 QUERY->add_arg( QUERY, "float", "x" );
83 // cos
84 QUERY->add_sfun( QUERY, cos_impl, "float", "cos" );
85 QUERY->add_arg( QUERY, "float", "x" );
87 // tan
88 QUERY->add_sfun( QUERY, tan_impl, "float", "tan" );
89 QUERY->add_arg( QUERY, "float", "x" );
91 // asin
92 QUERY->add_sfun( QUERY, asin_impl, "float", "asin" );
93 QUERY->add_arg( QUERY, "float", "x" );
95 // acos
96 QUERY->add_sfun( QUERY, acos_impl, "float", "acos" );
97 QUERY->add_arg( QUERY, "float", "x" );
99 // atan
100 QUERY->add_sfun( QUERY, atan_impl, "float", "atan" );
101 QUERY->add_arg( QUERY, "float", "x" );
103 // atan2
104 QUERY->add_sfun( QUERY, atan2_impl, "float", "atan2" );
105 QUERY->add_arg( QUERY, "float", "y" );
106 QUERY->add_arg( QUERY, "float", "x" );
108 // sinh
109 QUERY->add_sfun( QUERY, sinh_impl, "float", "sinh" );
110 QUERY->add_arg( QUERY, "float", "x" );
112 // cosh
113 QUERY->add_sfun( QUERY, cosh_impl, "float", "cosh" );
114 QUERY->add_arg( QUERY, "float", "x" );
116 // tanh
117 QUERY->add_sfun( QUERY, tanh_impl, "float", "tanh" );
118 QUERY->add_arg( QUERY, "float", "x" );
120 // hypot
121 QUERY->add_sfun( QUERY, hypot_impl, "float", "hypot" );
122 QUERY->add_arg( QUERY, "float", "x" );
123 QUERY->add_arg( QUERY, "float", "y" );
125 // pow
126 QUERY->add_sfun( QUERY, pow_impl, "float", "pow" );
127 QUERY->add_arg( QUERY, "float", "x" );
128 QUERY->add_arg( QUERY, "float", "y" );
130 // sqrt
131 QUERY->add_sfun( QUERY, sqrt_impl, "float", "sqrt" );
132 QUERY->add_arg( QUERY, "float", "x" );
134 // exp
135 QUERY->add_sfun( QUERY, exp_impl, "float", "exp" );
136 QUERY->add_arg( QUERY, "float", "x" );
138 // log
139 QUERY->add_sfun( QUERY, log_impl, "float", "log" );
140 QUERY->add_arg( QUERY, "float", "x" );
142 // log2
143 QUERY->add_sfun( QUERY, log2_impl, "float", "log2" );
144 QUERY->add_arg( QUERY, "float", "x" );
146 // log10
147 QUERY->add_sfun( QUERY, log10_impl, "float", "log10" );
148 QUERY->add_arg( QUERY, "float", "x" );
150 // floor
151 QUERY->add_sfun( QUERY, floor_impl, "float", "floor" );
152 QUERY->add_arg( QUERY, "float", "x" );
154 // ceil
155 QUERY->add_sfun( QUERY, ceil_impl, "float", "ceil" );
156 QUERY->add_arg( QUERY, "float", "x" );
158 // round
159 QUERY->add_sfun( QUERY, round_impl, "float", "round" );
160 QUERY->add_arg( QUERY, "float", "x" );
162 // trunc
163 QUERY->add_sfun( QUERY, trunc_impl, "float", "trunc" );
164 QUERY->add_arg( QUERY, "float", "x" );
166 // fmod
167 QUERY->add_sfun( QUERY, fmod_impl, "float", "fmod" );
168 QUERY->add_arg( QUERY, "float", "x" );
169 QUERY->add_arg( QUERY, "float", "y" );
171 // remainder
172 QUERY->add_sfun( QUERY, remainder_impl, "float", "remainder" );
173 QUERY->add_arg( QUERY, "float", "x" );
174 QUERY->add_arg( QUERY, "float", "y" );
176 // min
177 QUERY->add_sfun( QUERY, min_impl, "float", "min" );
178 QUERY->add_arg( QUERY, "float", "x" );
179 QUERY->add_arg( QUERY, "float", "y" );
181 // max
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" );
187 // isinf
188 QUERY->add_sfun( QUERY, isinf_impl, "int", "isinf" );
189 QUERY->add_arg( QUERY, "float", "x" );
191 // isnan
192 QUERY->add_sfun( QUERY, isnan_impl, "int", "isnan" );
193 QUERY->add_arg( QUERY, "float", "x" );
195 // nextpow2
196 QUERY->add_sfun( QUERY, nextpow2_impl, "int", "nextpow2" );
197 QUERY->add_arg( QUERY, "int", "n" );
199 // rand
200 QUERY->add_sfun( QUERY, rand_impl, "int", "rand" ); //! return int between 0 and RAND_MAX
202 // rand2
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" );
207 // randf
208 QUERY->add_sfun( QUERY, randf_impl, "float", "randf" ); //! rand between -1.0,1.0
210 // rand2f
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" );
215 // add mtof
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" );
220 // add ftom
221 QUERY->add_sfun( QUERY, ftom_impl, "float", "ftom" ); //! frequency to midi note
222 QUERY->add_arg( QUERY, "float", "value" );
224 // add powtodb
225 QUERY->add_sfun( QUERY, powtodb_impl, "float", "powtodb" ); //! linear power to decibel
226 QUERY->add_arg( QUERY, "float", "value" );
228 // add rmstodb
229 QUERY->add_sfun( QUERY, rmstodb_impl, "float", "rmstodb" ); //! rms to decibel
230 QUERY->add_arg( QUERY, "float", "value" );
232 // add dbtopow
233 QUERY->add_sfun( QUERY, dbtopow_impl, "float", "dbtopow" ); //! decibel to linear
234 QUERY->add_arg( QUERY, "float", "value" );
236 // add dbtorms
237 QUERY->add_sfun( QUERY, dbtorms_impl, "float", "dbtorms" ); //! decibel to rms
238 QUERY->add_arg( QUERY, "float", "value" );
240 // add re
241 QUERY->add_sfun( QUERY, re_impl, "float", "re" ); //! real component of complex
242 QUERY->add_arg( QUERY, "complex", "value" );
244 // add im
245 QUERY->add_sfun( QUERY, im_impl, "float", "im" ); //! imaginary component of complex
246 QUERY->add_arg( QUERY, "complex", "value" );
248 // add mag
249 QUERY->add_sfun( QUERY, modulus_impl, "float", "mag" ); //! mag
250 QUERY->add_arg( QUERY, "polar", "value" );
252 // add phase
253 QUERY->add_sfun( QUERY, phase_impl, "float", "phase" ); //! phase
254 QUERY->add_arg( QUERY, "polar", "value" );
256 // add rtop
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" );
261 // add ptor
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" );
266 // pi
267 //! see \example math.ck
268 QUERY->add_svar( QUERY, "float", "PI", TRUE, &g_pi );
270 // twopi
271 QUERY->add_svar( QUERY, "float", "TWO_PI", TRUE, &g_twopi );
273 // e
274 QUERY->add_svar( QUERY, "float", "E", TRUE, &g_e );
275 // e
276 QUERY->add_svar( QUERY, "float", "e", TRUE, &g_e );
278 // i
279 QUERY->add_svar( QUERY, "complex", "I", TRUE, &g_i );
280 QUERY->add_svar( QUERY, "complex", "i", TRUE, &g_i );
282 // j
283 QUERY->add_svar( QUERY, "complex", "J", TRUE, &g_i );
284 QUERY->add_svar( QUERY, "complex", "j", TRUE, &g_i );
286 // done
287 QUERY->end_class( QUERY );
289 return TRUE;
292 // sin
293 CK_DLL_SFUN( sin_impl )
295 RETURN->v_float = ::sin( GET_CK_FLOAT(ARGS) );
298 // cos
299 CK_DLL_SFUN( cos_impl )
301 RETURN->v_float = ::cos( GET_CK_FLOAT(ARGS) );
304 // tan
305 CK_DLL_SFUN( tan_impl )
307 RETURN->v_float = ::tan( GET_CK_FLOAT(ARGS) );
310 // asin
311 CK_DLL_SFUN( asin_impl )
313 RETURN->v_float = ::asin( GET_CK_FLOAT(ARGS) );
316 // acos
317 CK_DLL_SFUN( acos_impl )
319 RETURN->v_float = ::acos( GET_CK_FLOAT(ARGS) );
322 // atan
323 CK_DLL_SFUN( atan_impl )
325 RETURN->v_float = ::atan( GET_CK_FLOAT(ARGS) );
328 // atan2
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 );
336 // sinh
337 CK_DLL_SFUN( sinh_impl )
339 RETURN->v_float = ::sinh( GET_CK_FLOAT(ARGS) );
342 // cosh
343 CK_DLL_SFUN( cosh_impl )
345 RETURN->v_float = ::cosh( GET_CK_FLOAT(ARGS) );
348 // tanh
349 CK_DLL_SFUN( tanh_impl )
351 RETURN->v_float = ::tanh( GET_CK_FLOAT(ARGS) );
354 // hypot
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 );
362 // pow
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 );
370 // sqrt
371 CK_DLL_SFUN( sqrt_impl )
373 RETURN->v_float = ::sqrt( GET_CK_FLOAT(ARGS) );
376 // exp
377 CK_DLL_SFUN( exp_impl )
379 RETURN->v_float = ::exp( GET_CK_FLOAT(ARGS) );
382 // log
383 CK_DLL_SFUN( log_impl )
385 RETURN->v_float = ::log( GET_CK_FLOAT(ARGS) );
388 // log2
389 CK_DLL_SFUN( log2_impl )
391 RETURN->v_float = ::log( GET_CK_FLOAT(ARGS) )/::log( 2.0 );
394 // log10
395 CK_DLL_SFUN( log10_impl )
397 RETURN->v_float = ::log10( GET_CK_FLOAT(ARGS) );
400 // floor
401 CK_DLL_SFUN( floor_impl )
403 RETURN->v_float = ::floor( GET_CK_FLOAT(ARGS) );
406 // ceil
407 CK_DLL_SFUN( ceil_impl )
409 RETURN->v_float = ::ceil( GET_CK_FLOAT(ARGS) );
412 // round
413 CK_DLL_SFUN( round_impl )
415 RETURN->v_float = round( GET_CK_FLOAT(ARGS) );
418 // trunc
419 CK_DLL_SFUN( trunc_impl )
421 RETURN->v_float = trunc( GET_CK_FLOAT(ARGS) );
424 // fmod
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 );
432 // remainder
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 );
440 // min
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;
448 // max
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;
456 // isinf
457 CK_DLL_SFUN( isinf_impl )
459 t_CKFLOAT x = GET_CK_FLOAT(ARGS);
460 #ifdef __PLATFORM_WIN32__
461 RETURN->v_int = !_finite( x );
462 #else
463 RETURN->v_int = isinf( x );
464 #endif
467 // isnan
468 CK_DLL_SFUN( isnan_impl )
470 t_CKFLOAT x = GET_CK_FLOAT(ARGS);
471 #ifdef __PLATFORM_WIN32__
472 RETURN->v_int = _isnan( x );
473 #else
474 RETURN->v_int = isnan( x );
475 #endif
478 // nextpow2 - thanks to Niklas Werner, via music-dsp
479 CK_DLL_SFUN( nextpow2_impl )
481 t_CKINT x = GET_CK_INT(ARGS);
482 t_CKINT xx = x;
483 for( ; x &= x-1; xx = x );
484 RETURN->v_int = xx * 2;
487 // re
488 CK_DLL_SFUN( re_impl )
490 t_CKCOMPLEX x = GET_NEXT_COMPLEX(ARGS);
491 RETURN->v_float = x.re;
494 // im
495 CK_DLL_SFUN( im_impl )
497 t_CKCOMPLEX x = GET_NEXT_COMPLEX(ARGS);
498 RETURN->v_float = x.im;
501 // modulus
502 CK_DLL_SFUN( modulus_impl )
504 t_CKPOLAR x = GET_NEXT_POLAR(ARGS);
505 RETURN->v_float = x.modulus;
508 // phase
509 CK_DLL_SFUN( phase_impl )
511 t_CKPOLAR x = GET_NEXT_POLAR(ARGS);
512 RETURN->v_float = x.phase;
516 // rtop
517 CK_DLL_SFUN( rtop_impl )
519 // get array
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
524 if( !from || !to )
526 // log
527 EM_log( CK_LOG_WARNING, "Math.rtop( ... ) was given one or more NULL arrays..." );
528 return;
531 // find how much to copy
532 t_CKUINT count = ck_min( from->size(), to->size() );
533 t_CKCOMPLEX c;
534 t_CKCOMPLEX p;
536 // convert
537 for( t_CKUINT i = 0; i < count; i++ )
539 // go for it
540 from->get( i, &c );
541 p.re = ::hypot( c.re, c.im );
542 p.im = ::atan2( c.im, c.re );
543 to->set( i, p );
546 // zero out the rest
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;
555 // ptor
556 CK_DLL_SFUN( ptor_impl )
558 // get array
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
563 if( !from || !to )
565 // log
566 EM_log( CK_LOG_WARNING, "Math.ptor( ... ) was given one or more NULL arrays..." );
567 return;
570 // find how much to copy
571 t_CKUINT count = ck_min( from->size(), to->size() );
572 t_CKCOMPLEX c;
573 t_CKPOLAR p;
575 // convert
576 for( t_CKUINT i = 0; i < count; i++ )
578 // go for it
579 from->get( i, (t_CKCOMPLEX *)&p );
580 c.re = p.modulus * ::cos( p.phase );
581 c.im = p.modulus * ::sin( p.phase );
582 to->set( i, c );
585 // zero out the rest
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;