[t] Refactor some namespace pmc tests to use throws_like
[parrot.git] / src / pmc / scalar.pmc
blobff2f8760401b0fc1688c94b5324ecd5c2b9cff06
1 /*
2 Copyright (C) 2001-2009, Parrot Foundation.
3 $Id$
5 =head1 NAME
7 src/pmc/scalar.pmc - Scalar Abstract Superclass
9 =head1 DESCRIPTION
11 These are the vtable functions for the scalar base PMC class
13 =head2 Methods
15 =over 4
17 =cut
21 #include "pmc_bigint.h"
23 static PMC *
24 bitwise_left_shift_internal(PARROT_INTERP, PMC *self,
25                             PMC *dest, INTVAL shift_amount)
27     /* This handles both left and right shifts; the sign of shift_amount
28        controls the direction, shifting left if positive and right if negative.
29        If we get an error (which can only happen for left shifts) and
30        PARROT_ERRORS_OVERFLOW_FLAG is set, then we throw an error, else the
31        destination is promoted to a BigInt before shifting.  If dest == self,
32        then the shift is done in place.  */
33     const INTVAL base = VTABLE_get_integer(interp, self);
34     INTVAL result     = 0;
35     int overflow_p    = 0;
37     /* Compute the shift. */
38     if (shift_amount >= 8*INTVAL_SIZE) {
39         /* Extreme left shift; no need to do an integer shift first. */
40         overflow_p = 1;
41     }
42     else if (shift_amount >= 0) {
43         /* Left shift. */
44         result = base << shift_amount;
45         overflow_p = (result >> shift_amount) != base;
46     }
47     else if (shift_amount > -8*INTVAL_SIZE) {
48         /* Right shift.  By definition, this can never overflow. */
49         result = base >> -shift_amount;
50     }
51     else {
52         /* Extreme right shift. */
53         result = 0;
54     }
56     /* Store the result. */
57     if (! overflow_p) {
58         /* If SELF is the destination, we won't want to create a
59            new PMC, because then we won't have the result in SELF.
60            Only create a new PMC if we aren't saving the result
61            to SELF, or if they are both NULL */
62         if (dest != self || dest == NULL)
63             dest = pmc_new(interp, VTABLE_type(interp, self));
65         VTABLE_set_integer_native(interp, dest, result);
66     }
67     else if (PARROT_ERRORS_test(interp, PARROT_ERRORS_OVERFLOW_FLAG)) {
68         Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_ERR_OVERFLOW,
69             "Integer overflow");
70     }
71     else {
72         /* Overflow; must promote dest to BigInt, and do a BigInt shift. */
73         if (self == dest)
74             pmc_reuse(interp, self, enum_class_BigInt, 0);
75         else
76             dest = pmc_new(interp, enum_class_BigInt);
78         VTABLE_set_integer_native(interp, dest, base);
79         VTABLE_i_bitwise_shl_int(interp, dest, shift_amount);
80     }
82     return dest;
85 pmclass scalar {
89 =item C<void assign_pmc(PMC *value)>
91 Sets the PMC C<*value>, calling the appropriate C<set_*> method
92 according to the type of C<*value>.
94 =cut
98     VTABLE void assign_pmc(PMC *value) {
99         STRING * const s_int = CONST_STRING(INTERP, "Integer");
100         STRING        *s_num;
101         STRING        *s_str;
103         if (SELF->vtable->base_type == enum_class_Boolean)
104             /* doesn't morph */
105             pmc_reuse(INTERP, SELF, value->vtable->base_type, 0);
107         if (value->vtable->base_type == enum_class_Undef) {
108             pmc_reuse(INTERP, SELF, value->vtable->base_type, 0);
109             return;
110         }
112         if (VTABLE_isa(INTERP, value, s_int)) {
113             const INTVAL v = VTABLE_get_integer(INTERP, value);
114             SELF.set_integer_native(v);
115             return;
116         }
118         s_num = CONST_STRING(INTERP, "Float");
120         if (VTABLE_isa(INTERP, value, s_num)) {
121             const FLOATVAL v = VTABLE_get_number(INTERP, value);
122             SELF.set_number_native(v);
123             return;
124         }
126         s_str = CONST_STRING(INTERP, "String");
128         if (VTABLE_isa(INTERP, value, s_str)) {
129             STRING * const v = VTABLE_get_string(INTERP, value);
130             SELF.set_string_native(v);
131             return;
132         }
133         pmc_reuse(INTERP, SELF, value->vtable->base_type, 0);
134         SELF.set_pmc(value);
135     }
139 =back
141 =head1 Mathematical Methods
143 =over 4
145 =item C<PMC *subtract(PMC *value, PMC *dest)>
147 =cut
153 =item C<void add(PMC *value, PMC *dest)>
155 =item C<void add_int(INTVAL value, PMC *dest)>
157 =item C<void add_float(FLOATVAL value, PMC *dest)>
159 Adds C<value> to the number and returns the result in C<*dest>.
160 If C<dest> is NULL it's created.
162 =item C<void i_add(PMC *value)>
164 =item C<void i_add(INTVAL value)>
166 =item C<void i_add(FLOATVAL value)>
168 Adds C<value> to C<SELF> inplace.
170 =cut
174     MULTI PMC *add(Complex value, PMC *dest) {
175         const FLOATVAL a = SELF.get_number();
177         dest = pmc_new(INTERP, VTABLE_type(INTERP, value));
179         VTABLE_set_number_native(INTERP, dest,
180                 a + VTABLE_get_number_keyed_int(INTERP, value, 0));
181         VTABLE_set_number_keyed_int(INTERP, dest, 1,
182                 VTABLE_get_number_keyed_int(INTERP, value, 1));
183         return dest;
184     }
186     MULTI PMC *add(DEFAULT value, PMC *dest) {
187         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
189         VTABLE_set_number_native(INTERP, dest,
190                 SELF.get_number() + VTABLE_get_number(INTERP, value));
191         return dest;
192     }
194     VTABLE PMC *add_int(INTVAL value, PMC *dest) {
195         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
197         VTABLE_set_number_native(INTERP, dest,
198                 SELF.get_number() + (FLOATVAL)value);
199         return dest;
200     }
202     VTABLE PMC *add_float(FLOATVAL value, PMC *dest) {
203         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
205         VTABLE_set_number_native(INTERP, dest,
206                 SELF.get_number() + value);
207         return dest;
208     }
210     MULTI void i_add(Complex value) {
211         const FLOATVAL a = SELF.get_number();
213         pmc_reuse(INTERP, SELF, enum_class_Complex, 0);
214         VTABLE_set_number_native(INTERP, SELF,
215                 a + VTABLE_get_number_keyed_int(INTERP, value, 0));
216         VTABLE_set_number_keyed_int(INTERP, SELF, 1,
217                 VTABLE_get_number_keyed_int(INTERP, value, 1));
218     }
220     MULTI void i_add(DEFAULT value) {
221         VTABLE_set_number_native(INTERP, SELF,
222             SELF.get_number() + VTABLE_get_number(INTERP, value));
223     }
225     VTABLE void i_add_int(INTVAL value) {
226         VTABLE_set_number_native(INTERP, SELF,
227             SELF.get_number() + (FLOATVAL)value);
228     }
230     VTABLE void i_add_float(FLOATVAL value) {
231         VTABLE_set_number_native(INTERP, SELF,
232             SELF.get_number() + value);
233     }
237 =item C<PMC *subtract(PMC *value, PMC *dest)>
239 =item C<PMC *subtract_int(INTVAL value, PMC *dest)>
241 =item C<PMC *subtract_float(FLOATVAL value, PMC *dest)>
243 Subtracts C<value> from the number and returns the result in C<*dest>.
244 If C<dest> doesn't exist a new C<Float> is created.
246 =item C<void i_subtract(PMC *value)>
248 =item C<void i_subtract_int(INTVAL value)>
250 =item C<void i_subtract_float(FLOATVAL value)>
252 Subtracts C<value> from C<SELF> inplace.
254 =cut
258     MULTI PMC *subtract(Complex value, PMC *dest) {
259         const FLOATVAL a = SELF.get_number();
260         dest = pmc_new(INTERP, VTABLE_type(INTERP, value));
262         VTABLE_set_number_native(INTERP, dest,
263                 a - VTABLE_get_number_keyed_int(INTERP, value, 0));
264         VTABLE_set_number_keyed_int(INTERP, dest, 1,
265                 -VTABLE_get_number_keyed_int(INTERP, value, 1));
266         return dest;
267     }
269     MULTI PMC *subtract(DEFAULT value, PMC *dest) {
270         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
271         VTABLE_set_number_native(INTERP, dest,
272                 SELF.get_number() - VTABLE_get_number(INTERP, value));
273         return dest;
274     }
276     VTABLE PMC *subtract_int(INTVAL value, PMC *dest) {
277         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
279         VTABLE_set_number_native(INTERP, dest,
280                 SELF.get_number() - (FLOATVAL)value);
281         return dest;
282     }
284     VTABLE PMC *subtract_float(FLOATVAL value, PMC *dest) {
285         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
287         VTABLE_set_number_native(INTERP, dest,
288                 SELF.get_number() - value);
289         return dest;
290     }
292     MULTI void i_subtract(Complex value) {
293         const FLOATVAL a = SELF.get_number();
295         pmc_reuse(INTERP, SELF, enum_class_Complex, 0);
296         VTABLE_set_number_native(INTERP, SELF,
297                 a - VTABLE_get_number_keyed_int(INTERP, value, 0));
298         VTABLE_set_number_keyed_int(INTERP, SELF, 1,
299                 -VTABLE_get_number_keyed_int(INTERP, value, 1));
300     }
302     MULTI void i_subtract(DEFAULT value) {
303         VTABLE_set_number_native(INTERP, SELF,
304             SELF.get_number() - VTABLE_get_number(INTERP, value));
305     }
307     VTABLE void i_subtract_int(INTVAL value) {
308         VTABLE_set_number_native(INTERP, SELF,
309             SELF.get_number() - (FLOATVAL)value);
310     }
312     VTABLE void i_subtract_float(FLOATVAL value) {
313         VTABLE_set_number_native(INTERP, SELF,
314             SELF.get_number() - value);
315     }
319 =item C<PMC *multiply(PMC *value, PMC *dest)>
321 =item C<PMC *multiply_int(INTVAL value, PMC *dest)>
323 =item C<PMC *multiply_float(FLOATVAL value, PMC *dest)>
325 Multiplies the number by C<value> and returns the result in C<*dest>.
327 =cut
331     MULTI PMC *multiply(Complex value, PMC *dest) {
332         Parrot_ex_throw_from_c_args(INTERP, NULL,
333             EXCEPTION_INTERNAL_NOT_IMPLEMENTED, "TODO mul<Float, Complex>");
334     }
336     MULTI PMC *multiply(DEFAULT value, PMC *dest) {
337         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
339         VTABLE_set_number_native(INTERP, dest,
340             SELF.get_number() * VTABLE_get_number(INTERP, value));
341         return dest;
342     }
344     VTABLE PMC *multiply_int(INTVAL value, PMC *dest) {
345         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
347         VTABLE_set_number_native(INTERP, dest,
348             SELF.get_number() * value);
349         return dest;
350     }
352     VTABLE PMC *multiply_float(FLOATVAL value, PMC *dest) {
353         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
355         VTABLE_set_number_native(INTERP, dest,
356             SELF.get_number() * value);
357         return dest;
358     }
360     MULTI void i_multiply(Complex value) {
361         Parrot_ex_throw_from_c_args(INTERP, NULL,
362             EXCEPTION_INTERNAL_NOT_IMPLEMENTED,
363             "TODO i_mul<Float, Complex>");
364     }
366     MULTI void i_multiply(DEFAULT value) {
367         VTABLE_set_number_native(INTERP, SELF,
368             SELF.get_number() * VTABLE_get_number(INTERP, value));
369     }
371     VTABLE void i_multiply_int(INTVAL value) {
372         VTABLE_set_number_native(INTERP, SELF,
373             SELF.get_number() * (FLOATVAL)value);
374     }
376     VTABLE void i_multiply_float(FLOATVAL value) {
377         VTABLE_set_number_native(INTERP, SELF, SELF.get_number() * value);
378     }
382 =item C<PMC *divide(PMC *value, PMC *dest)>
384 =item C<PMC *divide_int(INTVAL value, PMC *dest)>
386 =item C<PMC *divide_float(FLOATVAL value, PMC *dest)>
388 Divides the number by C<value> and returns the result in C<*dest>.
390 =item C<void i_divide(PMC *value)>
392 =item C<void i_divide_int(INTVAL value)>
394 =item C<void i_divide_float(FLOATVAL value)>
396 Divides C<SELF> by C<value> inplace.
398 =cut
402     MULTI PMC *divide(PMC *value, PMC *dest) {
403         const FLOATVAL d = VTABLE_get_number(INTERP, value);
405         if (FLOAT_IS_ZERO(d))
406             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
407                 "float division by zero");
409         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
411         VTABLE_set_number_native(INTERP, dest, SELF.get_number() / d);
412         return dest;
413     }
415     VTABLE PMC *divide_int(INTVAL value, PMC *dest) {
416         if (value == 0)
417             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
418                 "float division by zero");
420         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
422         VTABLE_set_number_native(INTERP, dest, SELF.get_number() / value);
423         return dest;
424     }
426     VTABLE PMC *divide_float(FLOATVAL value, PMC *dest) {
427         if (FLOAT_IS_ZERO(value))
428             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
429                 "float division by zero");
431         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
433         VTABLE_set_number_native(INTERP, dest, SELF.get_number() / value);
434         return dest;
435     }
437     VTABLE void i_divide(PMC *value) {
438         const FLOATVAL d = VTABLE_get_number(INTERP, value);
440         if (FLOAT_IS_ZERO(d))
441             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
442                 "float division by zero");
444         VTABLE_set_number_native(INTERP, SELF, SELF.get_number() / d);
445     }
447     VTABLE void i_divide_int(INTVAL value) {
448         if (value == 0)
449             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
450                 "float division by zero");
452         VTABLE_set_number_native(INTERP, SELF, SELF.get_number() / value);
453     }
455     VTABLE void i_divide_float(FLOATVAL value) {
456         if (FLOAT_IS_ZERO(value))
457             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
458                 "float division by zero");
460         VTABLE_set_number_native(INTERP, SELF, SELF.get_number() / value);
461     }
465 =item C<PMC *floor_divide(PMC *value, PMC *dest)>
467 =item C<PMC *floor_divide_int(INTVAL value, PMC *dest)>
469 =item C<PMC *floor_divide_float(FLOATVAL value, PMC *dest)>
471 Divides the number by C<value> and returns the result in C<*dest>.
473 =item C<void i_floor_divide(PMC *value)>
475 =item C<void i_floor_divide_int(INTVAL value)>
477 =item C<void i_floor_divide_float(FLOATVAL value)>
479 Divides C<SELF> by C<value> inplace.
481 =cut
485     MULTI PMC *floor_divide(PMC *value, PMC *dest) {
486         FLOATVAL d = VTABLE_get_number(INTERP, value);
488         if (FLOAT_IS_ZERO(d))
489             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
490                 "float division by zero");
492         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
493         d    = floor(SELF.get_number() / d);
495         VTABLE_set_integer_native(INTERP, dest, (INTVAL)d);
496         return dest;
497     }
499     VTABLE PMC *floor_divide_int(INTVAL value, PMC *dest) {
500         if (value == 0)
501             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
502                 "float division by zero");
504         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
506         VTABLE_set_number_native(INTERP, dest,
507                 floor(SELF.get_number() / value));
508         return dest;
509     }
511     VTABLE PMC *floor_divide_float(FLOATVAL value, PMC *dest) {
512         if (FLOAT_IS_ZERO(value))
513             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
514                 "float division by zero");
516         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
518         VTABLE_set_number_native(INTERP, dest,
519                 floor(SELF.get_number() / value));
520         return dest;
521     }
523     VTABLE void i_floor_divide(PMC *value) {
524         const FLOATVAL d = VTABLE_get_number(INTERP, value);
526         if (FLOAT_IS_ZERO(d))
527             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
528                 "float division by zero");
530         VTABLE_set_number_native(INTERP, SELF,
531                 floor(SELF.get_number() / d));
532     }
534     VTABLE void i_floor_divide_int(INTVAL value) {
535         if (value == 0)
536             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
537                 "float division by zero");
539         VTABLE_set_number_native(INTERP, SELF,
540                 floor(SELF.get_number() / value));
541     }
543     VTABLE void i_floor_divide_float(FLOATVAL value) {
544         if (FLOAT_IS_ZERO(value))
545             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
546                 "float division by zero");
548         VTABLE_set_number_native(INTERP, SELF,
549                 floor(SELF.get_number() / value));
550     }
554 =item C<PMC *modulus(PMC *value, PMC *dest)>
556 =item C<PMC *modulus(INTVAL value, PMC *dest)>
558 =item C<PMC *modulus(FLOATVAL value, PMC *dest)>
560 Calculates the value of corrected C<mod> C<value> and returns
561 the result in C<dest>. See also ops/math.ops.
563 =item C<void i_modulus(PMC *value)>
565 =item C<void i_modulus(INTVAL value)>
567 =item C<void i_modulus(FLOATVAL value)>
569 Calculates modulus inplace
571 =cut
575     MULTI PMC *modulus(PMC *value, PMC *dest) {
576         const FLOATVAL d = VTABLE_get_number(INTERP, value);
578         if (FLOAT_IS_ZERO(d))
579             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
580                 "float modulus by zero");
582         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
584         VTABLE_set_number_native(INTERP, dest,
585                 floatval_mod(SELF.get_number(), d));
586         return dest;
587     }
589     VTABLE PMC *modulus_int(INTVAL value, PMC *dest) {
590         if (value == 0)
591             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
592                 "float modulus by zero");
594         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
596         VTABLE_set_number_native(INTERP, dest,
597                 floatval_mod(SELF.get_number(), (FLOATVAL)value));
598         return dest;
599     }
601     VTABLE PMC *modulus_float(FLOATVAL value, PMC *dest) {
602         if (FLOAT_IS_ZERO(value))
603             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
604                 "float modulus by zero");
606         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
608         VTABLE_set_number_native(INTERP, dest,
609                 floatval_mod(SELF.get_number(), value));
610         return dest;
611     }
613     VTABLE void i_modulus(PMC *value) {
614         const FLOATVAL d = VTABLE_get_number(INTERP, value);
616         if (FLOAT_IS_ZERO(d))
617             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
618                 "float modulus by zero");
620         VTABLE_set_number_native(INTERP, SELF,
621                 floatval_mod(SELF.get_number(), d));
622     }
624     VTABLE void i_modulus_int(INTVAL value) {
625         if (value == 0)
626             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
627                 "float modulus by zero");
629         VTABLE_set_number_native(INTERP, SELF,
630                 floatval_mod(SELF.get_number(), (FLOATVAL)value));
631     }
633     VTABLE void i_modulus_float(FLOATVAL value) {
634         if (FLOAT_IS_ZERO(value))
635             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
636                 "float modulus by zero");
638         VTABLE_set_number_native(INTERP, SELF,
639                 floatval_mod(SELF.get_number(), value));
640     }
644 =item C<PMC *pow(PMC *value, PMC *dest)>
646 =item C<PMC *pow_int(INTVAL value, PMC *dest)>
648 =item C<PMC *pow_float(FLOATVAL value, PMC *dest)>
650 Calculates  C<SELF pow value> and returns
651 the result in C<dest>. See also ops/math.ops.
653 =item C<void i_pow(PMC *value)>
655 =item C<void i_pow_int(INTVAL value)>
657 =item C<void i_pow_float(FLOATVAL value)>
659 Calculates pow inplace
661 =cut
665     MULTI PMC *pow(PMC *value, PMC *dest) {
666         const FLOATVAL d = VTABLE_get_number(INTERP, value);
668         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
670         VTABLE_set_number_native(INTERP, dest, pow(SELF.get_number(), d));
671         return dest;
672     }
674     VTABLE PMC *pow_int(INTVAL value, PMC *dest) {
675         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
677         VTABLE_set_number_native(INTERP, dest,
678                 pow(SELF.get_number(), (double)value));
680         return dest;
681     }
683     VTABLE PMC *pow_float(FLOATVAL value, PMC *dest) {
684         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
686         VTABLE_set_number_native(INTERP, dest,
687                 pow(SELF.get_number(), value));
688         return dest;
689     }
691     VTABLE void i_pow(PMC *value) {
692         const FLOATVAL d = VTABLE_get_number(INTERP, value);
694         VTABLE_set_number_native(INTERP, SELF,
695                 pow(SELF.get_number(), d));
696     }
698     VTABLE void i_pow_int(INTVAL value) {
699         VTABLE_set_number_native(INTERP, SELF,
700                 pow(SELF.get_number(), (float)value));
701     }
703     VTABLE void i_pow_float(FLOATVAL value) {
704         VTABLE_set_number_native(INTERP, SELF,
705                 pow(SELF.get_number(), value));
706     }
710 =item C<PMC *neg(PMC *dest)>
712 =item C<void i_neg()>
714 Set C<dest> to the negated value of C<SELF>.
716 =cut
720     VTABLE PMC *neg(PMC *dest) {
721         const INTVAL a = -SELF.get_integer();
723         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
725         VTABLE_set_integer_native(INTERP, dest, a);
726         return dest;
727     }
729     VTABLE void i_neg() {
730         VTABLE_set_integer_native(INTERP, SELF, -SELF.get_integer());
731     }
735 =back
737 =head2 Bitwise Methods
739 =over 4
741 =item C<PMC *bitwise_or(PMC *value, PMC *dest)>
743 =item C<PMC *bitwise_or_int(INTVAL value, PMC *dest)>
745 Returns in C<*dest> the bitwise C<OR> of the scalar and C<value>.
747 =item C<void i_bitwise_or(PMC *value)>
749 =item C<void i_bitwise_or_int(INTVAL value)>
751 Inplace bitwise or.
753 =cut
757     VTABLE PMC *bitwise_or(PMC *value, PMC *dest) {
758         const INTVAL result = SELF.get_integer() | VTABLE_get_integer(INTERP, value);
760         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
762         VTABLE_set_integer_native(INTERP, dest, result);
763         return dest;
764     }
767     VTABLE PMC *bitwise_or_int(INTVAL value, PMC *dest) {
768         const INTVAL result = SELF.get_integer() | value;
770         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
772         VTABLE_set_integer_native(INTERP, dest, result);
773         return dest;
774     }
776     VTABLE void i_bitwise_or(PMC *value) {
777         const INTVAL result =
778             SELF.get_integer() | VTABLE_get_integer(INTERP, value);
780         SELF.set_integer_native(result);
781     }
784     VTABLE void i_bitwise_or_int(INTVAL value) {
785         const INTVAL result = SELF.get_integer() | value;
786         SELF.set_integer_native(result);
787     }
791 =item C<PMC *bitwise_and(PMC *value, PMC *dest)>
793 =item C<PMC *bitwise_and_int(INTVAL value, PMC *dest)>
795 Returns in C<*dest> the bitwise C<AND> of the scalar and C<value>.
797 =item C<void i_bitwise_and(PMC *value)>
799 =item C<void i_bitwise_and_int(INTVAL value)>
801 Inplace bitwise and.
803 =cut
807     VTABLE PMC *bitwise_and(PMC *value, PMC *dest) {
808         const INTVAL result =
809             SELF.get_integer() & VTABLE_get_integer(INTERP, value);
811         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
813         VTABLE_set_integer_native(INTERP, dest, result);
814         return dest;
815     }
817     VTABLE PMC *bitwise_and_int(INTVAL value, PMC *dest) {
818         const INTVAL result = SELF.get_integer() & value;
820         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
822         VTABLE_set_integer_native(INTERP, dest, result);
823         return dest;
824     }
826     VTABLE void i_bitwise_and(PMC *value) {
827         const INTVAL result =
828             SELF.get_integer() & VTABLE_get_integer(INTERP, value);
829         SELF.set_integer_native(result);
830     }
833     VTABLE void i_bitwise_and_int(INTVAL value) {
834         const INTVAL result = SELF.get_integer() & value;
835         SELF.set_integer_native(result);
836     }
840 =item C<void bitwise_xor(PMC *value, PMC *dest)>
842 =item C<void bitwise_xor_int(INTVAL value, PMC *dest)>
844 Returns in C<*dest> the bitwise C<XOR> of the scalar and C<*value>.
846 =item C<void i_bitwise_xor(PMC *value)>
848 =item C<void i_bitwise_xor_int(INTVAL value)>
850 Inplace bitwise and.
852 =cut
856     MULTI PMC *bitwise_xor(PMC *value, PMC *dest) {
857         const INTVAL result =
858             SELF.get_integer() ^ VTABLE_get_integer(INTERP, value);
860         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
862         VTABLE_set_integer_native(INTERP, dest, result);
863         return dest;
864     }
866     VTABLE PMC *bitwise_xor_int(INTVAL value, PMC *dest) {
867         const INTVAL result = SELF.get_integer() ^ value;
869         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
871         VTABLE_set_integer_native(INTERP, dest, result);
872         return dest;
873     }
875     VTABLE void i_bitwise_xor(PMC *value) {
876         const INTVAL result =
877             SELF.get_integer() ^ VTABLE_get_integer(INTERP, value);
878         SELF.set_integer_native(result);
879     }
881     VTABLE void i_bitwise_xor_int(INTVAL value) {
882         const INTVAL result = SELF.get_integer() ^ value;
883         SELF.set_integer_native(result);
884     }
888 =item C<PMC *bitwise_not(PMC *dest)>
890 =item C<void i_bitwise_not()>
892 Returns in C<*dest> the bitwise negation of the scalar and C<value>.
894 =cut
898     VTABLE PMC *bitwise_not(PMC *dest) {
899         const INTVAL a = ~SELF.get_integer();
901         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
903         VTABLE_set_integer_native(INTERP, dest, a);
904         return dest;
905     }
907     VTABLE void i_bitwise_not() {
908         VTABLE_set_integer_native(INTERP, SELF, ~SELF.get_integer());
909     }
913 =item C<PMC *bitwise_shr(PMC *value, PMC *dest)>
915 =item C<PMC *bitwise_shr_int(INTVAL value, PMC *dest)>
917 Returns in C<*dest> the arithmetic shift right of the scalar by C<value>.
918 A negative C<value> shifts left.
919 The destination may become a C<BigInt> as a result (but only if the shift amount
920 is less than zero).
922 =item C<void i_bitwise_shr(PMC *value)>
924 =item C<void i_bitwise_shr_int(INTVAL value)>
926 Inplace shift right.  A negative C<value> shifts left.
927 SELF may become a C<BigInt> as a result (but only if the shift amount is less
928 than zero).
930 =cut
934     VTABLE PMC *bitwise_shr(PMC *value, PMC *dest) {
935         return bitwise_left_shift_internal(INTERP, SELF, dest,
936                                            -VTABLE_get_integer(INTERP, value));
937     }
939     VTABLE PMC *bitwise_shr_int(INTVAL value, PMC *dest) {
940         return bitwise_left_shift_internal(INTERP, SELF, dest, -value);
941     }
943     VTABLE void i_bitwise_shr(PMC *value) {
944         bitwise_left_shift_internal(INTERP, SELF, SELF,
945                                     -VTABLE_get_integer(INTERP, value));
946     }
948     VTABLE void i_bitwise_shr_int(INTVAL value) {
949         bitwise_left_shift_internal(INTERP, SELF, SELF, -value);
950     }
954 =item C<PMC *bitwise_lsr(PMC *value, PMC *dest)>
956 =item C<PMC *bitwise_lsr_int(INTVAL value, PMC *dest)>
958 Returns in C<*dest> the logical shift right of the scalar by C<*value>.
960 =item C<void i_bitwise_lsr(PMC *value)>
962 =item C<void i_bitwise_lsr_int(INTVAL value)>
964 Inplace shift right.
966 =cut
970     VTABLE PMC *bitwise_lsr(PMC *value, PMC *dest) {
971         const INTVAL result = (UINTVAL)SELF.get_integer() >>
972             VTABLE_get_integer(INTERP, value);
974         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
976         VTABLE_set_integer_native(INTERP, dest, result);
977         return dest;
978     }
980     VTABLE PMC *bitwise_lsr_int(INTVAL value, PMC *dest) {
981         const INTVAL result = (UINTVAL)SELF.get_integer() >> value;
983         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
985         VTABLE_set_integer_native(INTERP, dest, result);
986         return dest;
987     }
989     VTABLE void i_bitwise_lsr(PMC *value) {
990         const INTVAL result = (UINTVAL)SELF.get_integer() >>
991                 VTABLE_get_integer(INTERP, value);
992         SELF.set_integer_native(result);
993     }
995     VTABLE void i_bitwise_lsr_int(INTVAL value) {
996         const INTVAL result = (UINTVAL)SELF.get_integer() >> value;
997         SELF.set_integer_native(result);
998     }
1002 =item C<PMC *bitwise_shl(PMC *value, PMC *dest)>
1004 =item C<PMC *bitwise_shl_int(INTVAL value, PMC *dest)>
1006 Returns in C<*dest> the shift left of the scalar by C<*value>.  A negative
1007 C<value> shifts right.  The destination may become a C<BigInt> as a result.
1009 =item C<void i_bitwise_shl(PMC *value)>
1011 =item C<void i_bitwise_shl_int(INTVAL value)>
1013 Inplace shift left.  A negative C<value> shifts right.  SELF may become a
1014 C<BigInt> as a result.
1016 =cut
1020     VTABLE PMC *bitwise_shl(PMC *value, PMC *dest) {
1021         return bitwise_left_shift_internal(INTERP, SELF, dest,
1022                                            VTABLE_get_integer(INTERP, value));
1023     }
1025     VTABLE PMC *bitwise_shl_int(INTVAL value, PMC *dest) {
1026         return bitwise_left_shift_internal(INTERP, SELF, dest, value);
1027     }
1029     VTABLE void i_bitwise_shl(PMC *value) {
1030         bitwise_left_shift_internal(INTERP, SELF, SELF,
1031                                     VTABLE_get_integer(INTERP, value));
1032     }
1034     VTABLE void i_bitwise_shl_int(INTVAL value) {
1035         bitwise_left_shift_internal(INTERP, SELF, SELF, value);
1036     }
1040 =back
1042 =head2 String Methods
1044 =over 4
1046 =item C<PMC *concatenate(PMC *value, PMC *dest)>
1048 =item C<PMC *concatenate_str(STRING *value, PMC *dest)>
1050 Returns in C<*dest> the result of concatenating the scalar and C<*value>.
1052 =item C<void concatenate(PMC *value)>
1054 =item C<void concatenate_str(STRING *value)>
1056 Concatenate the string C<value> in place.
1058 =cut
1062     VTABLE PMC *concatenate(PMC *value, PMC *dest) {
1063         STRING * const s = Parrot_str_concat(INTERP, SELF.get_string(),
1064             VTABLE_get_string(INTERP, value), 0);
1066         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1068         VTABLE_set_string_native(INTERP, dest, s);
1069         return dest;
1070     }
1072     VTABLE PMC *concatenate_str(STRING *value, PMC *dest) {
1073         STRING * const s = Parrot_str_concat(INTERP,
1074             SELF.get_string(), value, 0);
1076         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1078         VTABLE_set_string_native(INTERP, dest, s);
1079         return dest;
1080     }
1082     VTABLE void i_concatenate(PMC *value) {
1083         STRING * const s = SELF.get_string();
1084         STRING * const v = VTABLE_get_string(INTERP, value);
1085         SELF.set_string_native(Parrot_str_append(INTERP, s, v));
1086     }
1088     VTABLE void i_concatenate_str(STRING *value) {
1089         STRING * const s = SELF.get_string();
1090         SELF.set_string_native(Parrot_str_append(INTERP, s, value));
1091     }
1095 =item C<PMC *repeat(PMC *value, PMC *dest)>
1097 =item C<PMC *repeat_int(INTVAL value, PMC *dest)>
1099 Returns in C<*dest> the result of repeating the scalar C<value> times.
1101 =item C<void i_repeat(PMC *value)>
1103 =item C<void i_repeat_int(INTVAL value)>
1105 Repeat the string C<SELF> in place C<value> times.
1107 =cut
1111     VTABLE PMC *repeat(PMC *value, PMC *dest) {
1112         STRING * const s = SELF.get_string();
1113         const UINTVAL  n = (UINTVAL)VTABLE_get_integer(INTERP, value);
1115         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1117         VTABLE_set_string_native(INTERP, dest,
1118             Parrot_str_repeat(INTERP, s, n));
1119         return dest;
1120     }
1122     VTABLE PMC *repeat_int(INTVAL value, PMC *dest) {
1123         STRING * const s = SELF.get_string();
1124         const UINTVAL  n = value;
1126         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1128         VTABLE_set_string_native(INTERP, dest,
1129             Parrot_str_repeat(INTERP, s, n));
1130         return dest;
1131     }
1134     VTABLE void i_repeat(PMC *value) {
1135         STRING * const s = SELF.get_string();
1136         const UINTVAL  n = (UINTVAL)VTABLE_get_integer(INTERP, value);
1137         SELF.set_string_native(Parrot_str_repeat(INTERP, s, n));
1138     }
1140     VTABLE void i_repeat_int(INTVAL value) {
1141         STRING * const s = SELF.get_string();
1142         const UINTVAL  n = value;
1143         SELF.set_string_native(Parrot_str_repeat(INTERP, s, n));
1144     }
1150 =back
1152 =head2 Compare Methods
1154 =over 4
1156 =item C<INTVAL cmp_num(PMC *value)>
1158 Returns the result of comparing the floating-point values of the scalar
1159 and C<*value>.
1161 =cut
1165     MULTI INTVAL cmp_num(PMC *value) {
1166         /* XXX - Floating-point precision errors possible? */
1167         FLOATVAL diff = VTABLE_get_number(INTERP, value) -
1168                         SELF.get_number();
1170         return FLOAT_IS_ZERO(diff) ? 0 : diff < 0.0 ? -1 : 1;
1171     }
1175 =item C<INTVAL cmp_string(PMC *value)>
1177 Returns the result of comparing the string values of the scalar and
1178 C<*value>.
1180 =cut
1184     MULTI INTVAL cmp_string(PMC *value) {
1185         return Parrot_str_compare(INTERP, SELF.get_string(),
1186             VTABLE_get_string(INTERP, value));
1187     }
1191 =item C<INTVAL is_equal(PMC *value)>
1193 Returns whether the PMC is equal to C<*value>.
1195 =cut
1200     MULTI INTVAL is_equal(PMC *value) {
1201         return (SELF->vtable         == value->vtable
1202             &&  PMC_data(SELF)       == PMC_data(value));
1203     }
1208 =item C<INTVAL is_equal_num(PMC *value)>
1210 Returns whether the PMC is numerically equal to C<*value>.
1212 =cut
1216     MULTI INTVAL is_equal_num(PMC *value) {
1217         return (VTABLE_get_number(INTERP, SELF) ==
1218                 VTABLE_get_number(INTERP, value));
1219     }
1223 =item C<INTVAL is_equal_string(PMC *value)>
1225 Returns whether the PMC has string equality with C<*value>.
1227 =cut
1231     MULTI INTVAL is_equal_string(PMC *value) {
1232         return (0 != Parrot_str_equal(INTERP, VTABLE_get_string(INTERP, SELF),
1233                                           VTABLE_get_string(INTERP, value)));
1234     }
1239 =back
1241 =head2 Logical Methods
1243 =over 4
1245 =item C<PMC *logical_or(PMC *value, PMC *dest)>
1247 Returns the result of the logical C<OR> of C<SELF> and C<value>, i.e. returns
1248 C<SELF> it is true or C<value>: C<dest> is alway ignored.
1250 =cut
1254     VTABLE PMC *logical_or(PMC *value, PMC *dest) {
1255         if (SELF.get_bool())
1256             return SELF;
1258         return value;
1259     }
1263 =item C< PMC *logical_and(PMC *value, PMC *dest)>
1265 Returns the result of the logical C<AND> of C<SELF> and C<value>, i.e.
1266 returns C<value> if C<SELF> is true else C<SELF>. C<dest> is always ignored.
1268 =cut
1272     VTABLE PMC *logical_and(PMC *value, PMC *dest) {
1273         if (SELF.get_bool())
1274             return value;
1276         return SELF;
1277     }
1281 =item C<PMC *logical_xor(PMC *value, PMC *dest)>
1283 Returns the result of the logical C<XOR> of C<SELF> and C<*value>.
1285 =cut
1289     VTABLE PMC *logical_xor(PMC *value, PMC *dest) {
1290         const INTVAL my_bool    = SELF.get_bool();
1291         const INTVAL value_bool = VTABLE_get_bool(INTERP, value);
1293         if (my_bool && ! value_bool)
1294             return SELF;
1295         else if (value_bool && ! my_bool)
1296             return value;
1298         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1299         VTABLE_set_bool(INTERP, dest, 0);
1300         return dest;
1301     }
1305 =item C<PMC *logical_not(PMC *dest)>
1307 =item C<void i_logical_not()>
1309 Returns in C<*dest> the result of the logical negation of the scalar and
1310 C<*value>.
1312 =cut
1316     VTABLE PMC *logical_not(PMC *dest) {
1317         const INTVAL a = ! SELF.get_bool();
1319         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1321         VTABLE_set_bool(INTERP, dest, a);
1322         return dest;
1323     }
1325     VTABLE void i_logical_not() {
1326         VTABLE_set_bool(INTERP, SELF, ! SELF.get_bool());
1327     }
1331 =item C<INTVAL defined()>
1333 Always returns true.
1335 =cut
1339     VTABLE INTVAL defined() {
1340         return 1;
1341     }
1345 =item C<STRING *substr_str(INTVAL offset, INTVAL length)>
1347 Returns the substring of length C<length> of the scalar starting at
1348 C<offset>.
1350 =cut
1354     VTABLE STRING *substr_str(INTVAL offset, INTVAL length) {
1355         return Parrot_str_substr(INTERP, VTABLE_get_string(INTERP, SELF),
1356             offset, length, NULL, 0);
1357     }
1361 =item C<void share_ro()>
1363 Sets this PMC as shared and read-only.
1365 =cut
1368     VTABLE PMC *share_ro() {
1369         PMC         *ret  = pt_shared_fixup(INTERP, SELF);
1370         PMC * const _true = pmc_new(INTERP, enum_class_Integer);
1372         VTABLE_set_integer_native(INTERP, _true, 1);
1374         /* first set readonly */
1375         VTABLE_setprop(INTERP, ret, CONST_STRING(INTERP, "_ro"), _true);
1377         /* We're sharing this, so make sure it has a PMC_sync */
1378         Parrot_gc_add_pmc_sync(INTERP, ret);
1379         PObj_is_PMC_shared_SET(ret);
1381         /* XXX FIXME workaround lack of metadata sharing*/
1382         PMC_metadata(SELF) = NULL;
1384         return ret;
1385     }
1391 =back
1393 =cut
1398  * Local variables:
1399  *   c-file-style: "parrot"
1400  * End:
1401  * vim: expandtab shiftwidth=4:
1402  */