fix codetest failure - ASSERT_ARGS does not have a ; after and
[parrot.git] / src / dynoplibs / math.ops
blob8f4717ddfe53345bb08be4b8288c658f108541ea
1 /*
2  * $Id$
3 ** math.ops
4 */
6 BEGIN_OPS_PREAMBLE
8 #include <math.h>
10 END_OPS_PREAMBLE
12 =head1 NAME
14 math.ops - Mathematical Opcodes
16 =cut
18 =head1 DESCRIPTION
20 Parrot's library of mathematical ops.
22 To use this library of ops, add this directive to your PIR:
24  .loadlib 'math_ops'
26 =cut
28 =head2 General Math
30 =over 4
32 =cut
34 ########################################
36 =item B<cmod>(out INT, in INT, in INT)
38 =item B<cmod>(invar PMC, invar PMC, in INT)
40 =item B<cmod>(invar PMC, invar PMC, invar PMC)
42 NOTE: This "uncorrected mod" algorithm uses the C language's built-in
43 mod operator (x % y), which is
45     ... the remainder when x is divided by y, and thus is zero
46     when y divides x exactly.
47     ...
48     The direction of truncation for / and the sign of the result
49     for % are machine-dependent for negative operands, as is the
50     action taken on overflow or underflow.
51                                                      -- [1], page 41
53 Also:
55     ... if the second operand is 0, the result is undefined.
56     Otherwise, it is always true that (a/b)*b + a%b is equal to z. If
57     both operands are non-negative, then the remainder is non-
58     negative and smaller than the divisor; if not, it is guaranteed
59     only that the absolute value of the remainder is smaller than
60     the absolute value of the divisor.
61                                                      -- [1], page 205
63 This op is provided for those who need it (such as speed-sensitive
64 applications with heavy use of mod, but using it only with positive
65 arguments), but a more mathematically useful mod based on ** floor(x/y)
66 and defined with y == 0 is provided by the mod op.
68   [1] Brian W. Kernighan and Dennis M. Ritchie, *The C Programming
69       Language*, Second Edition. Prentice Hall, 1988.
71 If the denominator is zero, a 'Divide by zero' exception is thrown.
73 =cut
75 inline op cmod(out INT, in INT, in INT) :base_core {
76     INTVAL den = $3;
77     if ($3 == 0) {
78         opcode_t *handler = Parrot_ex_throw_from_op_args(interp, expr NEXT(),
79             EXCEPTION_DIV_BY_ZERO,
80             "Divide by zero");
81         goto ADDRESS(handler);
82     }
83     $1 = $2 % den;
86 inline op cmod(invar PMC, invar PMC, in INT) :base_core {
87     INTVAL result;
89     if ($3 == 0) {
90         opcode_t *handler = Parrot_ex_throw_from_op_args(interp, expr NEXT(),
91             EXCEPTION_DIV_BY_ZERO,
92             "Divide by zero");
93         goto ADDRESS(handler);
94     }
96     result = VTABLE_get_integer(interp, $2) % $3;
98     $1 = Parrot_pmc_new_init_int(interp, VTABLE_type(interp, $2), result);
101 inline op cmod(invar PMC, invar PMC, invar PMC) :base_core {
102     INTVAL result;
103     INTVAL value = VTABLE_get_integer(interp, $3);
105     if (value == 0) {
106         opcode_t *handler = Parrot_ex_throw_from_op_args(interp, expr NEXT(),
107             EXCEPTION_DIV_BY_ZERO,
108             "Divide by zero");
109         goto ADDRESS(handler);
110     }
112     result = VTABLE_get_integer(interp, $2) % value;
114     $1 = Parrot_pmc_new_init_int(interp, VTABLE_type(interp, $2), result);
117 ########################################
119 =item B<cmod>(out NUM, in NUM, in NUM)
121 =item B<cmod>(invar PMC, invar PMC, in NUM)
123 NOTE: This "uncorrected mod" algorithm uses the built-in C math library's
124 fmod() function, which computes
126     ... the remainder of dividing x by y. The return value is
127     x - n * y, where n is the quotient of x / y, rounded towards
128     zero to an integer.
129                                 -- fmod() manpage on RedHat Linux 7.0
131 In addition, fmod() returns
133     the remainder, unless y is zero, when the function fails and
134     errno is set.
136 According to page 251 of [1], the result when y is zero is implementation-
137 defined.
139 This op is provided for those who need it, but a more mathematically
140 useful numeric mod based on floor(x/y) instead of truncate(x/y) and
141 defined with y == 0 is provided by the mod op.
143   [1] Brian W. Kernighan and Dennis M. Ritchie, *The C Programming
144       Language*, Second Edition. Prentice Hall, 1988.
146 If the denominator is zero, a 'Divide by zero' exception is thrown.
148 =cut
150 inline op cmod(out NUM, in NUM, in NUM) :base_core {
151     FLOATVAL den = $3;
152     if (FLOAT_IS_ZERO($3)) {
153         opcode_t *handler = Parrot_ex_throw_from_op_args(interp, expr NEXT(),
154             EXCEPTION_DIV_BY_ZERO,
155             "Divide by zero");
156         goto ADDRESS(handler);
157     }
158     $1 = fmod($2, den);
161 inline op cmod(invar PMC, invar PMC, in NUM) :base_core {
162     FLOATVAL result;
163     FLOATVAL value = $3;
165     if (FLOAT_IS_ZERO(value)) {
166         opcode_t *handler = Parrot_ex_throw_from_op_args(interp, expr NEXT(),
167             EXCEPTION_DIV_BY_ZERO,
168             "Divide by zero");
169         goto ADDRESS(handler);
170     }
172     result = fmod(VTABLE_get_integer(interp, $2), value);
174     $1 = Parrot_pmc_new_init_int(interp,
175         VTABLE_type(interp, $2), (INTVAL)result);
178 =back
180 =cut
182 ###############################################################################
184 =head2 Pseudorandom number operations
186 These operations perform various pseudorandom number operations.
188 =over 4
190 =item B<rand>(out NUM)
192 Set $1 to a random floating point number between 0 and 1, inclusive.
194 =cut
196 inline op rand(out NUM) {
197     $1 = Parrot_float_rand(0);
200 =item B<rand>(out INT)
202 Set $1 to a random integer between C<[-2^31, 2^31)> .
204 =cut
206 inline op rand(out INT) {
207     $1 = Parrot_int_rand(0);
210 =item B<rand>(out NUM, in NUM)
212 Set $1 to a random floating point number between 0 and and $2, inclusive.
214 =cut
216 inline op rand(out NUM, in NUM) {
217     $1 = $2 * Parrot_float_rand(0);
220 =item B<rand>(out INT, in INT)
222 Set $1 to a integer between 0 and and $2, inclusive.
224 =cut
226 inline op rand(out INT, in INT) {
227     $1 = Parrot_range_rand(0, $2, 0);
230 =item B<rand>(out NUM, in NUM, in NUM)
232 Set $1 to a random floating point number between $2 and and $3, inclusive.
234 =cut
236 inline op rand(out NUM, in NUM, in NUM) {
237     $1 = $2 + ($3 - $2) * Parrot_float_rand(0);
240 =item B<srand>(in NUM)
242 Set the random number seed to $1. $1 is casted to an INTVAL.
244 =cut
246 inline op srand(in NUM) {
247     Parrot_srand((INTVAL)$1);
250 =item B<srand>(in INT)
252 Set the random number seed to $1.
254 =cut
256 inline op srand(in INT) {
257     Parrot_srand((INTVAL)$1);
260 =item B<rand>(out INT, in INT, in INT)
262 Set $1 to a integer between $2 and and $3, inclusive.
264 =cut
266 inline op rand(out INT, in INT, in INT) {
267     $1 = Parrot_range_rand($2, $3, 0);
270 =back
272 =cut
274 =head1 COPYRIGHT
276 Copyright (C) 2001-2009, Parrot Foundation.
278 =head1 LICENSE
280 This program is free software. It is subject to the same license
281 as the Parrot interpreter itself.
283 =cut
287  * Local variables:
288  *   c-file-style: "parrot"
289  * End:
290  * vim: expandtab shiftwidth=4:
291  */