1. Carl Friedrich Bolz
  2. Pyrolog

Commits

Carl Friedrich Bolz  committed 816084b

implement floordiv

  • Participants
  • Parent commits e5468b0
  • Branches default

Comments (0)

Files changed (2)

File prolog/interpreter/arithmetic.py

View file
  • Ignore whitespace
     ("-", 2, "sub"),
     ("*", 2, "mul"),
     ("/", 2, "div"),
+    ("//", 2, "floordiv"),
     ("**", 2, "pow"),
     (">>", 2, "shr"),
     ("<<", 2, "shl"),
     def arith_div_float(self, other_float):
         return term.Float(other_float / float(self.num))
 
+    def arith_floordiv(self, other):
+        return other.arith_floordiv_number(self.num)
+
+    def arith_floordiv_number(self, other_num):
+        try:
+            res = rarithmetic.ovfcheck(other_num // self.num)
+        except OverflowError:
+            return self.arith_floordiv_bigint(rbigint.fromint(other_num))
+        return term.Number(res)
+
+    def arith_floordiv_bigint(self, other_value):
+        return make_int(term.BigInt(other_value.floordiv(rbigint.fromint(self.num))))
+
+    def arith_floordiv_float(self, other_float):
+        error.throw_type_error("integer", other_float)
+
+
     # ------------------ power ------------------ 
     def arith_pow(self, other):
         return other.arith_pow_number(self.num)
     def arith_div_float(self, other_float):
         return term.Float(other_float / self.floatval)
 
+    def arith_floordiv(self, other_float):
+        error.throw_type_error("integer", self)
+    def arith_floordiv_number(self, other_num):
+        error.throw_type_error("integer", self)
+    def arith_floordiv_bigint(self, other_value):
+        error.throw_type_error("integer", self)
+    def arith_floordiv_float(self, other_float):
+        error.throw_type_error("integer", other_float)
+
     # ------------------ power ------------------ 
     def arith_pow(self, other):
         return other.arith_pow_float(self.floatval)
     def arith_div_float(self, other_float):
         return term.Float(other_float / self.value.tofloat())
 
-    # ------------------ power ------------------ 
+    def arith_floordiv(self, other):
+        return other.arith_floordiv_bigint(self.value)
+
+    def arith_floordiv_number(self, other_num):
+        return make_int(term.BigInt(rbigint.fromint(other_num).div(self.value)))
+
+    def arith_floordiv_bigint(self, other_value):
+        return make_int(term.BigInt(other_value.div(self.value)))
+
+    def arith_floordiv_float(self, other_float):
+        error.throw_type_error("integer", other_float)
+    # ------------------ power ------------------
     def arith_pow(self, other):
         return other.arith_pow_bigint(self.value)
 

File prolog/interpreter/test/test_arithmetic.py

View file
  • Ignore whitespace
         py.test.raises(ZeroDivisionError, 'Number(1).arith_div(Number(0))')
         py.test.raises(ZeroDivisionError, 'Number(1).arith_div(Float(0))')
 
+    def test_floordiv(self):
+        assert Number(5).arith_floordiv(Number(2)).num == 2
+        assert Number(15).arith_floordiv(Number(5)).num == 3
+        py.test.raises(error.CatchableError, "Number(5).arith_floordiv(Float(2.5))")
+        py.test.raises(error.CatchableError, "Float(2.5).arith_floordiv(Number(5))")
+        py.test.raises(error.CatchableError, "Float(-10).arith_floordiv(Float(2.5))")
+        assert BigInt(rbigint.fromdecimalstr('50000000000000000')).arith_floordiv(BigInt(rbigint.fromdecimalstr('25000000000000000'))).num == 2
+        py.test.raises(error.CatchableError, "BigInt(rbigint.fromdecimalstr('100000000000000000000')).arith_floordiv(Float(100000000000000000000.0))")
+        py.test.raises(error.CatchableError, "Float(100000000000000000000).arith_floordiv(BigInt(rbigint.fromdecimalstr('100000000000000000000')))")
+        assert Number(5).arith_floordiv(BigInt(rbigint.fromdecimalstr('5'))).num == 1
+        assert BigInt(rbigint.fromdecimalstr('5')).arith_floordiv(Number(5)).num == 1
+
+        py.test.raises(ZeroDivisionError, 'BigInt(rbigint.fromdecimalstr(\'1\')).arith_floordiv(BigInt(rbigint.fromdecimalstr(\'0\')))')
+        py.test.raises(ZeroDivisionError, 'BigInt(rbigint.fromdecimalstr(\'1\')).arith_floordiv(Number(0))')
+        py.test.raises(ZeroDivisionError, 'Number(1).arith_floordiv(Number(0))')
+
     def test_power(self):
         assert Number(5).arith_pow(Number(2)).num == 25
         assert Float(2.3).arith_pow(Float(3.1)).floatval == 13.223800591254721