Skip to content
Permalink
Browse files

Merge pull request #820 from merryman/Fixnum#%

All Fixnum#modulo specs passing now.
  • Loading branch information
timfel committed Sep 5, 2013
2 parents 8e07b4c + 82fd204 commit ed33a4acd261cfd3420996bfad55607f11009b8e
@@ -18,17 +18,17 @@ def abs
def abs2
self * self
end

def %(other)
self - other * self.div(other)
end
alias modulo %

def div(other)
raise ZeroDivisionError, "divided by 0" if other == 0
(self / other).floor
end

def %(other)
self - other * self.div(other)
end
alias modulo %

def divmod(other)
[div(other), self % other]
end

This file was deleted.

This file was deleted.

This file was deleted.

@@ -1,5 +1 @@
fails:Fixnum#%
fails:Fixnum#modulo returns the modulus obtained from dividing self by the given argument
fails:Fixnum#modulo raises a ZeroDivisionError when the given argument is 0
fails:Fixnum#modulo raises a ZeroDivisionError when the given argument is 0 and a Float
fails:Fixnum#modulo raises a TypeError when given a non-Integer

This file was deleted.

This file was deleted.

@@ -0,0 +1,5 @@
fails:Thread#priority inherits the priority of the current thread while running
fails:Thread#priority maintain the priority of the current thread after death
fails:Thread#priority returns an integer
fails:Thread#priority= when set with an integer returns an integer
fails:Thread#priority= when set with a non-integer raises a type error
@@ -173,3 +173,52 @@ def method_pow(self, space, w_other):
space.obj_to_s(space.getclass(w_other))
)
)

@classdef.method("divmod")
def method_divmod(self, space, w_other):
if space.is_kind_of(w_other, space.w_float):
return space.send(self.method_to_f(space), "divmod", [w_other])
elif(space.is_kind_of(w_other, space.w_bignum) or
space.is_kind_of(w_other, space.w_fixnum)):
other = space.bigint_w(w_other)
if not other.tobool():
raise space.error(space.w_ZeroDivisionError, "devided by 0")
div, mod = self.bigint.divmod(other)
return space.newarray([space.newbigint_fromrbigint(div),
space.newbigint_fromrbigint(mod)])
else:
raise space.error(
space.w_TypeError,
"%s can't be coerced into Fixnum" % (
space.obj_to_s(space.getclass(w_other))
)
)

@classdef.method("%")
@classdef.method("modulo")
def method_mod(self, space, w_other):
if space.getclass(w_other) is space.w_fixnum:
return space.newint(
space.int_w(
self.method_mod_bigint_impl(
space,
space.bigint_w(w_other)
)
)
)
elif space.getclass(w_other) is space.w_float:
return space.send(self.method_to_f(space), "%", [w_other])
elif space.getclass(w_other) is space.w_bignum:
return self.method_mod_bigint_impl(space, space.bigint_w(w_other))
else:
raise space.error(
space.w_TypeError,
"%s can't be coerced into Fixnum" % (
space.obj_to_s(space.getclass(w_other))
)
)

def method_mod_bigint_impl(self, space, other):
if not other.tobool():
raise space.error(space.w_ZeroDivisionError, "devided by 0")
return space.newbigint_fromrbigint(self.bigint.mod(other))
@@ -272,3 +272,79 @@ def method_round(self, space):
@classdef.method("quo")
def method_quo(self, space):
raise space.error(space.w_NotImplementedError, "Numeric#quo")

