Source: float.js

  1. /**
  2. * @namespace Sk.builtin
  3. */
  4. /**
  5. * @constructor
  6. * Sk.builtin.float_
  7. *
  8. * @description
  9. * Constructor for Python float. Also used for builtin float().
  10. *
  11. * @extends {Sk.builtin.numtype}
  12. *
  13. * @param {!(Object|number|string)} x Object or number to convert to Python float.
  14. * @return {Sk.builtin.float_} Python float
  15. */
  16. Sk.builtin.float_ = function (x) {
  17. var tmp;
  18. if (x === undefined) {
  19. return new Sk.builtin.float_(0.0);
  20. }
  21. if (!(this instanceof Sk.builtin.float_)) {
  22. return new Sk.builtin.float_(x);
  23. }
  24. if (x instanceof Sk.builtin.str) {
  25. return Sk.builtin._str_to_float(x.v);
  26. }
  27. // Floats are just numbers
  28. if (typeof x === "number" || x instanceof Sk.builtin.int_ || x instanceof Sk.builtin.lng || x instanceof Sk.builtin.float_) {
  29. tmp = Sk.builtin.asnum$(x);
  30. if (typeof tmp === "string") {
  31. return Sk.builtin._str_to_float(tmp);
  32. }
  33. this.v = tmp;
  34. return this;
  35. }
  36. // Convert booleans
  37. if (x instanceof Sk.builtin.bool) {
  38. this.v = Sk.builtin.asnum$(x);
  39. return this;
  40. }
  41. // this is a special internal case
  42. if(typeof x === "boolean") {
  43. this.v = x ? 1.0 : 0.0;
  44. return this;
  45. }
  46. if (typeof x === "string") {
  47. this.v = parseFloat(x);
  48. return this;
  49. }
  50. // try calling __float__
  51. var special = Sk.abstr.lookupSpecial(x, Sk.builtin.str.$float_);
  52. if (special != null) {
  53. // method on builtin, provide this arg
  54. return Sk.misceval.callsimArray(special, [x]);
  55. }
  56. throw new Sk.builtin.TypeError("float() argument must be a string or a number");
  57. };
  58. Sk.abstr.setUpInheritance("float", Sk.builtin.float_, Sk.builtin.numtype);
  59. Sk.builtin._str_to_float = function (str) {
  60. var tmp;
  61. if (str.match(/^-inf$/i)) {
  62. tmp = -Infinity;
  63. } else if (str.match(/^[+]?inf$/i)) {
  64. tmp = Infinity;
  65. } else if (str.match(/^[-+]?nan$/i)) {
  66. tmp = NaN;
  67. } else if (!isNaN(str)) {
  68. tmp = parseFloat(str);
  69. } else {
  70. throw new Sk.builtin.ValueError("float: Argument: " + str + " is not number");
  71. }
  72. return new Sk.builtin.float_(tmp);
  73. };
  74. Sk.builtin.float_.prototype.nb$int_ = function () {
  75. var v = this.v;
  76. if (v < 0) {
  77. v = Math.ceil(v);
  78. } else {
  79. v = Math.floor(v);
  80. }
  81. // this should take care of int/long fitting
  82. return new Sk.builtin.int_(v);
  83. };
  84. Sk.builtin.float_.prototype.nb$float_ = function() {
  85. return this;
  86. };
  87. Sk.builtin.float_.prototype.nb$lng = function () {
  88. return new Sk.builtin.lng(this.v);
  89. };
  90. /**
  91. * Checks for float subtypes, though skulpt does not allow to
  92. * extend them for now.
  93. *
  94. * Javascript function, returns Javascript object.
  95. * @param {Object} op The object to check as subtype.
  96. * @return {boolean} true if op is a subtype of Sk.builtin.float_, false otherwise
  97. */
  98. Sk.builtin.float_.PyFloat_Check = function (op) {
  99. if (op === undefined) {
  100. return false;
  101. }
  102. // this is a little bit hacky
  103. // ToDo: subclassable builtins do not require this
  104. if (Sk.builtin.checkNumber(op)) {
  105. return true;
  106. }
  107. if (Sk.builtin.checkFloat(op)) {
  108. return true;
  109. }
  110. if (Sk.builtin.issubclass(op.ob$type, Sk.builtin.float_)) {
  111. return true;
  112. }
  113. return false;
  114. };
  115. /**
  116. * Checks if ob is a Python float.
  117. *
  118. * This method is just a wrapper, but uses the correct cpython API name.
  119. *
  120. * Javascript function, returns Javascript object.
  121. * @param {Object} op The object to check.
  122. * @return {boolean} true if op is an instance of Sk.builtin.float_, false otherwise
  123. */
  124. Sk.builtin.float_.PyFloat_Check_Exact = function (op) {
  125. return Sk.builtin.checkFloat(op);
  126. };
  127. Sk.builtin.float_.PyFloat_AsDouble = function (op) {
  128. var f; // nb_float;
  129. var fo; // PyFloatObject *fo;
  130. var val;
  131. // it is a subclass or direct float
  132. if (op && Sk.builtin.float_.PyFloat_Check(op)) {
  133. return Sk.ffi.remapToJs(op);
  134. }
  135. if (op == null) {
  136. throw new Error("bad argument for internal PyFloat_AsDouble function");
  137. }
  138. // check if special method exists (nb_float is not implemented in skulpt, hence we use __float__)
  139. f = Sk.builtin.type.typeLookup(op.ob$type, Sk.builtin.str.$float_);
  140. if (f == null) {
  141. throw new Sk.builtin.TypeError("a float is required");
  142. }
  143. // call internal float method
  144. fo = Sk.misceval.callsimArray(f, [op]);
  145. // return value of __float__ must be a python float
  146. if (!Sk.builtin.float_.PyFloat_Check(fo)) {
  147. throw new Sk.builtin.TypeError("nb_float should return float object");
  148. }
  149. val = Sk.ffi.remapToJs(fo);
  150. return val;
  151. };
  152. /**
  153. * Return this instance's Javascript value.
  154. *
  155. * Javascript function, returns Javascript object.
  156. *
  157. * @return {number} This instance's value.
  158. */
  159. Sk.builtin.float_.prototype.tp$index = function () {
  160. return this.v;
  161. };
  162. /** @override */
  163. Sk.builtin.float_.prototype.tp$hash = function () {
  164. //the hash of all numbers should be an int and since javascript doesn't really
  165. //care every number can be an int.
  166. return this.nb$int_();
  167. };
  168. /**
  169. * Returns a copy of this instance.
  170. *
  171. * Javascript function, returns Python object.
  172. *
  173. * @return {Sk.builtin.float_} The copy
  174. */
  175. Sk.builtin.float_.prototype.clone = function () {
  176. return new Sk.builtin.float_(this.v);
  177. };
  178. /**
  179. * Returns this instance's value as a string formatted using fixed-point notation.
  180. *
  181. * Javascript function, returns Javascript object.
  182. *
  183. * @param {Object|number} x The numer of digits to appear after the decimal point.
  184. * @return {string} The string representation of this instance's value.
  185. */
  186. Sk.builtin.float_.prototype.toFixed = function (x) {
  187. x = Sk.builtin.asnum$(x);
  188. return this.v.toFixed(x);
  189. };
  190. /** @override */
  191. Sk.builtin.float_.prototype.nb$add = function (other) {
  192. if (other instanceof Sk.builtin.int_ || other instanceof Sk.builtin.float_) {
  193. return new Sk.builtin.float_(this.v + other.v);
  194. } else if (other instanceof Sk.builtin.lng) {
  195. return new Sk.builtin.float_(this.v + parseFloat(other.str$(10, true)));
  196. }
  197. return Sk.builtin.NotImplemented.NotImplemented$;
  198. };
  199. /** @override */
  200. Sk.builtin.float_.prototype.nb$reflected_add = function (other) {
  201. // Should not automatically call this.nb$add, as nb$add may have
  202. // been overridden by a subclass
  203. return Sk.builtin.float_.prototype.nb$add.call(this, other);
  204. };
  205. /** @override */
  206. Sk.builtin.float_.prototype.nb$subtract = function (other) {
  207. if (other instanceof Sk.builtin.int_ || other instanceof Sk.builtin.float_) {
  208. return new Sk.builtin.float_(this.v - other.v);
  209. } else if (other instanceof Sk.builtin.lng) {
  210. return new Sk.builtin.float_(this.v - parseFloat(other.str$(10, true)));
  211. }
  212. return Sk.builtin.NotImplemented.NotImplemented$;
  213. };
  214. /** @override */
  215. Sk.builtin.float_.prototype.nb$reflected_subtract = function (other) {
  216. // Should not automatically call this.nb$add, as nb$add may have
  217. // been overridden by a subclass
  218. var negative_this = this.nb$negative();
  219. return Sk.builtin.float_.prototype.nb$add.call(negative_this, other);
  220. };
  221. /** @override */
  222. Sk.builtin.float_.prototype.nb$multiply = function (other) {
  223. if (other instanceof Sk.builtin.int_ || other instanceof Sk.builtin.float_) {
  224. return new Sk.builtin.float_(this.v * other.v);
  225. } else if (other instanceof Sk.builtin.lng) {
  226. return new Sk.builtin.float_(this.v * parseFloat(other.str$(10, true)));
  227. }
  228. return Sk.builtin.NotImplemented.NotImplemented$;
  229. };
  230. /** @override */
  231. Sk.builtin.float_.prototype.nb$reflected_multiply = function (other) {
  232. // Should not automatically call this.nb$multiply, as nb$multiply may have
  233. // been overridden by a subclass
  234. return Sk.builtin.float_.prototype.nb$multiply.call(this, other);
  235. };
  236. /** @override */
  237. Sk.builtin.float_.prototype.nb$divide = function (other) {
  238. if (other instanceof Sk.builtin.int_ || other instanceof Sk.builtin.float_) {
  239. if (other.v === 0) {
  240. throw new Sk.builtin.ZeroDivisionError("integer division or modulo by zero");
  241. }
  242. if (this.v === Infinity) {
  243. if (other.v === Infinity || other.v === -Infinity) {
  244. return new Sk.builtin.float_(NaN);
  245. } else if (other.nb$isnegative()) {
  246. return new Sk.builtin.float_(-Infinity);
  247. } else {
  248. return new Sk.builtin.float_(Infinity);
  249. }
  250. }
  251. if (this.v === -Infinity) {
  252. if (other.v === Infinity || other.v === -Infinity) {
  253. return new Sk.builtin.float_(NaN);
  254. } else if (other.nb$isnegative()) {
  255. return new Sk.builtin.float_(Infinity);
  256. } else {
  257. return new Sk.builtin.float_(-Infinity);
  258. }
  259. }
  260. return new Sk.builtin.float_(this.v / other.v);
  261. }
  262. if (other instanceof Sk.builtin.lng) {
  263. if (other.longCompare(Sk.builtin.biginteger.ZERO) === 0) {
  264. throw new Sk.builtin.ZeroDivisionError("integer division or modulo by zero");
  265. }
  266. if (this.v === Infinity) {
  267. if (other.nb$isnegative()) {
  268. return new Sk.builtin.float_(-Infinity);
  269. } else {
  270. return new Sk.builtin.float_(Infinity);
  271. }
  272. }
  273. if (this.v === -Infinity) {
  274. if (other.nb$isnegative()) {
  275. return new Sk.builtin.float_(Infinity);
  276. } else {
  277. return new Sk.builtin.float_(-Infinity);
  278. }
  279. }
  280. return new Sk.builtin.float_(this.v / parseFloat(other.str$(10, true)));
  281. }
  282. return Sk.builtin.NotImplemented.NotImplemented$;
  283. };
  284. /** @override */
  285. Sk.builtin.float_.prototype.nb$reflected_divide = function (other) {
  286. if (other instanceof Sk.builtin.int_ ||
  287. other instanceof Sk.builtin.lng) {
  288. other = new Sk.builtin.float_(other);
  289. }
  290. if (other instanceof Sk.builtin.float_) {
  291. return other.nb$divide(this);
  292. }
  293. return Sk.builtin.NotImplemented.NotImplemented$;
  294. };
  295. /** @override */
  296. Sk.builtin.float_.prototype.nb$floor_divide = function (other) {
  297. if (other instanceof Sk.builtin.int_ || other instanceof Sk.builtin.float_) {
  298. if (this.v === Infinity || this.v === -Infinity) {
  299. return new Sk.builtin.float_(NaN);
  300. }
  301. if (other.v === 0) {
  302. throw new Sk.builtin.ZeroDivisionError("integer division or modulo by zero");
  303. }
  304. if (other.v === Infinity) {
  305. if (this.nb$isnegative()) {
  306. return new Sk.builtin.float_(-1);
  307. } else {
  308. return new Sk.builtin.float_(0);
  309. }
  310. }
  311. if (other.v === -Infinity) {
  312. if (this.nb$isnegative() || !this.nb$nonzero()) {
  313. return new Sk.builtin.float_(0);
  314. } else {
  315. return new Sk.builtin.float_(-1);
  316. }
  317. }
  318. return new Sk.builtin.float_(Math.floor(this.v / other.v));
  319. }
  320. if (other instanceof Sk.builtin.lng) {
  321. if (other.longCompare(Sk.builtin.biginteger.ZERO) === 0) {
  322. throw new Sk.builtin.ZeroDivisionError("integer division or modulo by zero");
  323. }
  324. if (this.v === Infinity || this.v === -Infinity) {
  325. return new Sk.builtin.float_(NaN);
  326. }
  327. return new Sk.builtin.float_(Math.floor(this.v / parseFloat(other.str$(10, true))));
  328. }
  329. return Sk.builtin.NotImplemented.NotImplemented$;
  330. };
  331. /** @override */
  332. Sk.builtin.float_.prototype.nb$reflected_floor_divide = function (other) {
  333. if (other instanceof Sk.builtin.int_ ||
  334. other instanceof Sk.builtin.lng) {
  335. other = new Sk.builtin.float_(other);
  336. }
  337. if (other instanceof Sk.builtin.float_) {
  338. return other.nb$floor_divide(this);
  339. }
  340. return Sk.builtin.NotImplemented.NotImplemented$;
  341. };
  342. /** @override */
  343. Sk.builtin.float_.prototype.nb$remainder = function (other) {
  344. var thisAsLong;
  345. var op2;
  346. var tmp;
  347. var result;
  348. if (other instanceof Sk.builtin.int_ || other instanceof Sk.builtin.float_) {
  349. if (other.v === 0) {
  350. throw new Sk.builtin.ZeroDivisionError("integer division or modulo by zero");
  351. }
  352. if (this.v === 0) {
  353. return new Sk.builtin.float_(0);
  354. }
  355. if (other.v === Infinity) {
  356. if (this.v === Infinity || this.v === -Infinity) {
  357. return new Sk.builtin.float_(NaN);
  358. } else if (this.nb$ispositive()) {
  359. return new Sk.builtin.float_(this.v);
  360. } else {
  361. return new Sk.builtin.float_(Infinity);
  362. }
  363. }
  364. // Javacript logic on negatives doesn't work for Python... do this instead
  365. tmp = this.v % other.v;
  366. if (this.v < 0) {
  367. if (other.v > 0 && tmp < 0) {
  368. tmp = tmp + other.v;
  369. }
  370. } else {
  371. if (other.v < 0 && tmp !== 0) {
  372. tmp = tmp + other.v;
  373. }
  374. }
  375. if (other.v < 0 && tmp === 0) {
  376. tmp = -0.0; // otherwise the sign gets lost by javascript modulo
  377. } else if (tmp === 0 && Infinity/tmp === -Infinity) {
  378. tmp = 0.0;
  379. }
  380. return new Sk.builtin.float_(tmp);
  381. }
  382. if (other instanceof Sk.builtin.lng) {
  383. if (other.longCompare(Sk.builtin.biginteger.ZERO) === 0) {
  384. throw new Sk.builtin.ZeroDivisionError("integer division or modulo by zero");
  385. }
  386. if (this.v === 0) {
  387. return new Sk.builtin.float_(0);
  388. }
  389. op2 = parseFloat(other.str$(10, true));
  390. tmp = this.v % op2;
  391. if (tmp < 0) {
  392. if (op2 > 0 && tmp !== 0) {
  393. tmp = tmp + op2;
  394. }
  395. } else {
  396. if (op2 < 0 && tmp !== 0) {
  397. tmp = tmp + op2;
  398. }
  399. }
  400. if (other.nb$isnegative() && tmp === 0) {
  401. tmp = -0.0; // otherwise the sign gets lost by javascript modulo
  402. } else if (tmp === 0 && Infinity/tmp === -Infinity) {
  403. tmp = 0.0;
  404. }
  405. return new Sk.builtin.float_(tmp);
  406. }
  407. return Sk.builtin.NotImplemented.NotImplemented$;
  408. };
  409. /** @override */
  410. Sk.builtin.float_.prototype.nb$reflected_remainder = function (other) {
  411. if (other instanceof Sk.builtin.int_ ||
  412. other instanceof Sk.builtin.lng) {
  413. other = new Sk.builtin.float_(other);
  414. }
  415. if (other instanceof Sk.builtin.float_) {
  416. return other.nb$remainder(this);
  417. }
  418. return Sk.builtin.NotImplemented.NotImplemented$;
  419. };
  420. /** @override */
  421. Sk.builtin.float_.prototype.nb$divmod = function (other) {
  422. if (other instanceof Sk.builtin.int_ ||
  423. other instanceof Sk.builtin.lng) {
  424. other = new Sk.builtin.float_(other);
  425. }
  426. if (other instanceof Sk.builtin.float_) {
  427. return new Sk.builtin.tuple([
  428. this.nb$floor_divide(other),
  429. this.nb$remainder(other)
  430. ]);
  431. }
  432. return Sk.builtin.NotImplemented.NotImplemented$;
  433. };
  434. /** @override */
  435. Sk.builtin.float_.prototype.nb$reflected_divmod = function (other) {
  436. if (other instanceof Sk.builtin.int_ ||
  437. other instanceof Sk.builtin.lng) {
  438. other = new Sk.builtin.float_(other);
  439. }
  440. if (other instanceof Sk.builtin.float_) {
  441. return new Sk.builtin.tuple([
  442. other.nb$floor_divide(this),
  443. other.nb$remainder(this)
  444. ]);
  445. }
  446. return Sk.builtin.NotImplemented.NotImplemented$;
  447. };
  448. /** @override */
  449. Sk.builtin.float_.prototype.nb$power = function (other, mod) {
  450. var thisAsLong;
  451. var result;
  452. if (other instanceof Sk.builtin.int_ || other instanceof Sk.builtin.float_) {
  453. if (this.v < 0 && other.v % 1 !== 0) {
  454. throw new Sk.builtin.NegativePowerError("cannot raise a negative number to a fractional power");
  455. }
  456. if (this.v === 0 && other.v < 0) {
  457. throw new Sk.builtin.NegativePowerError("cannot raise zero to a negative power");
  458. }
  459. result = new Sk.builtin.float_(Math.pow(this.v, other.v));
  460. if ((Math.abs(result.v) === Infinity) &&
  461. (Math.abs(this.v) !== Infinity) &&
  462. (Math.abs(other.v) !== Infinity)) {
  463. throw new Sk.builtin.OverflowError("Numerical result out of range");
  464. }
  465. return result;
  466. }
  467. if (other instanceof Sk.builtin.lng) {
  468. if (this.v === 0 && other.longCompare(Sk.builtin.biginteger.ZERO) < 0) {
  469. throw new Sk.builtin.NegativePowerError("cannot raise zero to a negative power");
  470. }
  471. return new Sk.builtin.float_(Math.pow(this.v, parseFloat(other.str$(10, true))));
  472. }
  473. return Sk.builtin.NotImplemented.NotImplemented$;
  474. };
  475. /** @override */
  476. Sk.builtin.float_.prototype.nb$reflected_power = function (n, mod) {
  477. if (n instanceof Sk.builtin.int_ ||
  478. n instanceof Sk.builtin.lng) {
  479. n = new Sk.builtin.float_(n);
  480. }
  481. if (n instanceof Sk.builtin.float_) {
  482. return n.nb$power(this, mod);
  483. }
  484. return Sk.builtin.NotImplemented.NotImplemented$;
  485. };
  486. /** @override */
  487. Sk.builtin.float_.prototype.nb$abs = function () {
  488. return new Sk.builtin.float_(Math.abs(this.v));
  489. };
  490. /** @override */
  491. Sk.builtin.float_.prototype.nb$inplace_add = Sk.builtin.float_.prototype.nb$add;
  492. /** @override */
  493. Sk.builtin.float_.prototype.nb$inplace_subtract = Sk.builtin.float_.prototype.nb$subtract;
  494. /** @override */
  495. Sk.builtin.float_.prototype.nb$inplace_multiply = Sk.builtin.float_.prototype.nb$multiply;
  496. /** @override */
  497. Sk.builtin.float_.prototype.nb$inplace_divide = Sk.builtin.float_.prototype.nb$divide;
  498. /** @override */
  499. Sk.builtin.float_.prototype.nb$inplace_remainder = Sk.builtin.float_.prototype.nb$remainder;
  500. /** @override */
  501. Sk.builtin.float_.prototype.nb$inplace_floor_divide = Sk.builtin.float_.prototype.nb$floor_divide;
  502. /** @override */
  503. Sk.builtin.float_.prototype.nb$inplace_power = Sk.builtin.float_.prototype.nb$power;
  504. /**
  505. * @override
  506. *
  507. * @return {Sk.builtin.float_} A copy of this instance with the value negated.
  508. */
  509. Sk.builtin.float_.prototype.nb$negative = function () {
  510. return new Sk.builtin.float_(-this.v);
  511. };
  512. /** @override */
  513. Sk.builtin.float_.prototype.nb$positive = function () {
  514. return this.clone();
  515. };
  516. /** @override */
  517. Sk.builtin.float_.prototype.nb$nonzero = function () {
  518. return this.v !== 0;
  519. };
  520. /** @override */
  521. Sk.builtin.float_.prototype.nb$isnegative = function () {
  522. return this.v < 0;
  523. };
  524. /** @override */
  525. Sk.builtin.float_.prototype.nb$ispositive = function () {
  526. return this.v >= 0;
  527. };
  528. /**
  529. * Compare this instance's value to another Python object's value.
  530. *
  531. * Returns NotImplemented if comparison between float and other type is unsupported.
  532. *
  533. * Javscript function, returns Javascript object or Sk.builtin.NotImplemented.
  534. *
  535. * @return {(number|Sk.builtin.NotImplemented)} negative if this < other, zero if this == other, positive if this > other
  536. */
  537. Sk.builtin.float_.prototype.numberCompare = function (other) {
  538. var diff;
  539. var tmp;
  540. var thisAsLong;
  541. if (other instanceof Sk.builtin.int_ || other instanceof Sk.builtin.float_) {
  542. if (this.v == Infinity && other.v == Infinity) {
  543. return 0;
  544. }
  545. if (this.v == -Infinity && other.v == -Infinity) {
  546. return 0;
  547. }
  548. return this.v - other.v;
  549. }
  550. if (other instanceof Sk.builtin.lng) {
  551. if (this.v % 1 === 0) {
  552. thisAsLong = new Sk.builtin.lng(this.v);
  553. tmp = thisAsLong.longCompare(other);
  554. return tmp;
  555. }
  556. diff = this.nb$subtract(other);
  557. if (diff instanceof Sk.builtin.float_) {
  558. return diff.v;
  559. } else if (diff instanceof Sk.builtin.lng) {
  560. return diff.longCompare(Sk.builtin.biginteger.ZERO);
  561. }
  562. }
  563. return Sk.builtin.NotImplemented.NotImplemented$;
  564. };
  565. // Despite what jshint may want us to do, these two functions need to remain
  566. // as == and != Unless you modify the logic of numberCompare do not change
  567. // these.
  568. /** @override */
  569. Sk.builtin.float_.prototype.ob$eq = function (other) {
  570. if (other instanceof Sk.builtin.int_ ||
  571. other instanceof Sk.builtin.lng ||
  572. other instanceof Sk.builtin.float_) {
  573. return new Sk.builtin.bool(this.numberCompare(other) == 0); //jshint ignore:line
  574. } else if (other instanceof Sk.builtin.none) {
  575. return Sk.builtin.bool.false$;
  576. } else {
  577. return Sk.builtin.NotImplemented.NotImplemented$;
  578. }
  579. };
  580. /** @override */
  581. Sk.builtin.float_.prototype.ob$ne = function (other) {
  582. if (other instanceof Sk.builtin.int_ ||
  583. other instanceof Sk.builtin.lng ||
  584. other instanceof Sk.builtin.float_) {
  585. return new Sk.builtin.bool(this.numberCompare(other) != 0); //jshint ignore:line
  586. } else if (other instanceof Sk.builtin.none) {
  587. return Sk.builtin.bool.true$;
  588. } else {
  589. return Sk.builtin.NotImplemented.NotImplemented$;
  590. }
  591. };
  592. /** @override */
  593. Sk.builtin.float_.prototype.ob$lt = function (other) {
  594. if (other instanceof Sk.builtin.int_ ||
  595. other instanceof Sk.builtin.lng ||
  596. other instanceof Sk.builtin.float_) {
  597. return new Sk.builtin.bool(this.numberCompare(other) < 0);
  598. } else {
  599. return Sk.builtin.NotImplemented.NotImplemented$;
  600. }
  601. };
  602. /** @override */
  603. Sk.builtin.float_.prototype.ob$le = function (other) {
  604. if (other instanceof Sk.builtin.int_ ||
  605. other instanceof Sk.builtin.lng ||
  606. other instanceof Sk.builtin.float_) {
  607. return new Sk.builtin.bool(this.numberCompare(other) <= 0);
  608. } else {
  609. return Sk.builtin.NotImplemented.NotImplemented$;
  610. }
  611. };
  612. /** @override */
  613. Sk.builtin.float_.prototype.ob$gt = function (other) {
  614. if (other instanceof Sk.builtin.int_ ||
  615. other instanceof Sk.builtin.lng ||
  616. other instanceof Sk.builtin.float_) {
  617. return new Sk.builtin.bool(this.numberCompare(other) > 0);
  618. } else {
  619. return Sk.builtin.NotImplemented.NotImplemented$;
  620. }
  621. };
  622. /** @override */
  623. Sk.builtin.float_.prototype.ob$ge = function (other) {
  624. if (other instanceof Sk.builtin.int_ ||
  625. other instanceof Sk.builtin.lng ||
  626. other instanceof Sk.builtin.float_) {
  627. return new Sk.builtin.bool(this.numberCompare(other) >= 0);
  628. } else {
  629. return Sk.builtin.NotImplemented.NotImplemented$;
  630. }
  631. };
  632. /**
  633. * Round this instance to a given number of digits, or zero if omitted.
  634. *
  635. * Implements `__round__` dunder method.
  636. *
  637. * Javascript function, returns Python object.
  638. *
  639. * @param {Sk.builtin.int_} self This instance.
  640. * @param {Object|number=} ndigits The number of digits after the decimal point to which to round.
  641. * @return {Sk.builtin.float_|Sk.builtin.int_} The rounded float.
  642. */
  643. Sk.builtin.float_.prototype.round$ = function (self, ndigits) {
  644. Sk.builtin.pyCheckArgsLen("__round__", arguments.length, 1, 2);
  645. var result, multiplier, number, num10, rounded, bankRound, ndigs;
  646. if ((ndigits !== undefined) && !Sk.misceval.isIndex(ndigits)) {
  647. throw new Sk.builtin.TypeError("'" + Sk.abstr.typeName(ndigits) + "' object cannot be interpreted as an index");
  648. }
  649. number = Sk.builtin.asnum$(self);
  650. if (ndigits === undefined) {
  651. ndigs = 0;
  652. } else {
  653. ndigs = Sk.misceval.asIndex(ndigits);
  654. }
  655. if (Sk.__future__.bankers_rounding) {
  656. num10 = number * Math.pow(10, ndigs);
  657. rounded = Math.round(num10);
  658. bankRound = (((((num10>0)?num10:(-num10))%1)===0.5)?(((0===(rounded%2)))?rounded:(rounded-1)):rounded);
  659. result = bankRound / Math.pow(10, ndigs);
  660. if (ndigits === undefined) {
  661. return new Sk.builtin.int_(result);
  662. } else {
  663. return new Sk.builtin.float_(result);
  664. }
  665. } else {
  666. multiplier = Math.pow(10, ndigs);
  667. result = Math.round(number * multiplier) / multiplier;
  668. return new Sk.builtin.float_(result);
  669. }
  670. };
  671. Sk.builtin.float_.prototype.__format__= function (obj, format_spec) {
  672. var formatstr;
  673. Sk.builtin.pyCheckArgsLen("__format__", arguments.length, 2, 2);
  674. if (!Sk.builtin.checkString(format_spec)) {
  675. if (Sk.__future__.exceptions) {
  676. throw new Sk.builtin.TypeError("format() argument 2 must be str, not " + Sk.abstr.typeName(format_spec));
  677. } else {
  678. throw new Sk.builtin.TypeError("format expects arg 2 to be string or unicode, not " + Sk.abstr.typeName(format_spec));
  679. }
  680. } else {
  681. formatstr = Sk.ffi.remapToJs(format_spec);
  682. if (formatstr !== "") {
  683. throw new Sk.builtin.NotImplementedError("format spec is not yet implemented");
  684. }
  685. }
  686. return new Sk.builtin.str(obj);
  687. };
  688. Sk.builtin.float_.prototype.conjugate = new Sk.builtin.func(function (self) {
  689. return new Sk.builtin.float_(self.v);
  690. });
  691. /** @override */
  692. Sk.builtin.float_.prototype["$r"] = function () {
  693. return new Sk.builtin.str(this.str$(10, true));
  694. };
  695. /**
  696. * Return the string representation of this instance.
  697. *
  698. * Javascript function, returns Python object.
  699. *
  700. * @return {Sk.builtin.str} The Python string representation of this instance.
  701. */
  702. Sk.builtin.float_.prototype.tp$str = function () {
  703. return new Sk.builtin.str(this.str$(10, true));
  704. };
  705. /**
  706. * Convert this instance's value to a Javascript string.
  707. *
  708. * Javascript function, returns Javascript object.
  709. *
  710. * @param {number} base The base of the value.
  711. * @param {boolean} sign true if the value should be signed, false otherwise.
  712. * @return {string} The Javascript string representation of this instance.
  713. */
  714. Sk.builtin.float_.prototype.str$ = function (base, sign) {
  715. var post;
  716. var pre;
  717. var idx;
  718. var tmp;
  719. var work;
  720. if (isNaN(this.v)) {
  721. return "nan";
  722. }
  723. if (sign === undefined) {
  724. sign = true;
  725. }
  726. if (this.v == Infinity) {
  727. return "inf";
  728. }
  729. if (this.v == -Infinity && sign) {
  730. return "-inf";
  731. }
  732. if (this.v == -Infinity && !sign) {
  733. return "inf";
  734. }
  735. work = sign ? this.v : Math.abs(this.v);
  736. if (base === undefined || base === 10) {
  737. tmp = work.toPrecision(12);
  738. // transform fractions with 4 or more leading zeroes into exponents
  739. idx = tmp.indexOf(".");
  740. pre = work.toString().slice(0, idx);
  741. post = work.toString().slice(idx);
  742. if (pre.match(/^-?0$/) && post.slice(1).match(/^0{4,}/)) {
  743. if (tmp.length < 12) {
  744. tmp = work.toExponential();
  745. } else {
  746. tmp = work.toExponential(11);
  747. }
  748. }
  749. if (tmp.indexOf("e") < 0 && tmp.indexOf(".") >= 0) {
  750. while (tmp.charAt(tmp.length-1) == "0") {
  751. tmp = tmp.substring(0,tmp.length-1);
  752. }
  753. if (tmp.charAt(tmp.length-1) == ".") {
  754. tmp = tmp + "0";
  755. }
  756. }
  757. tmp = tmp.replace(new RegExp("\\.0+e"), "e", "i");
  758. // make exponent two digits instead of one (ie e+09 not e+9)
  759. tmp = tmp.replace(/(e[-+])([1-9])$/, "$10$2");
  760. // remove trailing zeroes before the exponent
  761. tmp = tmp.replace(/0+(e.*)/, "$1");
  762. } else {
  763. tmp = work.toString(base);
  764. }
  765. // restore negative zero sign
  766. if(this.v === 0 && 1/this.v === -Infinity) {
  767. tmp = "-" + tmp;
  768. }
  769. if (tmp.indexOf(".") < 0 && tmp.indexOf("E") < 0 && tmp.indexOf("e") < 0) {
  770. tmp = tmp + ".0";
  771. }
  772. return tmp;
  773. };