fix codetest failure - ASSERT_ARGS does not have a ; after and
[parrot.git] / src / ops / math.ops
blob3f44ac73e444c517bc8b91c69927d4de96ddbe42
1 /*
2  * $Id$
3 ** math.ops
4 */
6 =head1 NAME
8 math.ops - Mathematical Opcodes
10 =cut
12 =head1 DESCRIPTION
14 Operations that perform basic mathematics. See F<src/dynoplibs/> for more
15 advanced operations.
17 When making changes to any ops file, run C<make bootstrap-ops> to regenerate
18 all generated ops files.
20 =head2 Arithmetic operations
22 These operations store the results of arithmetic on other registers and
23 constants into their destination register, $1.
25 =over 4
27 =cut
29 ########################################
31 =item B<abs>(inout INT)
33 =item B<abs>(inout NUM)
35 =item B<abs>(invar PMC)
37 Set $1 to its absolute value.
39 =item B<abs>(out INT, in INT)
41 =item B<abs>(out NUM, in NUM)
43 =item B<abs>(out PMC, invar PMC)
45 Set $1 to absolute value of $2.
47 =cut
49 inline op abs(inout INT) :base_core {
50     $1 = abs($1);
53 inline op abs(inout NUM) :base_core {
54     $1 = fabs($1);
57 inline op abs(out INT, in INT) :base_core {
58     $1 = abs($2);
61 inline op abs(out NUM, in NUM) :base_core {
62     $1 = fabs($2);
65 inline op abs(invar PMC) :base_core {
66     VTABLE_i_absolute(interp, $1);
69 inline op abs(out PMC, invar PMC) :base_core {
70     $1 = VTABLE_absolute(interp, $2, $1);
73 ########################################
75 =item B<add>(inout INT, in INT)
77 =item B<add>(inout NUM, in NUM)
79 =item B<add>(invar PMC, invar PMC)
81 =item B<add>(invar PMC, in INT)
83 =item B<add>(invar PMC, in NUM)
85 Increase $1 by the amount in $2.
87 =item B<add>(out INT, in INT, in INT)
89 =item B<add>(out NUM, in NUM, in NUM)
91 =item B<add>(invar PMC, invar PMC, invar PMC)
93 =item B<add>(invar PMC, invar PMC, in INT)
95 =item B<add>(invar PMC, invar PMC, in NUM)
97 Set $1 to the sum of $2 and $3.
99 =cut
101 inline op add(inout INT, in INT) :base_core {
102     $1 += $2;
105 inline op add(inout NUM, in NUM) :base_core {
106     $1 += $2;
109 inline op add(invar PMC, invar PMC) :base_core {
110     VTABLE_i_add(interp, $1, $2);
113 inline op add(invar PMC, in INT) :base_core {
114     VTABLE_i_add_int(interp, $1, $2);
117 inline op add(invar PMC, in NUM) :base_core {
118     VTABLE_i_add_float(interp, $1, $2);
121 inline op add(out INT, in INT, in INT) :base_core {
122     $1 = $2 + $3;
125 inline op add(out NUM, in NUM, in NUM) :base_core {
126     $1 = $2 + $3;
129 inline op add(invar PMC, invar PMC, invar PMC) :base_core {
130     $1 = VTABLE_add(interp, $2, $3, $1);
133 inline op add(invar PMC, invar PMC, in INT) :base_core {
134     $1 = VTABLE_add_int(interp, $2, $3, $1);
137 inline op add(invar PMC, invar PMC, in NUM) :base_core {
138     $1 = VTABLE_add_float(interp, $2, $3, $1);
141 ########################################
143 =item B<dec>(inout INT)
145 =item B<dec>(inout NUM)
147 =item B<dec>(invar PMC)
149 Decrease $1 by one.
151 =cut
153 inline op dec(inout INT) :base_core {
154     $1--;
157 inline op dec(inout NUM) :base_core {
158     $1--;
161 inline op dec(invar PMC) :base_core {
162     VTABLE_decrement(interp, $1);
165 ########################################
167 =item B<div>(inout INT, in INT)
169 =item B<div>(inout NUM, in NUM)
171 =item B<div>(invar PMC, invar PMC)
173 =item B<div>(invar PMC, in INT)
175 =item B<div>(invar PMC, in NUM)
177 Divide $1 by $2.
179 =item B<div>(out INT, in INT, in INT)
181 =item B<div>(out NUM, in NUM, in NUM)
183 =item B<div>(invar PMC, invar PMC, invar PMC)
185 =item B<div>(invar PMC, invar PMC, in INT)
187 =item B<div>(invar PMC, invar PMC, in NUM)
189 Set $1 to the quotient of $2 divided by $3. In the case of INTVAL division, the
190 result is truncated (NOT rounded or floored).
191 If the denominator is zero, a 'Divide by zero' exception is thrown.
193 =cut
195 inline op div(inout INT, in INT) :base_core {
196     INTVAL den = $2;
197     if (den == 0) {
198         opcode_t *handler = Parrot_ex_throw_from_op_args(interp, expr NEXT(),
199             EXCEPTION_DIV_BY_ZERO,
200             "Divide by zero");
201         goto ADDRESS(handler);
202     }
203     $1 /= den;
206 inline op div(inout NUM, in NUM) :base_core {
207     FLOATVAL den = $2;
208     if (FLOAT_IS_ZERO(den)) {
209         opcode_t *handler = Parrot_ex_throw_from_op_args(interp, expr NEXT(),
210             EXCEPTION_DIV_BY_ZERO,
211             "Divide by zero");
212         goto ADDRESS(handler);
213     }
214     $1 /= den;
217 inline op div(invar PMC, invar PMC) :base_core {
218     VTABLE_i_divide(interp, $1, $2);
221 inline op div(invar PMC, in INT) :base_core {
222     VTABLE_i_divide_int(interp, $1, $2);
225 inline op div(invar PMC, in NUM) :base_core {
226     VTABLE_i_divide_float(interp, $1, $2);
228 inline op div(out INT, in INT, in INT) :base_core {
229     INTVAL den = $3;
230     if (den == 0) {
231         opcode_t *handler = Parrot_ex_throw_from_op_args(interp, expr NEXT(),
232             EXCEPTION_DIV_BY_ZERO,
233             "Divide by zero");
234         goto ADDRESS(handler);
235     }
236     $1 = $2 / den;
239 inline op div(out NUM, in NUM, in NUM) :base_core {
240     FLOATVAL den = $3;
241     if (FLOAT_IS_ZERO(den)) {
242         opcode_t *handler = Parrot_ex_throw_from_op_args(interp, expr NEXT(),
243             EXCEPTION_DIV_BY_ZERO,
244             "Divide by zero");
245         goto ADDRESS(handler);
246     }
247     $1 = $2 / den;
250 inline op div(invar PMC, invar PMC, invar PMC) :base_core {
251     $1 = VTABLE_divide(interp, $2, $3, $1);
254 inline op div(invar PMC, invar PMC, in INT) :base_core {
255     $1 = VTABLE_divide_int(interp, $2, $3, $1);
258 inline op div(invar PMC, invar PMC, in NUM) :base_core {
259     $1 = VTABLE_divide_float(interp, $2, $3, $1);
263 =item B<fdiv>(inout INT, in INT)
265 =item B<fdiv>(inout NUM, in NUM)
267 =item B<fdiv>(invar PMC, invar PMC)
269 =item B<fdiv>(invar PMC, in INT)
271 =item B<fdiv>(invar PMC, in NUM)
273 Floor divide $1 by $2.
275 =item B<fdiv>(out INT, in INT, in INT)
277 =item B<fdiv>(out NUM, in NUM, in NUM)
279 =item B<fdiv>(invar PMC, invar PMC, invar PMC)
281 =item B<fdiv>(invar PMC, invar PMC, in INT)
283 =item B<fdiv>(invar PMC, invar PMC, in NUM)
285 Set $1 to the quotient of $2 divided by $3. The result is the floor()
286 of the division i.e. the next whole integer towards -inf.
287 If the denominator is zero, a 'Divide by zero' exception is thrown.
289 =cut
291 inline op fdiv(inout INT, in INT) :base_core {
292     INTVAL   den = $2;
293     FLOATVAL f;
295     if (den == 0) {
296         opcode_t *handler = Parrot_ex_throw_from_op_args(interp, expr NEXT(),
297             EXCEPTION_DIV_BY_ZERO,
298             "Divide by zero");
299         goto ADDRESS(handler);
300     }
302     f  = floor(((FLOATVAL)$1) / den);
303     $1 = (INTVAL)f;
306 inline op fdiv(inout NUM, in NUM) :base_core {
307     FLOATVAL den = $2;
308     if (FLOAT_IS_ZERO(den)) {
309         opcode_t *handler = Parrot_ex_throw_from_op_args(interp, expr NEXT(),
310             EXCEPTION_DIV_BY_ZERO,
311             "Divide by zero");
312         goto ADDRESS(handler);
313     }
314     $1 = floor($1 / den);
317 inline op fdiv(invar PMC, invar PMC) :base_core {
318     VTABLE_i_floor_divide(interp, $1, $2);
321 inline op fdiv(invar PMC, in INT) :base_core {
322     VTABLE_i_floor_divide_int(interp, $1, $2);
325 inline op fdiv(invar PMC, in NUM) :base_core {
326     VTABLE_i_floor_divide_float(interp, $1, $2);
329 inline op fdiv(out INT, in INT, in INT) :base_core {
330     INTVAL   den = $3;
331     FLOATVAL f;
333     if (den == 0) {
334         opcode_t *handler = Parrot_ex_throw_from_op_args(interp, expr NEXT(),
335             EXCEPTION_DIV_BY_ZERO,
336             "Divide by zero");
337         goto ADDRESS(handler);
338     }
340     f  = floor((FLOATVAL)$2 / den);
341     $1 = (INTVAL)f;
344 inline op fdiv(out NUM, in NUM, in NUM) :base_core {
345     FLOATVAL den = $3;
346     if (FLOAT_IS_ZERO(den)) {
347         opcode_t *handler = Parrot_ex_throw_from_op_args(interp, expr NEXT(),
348             EXCEPTION_DIV_BY_ZERO,
349             "Divide by zero");
350         goto ADDRESS(handler);
351     }
352     $1 = floor($2 / den);
355 inline op fdiv(invar PMC, invar PMC, invar PMC) :base_core {
356     $1 = VTABLE_floor_divide(interp, $2, $3, $1);
359 inline op fdiv(invar PMC, invar PMC, in INT) :base_core {
360     $1 = VTABLE_floor_divide_int(interp, $2, $3, $1);
363 inline op fdiv(invar PMC, invar PMC, in NUM) :base_core {
364     $1 = VTABLE_floor_divide_float(interp, $2, $3, $1);
367 ########################################
369 =item B<ceil>(inout NUM)
371 Set $1 to the smallest integral value greater than or equal to $1.
373 =item B<ceil>(out INT, in NUM)
375 =item B<ceil>(out NUM, in NUM)
377 Set $1 to the smallest integral value greater than or equal to $2.
379 =cut
381 inline op ceil(inout NUM) :base_core {
382     $1 = ceil($1);
385 inline op ceil(out INT, in NUM) :base_core {
386     FLOATVAL f = ceil($2);
387     $1         = (INTVAL)f;
390 inline op ceil(out NUM, in NUM) :base_core {
391     $1 = ceil($2);
394 ########################################
396 =item B<floor>(inout NUM)
398 Set $1 to the largest integral value less than or equal to $1.
400 =item B<floor>(out INT, in NUM)
402 =item B<floor>(out NUM, in NUM)
404 Set $1 to the largest integral value less than or equal to $2.
406 =cut
408 inline op floor(inout NUM) :base_core {
409     $1 = floor($1);
412 inline op floor(out INT, in NUM) :base_core {
413     FLOATVAL f = floor($2);
414     $1         = (INTVAL)f;
417 inline op floor(out NUM, in NUM) :base_core {
418     $1 = floor($2);
421 ########################################
423 =item B<inc>(inout INT)
425 =item B<inc>(inout NUM)
427 =item B<inc>(invar PMC)
429 Increase $1 by one.
431 =cut
433 inline op inc(inout INT) :base_core {
434     $1++;
437 inline op inc(inout NUM) :base_core {
438     $1++;
441 inline op inc(invar PMC) :base_core {
442     VTABLE_increment(interp, $1);
446 ########################################
448 =item B<mod>(out INT, in INT, in INT)
450 =item B<mod>(out NUM, in NUM, in NUM)
452 =item B<mod>(invar PMC, invar PMC, invar PMC)
454 =item B<mod>(invar PMC, invar PMC, in INT)
456 =item B<mod>(invar PMC, invar PMC, in NUM)
458 Sets $1 to the modulus of $2 and $3.
460 =item B<mod>(inout INT, in INT)
462 =item B<mod>(inout NUM, in NUM)
464 =item B<mod>(invar PMC, invar PMC)
466 =item B<mod>(invar PMC, in INT)
468 =item B<mod>(invar PMC, in NUM)
470 Sets $1 to the modulus of $1 and $2.
473 NOTE: This "corrected mod" algorithm is based on the C code on page 70
474 of [1]. Assuming correct behavior of the built-in mod operator (%) with
475 positive arguments, this algorithm implements a mathematically convenient
476 version of mod, defined thus:
478   x mod y = x - y * floor(x / y)
480 For more information on this definition of mod, see section 3.4 of [2],
481 pages 81-85.
483 References:
485   [1] Donald E. Knuth, *MMIXware: A RISC Computer for the Third
486       Millennium* Springer, 1999.
488   [2] Ronald L. Graham, Donald E. Knuth and Oren Patashnik, *Concrete
489       Mathematics*, Second Edition. Addison-Wesley, 1994.
491 =cut
493 op mod(inout INT, in INT) :base_core {
494     $1 = intval_mod($1, $2);
497 op mod(inout NUM, in NUM) :base_core {
498     $1 = floatval_mod($1, $2);
501 inline op mod(invar PMC, invar PMC) :base_core {
502     VTABLE_i_modulus(interp, $1, $2);
505 inline op mod(invar PMC, in INT) :base_core {
506     VTABLE_i_modulus_int(interp, $1, $2);
509 inline op mod(invar PMC, in NUM) :base_core {
510     VTABLE_i_modulus_float(interp, $1, $2);
513 op mod(out INT, in INT, in INT) :base_core {
514     $1 = intval_mod($2, $3);
517 op mod(out NUM, in NUM, in NUM) :base_core {
518     $1 = floatval_mod($2, $3);
521 inline op mod(invar PMC, invar PMC, invar PMC) :base_core {
522     $1 = VTABLE_modulus(interp, $2, $3, $1);
525 inline op mod(invar PMC, invar PMC, in INT) :base_core {
526     $1 = VTABLE_modulus_int(interp, $2, $3, $1);
529 inline op mod(invar PMC, invar PMC, in NUM) :base_core {
530     $1 = VTABLE_modulus_float(interp, $2, $3, $1);
533 ########################################
535 =item B<mul>(inout INT, in INT)
537 =item B<mul>(inout NUM, in NUM)
539 =item B<mul>(invar PMC, invar PMC)
541 =item B<mul>(invar PMC, in INT)
543 =item B<mul>(invar PMC, in NUM)
545 Set $1 to the product of $1 and $2.
547 =item B<mul>(out INT, in INT, in INT)
549 =item B<mul>(out NUM, in NUM, in NUM)
551 =item B<mul>(invar PMC, invar PMC, invar PMC)
553 =item B<mul>(invar PMC, invar PMC, in INT)
555 =item B<mul>(invar PMC, invar PMC, in NUM)
557 Set $1 to the product of $2 and $3.
559 =cut
561 inline op mul(inout INT, in INT) :base_core {
562     $1 *= $2;
565 inline op mul(inout NUM, in NUM) :base_core {
566     $1 *= $2;
569 inline op mul(invar PMC, invar PMC) :base_core {
570     VTABLE_i_multiply(interp, $1, $2);
573 inline op mul(invar PMC, in INT) :base_core {
574     VTABLE_i_multiply_int(interp, $1, $2);
577 inline op mul(invar PMC, in NUM) :base_core {
578     VTABLE_i_multiply_float(interp, $1, $2);
581 inline op mul(out INT, in INT, in INT) :base_core {
582     $1 = $2 * $3;
585 inline op mul(out NUM, in NUM, in NUM) :base_core {
586     $1 = $2 * $3;
589 inline op mul(invar PMC, invar PMC, invar PMC) :base_core {
590     $1 = VTABLE_multiply(interp, $2, $3, $1);
593 inline op mul(invar PMC, invar PMC, in INT) :base_core {
594     $1 = VTABLE_multiply_int(interp, $2, $3, $1);
597 inline op mul(invar PMC, invar PMC, in NUM) :base_core {
598     $1 = VTABLE_multiply_float(interp, $2, $3, $1);
601 ########################################
603 =item B<neg>(inout INT)
605 =item B<neg>(inout NUM)
607 =item B<neg>(invar PMC)
609 Set $1 to its negative.
611 =item B<neg>(out INT, in INT)
613 =item B<neg>(out NUM, in NUM)
615 =item B<neg>(out PMC, invar PMC)
617 Set $1 to the negative of $2.
619 =cut
621 inline op neg(inout INT) :base_core {
622     $1 = - $1;
625 inline op neg(inout NUM) :base_core {
626     $1 = - $1;
629 inline op neg(invar PMC) :base_core {
630     VTABLE_i_neg(interp, $1);
633 inline op neg(out INT, in INT) :base_core {
634     $1 = - $2;
637 inline op neg(out NUM, in NUM) :base_core {
638     $1 = - $2;
641 inline op neg(out PMC, invar PMC) :base_core {
642     $1 = VTABLE_neg(interp, $2, $1);
645 ########################################
647 =item B<sub>(inout INT, in INT)
649 =item B<sub>(inout NUM, in NUM)
651 =item B<sub>(invar PMC, invar PMC)
653 =item B<sub>(invar PMC, in INT)
655 =item B<sub>(invar PMC, in NUM)
657 Decrease $1 by the amount in $2.
659 =item B<sub>(out INT, in INT, in INT)
661 =item B<sub>(out NUM, in NUM, in NUM)
663 =item B<sub>(invar PMC, invar PMC, invar PMC)
665 =item B<sub>(invar PMC, invar PMC, in INT)
667 =item B<sub>(invar PMC, invar PMC, in NUM)
669 Set $1 to $2 minus $3.
671 =cut
673 inline op sub(inout INT, in INT) :base_core {
674     $1 -= $2;
677 inline op sub(inout NUM, in NUM) :base_core {
678     $1 -= $2;
681 inline op sub(invar PMC, invar PMC) :base_core {
682     VTABLE_i_subtract(interp, $1, $2);
685 inline op sub(invar PMC, in INT) :base_core {
686     VTABLE_i_subtract_int(interp, $1, $2);
689 inline op sub(invar PMC, in NUM) :base_core {
690     VTABLE_i_subtract_float(interp, $1, $2);
693 inline op sub(out INT, in INT, in INT) :base_core {
694     $1 = $2 - $3;
697 inline op sub(out NUM, in NUM, in NUM) :base_core {
698     $1 = $2 - $3;
701 inline op sub(invar PMC, invar PMC, invar PMC) :base_core {
702     $1 = VTABLE_subtract(interp, $2, $3, $1);
705 inline op sub(invar PMC, invar PMC, in INT) :base_core {
706     $1 = VTABLE_subtract_int(interp, $2, $3, $1);
709 inline op sub(invar PMC, invar PMC, in NUM) :base_core {
710     $1 = VTABLE_subtract_float(interp, $2, $3, $1);
713 ########################################
715 =item B<sqrt>(out NUM, in NUM)
717 Set $1 to the square root of $2.
719 =cut
721 inline op sqrt(out NUM, in NUM) :base_core {
722     $1 = sqrt((FLOATVAL)$2);
725 =back
727 =cut
729 ###############################################################################
731 =head1 COPYRIGHT
733 Copyright (C) 2001-2009, Parrot Foundation.
735 =head1 LICENSE
737 This program is free software. It is subject to the same license
738 as the Parrot interpreter itself.
740 =cut
743  * Local variables:
744  *   c-file-style: "parrot"
745  * End:
746  * vim: expandtab shiftwidth=4:
747  */