atabac / python-on-a-chip

Automatically exported from code.google.com/p/python-on-a-chip
Other
0 stars 0 forks source link

Fix defect in modulo and division #152

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Reported by Oscar Lindberg via maillist on 2010/10/04:

In python:

a = -3
a % 10
7
a %= 10
a
7
-3 % 10
7

In IPM (in the desktop platform):

ipm> a = -3
ipm> a % 10
-3
ipm> a %= 10
ipm> a
-3
ipm> -3 % 10
7

Original issue reported on code.google.com by dwhall...@gmail.com on 4 Oct 2010 at 7:55

GoogleCodeExporter commented 9 years ago

Original comment by dwhall...@gmail.com on 22 Oct 2010 at 3:28

GoogleCodeExporter commented 9 years ago
In cpython: 
>>> 2 % 3
2
>>> (-2) % 3
1
>>> (2) % (-3)
-1
>>> (-2) % (-3)
-2

http://en.wikipedia.org/wiki/Modulo_operation says that in Python the result 
has the same sign as the divisor. But for C (ISO 1990) it depends on the 
implementation. So the implementation in pymite should probably just base the 
result on doing modulus for positive numbers. So basically: 

a mod n:

if n == 0:
  raise ZeroDiv
if n > 0:
  if a > 0:
    return a % n (where % is the C operation)
  else:
    return n - ((-a) % n) 
else:
  if a > 0:
    return (a%(-n))-n 
  else:
    return -((-a) % (-n)) 

There are probably ways to simplify this code, but I just wanted it to be clear 
at the moment. 

This will go in the BINARY_MODULO/INPLACE_MODULO case in the big switch in 
interp.c (about line 399). 

Original comment by oscar.li...@gmail.com on 22 Oct 2010 at 7:17

GoogleCodeExporter commented 9 years ago
I made a mistake in the pseudo code. For negative n and positive a, you can 
swap sign of n and do the mod, but then you need to ADD n, not subtract it: 

a mod n:

if n == 0:
  raise ZeroDiv
if n > 0:
  if a > 0:
    return a % n (where % is the C operation)
  else:
    return n - ((-a) % n) 
else:
  if a > 0:
    return (a%(-n))+n     <- Tthe error was here
  else:
    return -((-a) % (-n)) 

Original comment by oscar.li...@gmail.com on 22 Oct 2010 at 11:33

GoogleCodeExporter commented 9 years ago
I've discovered that a similar problem affects the division operation:

CPython
{{{

>>> 3/4
0
>>> -3/4
-1
>>> -4/3
-2
>>> -3/-4
0
}}}

PyMite
{{{

ipm> 3/4
0
ipm> -3/4
0
ipm> -4/3
-1
ipm> -3/-4
0
}}}

Original comment by dwhall...@gmail.com on 24 Oct 2010 at 6:05

GoogleCodeExporter commented 9 years ago
r547b79b1f1
- Created int_divmod() func to fix modulo and division
- Followed CPython 2.6.4's impl of Objects/intobject.c::i_divmod().
- Used int_divmod in *_MODULO, *_DIVIDE bytecodes
- Created PM_RET_EX_OFLOW exception
- Added OverflowError exception string to plat_reportError() on platforms that 
HAVE_DEBUG_INFO
- Added system test t352

Test builds for desktop, mbed, arduino_mega passed.
Tests pass.

Original comment by dwhall...@gmail.com on 25 Oct 2010 at 12:48