@classdef.method("divmod")
def method_divmod(self, space, w_other):
if math.isnan(self.floatvalue) or math.isinf(self.floatvalue):
raise space.error(
space.w_FloatDomainError,
space.obj_to_s(space.getclass(w_other))
)
if (space.is_kind_of(w_other, space.w_fixnum) or
space.is_kind_of(w_other, space.w_bignum) or
space.is_kind_of(w_other, space.w_float)):
y = space.float_w(w_other)
if math.isnan(y):
raise space.error(
space.w_FloatDomainError,
space.obj_to_s(space.getclass(w_other))
)
x = self.floatvalue
mod = space.float_w(self.method_mod_float_impl(space, y))
# TAKEN FROM: pypy/module/cpytext/floatobject.py
div = (x - mod) / y
if (mod):
# ensure the remainder has the same sign as the denominator
if ((y < 0.0) != (mod < 0.0)):
mod += y
div -= 1.0
else:
mod *= mod # hide "mod = +0" from optimizer
if y < 0.0:
mod = -mod
# snap quotient to nearest integral value
if div:
floordiv = math.floor(div)
if (div - floordiv > 0.5):
floordiv += 1.0
else:
# div is zero - get the same sign as the true quotient
div *= div # hide "div = +0" from optimizers
floordiv = div * x / y # zero w/ sign of vx/wx
try:
return space.newarray([self.float_to_w_int(space, round_away(div)), space.newfloat(mod)])
except OverflowError:
return space.newarray([space.newbigint_fromfloat(div), space.newfloat(mod)])
else:
raise space.error(
space.w_TypeError,
"%s can't be coerced into Float" % (
space.obj_to_s(space.getclass(w_other))
)
)

@classdef.method("%")
@classdef.method("modulo")
def method_mod(self, space, w_other):
if (space.is_kind_of(w_other, space.w_fixnum) or
space.is_kind_of(w_other, space.w_bignum) or
space.is_kind_of(w_other, space.w_float)):
return self.method_mod_float_impl(space, space.float_w(w_other))
else:
raise space.error(
space.w_TypeError,
"%s can't be coerced into Float" % (
space.obj_to_s(space.getclass(w_other))
)
)

def method_mod_float_impl(self, space, other):
if other == 0.0:
raise space.error(space.w_ZeroDivisionError, "devided by 0")
elif self.floatvalue == -0.0:
return space.newfloat(-0.0)
elif math.isinf(other) and other < 0.0:
return space.newfloat(other)
elif math.isnan(self.floatvalue) or math.isinf(self.floatvalue):
return space.newfloat(NAN)
return space.newfloat(math.fmod(self.floatvalue, other))
@@ -7,6 +7,7 @@
from rpython.rlib.rarithmetic import (r_uint, r_longlong, r_ulonglong,
ovfcheck, LONG_BIT)
from rpython.rlib.rbigint import rbigint
from rpython.rlib.rfloat import round_away
from rpython.rtyper.lltypesystem import lltype, rffi

from topaz.coerce import Coerce
@@ -218,8 +219,50 @@ def method_pow_int_impl(self, space, w_other):
else:
return space.send(space.newfloat(float(temp)), "**", [w_other])

@classdef.method("%", other="int")
def method_mod(self, space, other):
@classdef.method("divmod")
def method_divmod(self, space, w_other):
if space.is_kind_of(w_other, space.w_float):
return space.send(self.method_to_f(space), "divmod", [w_other])
elif space.is_kind_of(w_other, space.w_bignum):
return space.send(space.newbigint_fromint(self.intvalue), "divmod", [w_other])
elif space.is_kind_of(w_other, space.w_fixnum):
y = space.int_w(w_other)
if y == 0:
raise space.error(
space.w_ZeroDivisionError,
"devided by 0"
)
mod = space.int_w(self.method_mod_int_impl(space, y))
div = (self.intvalue - mod) / y
return space.newarray([space.newint(int(round_away(div))), space.newfloat(mod)])
else:
raise space.error(
space.w_TypeError,
"%s can't be coerced into Fixnum" % (
space.obj_to_s(space.getclass(w_other))
)
)

@classdef.method("%")
@classdef.method("modulo")
def method_mod(self, space, w_other):
if space.is_kind_of(w_other, space.w_fixnum):
return self.method_mod_int_impl(space, space.int_w(w_other))
elif space.is_kind_of(w_other, space.w_float):
return space.send(self.method_to_f(space), "%", [w_other])
elif space.is_kind_of(w_other, space.w_bignum):
return space.send(space.newbigint_fromint(self.intvalue), "%", [w_other])
else:
raise space.error(
space.w_TypeError,
"%s can't be coerced into Fixnum" % (
space.obj_to_s(space.getclass(w_other))
)
)

def method_mod_int_impl(self, space, other):
if other == 0:
raise space.error(space.w_ZeroDivisionError, "devided by 0")
return space.newint(self.intvalue % other)

@classdef.method("<<", other="int")

0 comments on commit ed33a4a

Please sign in to comment.
You can’t perform that action at this time.