PageRenderTime 47ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/pypy/rlib/rarithmetic.py

https://bitbucket.org/pypy/pypy/
Python | 515 lines | 465 code | 3 blank | 47 comment | 0 complexity | b5af2860153257a42de019b4eb213a52 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. """
  2. This file defines restricted arithmetic:
  3. classes and operations to express integer arithmetic,
  4. such that before and after translation semantics are
  5. consistent
  6. r_uint an unsigned integer which has no overflow
  7. checking. It is always positive and always
  8. truncated to the internal machine word size.
  9. intmask mask a possibly long value when running on CPython
  10. back to a signed int value
  11. ovfcheck check on CPython whether the result of a signed
  12. integer operation did overflow
  13. ovfcheck_float_to_int
  14. convert to an integer or raise OverflowError
  15. r_longlong
  16. like r_int but double word size
  17. r_ulonglong
  18. like r_uint but double word size
  19. widen(x)
  20. if x is of a type smaller than lltype.Signed or
  21. lltype.Unsigned, widen it to lltype.Signed.
  22. Useful because the translator doesn't support
  23. arithmetic on the smaller types.
  24. These are meant to be erased by translation, r_uint
  25. in the process should mark unsigned values, ovfcheck should
  26. mark where overflow checking is required.
  27. """
  28. import sys
  29. from pypy.rpython import extregistry
  30. from pypy.rlib import objectmodel
  31. # set up of machine internals
  32. _bits = 0
  33. _itest = 1
  34. _Ltest = 1L
  35. while _itest == _Ltest and type(_itest) is int:
  36. _itest *= 2
  37. _Ltest *= 2
  38. _bits += 1
  39. LONG_BIT = _bits+1
  40. LONG_MASK = _Ltest*2-1
  41. LONG_TEST = _Ltest
  42. LONGLONG_BIT = 64
  43. LONGLONG_MASK = (2**LONGLONG_BIT)-1
  44. LONGLONG_TEST = 2**(LONGLONG_BIT-1)
  45. LONG_BIT_SHIFT = 0
  46. while (1 << LONG_BIT_SHIFT) != LONG_BIT:
  47. LONG_BIT_SHIFT += 1
  48. assert LONG_BIT_SHIFT < 99, "LONG_BIT_SHIFT value not found?"
  49. def intmask(n):
  50. if isinstance(n, int):
  51. return int(n) # possibly bool->int
  52. if isinstance(n, objectmodel.Symbolic):
  53. return n # assume Symbolics don't overflow
  54. assert not isinstance(n, float)
  55. n = long(n)
  56. n &= LONG_MASK
  57. if n >= LONG_TEST:
  58. n -= 2*LONG_TEST
  59. return int(n)
  60. def longlongmask(n):
  61. assert isinstance(n, (int, long))
  62. n = long(n)
  63. n &= LONGLONG_MASK
  64. if n >= LONGLONG_TEST:
  65. n -= 2*LONGLONG_TEST
  66. return r_longlong(n)
  67. def widen(n):
  68. from pypy.rpython.lltypesystem import lltype
  69. if _should_widen_type(lltype.typeOf(n)):
  70. return intmask(n)
  71. else:
  72. return n
  73. widen._annspecialcase_ = 'specialize:argtype(0)'
  74. def _should_widen_type(tp):
  75. from pypy.rpython.lltypesystem import lltype, rffi
  76. if tp is lltype.Bool:
  77. return True
  78. if tp is lltype.Signed:
  79. return False
  80. r_class = rffi.platform.numbertype_to_rclass[tp]
  81. assert issubclass(r_class, base_int)
  82. return r_class.BITS < LONG_BIT or (
  83. r_class.BITS == LONG_BIT and r_class.SIGNED)
  84. _should_widen_type._annspecialcase_ = 'specialize:memo'
  85. del _bits, _itest, _Ltest
  86. def ovfcheck(r):
  87. "NOT_RPYTHON"
  88. # to be used as ovfcheck(x <op> y)
  89. # raise OverflowError if the operation did overflow
  90. assert not isinstance(r, r_uint), "unexpected ovf check on unsigned"
  91. assert not isinstance(r, r_longlong), "ovfcheck not supported on r_longlong"
  92. assert not isinstance(r,r_ulonglong),"ovfcheck not supported on r_ulonglong"
  93. if type(r) is long:
  94. raise OverflowError, "signed integer expression did overflow"
  95. return r
  96. # Strange things happening for float to int on 64 bit:
  97. # int(float(i)) != i because of rounding issues.
  98. # These are the minimum and maximum float value that can
  99. # successfully be casted to an int.
  100. if sys.maxint == 2147483647:
  101. def ovfcheck_float_to_int(x):
  102. from pypy.rlib.rfloat import isnan
  103. if isnan(x):
  104. raise OverflowError
  105. if -2147483649.0 < x < 2147483648.0:
  106. return int(x)
  107. raise OverflowError
  108. else:
  109. # The following values are not quite +/-sys.maxint.
  110. # Note the "<= x <" here, as opposed to "< x <" above.
  111. # This is justified by test_typed in translator/c/test.
  112. def ovfcheck_float_to_int(x):
  113. from pypy.rlib.rfloat import isnan
  114. if isnan(x):
  115. raise OverflowError
  116. if -9223372036854776832.0 <= x < 9223372036854775296.0:
  117. return int(x)
  118. raise OverflowError
  119. def compute_restype(self_type, other_type):
  120. if self_type is other_type:
  121. if self_type is bool:
  122. return int
  123. return self_type
  124. if other_type in (bool, int, long):
  125. if self_type is bool:
  126. return int
  127. return self_type
  128. if self_type in (bool, int, long):
  129. return other_type
  130. if self_type.SIGNED == other_type.SIGNED:
  131. return build_int(None, self_type.SIGNED, max(self_type.BITS, other_type.BITS))
  132. raise AssertionError, "Merging these types (%s, %s) is not supported" % (self_type, other_type)
  133. def signedtype(t):
  134. if t in (bool, int, long):
  135. return True
  136. else:
  137. return t.SIGNED
  138. signedtype._annspecialcase_ = 'specialize:memo'
  139. def normalizedinttype(t):
  140. if t is int:
  141. return int
  142. if t.BITS <= r_int.BITS:
  143. return build_int(None, t.SIGNED, r_int.BITS)
  144. else:
  145. assert t.BITS <= r_longlong.BITS
  146. return build_int(None, t.SIGNED, r_longlong.BITS)
  147. def most_neg_value_of_same_type(x):
  148. from pypy.rpython.lltypesystem import lltype
  149. return most_neg_value_of(lltype.typeOf(x))
  150. most_neg_value_of_same_type._annspecialcase_ = 'specialize:argtype(0)'
  151. def most_neg_value_of(tp):
  152. from pypy.rpython.lltypesystem import lltype, rffi
  153. if tp is lltype.Signed:
  154. return -sys.maxint-1
  155. r_class = rffi.platform.numbertype_to_rclass[tp]
  156. assert issubclass(r_class, base_int)
  157. if r_class.SIGNED:
  158. return r_class(-(r_class.MASK >> 1) - 1)
  159. else:
  160. return r_class(0)
  161. most_neg_value_of._annspecialcase_ = 'specialize:memo'
  162. def highest_bit(n):
  163. """
  164. Calculates the highest set bit in n. This function assumes that n is a
  165. power of 2 (and thus only has a single set bit).
  166. """
  167. assert n and (n & (n - 1)) == 0
  168. i = -1
  169. while n:
  170. i += 1
  171. n >>= 1
  172. return i
  173. class base_int(long):
  174. """ fake unsigned integer implementation """
  175. def _widen(self, other, value):
  176. """
  177. if one argument is int or long, the other type wins.
  178. otherwise, produce the largest class to hold the result.
  179. """
  180. self_type = type(self)
  181. other_type = type(other)
  182. try:
  183. return self.typemap[self_type, other_type](value)
  184. except KeyError:
  185. pass
  186. restype = compute_restype(self_type, other_type)
  187. self.typemap[self_type, other_type] = restype
  188. return restype(value)
  189. def __new__(klass, val):
  190. if klass is base_int:
  191. raise TypeError("abstract base!")
  192. else:
  193. return super(base_int, klass).__new__(klass, val)
  194. def __add__(self, other):
  195. x = long(self)
  196. y = long(other)
  197. return self._widen(other, x + y)
  198. __radd__ = __add__
  199. def __sub__(self, other):
  200. x = long(self)
  201. y = long(other)
  202. return self._widen(other, x - y)
  203. def __rsub__(self, other):
  204. y = long(self)
  205. x = long(other)
  206. return self._widen(other, x - y)
  207. def __mul__(self, other):
  208. x = long(self)
  209. if not isinstance(other, (int, long)):
  210. return x * other
  211. y = long(other)
  212. return self._widen(other, x * y)
  213. __rmul__ = __mul__
  214. def __div__(self, other):
  215. x = long(self)
  216. y = long(other)
  217. return self._widen(other, x // y)
  218. __floordiv__ = __div__
  219. def __rdiv__(self, other):
  220. y = long(self)
  221. x = long(other)
  222. return self._widen(other, x // y)
  223. __rfloordiv__ = __rdiv__
  224. def __mod__(self, other):
  225. x = long(self)
  226. y = long(other)
  227. return self._widen(other, x % y)
  228. def __rmod__(self, other):
  229. y = long(self)
  230. x = long(other)
  231. return self._widen(other, x % y)
  232. def __divmod__(self, other):
  233. x = long(self)
  234. y = long(other)
  235. res = divmod(x, y)
  236. return (self.__class__(res[0]), self.__class__(res[1]))
  237. def __lshift__(self, n):
  238. x = long(self)
  239. y = long(n)
  240. return self.__class__(x << y)
  241. def __rlshift__(self, n):
  242. y = long(self)
  243. x = long(n)
  244. return self._widen(n, x << y)
  245. def __rshift__(self, n):
  246. x = long(self)
  247. y = long(n)
  248. return self._widen(n, x >> y)
  249. def __rrshift__(self, n):
  250. y = long(self)
  251. x = long(n)
  252. return self._widen(n, x >> y)
  253. def __or__(self, other):
  254. x = long(self)
  255. y = long(other)
  256. return self._widen(other, x | y)
  257. __ror__ = __or__
  258. def __and__(self, other):
  259. x = long(self)
  260. y = long(other)
  261. return self._widen(other, x & y)
  262. __rand__ = __and__
  263. def __xor__(self, other):
  264. x = long(self)
  265. y = long(other)
  266. return self._widen(other, x ^ y)
  267. __rxor__ = __xor__
  268. def __neg__(self):
  269. x = long(self)
  270. return self.__class__(-x)
  271. def __abs__(self):
  272. x = long(self)
  273. return self.__class__(abs(x))
  274. def __pos__(self):
  275. return self.__class__(self)
  276. def __invert__(self):
  277. x = long(self)
  278. return self.__class__(~x)
  279. def __pow__(self, other, m=None):
  280. x = long(self)
  281. y = long(other)
  282. res = pow(x, y, m)
  283. return self._widen(other, res)
  284. def __rpow__(self, other, m=None):
  285. y = long(self)
  286. x = long(other)
  287. res = pow(x, y, m)
  288. return self._widen(other, res)
  289. class signed_int(base_int):
  290. SIGNED = True
  291. def __new__(klass, val=0):
  292. if type(val) is float:
  293. val = long(val)
  294. if val > klass.MASK>>1 or val < -(klass.MASK>>1)-1:
  295. raise OverflowError("%s does not fit in signed %d-bit integer"%(val, klass.BITS))
  296. if val < 0:
  297. val = ~ ((~val) & klass.MASK)
  298. return super(signed_int, klass).__new__(klass, val)
  299. typemap = {}
  300. class unsigned_int(base_int):
  301. SIGNED = False
  302. def __new__(klass, val=0):
  303. if isinstance(val, (float, long)):
  304. val = long(val)
  305. return super(unsigned_int, klass).__new__(klass, val & klass.MASK)
  306. typemap = {}
  307. _inttypes = {}
  308. def build_int(name, sign, bits, force_creation=False):
  309. sign = bool(sign)
  310. if not force_creation:
  311. try:
  312. return _inttypes[sign, bits]
  313. except KeyError:
  314. pass
  315. if sign:
  316. base_int_type = signed_int
  317. else:
  318. base_int_type = unsigned_int
  319. mask = (2 ** bits) - 1
  320. if name is None:
  321. raise TypeError('No predefined %sint%d'%(['u', ''][sign], bits))
  322. int_type = type(name, (base_int_type,), {'MASK': mask,
  323. 'BITS': bits,
  324. 'SIGN': sign})
  325. if not force_creation:
  326. _inttypes[sign, bits] = int_type
  327. class ForValuesEntry(extregistry.ExtRegistryEntry):
  328. _type_ = int_type
  329. def compute_annotation(self):
  330. from pypy.annotation import model as annmodel
  331. return annmodel.SomeInteger(knowntype=int_type)
  332. class ForTypeEntry(extregistry.ExtRegistryEntry):
  333. _about_ = int_type
  334. def compute_result_annotation(self, *args_s, **kwds_s):
  335. from pypy.annotation import model as annmodel
  336. return annmodel.SomeInteger(knowntype=int_type)
  337. def specialize_call(self, hop):
  338. v_result, = hop.inputargs(hop.r_result.lowleveltype)
  339. hop.exception_cannot_occur()
  340. return v_result
  341. return int_type
  342. class BaseIntValueEntry(extregistry.ExtRegistryEntry):
  343. _type_ = base_int
  344. def compute_annotation(self):
  345. from pypy.annotation import model as annmodel
  346. return annmodel.SomeInteger(knowntype=r_ulonglong)
  347. class BaseIntTypeEntry(extregistry.ExtRegistryEntry):
  348. _about_ = base_int
  349. def compute_result_annotation(self, *args_s, **kwds_s):
  350. raise TypeError("abstract base!")
  351. r_int = build_int('r_int', True, LONG_BIT)
  352. r_uint = build_int('r_uint', False, LONG_BIT)
  353. r_longlong = build_int('r_longlong', True, 64)
  354. r_ulonglong = build_int('r_ulonglong', False, 64)
  355. longlongmax = r_longlong(LONGLONG_TEST - 1)
  356. if r_longlong is not r_int:
  357. r_int64 = r_longlong
  358. else:
  359. r_int64 = int
  360. # the 'float' C type
  361. class r_singlefloat(object):
  362. """A value of the C type 'float'.
  363. This is a single-precision floating-point number.
  364. Regular 'float' values in Python and RPython are double-precision.
  365. Note that we consider this as a black box for now - the only thing
  366. you can do with it is cast it back to a regular float."""
  367. def __init__(self, floatval):
  368. import struct
  369. # simulates the loss of precision
  370. self._bytes = struct.pack("f", floatval)
  371. def __float__(self):
  372. import struct
  373. return struct.unpack("f", self._bytes)[0]
  374. def __nonzero__(self):
  375. raise TypeError("not supported on r_singlefloat instances")
  376. def __cmp__(self, other):
  377. raise TypeError("not supported on r_singlefloat instances")
  378. def __eq__(self, other):
  379. return self.__class__ is other.__class__ and self._bytes == other._bytes
  380. def __ne__(self, other):
  381. return not self.__eq__(other)
  382. class r_longfloat(object):
  383. """A value of the C type 'long double'.
  384. Note that we consider this as a black box for now - the only thing
  385. you can do with it is cast it back to a regular float."""
  386. def __init__(self, floatval):
  387. self.value = floatval
  388. def __float__(self):
  389. return self.value
  390. def __nonzero__(self):
  391. raise TypeError("not supported on r_longfloat instances")
  392. def __cmp__(self, other):
  393. raise TypeError("not supported on r_longfloat instances")
  394. def __eq__(self, other):
  395. return self.__class__ is other.__class__ and self.value == other.value
  396. def __ne__(self, other):
  397. return not self.__eq__(other)
  398. class For_r_singlefloat_values_Entry(extregistry.ExtRegistryEntry):
  399. _type_ = r_singlefloat
  400. def compute_annotation(self):
  401. from pypy.annotation import model as annmodel
  402. return annmodel.SomeSingleFloat()
  403. class For_r_singlefloat_type_Entry(extregistry.ExtRegistryEntry):
  404. _about_ = r_singlefloat
  405. def compute_result_annotation(self, *args_s, **kwds_s):
  406. from pypy.annotation import model as annmodel
  407. return annmodel.SomeSingleFloat()
  408. def specialize_call(self, hop):
  409. from pypy.rpython.lltypesystem import lltype
  410. v, = hop.inputargs(lltype.Float)
  411. hop.exception_cannot_occur()
  412. # we use cast_primitive to go between Float and SingleFloat.
  413. return hop.genop('cast_primitive', [v],
  414. resulttype = lltype.SingleFloat)
  415. def int_between(n, m, p):
  416. """ check that n <= m < p. This assumes that n <= p. This is useful because
  417. the JIT special-cases it. """
  418. from pypy.rpython.lltypesystem import lltype
  419. from pypy.rpython.lltypesystem.lloperation import llop
  420. if not objectmodel.we_are_translated():
  421. assert n <= p
  422. return llop.int_between(lltype.Bool, n, m, p)