6 VERSION = PARROT_VERSION;
10 math.ops - Mathematical Operations
16 Operations that perform some sort of mathematics, including both basic
17 math and transcendental functions.
19 The variants with a prepended B<n_> like <n_abs> generate a new target PMC.
20 If possible, they use the appropriate language type, specified with C<.HLL>.
22 =head2 General infix operations
24 These operations take an infix operation number and PMC arguments.
28 =item B<infix>(inconst INT, invar PMC, in INT)
30 =item B<infix>(inconst INT, invar PMC, in NUM)
32 =item B<infix>(inconst INT, invar PMC, in STR)
34 =item B<infix>(inconst INT, invar PMC, invar PMC)
36 General inplace infix dispatch opcode. $1 is the MMD function number.
38 =item B<infix>(inconst INT, out PMC, invar PMC, in INT)
40 =item B<infix>(inconst INT, out PMC, invar PMC, in NUM)
42 =item B<infix>(inconst INT, out PMC, invar PMC, in STR)
44 =item B<infix>(inconst INT, out PMC, invar PMC, invar PMC)
46 General infix dispatch opcode. $1 is the MMD function number.
48 =item B<n_infix>(inconst INT, out PMC, invar PMC, in INT)
50 =item B<n_infix>(inconst INT, out PMC, invar PMC, in NUM)
52 =item B<n_infix>(inconst INT, out PMC, invar PMC, in STR)
54 =item B<n_infix>(inconst INT, out PMC, invar PMC, invar PMC)
56 General infix dispatch opcode. $1 is the MMD function number.
57 These opcodes return a new result PMC $2.
61 inline op infix(inconst INT, invar PMC, in INT) :base_core {
62 mmd_dispatch_v_pi(interp, $2, $3, $1);
65 inline op infix(inconst INT, invar PMC, in NUM) :base_core {
66 mmd_dispatch_v_pn(interp, $2, $3, $1);
69 inline op infix(inconst INT, invar PMC, in STR) :base_core {
70 mmd_dispatch_v_ps(interp, $2, $3, $1);
73 inline op infix(inconst INT, invar PMC, invar PMC) :base_core {
74 mmd_dispatch_v_pp(interp, $2, $3, $1);
77 inline op infix(inconst INT, out PMC, invar PMC, in INT) :base_core {
78 $2 = mmd_dispatch_p_pip(interp, $3, $4, $2, $1);
81 inline op infix(inconst INT, out PMC, invar PMC, in NUM) :base_core {
82 $2 = mmd_dispatch_p_pnp(interp, $3, $4, $2, $1);
85 inline op infix(inconst INT, out PMC, invar PMC, in STR) :base_core {
86 $2 = mmd_dispatch_p_psp(interp, $3, $4, $2, $1);
89 inline op infix(inconst INT, out PMC, invar PMC, invar PMC) :base_core {
90 $2 = mmd_dispatch_p_ppp(interp, $3, $4, $2, $1);
93 inline op n_infix(inconst INT, out PMC, invar PMC, in INT) :base_core {
94 $2 = mmd_dispatch_p_pip(interp, $3, $4, NULL, $1);
97 inline op n_infix(inconst INT, out PMC, invar PMC, in NUM) :base_core {
98 $2 = mmd_dispatch_p_pnp(interp, $3, $4, NULL, $1);
101 inline op n_infix(inconst INT, out PMC, invar PMC, in STR) :base_core {
102 $2 = mmd_dispatch_p_psp(interp, $3, $4, NULL, $1);
105 inline op n_infix(inconst INT, out PMC, invar PMC, invar PMC) :base_core {
106 $2 = mmd_dispatch_p_ppp(interp, $3, $4, NULL, $1);
108 ###############################################################################
112 =head2 Arithmetic operations
114 These operations store the results of arithmetic on other registers and
115 constants into their destination register, $1.
121 ########################################
123 =item B<abs>(inout INT)
125 =item B<abs>(inout NUM)
127 =item B<abs>(invar PMC)
129 Set $1 to its absolute value.
131 =item B<abs>(out INT, in INT)
133 =item B<abs>(out NUM, in NUM)
135 =item B<abs>(out PMC, invar PMC)
137 Set $1 to absolute value of $2.
139 =item B<n_abs>(out PMC, invar PMC)
141 Create new $1 as the absolute of $2.
145 inline op abs(inout INT) :base_core {
149 inline op abs(inout NUM) :base_core {
153 inline op abs(out INT, in INT) :base_core {
160 inline op abs(out NUM, in NUM) :base_core {
167 inline op abs(invar PMC) :base_core {
168 VTABLE_i_absolute(interp, $1);
171 inline op abs(out PMC, invar PMC) :base_core {
172 $1 = VTABLE_absolute(interp, $2, $1);
175 inline op n_abs(out PMC, invar PMC) :base_core {
176 $1 = VTABLE_absolute(interp, $2, NULL);
179 ########################################
181 =item B<add>(inout INT, in INT)
183 =item B<add>(inout NUM, in NUM)
185 Increase $1 by the amount in $2.
187 =item B<add>(out INT, in INT, in INT)
189 =item B<add>(out NUM, in NUM, in NUM)
191 Set $1 to the sum of $2 and $3.
193 Please note that all PMC variants of all infix functions are handled
194 by the C<infix> and C<n_infix> opcodes. Thus there is no distinct implementation
195 of e.g. C<add_p_p_p>.
199 inline op add(inout INT, in INT) :base_core {
203 inline op add(inout NUM, in NUM) :base_core {
207 inline op add(out INT, in INT, in INT) :base_core {
211 inline op add(out NUM, in NUM, in NUM) :base_core {
215 ########################################
217 =item B<cmod>(out INT, in INT, in INT)
219 NOTE: This "uncorrected mod" algorithm uses the C language's built-in
220 mod operator (x % y), which is
222 ... the remainder when x is divided by y, and thus is zero
223 when y divides x exactly.
225 The direction of truncation for / and the sign of the result
226 for % are machine-dependent for negative operands, as is the
227 action taken on overflow or underflow.
232 ... if the second operand is 0, the result is undefined.
233 Otherwise, it is always true that (a/b)*b + a%b is equal to z. If
234 both operands are non-negative, then the remainder is non-
235 negative and smaller than the divisor; if not, it is guaranteed
236 only that the absolute value of the remainder is smaller than
237 the absolute value of the divisor.
240 This op is provided for those who need it (such as speed-sensitive
241 applications with heavy use of mod, but using it only with positive
242 arguments), but a more mathematically useful mod based on ** floor(x/y)
243 and defined with y == 0 is provided by the mod op.
245 [1] Brian W. Kernighan and Dennis M. Ritchie, *The C Programming
246 Language*, Second Edition. Prentice Hall, 1988.
248 If the denominator is zero, a 'Divide by zero' exception is thrown.
252 inline op cmod(out INT, in INT, in INT) :base_core {
255 real_exception(interp, NULL, E_ZeroDivisionError,
260 ########################################
262 =item B<cmod>(out NUM, in NUM, in NUM)
264 NOTE: This "uncorrected mod" algorithm uses the built-in C math library's
265 fmod() function, which computes
267 ... the remainder of dividing x by y. The return value is
268 x - n * y, where n is the quotient of x / y, rounded towards
270 -- fmod() manpage on RedHat Linux 7.0
272 In addition, fmod() returns
274 the remainder, unless y is zero, when the function fails and
277 According to page 251 of [1], the result when y is zero is implementation-
280 This op is provided for those who need it, but a more mathematically
281 useful numeric mod based on floor(x/y) instead of truncate(x/y) and
282 defined with y == 0 is provided by the mod op.
284 [1] Brian W. Kernighan and Dennis M. Ritchie, *The C Programming
285 Language*, Second Edition. Prentice Hall, 1988.
287 If the denominator is zero, a 'Divide by zero' exception is thrown.
291 inline op cmod(out NUM, in NUM, in NUM) :base_core {
293 if (FLOAT_IS_ZERO($3))
294 real_exception(interp, NULL, E_ZeroDivisionError,
299 ########################################
301 =item B<dec>(inout INT)
303 =item B<dec>(inout NUM)
305 =item B<dec>(invar PMC)
311 inline op dec(inout INT) :base_core {
315 inline op dec(inout NUM) :base_core {
319 inline op dec(invar PMC) :base_core {
320 VTABLE_decrement(interp, $1);
323 ########################################
325 =item B<div>(inout INT, in INT)
327 =item B<div>(inout NUM, in NUM)
331 =item B<div>(out INT, in INT, in INT)
333 =item B<div>(out NUM, in NUM, in NUM)
335 Set $1 to the quotient of $2 divided by $3. In the case of INTVAL division, the
336 result is truncated (NOT rounded or floored).
337 If the denominator is zero, a 'Divide by zero' exception is thrown.
341 inline op div(inout INT, in INT) :base_core {
344 real_exception(interp, NULL, E_ZeroDivisionError,
349 inline op div(inout NUM, in NUM) :base_core {
351 if (FLOAT_IS_ZERO($2))
352 real_exception(interp, NULL, E_ZeroDivisionError,
357 inline op div(out INT, in INT, in INT) :base_core {
360 real_exception(interp, NULL, E_ZeroDivisionError,
365 inline op div(out NUM, in NUM, in NUM) :base_core {
367 if (FLOAT_IS_ZERO($3))
368 real_exception(interp, NULL, E_ZeroDivisionError,
373 =item B<fdiv>(inout INT, in INT)
375 =item B<fdiv>(inout NUM, in NUM)
377 Floor divide $1 by $2.
379 =item B<fdiv>(out INT, in INT, in INT)
381 =item B<fdiv>(out NUM, in NUM, in NUM)
383 Set $1 to the quotient of $2 divided by $3. The result is the floor()
384 of the division i.e. the next whole integer towards -inf.
385 If the denominator is zero, a 'Divide by zero' exception is thrown.
389 inline op fdiv(inout INT, in INT) :base_core {
394 real_exception(interp, NULL, E_ZeroDivisionError,
401 inline op fdiv(inout NUM, in NUM) :base_core {
403 if (FLOAT_IS_ZERO($2))
404 real_exception(interp, NULL, E_ZeroDivisionError,
406 $1 = floor($1 / den);
409 inline op fdiv(out INT, in INT, in INT) :base_core {
414 real_exception(interp, NULL, E_ZeroDivisionError,
421 inline op fdiv(out NUM, in NUM, in NUM) :base_core {
423 if (FLOAT_IS_ZERO($3))
424 real_exception(interp, NULL, E_ZeroDivisionError,
426 $1 = floor($2 / den);
429 ########################################
431 =item B<ceil>(inout NUM)
433 Set $1 to the smallest integral value greater than or equal to $1.
435 =item B<ceil>(out INT, in NUM)
437 =item B<ceil>(out NUM, in NUM)
439 Set $1 to the smallest integral value greater than or equal to $2.
443 inline op ceil(inout NUM) :base_core {
447 inline op ceil(out INT, in NUM) :base_core {
448 FLOATVAL f = ceil($2);
452 inline op ceil(out NUM, in NUM) :base_core {
456 ########################################
458 =item B<floor>(inout NUM)
460 Set $1 to the largest integral value less than or equal to $1.
462 =item B<floor>(out INT, in NUM)
464 =item B<floor>(out NUM, in NUM)
466 Set $1 to the largest integral value less than or equal to $2.
470 inline op floor(inout NUM) :base_core {
474 inline op floor(out INT, in NUM) :base_core {
475 FLOATVAL f = floor($2);
479 inline op floor(out NUM, in NUM) :base_core {
483 ########################################
485 =item B<inc>(inout INT)
487 =item B<inc>(inout NUM)
489 =item B<inc>(invar PMC)
495 inline op inc(inout INT) :base_core {
499 inline op inc(inout NUM) :base_core {
503 inline op inc(invar PMC) :base_core {
504 VTABLE_increment(interp, $1);
508 ########################################
510 =item B<mod>(out INT, in INT, in INT)
512 =item B<mod>(out NUM, in NUM, in NUM)
514 Sets $1 to the modulus of $2 and $3.
516 =item B<mod>(inout INT, in INT)
518 =item B<mod>(inout NUM, in NUM)
520 Sets $1 to the modulus of $1 and $2.
523 NOTE: This "corrected mod" algorithm is based on the C code on page 70
524 of [1]. Assuming correct behavior of the built-in mod operator (%) with
525 positive arguments, this algorithm implements a mathematically convenient
526 version of mod, defined thus:
528 x mod y = x - y * floor(x / y)
530 For more information on this definition of mod, see section 3.4 of [2],
535 [1] Donald E. Knuth, *MMIXware: A RISC Computer for the Third
536 Millennium* Springer, 1999.
538 [2] Ronald L. Graham, Donald E. Knuth and Oren Patashnik, *Concrete
539 Mathematics*, Second Edition. Addison-Wesley, 1994.
543 op mod(inout INT, in INT) :base_core {
544 $1 = intval_mod($1, $2);
547 op mod(out INT, in INT, in INT) :base_core {
548 $1 = intval_mod($2, $3);
551 op mod(out NUM, in NUM, in NUM) :base_core {
552 $1 = floatval_mod($2, $3);
555 op mod(inout NUM, in NUM) :base_core {
556 $1 = floatval_mod($1, $2);
559 ########################################
561 =item B<mul>(inout INT, in INT)
563 =item B<mul>(inout NUM, in NUM)
565 Set $1 to the product of $1 and $2.
567 =item B<mul>(out INT, in INT, in INT)
569 =item B<mul>(out NUM, in NUM, in NUM)
571 Set $1 to the product of $2 and $3.
575 inline op mul(inout INT, in INT) :base_core {
579 inline op mul(inout NUM, in NUM) :base_core {
583 inline op mul(out INT, in INT, in INT) :base_core {
587 inline op mul(out NUM, in NUM, in NUM) :base_core {
591 ########################################
593 =item B<neg>(inout INT)
595 =item B<neg>(inout NUM)
597 =item B<neg>(invar PMC)
599 Set $1 to its negative.
601 =item B<neg>(out INT, in INT)
603 =item B<neg>(out NUM, in NUM)
605 =item B<neg>(out PMC, invar PMC)
607 Set $1 to the negative of $2.
609 =item B<n_neg>(out PMC, invar PMC)
611 Create $1 as the negative of $2.
615 inline op neg(inout INT) :base_core {
619 inline op neg(inout NUM) :base_core {
623 inline op neg(invar PMC) :base_core {
624 VTABLE_i_neg(interp, $1);
627 inline op neg(out INT, in INT) :base_core {
631 inline op neg(out NUM, in NUM) :base_core {
635 inline op neg(out PMC, invar PMC) :base_core {
636 $1 = VTABLE_neg(interp, $2, $1);
639 inline op n_neg(out PMC, invar PMC) :base_core {
640 $1 = VTABLE_neg(interp, $2, NULL);
643 ########################################
645 =item B<pow>(out NUM, in NUM, in NUM)
647 Set $1 to $2 raised to the power $3.
651 inline op pow(out NUM, in NUM, in NUM) :base_core {
652 $1 = pow((FLOATVAL)$2, (FLOATVAL)$3);
655 ########################################
657 =item B<sub>(inout INT, in INT)
659 =item B<sub>(inout NUM, in NUM)
661 Decrease $1 by the amount in $2.
663 =item B<sub>(out INT, in INT, in INT)
665 =item B<sub>(out NUM, in NUM, in NUM)
667 Set $1 to $2 minus $3.
671 inline op sub(inout INT, in INT) :base_core {
675 inline op sub(inout NUM, in NUM) :base_core {
679 inline op sub(out INT, in INT, in INT) :base_core {
683 inline op sub(out NUM, in NUM, in NUM) :base_core {
687 ########################################
689 =item B<sqrt>(out NUM, in NUM)
691 Set $1 to the square root of $2.
695 inline op sqrt(out NUM, in NUM) :base_core {
696 $1 = sqrt((FLOATVAL)$2);
705 ###############################################################################
707 =head2 Transcendental mathematical operations
709 These operations perform various transcendental operations such as logarithmics
716 ########################################
718 =item B<acos>(out NUM, in NUM)
720 Set $1 to the arc cosine (in radians) of $2.
724 inline op acos(out NUM, in NUM) :base_math {
725 $1 = acos((FLOATVAL)$2);
728 ########################################
730 =item B<asec>(out NUM, in NUM)
732 Set $1 to the arc secant (in radians) of $2.
736 inline op asec(out NUM, in NUM) :base_math {
737 $1 = acos(((FLOATVAL)1) / ((FLOATVAL)$2));
740 ########################################
743 =item B<asin>(out NUM, in NUM)
745 Set $1 to the arc sine (in radians) of $2.
749 inline op asin(out NUM, in NUM) :base_math {
750 $1 = asin((FLOATVAL)$2);
753 ########################################
755 =item B<atan>(out NUM, in NUM)
757 =item B<atan>(out NUM, in NUM, in NUM)
759 The two-argument versions set $1 to the arc tangent (in radians) of $2.
761 The three-argument versions set $1 to the arc tangent (in radians) of
762 $2 / $3, taking account of the signs of the arguments in determining the
763 quadrant of the result.
767 inline op atan(out NUM, in NUM) :base_math {
768 $1 = atan((FLOATVAL)$2);
771 inline op atan(out NUM, in NUM, in NUM) :base_math {
772 $1 = atan2((FLOATVAL)$2, (FLOATVAL)$3);
775 ########################################
777 =item B<cos>(out NUM, in NUM)
779 Set $1 to the cosine of $2 (given in radians).
783 inline op cos(out NUM, in NUM) :base_math {
784 $1 = cos((FLOATVAL)$2);
787 ########################################
789 =item B<cosh>(out NUM, in NUM)
791 Set $1 to the hyperbolic cosine of $2 (given in radians).
795 inline op cosh(out NUM, in NUM) :base_math {
796 $1 = cosh((FLOATVAL)$2);
799 ########################################
801 =item B<exp>(out NUM, in NUM)
803 Set $1 to I<e> raised to the power $2. I<e> is the base of the natural
808 inline op exp(out NUM, in NUM) :base_math {
809 $1 = exp((FLOATVAL)$2);
812 ########################################
814 =item B<ln>(out NUM, in NUM)
816 Set $1 to the natural (base I<e>) logarithm of $2.
820 inline op ln(out NUM, in NUM) :base_math {
821 $1 = log((FLOATVAL)$2);
824 ########################################
826 =item B<log10>(out NUM, in NUM)
828 Set $1 to the base 10 logarithm of $2.
832 inline op log10(out NUM, in NUM) :base_math {
833 $1 = log10((FLOATVAL)$2);
836 ########################################
838 =item B<log2>(out NUM, in NUM)
840 Set $1 to the base 2 logarithm of $2.
844 op log2(out NUM, in NUM) :base_math {
845 FLOATVAL temp = log((FLOATVAL)2.0);
846 $1 = log((FLOATVAL)$2) / temp;
849 ########################################
851 =item B<sec>(out NUM, in NUM)
853 Set $1 to the secant of $2 (given in radians).
857 inline op sec(out NUM, in NUM) :base_math {
858 $1 = ((FLOATVAL)1) / cos((FLOATVAL)$2);
861 ########################################
863 =item B<sech>(out NUM, in NUM)
865 Set $1 to the hyperbolic secant of $2 (given in radians).
869 inline op sech(out NUM, in NUM) :base_math {
870 $1 = ((FLOATVAL)1) / cosh((FLOATVAL)$2);
873 ########################################
875 =item B<sin>(out NUM, in NUM)
877 Set $1 to the sine of $2 (given in radians).
881 inline op sin(out NUM, in NUM) :base_math {
882 $1 = sin((FLOATVAL)$2);
885 ########################################
887 =item B<sinh>(out NUM, in NUM)
889 Set $1 to the hyperbolic sine of $2 (given in radians).
893 inline op sinh(out NUM, in NUM) :base_math {
894 $1 = sinh((FLOATVAL)$2);
897 ########################################
899 =item B<tan>(out NUM, in NUM)
901 Set $1 to the tangent of $2 (given in radians).
905 inline op tan(out NUM, in NUM) :base_math {
906 $1 = tan((FLOATVAL)$2);
909 ########################################
911 =item B<tanh>(out NUM, in NUM)
913 Set $1 to the hyperbolic tangent of $2 (given in radians).
917 inline op tanh(out NUM, in NUM) :base_math {
918 $1 = tanh((FLOATVAL)$2);
925 ###############################################################################
927 =head2 Other mathematical operations
929 Implementations of various mathematical operations
935 ########################################
937 =item B<gcd>(out INT, in INT, in INT)
939 Greatest Common divisor of $2 and $3.
943 inline op gcd(out INT, in INT, in INT) :advanced_math {
945 INTVAL a = $2 < 0 ? -$2 : $2;
946 INTVAL b = $3 < 0 ? -$3 : $3;
948 if (a==0) { $1=b; goto NEXT(); }
949 if (b==0) { $1=a; goto NEXT(); }
951 while (!((a | b) & 1)) {
959 else if (!(b & 1)) b>>=1;
960 else if (a<b) b = (b-a)>>1;
968 ########################################
970 =item B<lcm>(out INT, in INT, in INT)
972 Least Common Multiple of $2 and $3
976 inline op lcm(out INT, in INT, in INT) :advanced_math {
979 INTVAL a = $2 < 0 ? -$2 : $2;
980 INTVAL b = $3 < 0 ? -$3 : $3;
981 INTVAL saved_var1 = a, saved_var2 = b;
983 if (a==0 || b==0) { $1=0; goto NEXT(); }
985 while (!((a | b) & 1)) {
993 else if (!(b & 1)) b>>=1;
994 else if (a<b) b = (b-a)>>1;
1000 $1 = saved_var1*saved_var2;
1003 ########################################
1005 =item B<fact>(out INT, in INT)
1007 =item B<fact>(out NUM, in INT)
1009 Factorial, n!. Calculates the product of 1 to N.
1013 inline op fact(out INT, in INT) :advanced_math {
1014 /* Coercing a negative to a UINT can get pretty ugly
1015 * in this situation. */
1025 inline op fact(out NUM, in INT) :advanced_math {
1026 /* Coercing a negative to a UINT can get pretty ugly
1027 * in this situation. */
1041 ###############################################################################
1045 Copyright (C) 2001-2008, The Perl Foundation.
1049 This program is free software. It is subject to the same license
1050 as the Parrot interpreter itself.
1056 * c-file-style: "parrot"
1058 * vim: expandtab shiftwidth=4: