PageRenderTime 60ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/rpython/rlib/rarithmetic.py

https://bitbucket.org/pypy/pypy/
Python | 756 lines | 634 code | 61 blank | 61 comment | 61 complexity | c886d0ebbee30ace310ba14406b022bf 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. ovfcheck_float_to_longlong
  16. convert to a longlong or raise OverflowError
  17. r_longlong
  18. like r_int but double word size
  19. r_ulonglong
  20. like r_uint but double word size
  21. widen(x)
  22. if x is of a type smaller than lltype.Signed or
  23. lltype.Unsigned, widen it to lltype.Signed.
  24. Useful because the translator doesn't support
  25. arithmetic on the smaller types.
  26. These are meant to be erased by translation, r_uint
  27. in the process should mark unsigned values, ovfcheck should
  28. mark where overflow checking is required.
  29. """
  30. import sys, struct
  31. from rpython.rtyper import extregistry
  32. from rpython.rlib import objectmodel
  33. from rpython.flowspace.model import Constant, const
  34. from rpython.flowspace.specialcase import register_flow_sc
  35. """
  36. Long-term target:
  37. We want to make pypy very flexible concerning its data type layout.
  38. This is a larger task for later.
  39. Short-term target:
  40. We want to run PyPy on windows 64 bit.
  41. Problem:
  42. On windows 64 bit, integers are only 32 bit. This is a problem for PyPy
  43. right now, since it assumes that a c long can hold a pointer.
  44. We therefore set up the target machine constants to obey this rule.
  45. Right now this affects 64 bit Python only on windows.
  46. Note: We use the struct module, because the array module doesn's support
  47. all typecodes.
  48. """
  49. def _get_bitsize(typecode):
  50. return len(struct.pack(typecode, 1)) * 8
  51. _long_typecode = 'l'
  52. if _get_bitsize('P') > _get_bitsize('l'):
  53. _long_typecode = 'P'
  54. def _get_long_bit():
  55. # whatever size a long has, make it big enough for a pointer.
  56. return _get_bitsize(_long_typecode)
  57. # exported for now for testing array values.
  58. # might go into its own module.
  59. def get_long_pattern(x):
  60. """get the bit pattern for a long, adjusted to pointer size"""
  61. return struct.pack(_long_typecode, x)
  62. # used in tests for ctypes and for genc and friends
  63. # to handle the win64 special case:
  64. is_emulated_long = _long_typecode != 'l'
  65. LONG_BIT = _get_long_bit()
  66. LONG_MASK = (2**LONG_BIT)-1
  67. LONG_TEST = 2**(LONG_BIT-1)
  68. # XXX this is a good guess, but what if a long long is 128 bit?
  69. LONGLONG_BIT = 64
  70. LONGLONG_MASK = (2**LONGLONG_BIT)-1
  71. LONGLONG_TEST = 2**(LONGLONG_BIT-1)
  72. LONG_BIT_SHIFT = 0
  73. while (1 << LONG_BIT_SHIFT) != LONG_BIT:
  74. LONG_BIT_SHIFT += 1
  75. assert LONG_BIT_SHIFT < 99, "LONG_BIT_SHIFT value not found?"
  76. LONGLONGLONG_BIT = 128
  77. LONGLONGLONG_MASK = (2**LONGLONGLONG_BIT)-1
  78. LONGLONGLONG_TEST = 2**(LONGLONGLONG_BIT-1)
  79. """
  80. int is no longer necessarily the same size as the target int.
  81. We therefore can no longer use the int type as it is, but need
  82. to use long everywhere.
  83. """
  84. # XXX returning int(n) should not be necessary and should be simply n.
  85. # XXX TODO: replace all int(n) by long(n) and fix everything that breaks.
  86. # XXX Then relax it and replace int(n) by n.
  87. def intmask(n):
  88. """
  89. NOT_RPYTHON
  90. """
  91. if isinstance(n, objectmodel.Symbolic):
  92. return n # assume Symbolics don't overflow
  93. assert not isinstance(n, float)
  94. if is_valid_int(n):
  95. return int(n)
  96. n = long(n)
  97. n &= LONG_MASK
  98. if n >= LONG_TEST:
  99. n -= 2*LONG_TEST
  100. return int(n)
  101. def longlongmask(n):
  102. """
  103. NOT_RPYTHON
  104. """
  105. assert isinstance(n, (int, long))
  106. n = long(n)
  107. n &= LONGLONG_MASK
  108. if n >= LONGLONG_TEST:
  109. n -= 2*LONGLONG_TEST
  110. return r_longlong(n)
  111. def longlonglongmask(n):
  112. # Assume longlonglong doesn't overflow. This is perfectly fine for rbigint.
  113. # We deal directly with overflow there anyway.
  114. return r_longlonglong(n)
  115. def widen(n):
  116. from rpython.rtyper.lltypesystem import lltype
  117. if _should_widen_type(lltype.typeOf(n)):
  118. return intmask(n)
  119. else:
  120. return n
  121. widen._annspecialcase_ = 'specialize:argtype(0)'
  122. def _should_widen_type(tp):
  123. from rpython.rtyper.lltypesystem import lltype, rffi
  124. if tp is lltype.Bool:
  125. return True
  126. if tp is lltype.Signed:
  127. return False
  128. r_class = rffi.platform.numbertype_to_rclass[tp]
  129. assert issubclass(r_class, base_int)
  130. return r_class.BITS < LONG_BIT or (
  131. r_class.BITS == LONG_BIT and r_class.SIGNED)
  132. _should_widen_type._annspecialcase_ = 'specialize:memo'
  133. # the replacement for sys.maxint
  134. maxint = int(LONG_TEST - 1)
  135. # for now, it should be equal to sys.maxint on all supported platforms
  136. assert maxint == sys.maxint
  137. def is_valid_int(r):
  138. if objectmodel.we_are_translated():
  139. return isinstance(r, int)
  140. return isinstance(r, (base_int, int, long, bool)) and (
  141. -maxint - 1 <= r <= maxint)
  142. is_valid_int._annspecialcase_ = 'specialize:argtype(0)'
  143. def ovfcheck(r):
  144. "NOT_RPYTHON"
  145. # to be used as ovfcheck(x <op> y)
  146. # raise OverflowError if the operation did overflow
  147. assert not isinstance(r, r_uint), "unexpected ovf check on unsigned"
  148. assert not isinstance(r, r_longlong), "ovfcheck not supported on r_longlong"
  149. assert not isinstance(r, r_ulonglong), "ovfcheck not supported on r_ulonglong"
  150. if type(r) is long and not is_valid_int(r):
  151. # checks only if applicable to r's type.
  152. # this happens in the garbage collector.
  153. raise OverflowError("signed integer expression did overflow")
  154. return r
  155. # Strange things happening for float to int on 64 bit:
  156. # int(float(i)) != i because of rounding issues.
  157. # These are the minimum and maximum float value that can
  158. # successfully be casted to an int.
  159. # The following values are not quite +/-sys.maxint.
  160. # Note the "<= x <" here, as opposed to "< x <" above.
  161. # This is justified by test_typed in translator/c/test.
  162. def ovfcheck_float_to_longlong(x):
  163. from rpython.rlib.rfloat import isnan
  164. if isnan(x):
  165. raise OverflowError
  166. if -9223372036854776832.0 <= x < 9223372036854775296.0:
  167. return r_longlong(x)
  168. raise OverflowError
  169. if sys.maxint == 2147483647:
  170. def ovfcheck_float_to_int(x):
  171. from rpython.rlib.rfloat import isnan
  172. if isnan(x):
  173. raise OverflowError
  174. if -2147483649.0 < x < 2147483648.0:
  175. return int(x)
  176. raise OverflowError
  177. else:
  178. def ovfcheck_float_to_int(x):
  179. return int(ovfcheck_float_to_longlong(x))
  180. def compute_restype(self_type, other_type):
  181. if self_type is other_type:
  182. if self_type is bool:
  183. return int
  184. return self_type
  185. if other_type in (bool, int, long):
  186. if self_type is bool:
  187. return int
  188. return self_type
  189. if self_type in (bool, int, long):
  190. return other_type
  191. if self_type is float or other_type is float:
  192. return float
  193. if self_type.SIGNED == other_type.SIGNED:
  194. return build_int(None, self_type.SIGNED, max(self_type.BITS, other_type.BITS))
  195. raise AssertionError("Merging these types (%s, %s) is not supported" % (self_type, other_type))
  196. def signedtype(t):
  197. if t in (bool, int, long):
  198. return True
  199. else:
  200. return t.SIGNED
  201. signedtype._annspecialcase_ = 'specialize:memo'
  202. def normalizedinttype(t):
  203. if t is int:
  204. return int
  205. if t.BITS <= r_int.BITS:
  206. return build_int(None, t.SIGNED, r_int.BITS)
  207. else:
  208. assert t.BITS <= r_longlong.BITS
  209. return build_int(None, t.SIGNED, r_longlong.BITS)
  210. def most_neg_value_of_same_type(x):
  211. from rpython.rtyper.lltypesystem import lltype
  212. return most_neg_value_of(lltype.typeOf(x))
  213. most_neg_value_of_same_type._annspecialcase_ = 'specialize:argtype(0)'
  214. def most_neg_value_of(tp):
  215. from rpython.rtyper.lltypesystem import lltype, rffi
  216. if tp is lltype.Signed:
  217. return -sys.maxint-1
  218. r_class = rffi.platform.numbertype_to_rclass[tp]
  219. assert issubclass(r_class, base_int)
  220. if r_class.SIGNED:
  221. return r_class(-(r_class.MASK >> 1) - 1)
  222. else:
  223. return r_class(0)
  224. most_neg_value_of._annspecialcase_ = 'specialize:memo'
  225. def most_pos_value_of_same_type(x):
  226. from rpython.rtyper.lltypesystem import lltype
  227. return most_pos_value_of(lltype.typeOf(x))
  228. most_pos_value_of_same_type._annspecialcase_ = 'specialize:argtype(0)'
  229. def most_pos_value_of(tp):
  230. from rpython.rtyper.lltypesystem import lltype, rffi
  231. if tp is lltype.Signed:
  232. return sys.maxint
  233. r_class = rffi.platform.numbertype_to_rclass[tp]
  234. assert issubclass(r_class, base_int)
  235. if r_class.SIGNED:
  236. return r_class(r_class.MASK >> 1)
  237. else:
  238. return r_class(r_class.MASK)
  239. most_pos_value_of._annspecialcase_ = 'specialize:memo'
  240. def is_signed_integer_type(tp):
  241. from rpython.rtyper.lltypesystem import lltype, rffi
  242. if tp is lltype.Signed:
  243. return True
  244. try:
  245. r_class = rffi.platform.numbertype_to_rclass[tp]
  246. return r_class.SIGNED
  247. except KeyError:
  248. return False # not an integer type
  249. is_signed_integer_type._annspecialcase_ = 'specialize:memo'
  250. def highest_bit(n):
  251. """
  252. Calculates the highest set bit in n. This function assumes that n is a
  253. power of 2 (and thus only has a single set bit).
  254. """
  255. assert n and (n & (n - 1)) == 0
  256. i = -1
  257. while n:
  258. i += 1
  259. n >>= 1
  260. return i
  261. class base_int(long):
  262. """ fake unsigned integer implementation """
  263. def _widen(self, other, value):
  264. """
  265. if one argument is int or long, the other type wins.
  266. if one argument is float, the result is float.
  267. otherwise, produce the largest class to hold the result.
  268. """
  269. self_type = type(self)
  270. other_type = type(other)
  271. try:
  272. return self.typemap[self_type, other_type](value)
  273. except KeyError:
  274. pass
  275. restype = compute_restype(self_type, other_type)
  276. self.typemap[self_type, other_type] = restype
  277. return restype(value)
  278. def __new__(klass, val):
  279. if klass is base_int:
  280. raise TypeError("abstract base!")
  281. else:
  282. return super(base_int, klass).__new__(klass, val)
  283. def __add__(self, other):
  284. x = long(self)
  285. y = long(other)
  286. return self._widen(other, x + y)
  287. __radd__ = __add__
  288. def __sub__(self, other):
  289. x = long(self)
  290. y = long(other)
  291. return self._widen(other, x - y)
  292. def __rsub__(self, other):
  293. y = long(self)
  294. x = long(other)
  295. return self._widen(other, x - y)
  296. def __mul__(self, other):
  297. x = long(self)
  298. if not isinstance(other, (int, long)):
  299. return x * other
  300. y = long(other)
  301. return self._widen(other, x * y)
  302. __rmul__ = __mul__
  303. def __div__(self, other):
  304. x = long(self)
  305. y = long(other)
  306. return self._widen(other, x // y)
  307. __floordiv__ = __div__
  308. def __rdiv__(self, other):
  309. y = long(self)
  310. x = long(other)
  311. return self._widen(other, x // y)
  312. __rfloordiv__ = __rdiv__
  313. def __mod__(self, other):
  314. x = long(self)
  315. y = long(other)
  316. return self._widen(other, x % y)
  317. def __rmod__(self, other):
  318. y = long(self)
  319. x = long(other)
  320. return self._widen(other, x % y)
  321. def __divmod__(self, other):
  322. x = long(self)
  323. y = long(other)
  324. res = divmod(x, y)
  325. return (self.__class__(res[0]), self.__class__(res[1]))
  326. def __lshift__(self, n):
  327. x = long(self)
  328. y = long(n)
  329. return self.__class__(x << y)
  330. def __rlshift__(self, n):
  331. y = long(self)
  332. x = long(n)
  333. return self._widen(n, x << y)
  334. def __rshift__(self, n):
  335. x = long(self)
  336. y = long(n)
  337. return self._widen(n, x >> y)
  338. def __rrshift__(self, n):
  339. y = long(self)
  340. x = long(n)
  341. return self._widen(n, x >> y)
  342. def __or__(self, other):
  343. x = long(self)
  344. y = long(other)
  345. return self._widen(other, x | y)
  346. __ror__ = __or__
  347. def __and__(self, other):
  348. x = long(self)
  349. y = long(other)
  350. return self._widen(other, x & y)
  351. __rand__ = __and__
  352. def __xor__(self, other):
  353. x = long(self)
  354. y = long(other)
  355. return self._widen(other, x ^ y)
  356. __rxor__ = __xor__
  357. def __neg__(self):
  358. x = long(self)
  359. return self.__class__(-x)
  360. def __abs__(self):
  361. x = long(self)
  362. return self.__class__(abs(x))
  363. def __pos__(self):
  364. return self.__class__(self)
  365. def __invert__(self):
  366. x = long(self)
  367. return self.__class__(~x)
  368. def __pow__(self, other, m=None):
  369. x = long(self)
  370. y = long(other)
  371. res = pow(x, y, m)
  372. return self._widen(other, res)
  373. def __rpow__(self, other, m=None):
  374. y = long(self)
  375. x = long(other)
  376. res = pow(x, y, m)
  377. return self._widen(other, res)
  378. class signed_int(base_int):
  379. SIGNED = True
  380. def __new__(klass, val=0):
  381. if isinstance(val, (float, str)):
  382. val = long(val)
  383. if val > klass.MASK >> 1 or val < -(klass.MASK >> 1) - 1:
  384. raise OverflowError("%s does not fit in signed %d-bit integer" % (val, klass.BITS))
  385. if val < 0:
  386. val = ~ ((~val) & klass.MASK)
  387. return super(signed_int, klass).__new__(klass, val)
  388. typemap = {}
  389. class unsigned_int(base_int):
  390. SIGNED = False
  391. def __new__(klass, val=0):
  392. if isinstance(val, (float, long, str)):
  393. val = long(val)
  394. return super(unsigned_int, klass).__new__(klass, val & klass.MASK)
  395. typemap = {}
  396. _inttypes = {}
  397. def build_int(name, sign, bits, force_creation=False):
  398. sign = bool(sign)
  399. if not force_creation:
  400. try:
  401. return _inttypes[sign, bits]
  402. except KeyError:
  403. pass
  404. if sign:
  405. base_int_type = signed_int
  406. else:
  407. base_int_type = unsigned_int
  408. mask = (2 ** bits) - 1
  409. if name is None:
  410. raise TypeError('No predefined %sint%d'%(['u', ''][sign], bits))
  411. int_type = type(name, (base_int_type,), {'MASK': mask,
  412. 'BITS': bits,
  413. 'SIGN': sign})
  414. if not force_creation:
  415. _inttypes[sign, bits] = int_type
  416. class ForValuesEntry(extregistry.ExtRegistryEntry):
  417. _type_ = int_type
  418. def compute_annotation(self):
  419. from rpython.annotator import model as annmodel
  420. return annmodel.SomeInteger(knowntype=int_type)
  421. class ForTypeEntry(extregistry.ExtRegistryEntry):
  422. _about_ = int_type
  423. def compute_result_annotation(self, *args_s, **kwds_s):
  424. from rpython.annotator import model as annmodel
  425. return annmodel.SomeInteger(knowntype=int_type)
  426. def specialize_call(self, hop):
  427. v_result, = hop.inputargs(hop.r_result.lowleveltype)
  428. hop.exception_cannot_occur()
  429. return v_result
  430. return int_type
  431. class BaseIntValueEntry(extregistry.ExtRegistryEntry):
  432. _type_ = base_int
  433. def compute_annotation(self):
  434. from rpython.annotator import model as annmodel
  435. return annmodel.SomeInteger(knowntype=r_ulonglong)
  436. class BaseIntTypeEntry(extregistry.ExtRegistryEntry):
  437. _about_ = base_int
  438. def compute_result_annotation(self, *args_s, **kwds_s):
  439. raise TypeError("abstract base!")
  440. r_int = build_int('r_int', True, LONG_BIT)
  441. r_uint = build_int('r_uint', False, LONG_BIT)
  442. @register_flow_sc(r_uint)
  443. def sc_r_uint(ctx, w_value):
  444. # (normally, the 32-bit constant is a long, and is not allowed to
  445. # show up in the flow graphs at all)
  446. if isinstance(w_value, Constant):
  447. return Constant(r_uint(w_value.value))
  448. return ctx.appcall(r_uint, w_value)
  449. r_longlong = build_int('r_longlong', True, 64)
  450. r_ulonglong = build_int('r_ulonglong', False, 64)
  451. r_longlonglong = build_int('r_longlonglong', True, 128)
  452. longlongmax = r_longlong(LONGLONG_TEST - 1)
  453. if r_longlong is not r_int:
  454. r_int64 = r_longlong
  455. r_uint64 = r_ulonglong
  456. r_int32 = int # XXX: what about r_int
  457. r_uint32 = r_uint
  458. else:
  459. r_int64 = int # XXX: what about r_int
  460. r_uint64 = r_uint # is r_ulonglong
  461. r_int32 = build_int('r_int32', True, 32) # also needed for rposix_stat.time_t_to_FILE_TIME in the 64 bit case
  462. r_uint32 = build_int('r_uint32', False, 32)
  463. SHRT_MIN = -2**(_get_bitsize('h') - 1)
  464. SHRT_MAX = 2**(_get_bitsize('h') - 1) - 1
  465. USHRT_MAX = 2**_get_bitsize('h') - 1
  466. INT_MIN = int(-2**(_get_bitsize('i') - 1))
  467. INT_MAX = int(2**(_get_bitsize('i') - 1) - 1)
  468. UINT_MAX = r_uint(2**_get_bitsize('i') - 1)
  469. # the 'float' C type
  470. class r_singlefloat(object):
  471. """A value of the C type 'float'.
  472. This is a single-precision floating-point number.
  473. Regular 'float' values in Python and RPython are double-precision.
  474. Note that we consider this as a black box for now - the only thing
  475. you can do with it is cast it back to a regular float."""
  476. def __init__(self, floatval):
  477. import struct
  478. # simulates the loss of precision
  479. self._bytes = struct.pack("f", floatval)
  480. def __float__(self):
  481. import struct
  482. return struct.unpack("f", self._bytes)[0]
  483. def __nonzero__(self):
  484. raise TypeError("not supported on r_singlefloat instances")
  485. def __cmp__(self, other):
  486. raise TypeError("not supported on r_singlefloat instances")
  487. def __eq__(self, other):
  488. return self.__class__ is other.__class__ and self._bytes == other._bytes
  489. def __ne__(self, other):
  490. return not self.__eq__(other)
  491. def __repr__(self):
  492. return 'r_singlefloat(%s)' % (float(self),)
  493. class r_longfloat(object):
  494. """A value of the C type 'long double'.
  495. Note that we consider this as a black box for now - the only thing
  496. you can do with it is cast it back to a regular float."""
  497. def __init__(self, floatval):
  498. self.value = floatval
  499. def __float__(self):
  500. return self.value
  501. def __nonzero__(self):
  502. raise TypeError("not supported on r_longfloat instances")
  503. def __cmp__(self, other):
  504. raise TypeError("not supported on r_longfloat instances")
  505. def __eq__(self, other):
  506. return self.__class__ is other.__class__ and self.value == other.value
  507. def __ne__(self, other):
  508. return not self.__eq__(other)
  509. class For_r_singlefloat_values_Entry(extregistry.ExtRegistryEntry):
  510. _type_ = r_singlefloat
  511. def compute_annotation(self):
  512. from rpython.annotator import model as annmodel
  513. return annmodel.SomeSingleFloat()
  514. class For_r_singlefloat_type_Entry(extregistry.ExtRegistryEntry):
  515. _about_ = r_singlefloat
  516. def compute_result_annotation(self, *args_s, **kwds_s):
  517. from rpython.annotator import model as annmodel
  518. return annmodel.SomeSingleFloat()
  519. def specialize_call(self, hop):
  520. from rpython.rtyper.lltypesystem import lltype
  521. v, = hop.inputargs(lltype.Float)
  522. hop.exception_cannot_occur()
  523. # we use cast_primitive to go between Float and SingleFloat.
  524. return hop.genop('cast_primitive', [v],
  525. resulttype = lltype.SingleFloat)
  526. def int_between(n, m, p):
  527. """ check that n <= m < p. This assumes that n <= p. This is useful because
  528. the JIT special-cases it. """
  529. from rpython.rtyper.lltypesystem import lltype
  530. from rpython.rtyper.lltypesystem.lloperation import llop
  531. if not objectmodel.we_are_translated():
  532. assert n <= p
  533. return llop.int_between(lltype.Bool, n, m, p)
  534. def int_force_ge_zero(n):
  535. """ The JIT special-cases this too. """
  536. from rpython.rtyper.lltypesystem import lltype
  537. from rpython.rtyper.lltypesystem.lloperation import llop
  538. return llop.int_force_ge_zero(lltype.Signed, n)
  539. def int_c_div(x, y):
  540. """Return the result of the C-style 'x / y'. This differs from the
  541. Python-style division if (x < 0 xor y < 0). The JIT implements it
  542. with a Python-style division followed by correction code. This
  543. is not that bad, because the JIT removes the correction code if
  544. x and y are both nonnegative, and if y is any nonnegative constant
  545. then the division turns into a rshift or a mul.
  546. """
  547. from rpython.rtyper.lltypesystem import lltype
  548. from rpython.rtyper.lltypesystem.lloperation import llop
  549. return llop.int_floordiv(lltype.Signed, x, y)
  550. def int_c_mod(x, y):
  551. """Return the result of the C-style 'x % y'. This differs from the
  552. Python-style division if (x < 0 xor y < 0).
  553. """
  554. from rpython.rtyper.lltypesystem import lltype
  555. from rpython.rtyper.lltypesystem.lloperation import llop
  556. return llop.int_mod(lltype.Signed, x, y)
  557. @objectmodel.specialize.ll()
  558. def byteswap(arg):
  559. """ Convert little->big endian and the opposite
  560. """
  561. from rpython.rtyper.lltypesystem import lltype, rffi
  562. from rpython.rlib.longlong2float import longlong2float, float2longlong,\
  563. uint2singlefloat, singlefloat2uint
  564. T = lltype.typeOf(arg)
  565. if T == lltype.SingleFloat:
  566. arg = singlefloat2uint(arg)
  567. elif T == lltype.Float:
  568. arg = float2longlong(arg)
  569. elif T == lltype.LongFloat:
  570. assert False
  571. else:
  572. # we cannot do arithmetics on small ints
  573. arg = widen(arg)
  574. if rffi.sizeof(T) == 1:
  575. res = arg
  576. elif rffi.sizeof(T) == 2:
  577. a, b = arg & 0xFF, arg & 0xFF00
  578. res = (a << 8) | (b >> 8)
  579. elif rffi.sizeof(T) == 4:
  580. FF = r_uint(0xFF)
  581. arg = r_uint(arg)
  582. a, b, c, d = (arg & FF, arg & (FF << 8), arg & (FF << 16),
  583. arg & (FF << 24))
  584. res = (a << 24) | (b << 8) | (c >> 8) | (d >> 24)
  585. elif rffi.sizeof(T) == 8:
  586. FF = r_ulonglong(0xFF)
  587. arg = r_ulonglong(arg)
  588. a, b, c, d = (arg & FF, arg & (FF << 8), arg & (FF << 16),
  589. arg & (FF << 24))
  590. e, f, g, h = (arg & (FF << 32), arg & (FF << 40), arg & (FF << 48),
  591. arg & (FF << 56))
  592. res = ((a << 56) | (b << 40) | (c << 24) | (d << 8) | (e >> 8) |
  593. (f >> 24) | (g >> 40) | (h >> 56))
  594. else:
  595. assert False # unreachable code
  596. if T == lltype.SingleFloat:
  597. return uint2singlefloat(rffi.cast(rffi.UINT, res))
  598. if T == lltype.Float:
  599. return longlong2float(rffi.cast(rffi.LONGLONG, res))
  600. return rffi.cast(T, res)
  601. # String parsing support
  602. # ---------------------------
  603. def string_to_int(s, base=10):
  604. """Utility to converts a string to an integer.
  605. If base is 0, the proper base is guessed based on the leading
  606. characters of 's'. Raises ParseStringError in case of error.
  607. Raises ParseStringOverflowError in case the result does not fit.
  608. """
  609. from rpython.rlib.rstring import (
  610. NumberStringParser, ParseStringOverflowError, strip_spaces)
  611. s = literal = strip_spaces(s)
  612. p = NumberStringParser(s, literal, base, 'int')
  613. base = p.base
  614. result = 0
  615. while True:
  616. digit = p.next_digit()
  617. if digit == -1:
  618. return result
  619. if p.sign == -1:
  620. digit = -digit
  621. try:
  622. result = ovfcheck(result * base)
  623. result = ovfcheck(result + digit)
  624. except OverflowError:
  625. raise ParseStringOverflowError(p)
  626. string_to_int._elidable_function_ = True