PageRenderTime 46ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/pypy/objspace/std/floatobject.py

https://bitbucket.org/pypy/pypy/
Python | 874 lines | 800 code | 40 blank | 34 comment | 60 complexity | 403e971ad736f9d0c7ac61ddab668e23 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. import math
  2. import operator
  3. import sys
  4. from rpython.rlib import rarithmetic, rfloat
  5. from rpython.rlib.rarithmetic import LONG_BIT, intmask, ovfcheck_float_to_int
  6. from rpython.rlib.rarithmetic import int_between
  7. from rpython.rlib.rbigint import rbigint
  8. from rpython.rlib.rfloat import (
  9. DTSF_ADD_DOT_0, DTSF_STR_PRECISION, INFINITY, NAN, copysign,
  10. float_as_rbigint_ratio, formatd, isfinite, isinf, isnan)
  11. from rpython.rlib.rstring import ParseStringError
  12. from rpython.rlib.unroll import unrolling_iterable
  13. from rpython.rtyper.lltypesystem.module.ll_math import math_fmod
  14. from rpython.tool.sourcetools import func_with_new_name
  15. from pypy.interpreter.baseobjspace import W_Root
  16. from pypy.interpreter.error import OperationError, oefmt
  17. from pypy.interpreter.gateway import WrappedDefault, interp2app, unwrap_spec
  18. from pypy.interpreter.typedef import GetSetProperty, TypeDef
  19. from pypy.objspace.std import newformat
  20. from pypy.objspace.std.longobject import W_LongObject
  21. from pypy.objspace.std.util import wrap_parsestringerror
  22. def float2string(x, code, precision):
  23. # we special-case explicitly inf and nan here
  24. if isfinite(x):
  25. s = formatd(x, code, precision, DTSF_ADD_DOT_0)
  26. elif isinf(x):
  27. if x > 0.0:
  28. s = "inf"
  29. else:
  30. s = "-inf"
  31. else: # isnan(x):
  32. s = "nan"
  33. return s
  34. def detect_floatformat():
  35. from rpython.rtyper.lltypesystem import rffi, lltype
  36. buf = lltype.malloc(rffi.CCHARP.TO, 8, flavor='raw')
  37. rffi.cast(rffi.DOUBLEP, buf)[0] = 9006104071832581.0
  38. packed = rffi.charpsize2str(buf, 8)
  39. if packed == "\x43\x3f\xff\x01\x02\x03\x04\x05":
  40. double_format = 'IEEE, big-endian'
  41. elif packed == "\x05\x04\x03\x02\x01\xff\x3f\x43":
  42. double_format = 'IEEE, little-endian'
  43. else:
  44. double_format = 'unknown'
  45. lltype.free(buf, flavor='raw')
  46. #
  47. buf = lltype.malloc(rffi.CCHARP.TO, 4, flavor='raw')
  48. rffi.cast(rffi.FLOATP, buf)[0] = rarithmetic.r_singlefloat(16711938.0)
  49. packed = rffi.charpsize2str(buf, 4)
  50. if packed == "\x4b\x7f\x01\x02":
  51. float_format = 'IEEE, big-endian'
  52. elif packed == "\x02\x01\x7f\x4b":
  53. float_format = 'IEEE, little-endian'
  54. else:
  55. float_format = 'unknown'
  56. lltype.free(buf, flavor='raw')
  57. return double_format, float_format
  58. _double_format, _float_format = detect_floatformat()
  59. _alpha = zip("abcdef", range(10, 16)) + zip("ABCDEF", range(10, 16))
  60. _hex_to_int = zip("0123456789", range(10)) + _alpha
  61. _hex_to_int_iterable = unrolling_iterable(_hex_to_int)
  62. def _hex_from_char(c):
  63. for h, v in _hex_to_int_iterable:
  64. if h == c:
  65. return v
  66. return -1
  67. def _hex_digit(s, j, co_end, float_digits):
  68. if j < float_digits:
  69. i = co_end - j
  70. else:
  71. i = co_end - 1 - j
  72. return _hex_from_char(s[i])
  73. def _char_from_hex(number):
  74. return "0123456789abcdef"[number]
  75. def make_compare_func(opname):
  76. op = getattr(operator, opname)
  77. if opname == 'eq' or opname == 'ne':
  78. def do_compare_bigint(f1, b2):
  79. """f1 is a float. b2 is a bigint."""
  80. if not isfinite(f1) or math.floor(f1) != f1:
  81. return opname == 'ne'
  82. b1 = rbigint.fromfloat(f1)
  83. res = b1.eq(b2)
  84. if opname == 'ne':
  85. res = not res
  86. return res
  87. else:
  88. def do_compare_bigint(f1, b2):
  89. """f1 is a float. b2 is a bigint."""
  90. if not isfinite(f1):
  91. return op(f1, 0.0)
  92. if opname == 'gt' or opname == 'le':
  93. # 'float > long' <==> 'ceil(float) > long'
  94. # 'float <= long' <==> 'ceil(float) <= long'
  95. f1 = math.ceil(f1)
  96. else:
  97. # 'float < long' <==> 'floor(float) < long'
  98. # 'float >= long' <==> 'floor(float) >= long'
  99. f1 = math.floor(f1)
  100. b1 = rbigint.fromfloat(f1)
  101. return getattr(b1, opname)(b2)
  102. def _compare(self, space, w_other):
  103. if isinstance(w_other, W_FloatObject):
  104. return space.newbool(op(self.floatval, w_other.floatval))
  105. if space.isinstance_w(w_other, space.w_int):
  106. f1 = self.floatval
  107. i2 = space.int_w(w_other)
  108. # (double-)floats have always at least 48 bits of precision
  109. if LONG_BIT > 32 and not int_between(-1, i2 >> 48, 1):
  110. res = do_compare_bigint(f1, rbigint.fromint(i2))
  111. else:
  112. f2 = float(i2)
  113. res = op(f1, f2)
  114. return space.newbool(res)
  115. if space.isinstance_w(w_other, space.w_long):
  116. return space.newbool(do_compare_bigint(self.floatval,
  117. space.bigint_w(w_other)))
  118. return space.w_NotImplemented
  119. return func_with_new_name(_compare, 'descr_' + opname)
  120. class W_FloatObject(W_Root):
  121. """This is a implementation of the app-level 'float' type.
  122. The constructor takes an RPython float as an argument."""
  123. _immutable_fields_ = ['floatval']
  124. def __init__(self, floatval):
  125. self.floatval = floatval
  126. def unwrap(self, space):
  127. return self.floatval
  128. def int_w(self, space, allow_conversion=True):
  129. self._typed_unwrap_error(space, "integer")
  130. def bigint_w(self, space, allow_conversion=True):
  131. self._typed_unwrap_error(space, "integer")
  132. def float_w(self, space, allow_conversion=True):
  133. return self.floatval
  134. def _float_w(self, space):
  135. return self.floatval
  136. def int(self, space):
  137. # this is a speed-up only, for space.int(w_float).
  138. if (type(self) is not W_FloatObject and
  139. space.is_overloaded(self, space.w_float, '__int__')):
  140. return W_Root.int(self, space)
  141. return self.descr_trunc(space)
  142. def is_w(self, space, w_other):
  143. from rpython.rlib.longlong2float import float2longlong
  144. if not isinstance(w_other, W_FloatObject):
  145. return False
  146. if self.user_overridden_class or w_other.user_overridden_class:
  147. return self is w_other
  148. one = float2longlong(space.float_w(self))
  149. two = float2longlong(space.float_w(w_other))
  150. return one == two
  151. def immutable_unique_id(self, space):
  152. if self.user_overridden_class:
  153. return None
  154. from rpython.rlib.longlong2float import float2longlong
  155. from pypy.objspace.std.util import IDTAG_FLOAT as tag
  156. from pypy.objspace.std.util import IDTAG_SHIFT
  157. val = float2longlong(space.float_w(self))
  158. b = rbigint.fromrarith_int(val)
  159. b = b.lshift(IDTAG_SHIFT).int_or_(tag)
  160. return space.newlong_from_rbigint(b)
  161. def __repr__(self):
  162. return "<W_FloatObject(%f)>" % self.floatval
  163. @staticmethod
  164. @unwrap_spec(w_x=WrappedDefault(0.0))
  165. def descr__new__(space, w_floattype, w_x):
  166. def _string_to_float(space, w_source, string):
  167. try:
  168. return rfloat.string_to_float(string)
  169. except ParseStringError as e:
  170. raise wrap_parsestringerror(space, e, w_source)
  171. w_value = w_x # 'x' is the keyword argument name in CPython
  172. if space.lookup(w_value, "__float__") is not None:
  173. w_obj = space.float(w_value)
  174. if space.is_w(w_floattype, space.w_float):
  175. return w_obj
  176. value = space.float_w(w_obj)
  177. elif space.isinstance_w(w_value, space.w_unicode):
  178. from unicodeobject import unicode_to_decimal_w
  179. value = _string_to_float(space, w_value,
  180. unicode_to_decimal_w(space, w_value))
  181. else:
  182. try:
  183. value = space.charbuf_w(w_value)
  184. except OperationError as e:
  185. if e.match(space, space.w_TypeError):
  186. raise oefmt(
  187. space.w_TypeError,
  188. "float() argument must be a string or a number")
  189. raise
  190. value = _string_to_float(space, w_value, value)
  191. w_obj = space.allocate_instance(W_FloatObject, w_floattype)
  192. W_FloatObject.__init__(w_obj, value)
  193. return w_obj
  194. @staticmethod
  195. @unwrap_spec(kind=str)
  196. def descr___getformat__(space, w_cls, kind):
  197. if kind == "float":
  198. return space.wrap(_float_format)
  199. elif kind == "double":
  200. return space.wrap(_double_format)
  201. raise oefmt(space.w_ValueError, "only float and double are valid")
  202. @staticmethod
  203. @unwrap_spec(s=str)
  204. def descr_fromhex(space, w_cls, s):
  205. length = len(s)
  206. i = 0
  207. value = 0.0
  208. while i < length and s[i].isspace():
  209. i += 1
  210. if i == length:
  211. raise oefmt(space.w_ValueError, "invalid hex string")
  212. sign = 1
  213. if s[i] == "-":
  214. sign = -1
  215. i += 1
  216. elif s[i] == "+":
  217. i += 1
  218. if length == i:
  219. raise oefmt(space.w_ValueError, "invalid hex string")
  220. if s[i] == "i" or s[i] == "I":
  221. i += 1
  222. if length - i >= 2 and s[i:i + 2].lower() == "nf":
  223. i += 2
  224. value = rfloat.INFINITY
  225. if length - i >= 5 and s[i:i + 5].lower() == "inity":
  226. i += 5
  227. elif s[i] == "n" or s[i] == "N":
  228. i += 1
  229. if length - i >= 2 and s[i:i + 2].lower() == "an":
  230. i += 2
  231. value = rfloat.NAN
  232. else:
  233. if (s[i] == "0" and length - i > 1 and
  234. (s[i + 1] == "x" or s[i + 1] == "X")):
  235. i += 2
  236. co_start = i
  237. while i < length and _hex_from_char(s[i]) >= 0:
  238. i += 1
  239. whole_end = i
  240. if i < length and s[i] == ".":
  241. i += 1
  242. while i < length and _hex_from_char(s[i]) >= 0:
  243. i += 1
  244. co_end = i - 1
  245. else:
  246. co_end = i
  247. total_digits = co_end - co_start
  248. float_digits = co_end - whole_end
  249. if not total_digits:
  250. raise oefmt(space.w_ValueError, "invalid hex string")
  251. const_one = rfloat.DBL_MIN_EXP - rfloat.DBL_MANT_DIG + sys.maxint // 2
  252. const_two = sys.maxint // 2 + 1 - rfloat.DBL_MAX_EXP
  253. if total_digits > min(const_one, const_two) // 4:
  254. raise oefmt(space.w_ValueError, "way too long")
  255. if i < length and (s[i] == "p" or s[i] == "P"):
  256. i += 1
  257. if i == length:
  258. raise oefmt(space.w_ValueError, "invalid hex string")
  259. exp_sign = 1
  260. if s[i] == "-" or s[i] == "+":
  261. if s[i] == "-":
  262. exp_sign = -1
  263. i += 1
  264. if i == length:
  265. raise oefmt(space.w_ValueError, "invalid hex string")
  266. if not s[i].isdigit():
  267. raise oefmt(space.w_ValueError, "invalid hex string")
  268. exp = ord(s[i]) - ord('0')
  269. i += 1
  270. while i < length and s[i].isdigit():
  271. exp = exp * 10 + (ord(s[i]) - ord('0'))
  272. if exp >= (sys.maxint-9) // 10:
  273. if exp_sign > 0:
  274. exp_sign = 2 # overflow in positive numbers
  275. else:
  276. exp_sign = -2 # overflow in negative numbers
  277. i += 1
  278. if exp_sign == -1:
  279. exp = -exp
  280. elif exp_sign == -2:
  281. exp = -sys.maxint / 2
  282. elif exp_sign == 2:
  283. exp = sys.maxint / 2
  284. else:
  285. exp = 0
  286. while (total_digits and
  287. _hex_digit(s, total_digits - 1, co_end, float_digits) == 0):
  288. total_digits -= 1
  289. if not total_digits or exp <= -sys.maxint / 2:
  290. value = 0.0
  291. elif exp >= sys.maxint // 2:
  292. raise oefmt(space.w_OverflowError, "too large")
  293. else:
  294. exp -= 4 * float_digits
  295. top_exp = exp + 4 * (total_digits - 1)
  296. digit = _hex_digit(s, total_digits - 1, co_end, float_digits)
  297. while digit:
  298. top_exp += 1
  299. digit //= 2
  300. if top_exp < rfloat.DBL_MIN_EXP - rfloat.DBL_MANT_DIG:
  301. value = 0.0
  302. elif top_exp > rfloat.DBL_MAX_EXP:
  303. raise oefmt(space.w_OverflowError, "too large")
  304. else:
  305. lsb = max(top_exp, rfloat.DBL_MIN_EXP) - rfloat.DBL_MANT_DIG
  306. value = 0
  307. if exp >= lsb:
  308. for j in range(total_digits - 1, -1, -1):
  309. value = 16.0 * value + _hex_digit(s, j, co_end,
  310. float_digits)
  311. value = math.ldexp(value, exp)
  312. else:
  313. half_eps = 1 << ((lsb - exp - 1) % 4)
  314. key_digit = (lsb - exp - 1) // 4
  315. for j in range(total_digits - 1, key_digit, -1):
  316. value = 16.0 * value + _hex_digit(s, j, co_end,
  317. float_digits)
  318. digit = _hex_digit(s, key_digit, co_end, float_digits)
  319. value = 16.0 * value + (digit & (16 - 2*half_eps))
  320. if digit & half_eps:
  321. round_up = False
  322. if (digit & (3 * half_eps - 1) or
  323. (half_eps == 8 and
  324. _hex_digit(s, key_digit + 1, co_end, float_digits) & 1)):
  325. round_up = True
  326. else:
  327. for j in range(key_digit - 1, -1, -1):
  328. if _hex_digit(s, j, co_end, float_digits):
  329. round_up = True
  330. break
  331. if round_up:
  332. value += 2 * half_eps
  333. mant_dig = rfloat.DBL_MANT_DIG
  334. if (top_exp == rfloat.DBL_MAX_EXP and
  335. value == math.ldexp(2 * half_eps, mant_dig)):
  336. raise oefmt(space.w_OverflowError, "too large")
  337. value = math.ldexp(value, (exp + 4*key_digit))
  338. while i < length and s[i].isspace():
  339. i += 1
  340. if i != length:
  341. raise oefmt(space.w_ValueError, "invalid hex string")
  342. w_float = space.wrap(sign * value)
  343. return space.call_function(w_cls, w_float)
  344. def _to_float(self, space, w_obj):
  345. if isinstance(w_obj, W_FloatObject):
  346. return w_obj
  347. if space.isinstance_w(w_obj, space.w_int):
  348. return W_FloatObject(float(space.int_w(w_obj)))
  349. if space.isinstance_w(w_obj, space.w_long):
  350. return W_FloatObject(space.float_w(w_obj))
  351. def descr_repr(self, space):
  352. return space.wrap(float2string(self.floatval, 'r', 0))
  353. def descr_str(self, space):
  354. return space.wrap(float2string(self.floatval, 'g', DTSF_STR_PRECISION))
  355. def descr_hash(self, space):
  356. return space.wrap(_hash_float(space, self.floatval))
  357. def descr_format(self, space, w_spec):
  358. return newformat.run_formatter(space, w_spec, "format_float", self)
  359. def descr_coerce(self, space, w_other):
  360. w_other = self._to_float(space, w_other)
  361. if w_other is None:
  362. return space.w_NotImplemented
  363. return space.newtuple([self, w_other])
  364. def descr_nonzero(self, space):
  365. return space.newbool(self.floatval != 0.0)
  366. def descr_float(self, space):
  367. if space.is_w(space.type(self), space.w_float):
  368. return self
  369. a = self.floatval
  370. return W_FloatObject(a)
  371. def descr_long(self, space):
  372. try:
  373. return W_LongObject.fromfloat(space, self.floatval)
  374. except OverflowError:
  375. raise oefmt(space.w_OverflowError,
  376. "cannot convert float infinity to integer")
  377. except ValueError:
  378. raise oefmt(space.w_ValueError,
  379. "cannot convert float NaN to integer")
  380. def descr_trunc(self, space):
  381. try:
  382. value = ovfcheck_float_to_int(self.floatval)
  383. except OverflowError:
  384. return self.descr_long(space)
  385. else:
  386. return space.newint(value)
  387. def descr_neg(self, space):
  388. return W_FloatObject(-self.floatval)
  389. def descr_pos(self, space):
  390. return self.descr_float(space)
  391. def descr_abs(self, space):
  392. return W_FloatObject(abs(self.floatval))
  393. def descr_getnewargs(self, space):
  394. return space.newtuple([self.descr_float(space)])
  395. descr_eq = make_compare_func('eq')
  396. descr_ne = make_compare_func('ne')
  397. descr_lt = make_compare_func('lt')
  398. descr_le = make_compare_func('le')
  399. descr_gt = make_compare_func('gt')
  400. descr_ge = make_compare_func('ge')
  401. def descr_add(self, space, w_rhs):
  402. w_rhs = self._to_float(space, w_rhs)
  403. if w_rhs is None:
  404. return space.w_NotImplemented
  405. return W_FloatObject(self.floatval + w_rhs.floatval)
  406. def descr_radd(self, space, w_lhs):
  407. w_lhs = self._to_float(space, w_lhs)
  408. if w_lhs is None:
  409. return space.w_NotImplemented
  410. return W_FloatObject(w_lhs.floatval + self.floatval)
  411. def descr_sub(self, space, w_rhs):
  412. w_rhs = self._to_float(space, w_rhs)
  413. if w_rhs is None:
  414. return space.w_NotImplemented
  415. return W_FloatObject(self.floatval - w_rhs.floatval)
  416. def descr_rsub(self, space, w_lhs):
  417. w_lhs = self._to_float(space, w_lhs)
  418. if w_lhs is None:
  419. return space.w_NotImplemented
  420. return W_FloatObject(w_lhs.floatval - self.floatval)
  421. def descr_mul(self, space, w_rhs):
  422. w_rhs = self._to_float(space, w_rhs)
  423. if w_rhs is None:
  424. return space.w_NotImplemented
  425. return W_FloatObject(self.floatval * w_rhs.floatval)
  426. def descr_rmul(self, space, w_lhs):
  427. w_lhs = self._to_float(space, w_lhs)
  428. if w_lhs is None:
  429. return space.w_NotImplemented
  430. return W_FloatObject(w_lhs.floatval * self.floatval)
  431. def descr_div(self, space, w_rhs):
  432. w_rhs = self._to_float(space, w_rhs)
  433. if w_rhs is None:
  434. return space.w_NotImplemented
  435. rhs = w_rhs.floatval
  436. if rhs == 0.0:
  437. raise oefmt(space.w_ZeroDivisionError, "float division")
  438. return W_FloatObject(self.floatval / rhs)
  439. def descr_rdiv(self, space, w_lhs):
  440. w_lhs = self._to_float(space, w_lhs)
  441. if w_lhs is None:
  442. return space.w_NotImplemented
  443. selfval = self.floatval
  444. if selfval == 0.0:
  445. raise oefmt(space.w_ZeroDivisionError, "float division")
  446. return W_FloatObject(w_lhs.floatval / selfval)
  447. def descr_floordiv(self, space, w_rhs):
  448. w_rhs = self._to_float(space, w_rhs)
  449. if w_rhs is None:
  450. return space.w_NotImplemented
  451. return _divmod_w(space, self, w_rhs)[0]
  452. def descr_rfloordiv(self, space, w_lhs):
  453. w_lhs = self._to_float(space, w_lhs)
  454. if w_lhs is None:
  455. return space.w_NotImplemented
  456. return _divmod_w(space, w_lhs, self)[0]
  457. def descr_mod(self, space, w_rhs):
  458. w_rhs = self._to_float(space, w_rhs)
  459. if w_rhs is None:
  460. return space.w_NotImplemented
  461. x = self.floatval
  462. y = w_rhs.floatval
  463. if y == 0.0:
  464. raise oefmt(space.w_ZeroDivisionError, "float modulo")
  465. mod = math_fmod(x, y)
  466. if mod:
  467. # ensure the remainder has the same sign as the denominator
  468. if (y < 0.0) != (mod < 0.0):
  469. mod += y
  470. else:
  471. # the remainder is zero, and in the presence of signed zeroes
  472. # fmod returns different results across platforms; ensure
  473. # it has the same sign as the denominator; we'd like to do
  474. # "mod = y * 0.0", but that may get optimized away
  475. mod = copysign(0.0, y)
  476. return W_FloatObject(mod)
  477. def descr_rmod(self, space, w_lhs):
  478. w_lhs = self._to_float(space, w_lhs)
  479. if w_lhs is None:
  480. return space.w_NotImplemented
  481. return w_lhs.descr_mod(space, self)
  482. def descr_divmod(self, space, w_rhs):
  483. w_rhs = self._to_float(space, w_rhs)
  484. if w_rhs is None:
  485. return space.w_NotImplemented
  486. return space.newtuple(_divmod_w(space, self, w_rhs))
  487. def descr_rdivmod(self, space, w_lhs):
  488. w_lhs = self._to_float(space, w_lhs)
  489. if w_lhs is None:
  490. return space.w_NotImplemented
  491. return space.newtuple(_divmod_w(space, w_lhs, self))
  492. @unwrap_spec(w_third_arg=WrappedDefault(None))
  493. def descr_pow(self, space, w_rhs, w_third_arg):
  494. w_rhs = self._to_float(space, w_rhs)
  495. if w_rhs is None:
  496. return space.w_NotImplemented
  497. if not space.is_w(w_third_arg, space.w_None):
  498. raise oefmt(space.w_TypeError, "pow() 3rd argument not allowed "
  499. "unless all arguments are integers")
  500. x = self.floatval
  501. y = w_rhs.floatval
  502. try:
  503. result = _pow(space, x, y)
  504. except PowDomainError:
  505. raise oefmt(space.w_ValueError, "negative number cannot be raised "
  506. "to a fractional power")
  507. return W_FloatObject(result)
  508. @unwrap_spec(w_third_arg=WrappedDefault(None))
  509. def descr_rpow(self, space, w_lhs, w_third_arg):
  510. w_lhs = self._to_float(space, w_lhs)
  511. if w_lhs is None:
  512. return space.w_NotImplemented
  513. return w_lhs.descr_pow(space, self, w_third_arg)
  514. def descr_get_real(self, space):
  515. return space.float(self)
  516. def descr_get_imag(self, space):
  517. return space.wrap(0.0)
  518. def descr_conjugate(self, space):
  519. return space.float(self)
  520. def descr_is_integer(self, space):
  521. v = self.floatval
  522. if not rfloat.isfinite(v):
  523. return space.w_False
  524. return space.wrap(math.floor(v) == v)
  525. def descr_as_integer_ratio(self, space):
  526. value = self.floatval
  527. try:
  528. num, den = float_as_rbigint_ratio(value)
  529. except OverflowError:
  530. raise oefmt(space.w_OverflowError,
  531. "cannot pass infinity to as_integer_ratio()")
  532. except ValueError:
  533. raise oefmt(space.w_ValueError,
  534. "cannot pass nan to as_integer_ratio()")
  535. w_num = space.newlong_from_rbigint(num)
  536. w_den = space.newlong_from_rbigint(den)
  537. # Try to return int
  538. return space.newtuple([space.int(w_num), space.int(w_den)])
  539. def descr_hex(self, space):
  540. TOHEX_NBITS = rfloat.DBL_MANT_DIG + 3 - (rfloat.DBL_MANT_DIG + 2) % 4
  541. value = self.floatval
  542. if not isfinite(value):
  543. return self.descr_str(space)
  544. if value == 0.0:
  545. if copysign(1., value) == -1.:
  546. return space.wrap("-0x0.0p+0")
  547. else:
  548. return space.wrap("0x0.0p+0")
  549. mant, exp = math.frexp(value)
  550. shift = 1 - max(rfloat.DBL_MIN_EXP - exp, 0)
  551. mant = math.ldexp(mant, shift)
  552. mant = abs(mant)
  553. exp -= shift
  554. result = ['\0'] * ((TOHEX_NBITS - 1) // 4 + 2)
  555. result[0] = _char_from_hex(int(mant))
  556. mant -= int(mant)
  557. result[1] = "."
  558. for i in range((TOHEX_NBITS - 1) // 4):
  559. mant *= 16.0
  560. result[i + 2] = _char_from_hex(int(mant))
  561. mant -= int(mant)
  562. if exp < 0:
  563. sign = "-"
  564. else:
  565. sign = "+"
  566. exp = abs(exp)
  567. s = ''.join(result)
  568. if value < 0.0:
  569. return space.wrap("-0x%sp%s%d" % (s, sign, exp))
  570. else:
  571. return space.wrap("0x%sp%s%d" % (s, sign, exp))
  572. W_FloatObject.typedef = TypeDef("float",
  573. __doc__ = '''float(x) -> floating point number
  574. Convert a string or number to a floating point number, if possible.''',
  575. __new__ = interp2app(W_FloatObject.descr__new__),
  576. __getformat__ = interp2app(W_FloatObject.descr___getformat__, as_classmethod=True),
  577. fromhex = interp2app(W_FloatObject.descr_fromhex, as_classmethod=True),
  578. __repr__ = interp2app(W_FloatObject.descr_repr),
  579. __str__ = interp2app(W_FloatObject.descr_str),
  580. __hash__ = interp2app(W_FloatObject.descr_hash),
  581. __format__ = interp2app(W_FloatObject.descr_format),
  582. __coerce__ = interp2app(W_FloatObject.descr_coerce),
  583. __nonzero__ = interp2app(W_FloatObject.descr_nonzero),
  584. __int__ = interp2app(W_FloatObject.descr_trunc),
  585. __float__ = interp2app(W_FloatObject.descr_float),
  586. __long__ = interp2app(W_FloatObject.descr_long),
  587. __trunc__ = interp2app(W_FloatObject.descr_trunc),
  588. __neg__ = interp2app(W_FloatObject.descr_neg),
  589. __pos__ = interp2app(W_FloatObject.descr_pos),
  590. __abs__ = interp2app(W_FloatObject.descr_abs),
  591. __getnewargs__ = interp2app(W_FloatObject.descr_getnewargs),
  592. __eq__ = interp2app(W_FloatObject.descr_eq),
  593. __ne__ = interp2app(W_FloatObject.descr_ne),
  594. __lt__ = interp2app(W_FloatObject.descr_lt),
  595. __le__ = interp2app(W_FloatObject.descr_le),
  596. __gt__ = interp2app(W_FloatObject.descr_gt),
  597. __ge__ = interp2app(W_FloatObject.descr_ge),
  598. __add__ = interp2app(W_FloatObject.descr_add),
  599. __radd__ = interp2app(W_FloatObject.descr_radd),
  600. __sub__ = interp2app(W_FloatObject.descr_sub),
  601. __rsub__ = interp2app(W_FloatObject.descr_rsub),
  602. __mul__ = interp2app(W_FloatObject.descr_mul),
  603. __rmul__ = interp2app(W_FloatObject.descr_rmul),
  604. __div__ = interp2app(W_FloatObject.descr_div),
  605. __rdiv__ = interp2app(W_FloatObject.descr_rdiv),
  606. __truediv__ = interp2app(W_FloatObject.descr_div),
  607. __rtruediv__ = interp2app(W_FloatObject.descr_rdiv),
  608. __floordiv__ = interp2app(W_FloatObject.descr_floordiv),
  609. __rfloordiv__ = interp2app(W_FloatObject.descr_rfloordiv),
  610. __mod__ = interp2app(W_FloatObject.descr_mod),
  611. __rmod__ = interp2app(W_FloatObject.descr_rmod),
  612. __divmod__ = interp2app(W_FloatObject.descr_divmod),
  613. __rdivmod__ = interp2app(W_FloatObject.descr_rdivmod),
  614. __pow__ = interp2app(W_FloatObject.descr_pow),
  615. __rpow__ = interp2app(W_FloatObject.descr_rpow),
  616. real = GetSetProperty(W_FloatObject.descr_get_real),
  617. imag = GetSetProperty(W_FloatObject.descr_get_imag),
  618. conjugate = interp2app(W_FloatObject.descr_conjugate),
  619. is_integer = interp2app(W_FloatObject.descr_is_integer),
  620. as_integer_ratio = interp2app(W_FloatObject.descr_as_integer_ratio),
  621. hex = interp2app(W_FloatObject.descr_hex),
  622. )
  623. def _hash_float(space, v):
  624. if isnan(v):
  625. return 0
  626. # This is designed so that Python numbers of different types
  627. # that compare equal hash to the same value; otherwise comparisons
  628. # of mapping keys will turn out weird.
  629. fractpart, intpart = math.modf(v)
  630. if fractpart == 0.0:
  631. # This must return the same hash as an equal int or long.
  632. try:
  633. x = ovfcheck_float_to_int(intpart)
  634. # Fits in a C long == a Python int, so is its own hash.
  635. return x
  636. except OverflowError:
  637. # Convert to long and use its hash.
  638. try:
  639. w_lval = W_LongObject.fromfloat(space, v)
  640. except (OverflowError, ValueError):
  641. # can't convert to long int -- arbitrary
  642. if v < 0:
  643. return -271828
  644. else:
  645. return 314159
  646. return space.int_w(space.hash(w_lval))
  647. # The fractional part is non-zero, so we don't have to worry about
  648. # making this match the hash of some other type.
  649. # Use frexp to get at the bits in the double.
  650. # Since the VAX D double format has 56 mantissa bits, which is the
  651. # most of any double format in use, each of these parts may have as
  652. # many as (but no more than) 56 significant bits.
  653. # So, assuming sizeof(long) >= 4, each part can be broken into two
  654. # longs; frexp and multiplication are used to do that.
  655. # Also, since the Cray double format has 15 exponent bits, which is
  656. # the most of any double format in use, shifting the exponent field
  657. # left by 15 won't overflow a long (again assuming sizeof(long) >= 4).
  658. v, expo = math.frexp(v)
  659. v *= 2147483648.0 # 2**31
  660. hipart = int(v) # take the top 32 bits
  661. v = (v - hipart) * 2147483648.0 # get the next 32 bits
  662. x = intmask(hipart + int(v) + (expo << 15))
  663. return x
  664. def _divmod_w(space, w_float1, w_float2):
  665. x = w_float1.floatval
  666. y = w_float2.floatval
  667. if y == 0.0:
  668. raise oefmt(space.w_ZeroDivisionError, "float modulo")
  669. mod = math_fmod(x, y)
  670. # fmod is typically exact, so vx-mod is *mathematically* an
  671. # exact multiple of wx. But this is fp arithmetic, and fp
  672. # vx - mod is an approximation; the result is that div may
  673. # not be an exact integral value after the division, although
  674. # it will always be very close to one.
  675. div = (x - mod) / y
  676. if (mod):
  677. # ensure the remainder has the same sign as the denominator
  678. if ((y < 0.0) != (mod < 0.0)):
  679. mod += y
  680. div -= 1.0
  681. else:
  682. # the remainder is zero, and in the presence of signed zeroes
  683. # fmod returns different results across platforms; ensure
  684. # it has the same sign as the denominator; we'd like to do
  685. # "mod = wx * 0.0", but that may get optimized away
  686. mod *= mod # hide "mod = +0" from optimizer
  687. if y < 0.0:
  688. mod = -mod
  689. # snap quotient to nearest integral value
  690. if div:
  691. floordiv = math.floor(div)
  692. if (div - floordiv > 0.5):
  693. floordiv += 1.0
  694. else:
  695. # div is zero - get the same sign as the true quotient
  696. div *= div # hide "div = +0" from optimizers
  697. floordiv = div * x / y # zero w/ sign of vx/wx
  698. return [W_FloatObject(floordiv), W_FloatObject(mod)]
  699. class PowDomainError(ValueError):
  700. """Signals a negative number raised to a fractional power"""
  701. def _pow(space, x, y):
  702. # Sort out special cases here instead of relying on pow()
  703. if y == 2.0: # special case for performance:
  704. return x * x # x * x is always correct
  705. if y == 0.0:
  706. # x**0 is 1, even 0**0
  707. return 1.0
  708. if isnan(x):
  709. # nan**y = nan, unless y == 0
  710. return x
  711. if isnan(y):
  712. # x**nan = nan, unless x == 1; x**nan = x
  713. if x == 1.0:
  714. return 1.0
  715. else:
  716. return y
  717. if isinf(y):
  718. # x**inf is: 0.0 if abs(x) < 1; 1.0 if abs(x) == 1; inf if
  719. # abs(x) > 1 (including case where x infinite)
  720. #
  721. # x**-inf is: inf if abs(x) < 1; 1.0 if abs(x) == 1; 0.0 if
  722. # abs(x) > 1 (including case where v infinite)
  723. x = abs(x)
  724. if x == 1.0:
  725. return 1.0
  726. elif (y > 0.0) == (x > 1.0):
  727. return INFINITY
  728. else:
  729. return 0.0
  730. if isinf(x):
  731. # (+-inf)**w is: inf for w positive, 0 for w negative; in oth
  732. # cases, we need to add the appropriate sign if w is an odd
  733. # integer.
  734. y_is_odd = math.fmod(abs(y), 2.0) == 1.0
  735. if y > 0.0:
  736. if y_is_odd:
  737. return x
  738. else:
  739. return abs(x)
  740. else:
  741. if y_is_odd:
  742. return copysign(0.0, x)
  743. else:
  744. return 0.0
  745. if x == 0.0:
  746. if y < 0.0:
  747. raise oefmt(space.w_ZeroDivisionError,
  748. "0.0 cannot be raised to a negative power")
  749. negate_result = False
  750. # special case: "(-1.0) ** bignum" should not raise PowDomainError,
  751. # unlike "math.pow(-1.0, bignum)". See http://mail.python.org/
  752. # - pipermail/python-bugs-list/2003-March/016795.html
  753. if x < 0.0:
  754. if isnan(y):
  755. return NAN
  756. if math.floor(y) != y:
  757. raise PowDomainError
  758. # y is an exact integer, albeit perhaps a very large one.
  759. # Replace x by its absolute value and remember to negate the
  760. # pow result if y is odd.
  761. x = -x
  762. negate_result = math.fmod(abs(y), 2.0) == 1.0
  763. if x == 1.0:
  764. # (-1) ** large_integer also ends up here
  765. if negate_result:
  766. return -1.0
  767. else:
  768. return 1.0
  769. try:
  770. # We delegate to our implementation of math.pow() the error detection.
  771. z = math.pow(x, y)
  772. except OverflowError:
  773. raise oefmt(space.w_OverflowError, "float power")
  774. except ValueError:
  775. raise oefmt(space.w_ValueError, "float power")
  776. if negate_result:
  777. z = -z
  778. return z