Index: src/pmc/boolean.pmc =================================================================== --- src/pmc/boolean.pmc (revision 48723) +++ src/pmc/boolean.pmc (working copy) @@ -99,6 +99,28 @@ VTABLE void set_string_native(STRING *value) { SELF.set_bool(Parrot_str_boolean(INTERP, value)); } + +/* + +=item C + +=item C + +Set C to the ''negated'' value of C. The negative of a +boolean value is the identical value. + +=cut + +*/ + + VTABLE PMC *neg(PMC *dest) { + dest = Parrot_pmc_new_init_int(INTERP, VTABLE_type(INTERP, SELF), + SELF.get_bool()); + return dest; + } + + VTABLE void i_neg() { + } } /* Index: src/pmc/integer.pmc =================================================================== --- src/pmc/integer.pmc (revision 48723) +++ src/pmc/integer.pmc (working copy) @@ -257,7 +257,7 @@ =item C -Sets the value of the integer to the value of the C C<*value>. +Sets the value of the integer to the value of the native integer C<*value>. =cut @@ -987,6 +987,46 @@ /* +=item C + +=item C + +Set C to the negated value of C. If the value of C +is the minimum integer, a BigInt is created. + +=cut + +*/ + + VTABLE PMC *neg(PMC *dest) { + const INTVAL a = SELF.get_integer(); + + if (a != PARROT_INTVAL_MIN) + return Parrot_pmc_new_init_int(INTERP, VTABLE_type(INTERP, SELF), + -a); + else { + PMC *promoted; + maybe_throw_overflow_error(INTERP); + promoted = Parrot_pmc_new_init_int(INTERP, enum_class_BigInt, 0); + return VTABLE_subtract_int(INTERP, promoted, a, promoted); + } + } + + VTABLE void i_neg() { + const INTVAL a = SELF.get_integer(); + + if (a != PARROT_INTVAL_MIN) + VTABLE_set_integer_native(INTERP, SELF, -a); + else { + maybe_throw_overflow_error(INTERP); + SELF = upgrade_self_to_bignum(INTERP, SELF); + VTABLE_set_integer_native(INTERP, SELF, 0); + VTABLE_i_subtract_int(INTERP, SELF, a); + } + } + +/* + =item C The C<==> operation. @@ -1158,23 +1198,38 @@ =item C -Sets C to the absolute value of SELF. +Sets C to the absolute value of C. If the value of C +is the minimum integer, a BigInt is created. =cut */ VTABLE PMC *absolute(PMC *dest) { - const INTVAL a = abs(SELF.get_integer()); + const INTVAL a = SELF.get_integer(); - /* TT # 1245 overflow for -maxint */ - return Parrot_pmc_new_init_int(INTERP, VTABLE_type(INTERP, SELF), a); + if (a != PARROT_INTVAL_MIN) + return Parrot_pmc_new_init_int(INTERP, VTABLE_type(INTERP, SELF), + abs(a)); + else { + PMC *promoted; + maybe_throw_overflow_error(INTERP); + promoted = Parrot_pmc_new_init_int(INTERP, enum_class_BigInt, a); + return VTABLE_neg(INTERP, promoted, dest); + } } VTABLE void i_absolute() { - const INTVAL a = abs(SELF.get_integer()); - VTABLE_set_integer_native(INTERP, SELF, a); + const INTVAL a = SELF.get_integer(); + + if (a != PARROT_INTVAL_MIN) + VTABLE_set_integer_native(INTERP, SELF, abs(a)); + else { + maybe_throw_overflow_error(INTERP); + SELF = upgrade_self_to_bignum(INTERP, SELF); + return VTABLE_i_neg(INTERP, SELF); + } } Index: t/pmc/bigint.t =================================================================== --- t/pmc/bigint.t (revision 48723) +++ t/pmc/bigint.t (working copy) @@ -20,7 +20,7 @@ .include 'test_more.pir' - plan(34) + plan(32) check_libgmp_good() set_and_get() @@ -28,9 +28,10 @@ subtraction() multiplication() division() - division_by_zero() negation() + negate_min_integer() absolute_value() + absolute_min_integer() overflow_coercion() interface() boolean() @@ -504,6 +505,23 @@ ok($I1, 'negation') .end +.loadlib 'sys_ops' +.include 'sysinfo.pasm' + +.sub negate_min_integer + .local int max + .local int min + .local pmc max_1 + .local pmc neg_min + max = sysinfo .SYSINFO_PARROT_INTMAX + min = sysinfo .SYSINFO_PARROT_INTMIN + max_1 = box max + inc max_1 + neg_min = box min + neg neg_min # Use 1-operand form of neg. + is(neg_min, max_1, 'negate minimum native integer') +.end + .sub absolute_value $P0 = new ['BigInt'] $P0 = '-1230000000000000000000' @@ -522,6 +540,21 @@ is($S0,'1230000000000000000000','... and in-place works too') .end +.sub absolute_min_integer + .local int max + .local int min + .local pmc max_1 + .local pmc neg_min + .local pmc result + max = sysinfo .SYSINFO_PARROT_INTMAX + min = sysinfo .SYSINFO_PARROT_INTMIN + max_1 = box max + inc max_1 + neg_min = box min + result = abs neg_min # Use 2-operand form of abs. + is(result, max_1, 'absolute minimum native integer') +.end + .sub overflow_coercion # check libgmp included in Parrot build $P0 = getinterp @@ -745,7 +778,7 @@ ne $S0, $S6, k25 inc $I1 k25: - todo( $I1, 'integer negation of MinInt converts MaxInt+1 to BigInt', 'TT #1616') + ok($I1, 'integer negation of MinInt converts to BigInt') $I1 = 0 $P0 = new ['Integer'] @@ -760,7 +793,7 @@ ne $S0, $S6, k27 inc $I1 k27: - todo( $I1, 'integer absolute-value of MinInt converts MaxInt+1 to BigInt', 'TT #1616') + ok($I1, 'integer abs(MinInt) converts to BigInt') $P0 = new ['Integer'] $P0 = $I3