complex.js 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189
  1. /**
  2. * hypot is a ESCMA6 function and maybe not available across all browsers
  3. */
  4. Math.hypot = Math.hypot || function() {
  5. var y = 0;
  6. var length = arguments.length;
  7. for (var i = 0; i < length; i++) {
  8. if (arguments[i] === Infinity || arguments[i] === -Infinity) {
  9. return Infinity;
  10. }
  11. y += arguments[i] * arguments[i];
  12. }
  13. return Math.sqrt(y);
  14. };
  15. /**
  16. * complex_new see https://hg.python.org/cpython/file/f0e2caad4200/Objects/complexobject.c#l911
  17. * @constructor
  18. * @param {Object} real part of the complex number
  19. * @param {?Object=} imag part of the complex number
  20. * @this {Sk.builtin.object}
  21. *
  22. * Prefering here == instead of ===, otherwise also undefined has to be matched explicitly
  23. *
  24. * FIXME: it seems that we somehow need to call __float__/__int__ if arguments provide those methods
  25. *
  26. */
  27. Sk.builtin.complex = function (real, imag) {
  28. Sk.builtin.pyCheckArgs("complex", arguments, 0, 2);
  29. var r, i, tmp; // PyObject
  30. var nbr, nbi; // real, imag as numbers
  31. var own_r = false;
  32. var cr = {}; // PyComplexObject
  33. var ci = {}; // PyComplexObject
  34. var cr_is_complex = false;
  35. var ci_is_complex = false;
  36. // not sure why this is required
  37. if (!(this instanceof Sk.builtin.complex)) {
  38. return new Sk.builtin.complex(real, imag);
  39. }
  40. // check if kwargs
  41. // ToDo: this is only a temporary replacement
  42. r = real == null ? Sk.builtin.bool.false$ : real; // r = Py_False;
  43. i = imag;
  44. // handle case if passed in arguments are of type complex
  45. if (r instanceof Sk.builtin.complex && i == null) {
  46. return real;
  47. }
  48. if (r != null && Sk.builtin.checkString(r)) {
  49. if(i != null) {
  50. throw new Sk.builtin.TypeError("complex() can't take second arg if first is a string");
  51. }
  52. return Sk.builtin.complex.complex_subtype_from_string(r);
  53. }
  54. if (i != null && Sk.builtin.checkString(i)) {
  55. throw new Sk.builtin.TypeError("complex() second arg can't be a string");
  56. }
  57. // try_complex_special_method
  58. tmp = Sk.builtin.complex.try_complex_special_method(r);
  59. if (tmp != null && tmp !== Sk.builtin.NotImplemented.NotImplemented$) {
  60. if (!Sk.builtin.checkComplex(tmp)) {
  61. throw new Sk.builtin.TypeError("__complex__ should return a complex object");
  62. }
  63. r = tmp;
  64. }
  65. // this check either returns a javascript number or the passed object
  66. // but it actually, should check for r->ob_type->tp_as_number
  67. // this check is useless
  68. nbr = Sk.builtin.asnum$(r);
  69. if (i != null) {
  70. nbi = Sk.builtin.asnum$(i);
  71. }
  72. // this function mimics the tp_as_number->nb_float check in cpython
  73. var nb_float = function(op) {
  74. if(Sk.builtin.checkNumber(op)) {
  75. return true;
  76. }
  77. if(Sk.builtin.type.typeLookup(op.ob$type, "__float__") !== undefined) {
  78. return true;
  79. }
  80. };
  81. // check for valid arguments
  82. if (nbr == null || (!nb_float(r) && !Sk.builtin.checkComplex(r)) || ((i != null) && (nbi == null || (!nb_float(i) && !Sk.builtin.checkComplex(i))))) {
  83. throw new Sk.builtin.TypeError("complex() argument must be a string or number");
  84. }
  85. /* If we get this far, then the "real" and "imag" parts should
  86. both be treated as numbers, and the constructor should return a
  87. complex number equal to (real + imag*1j).
  88. Note that we do NOT assume the input to already be in canonical
  89. form; the "real" and "imag" parts might themselves be complex
  90. numbers, which slightly complicates the code below. */
  91. if (Sk.builtin.complex._complex_check(r)) {
  92. /* Note that if r is of a complex subtype, we're only
  93. retaining its real & imag parts here, and the return
  94. value is (properly) of the builtin complex type. */
  95. cr.real = r.real.v;
  96. cr.imag = r.imag.v;
  97. cr_is_complex = true;
  98. } else {
  99. /* The "real" part really is entirely real, and contributes
  100. nothing in the imaginary direction.
  101. Just treat it as a double. */
  102. tmp = Sk.builtin.float_.PyFloat_AsDouble(r); // tmp = PyNumber_Float(r);
  103. if (tmp == null) {
  104. return null;
  105. }
  106. cr.real = tmp;
  107. cr.imag = 0.0;
  108. }
  109. if (i == null) {
  110. ci.real = 0.0;
  111. } else if (Sk.builtin.complex._complex_check(i)) {
  112. ci.real = i.real.v;
  113. ci.imag = i.imag.v;
  114. ci_is_complex = true;
  115. } else {
  116. /* The "imag" part really is entirely imaginary, and
  117. contributes nothing in the real direction.
  118. Just treat it as a double. */
  119. tmp = Sk.builtin.float_.PyFloat_AsDouble(i);
  120. if (tmp == null) {
  121. return null;
  122. }
  123. ci.real = tmp;
  124. ci.imag = 0.0;
  125. }
  126. /* If the input was in canonical form, then the "real" and "imag"
  127. parts are real numbers, so that ci.imag and cr.imag are zero.
  128. We need this correction in case they were not real numbers. */
  129. if (ci_is_complex === true) {
  130. cr.real -= ci.imag;
  131. }
  132. if (cr_is_complex === true) {
  133. ci.real += cr.imag;
  134. }
  135. // adjust for negated imaginary literal
  136. if (cr.real === 0 && (ci.real < 0 || Sk.builtin.complex._isNegativeZero(ci.real))) {
  137. cr.real = -0;
  138. }
  139. // save them as properties
  140. this.real = new Sk.builtin.float_(cr.real);
  141. this.imag = new Sk.builtin.float_(ci.real);
  142. this.__class__ = Sk.builtin.complex;
  143. return this;
  144. };
  145. Sk.abstr.setUpInheritance("complex", Sk.builtin.complex, Sk.builtin.numtype);
  146. //Sk.builtin.complex.co_kwargs = true;
  147. Sk.builtin.complex.prototype.nb$int_ = function () {
  148. throw new Sk.builtin.TypeError("can't convert complex to int");
  149. };
  150. Sk.builtin.complex.prototype.nb$float_ = function() {
  151. throw new Sk.builtin.TypeError("can't convert complex to float");
  152. };
  153. Sk.builtin.complex.prototype.nb$lng = function () {
  154. throw new Sk.builtin.TypeError("can't convert complex to long");
  155. };
  156. Sk.builtin.complex.prototype.__doc__ = new Sk.builtin.str("complex(real[, imag]) -> complex number\n\nCreate a complex number from a real part and an optional imaginary part.\nThis is equivalent to (real + imag*1j) where imag defaults to 0.");
  157. Sk.builtin.complex._isNegativeZero = function (val) {
  158. if (val !== 0) {
  159. return false;
  160. }
  161. return 1/val === -Infinity;
  162. };
  163. /**
  164. * Internal method to check if op has __complex__
  165. */
  166. Sk.builtin.complex.try_complex_special_method = function (op) {
  167. var complexstr = new Sk.builtin.str("__complex__");
  168. var f; // PyObject
  169. var res;
  170. // return early
  171. if (op == null) {
  172. return null;
  173. }
  174. // the lookup special method does already all the magic
  175. f = Sk.abstr.lookupSpecial(op, "__complex__");
  176. if (f != null) {
  177. // method on builtin, provide this arg
  178. res = Sk.misceval.callsim(f, op);
  179. return res;
  180. }
  181. return null;
  182. };
  183. /**
  184. Check if given argument is number or complex and always
  185. returns complex type.
  186. */
  187. Sk.builtin.complex.check_number_or_complex = function (other) {
  188. /* exit early */
  189. if (!Sk.builtin.checkNumber(other) && other.tp$name !== "complex") {
  190. throw new Sk.builtin.TypeError("unsupported operand type(s) for +: 'complex' and '" + Sk.abstr.typeName(other) + "'");
  191. }
  192. /* converting to complex allows us to use always only one formula */
  193. if (Sk.builtin.checkNumber(other)) {
  194. other = new Sk.builtin.complex(other); // create complex
  195. }
  196. return other;
  197. };
  198. /**
  199. Parses a string repr of a complex number
  200. */
  201. Sk.builtin.complex.complex_subtype_from_string = function (val) {
  202. var index;
  203. var start;
  204. var val_wws; // val with removed beginning ws and (
  205. var x = 0.0, y = 0.0; // real, imag parts
  206. var got_bracket = false; // flag for braces
  207. var len; // total length of val
  208. var match; // regex result
  209. // first check if val is javascript string or python string
  210. if (Sk.builtin.checkString(val)) {
  211. val = Sk.ffi.remapToJs(val);
  212. } else if (typeof val !== "string") {
  213. throw new TypeError("provided unsupported string-alike argument");
  214. }
  215. /* This is an python specific error, this does not do any harm in js, but we want
  216. * to be as close to the orginial impl. as possible.
  217. *
  218. * Check also for empty strings. They are not allowed.
  219. */
  220. if (val.indexOf("\0") !== -1 || val.length === 0 || val === "") {
  221. throw new Sk.builtin.ValueError("complex() arg is a malformed string");
  222. }
  223. // transform to unicode
  224. // ToDo: do we need this?
  225. index = 0; // first char
  226. // do some replacements for javascript floats
  227. val = val.replace(/inf|infinity/gi, "Infinity");
  228. val = val.replace(/nan/gi, "NaN");
  229. /* position on first nonblank */
  230. start = 0;
  231. while (val[index] === " ") {
  232. index++;
  233. }
  234. if (val[index] === "(") {
  235. /* skip over possible bracket from repr(). */
  236. got_bracket = true;
  237. index++;
  238. while (val[index] === " ") {
  239. index++;
  240. }
  241. }
  242. /* a valid complex string usually takes one of the three forms:
  243. <float> - real part only
  244. <float>j - imaginary part only
  245. <float><signed-float>j - real and imaginary parts
  246. where <float> represents any numeric string that's accepted by the
  247. float constructor (including 'nan', 'inf', 'infinity', etc.), and
  248. <signed-float> is any string of the form <float> whose first character
  249. is '+' or '-'.
  250. For backwards compatibility, the extra forms
  251. <float><sign>j
  252. <sign>j
  253. j
  254. are also accepted, though support for these forms my be removed from
  255. a future version of Python.
  256. * This is a complete regular expression for matching any valid python floats, e.g.:
  257. * - 1.0
  258. * - 0.
  259. * - .1
  260. * - nan/inf/infinity
  261. * - +-1.0
  262. * - +3.E-3
  263. *
  264. * In order to work, this pattern requires only lower case characters
  265. * There is case insensitive group option in js.
  266. *
  267. * the [eE] could be refactored to soley e
  268. */
  269. var float_regex2 = /^(?:[+-]?(?:(?:(?:\d*\.\d+)|(?:\d+\.?))(?:[eE][+-]?\d+)?|NaN|Infinity))/;
  270. val_wws = val.substr(index); // val with removed whitespace and "("
  271. /* first try to match a float at the beginning */
  272. match = val_wws.match(float_regex2);
  273. if (match !== null) {
  274. // one of the first 4 cases
  275. index += match[0].length;
  276. /* <float>j */
  277. if (val[index] === "j" || val[index] === "J") {
  278. y = parseFloat(match[0]);
  279. index++;
  280. } else if(val[index] === "+" || val[index] === "-") {
  281. /* <float><signed-float>j | <float><sign>j */
  282. x = parseFloat(match[0]);
  283. match = val.substr(index).match(float_regex2);
  284. if (match !== null) {
  285. /* <float><signed-float>j */
  286. y = parseFloat(match[0]);
  287. index += match[0].length;
  288. } else {
  289. /* <float><sign>j */
  290. y = val[index] === "+" ? 1.0 : -1.0;
  291. index++;
  292. }
  293. if (val[index] !== "j" && val[index] !== "J") {
  294. throw new Sk.builtin.ValueError("complex() arg is malformed string");
  295. }
  296. index++;
  297. } else {
  298. /* <float> */
  299. x = parseFloat(match[0]);
  300. }
  301. } else {
  302. // maybe <sign>j or j
  303. match = match = val_wws.match(/^([+-]?[jJ])/);
  304. if (match !== null) {
  305. if (match[0].length === 1) {
  306. y = 1.0; // must be j
  307. } else {
  308. y = match[0][0] === "+" ? 1.0 : -1.0;
  309. }
  310. index += match[0].length;
  311. }
  312. }
  313. while (val[index] === " ") {
  314. index++;
  315. }
  316. if (got_bracket) {
  317. /* if there was an opening parenthesis, then the corresponding
  318. closing parenthesis should be right here */
  319. if (val[index] !== ")") {
  320. throw new Sk.builtin.ValueError("complex() arg is malformed string");
  321. }
  322. index++;
  323. while (val[index] === " ") {
  324. index++;
  325. }
  326. }
  327. /* we should now be at the end of the string */
  328. if (val.length !== index) {
  329. throw new Sk.builtin.ValueError("complex() arg is malformed string");
  330. }
  331. // return here complex number parts
  332. return new Sk.builtin.complex(new Sk.builtin.float_(x), new Sk.builtin.float_(y));
  333. };
  334. /**
  335. _PyHASH_IMAG refers to _PyHASH_MULTIPLIER which refers to 1000003
  336. */
  337. Sk.builtin.complex.prototype.tp$hash = function () {
  338. return new Sk.builtin.int_(this.tp$getattr("imag").v * 1000003 + this.tp$getattr("real").v);
  339. };
  340. Sk.builtin.complex.prototype.nb$add = function (other) {
  341. var real;
  342. var imag;
  343. other = Sk.builtin.complex.check_number_or_complex(other);
  344. real = this.tp$getattr("real").v + other.tp$getattr("real").v;
  345. imag = this.tp$getattr("imag").v + other.tp$getattr("imag").v;
  346. return new Sk.builtin.complex(new Sk.builtin.float_(real), new Sk.builtin.float_(imag));
  347. };
  348. /* internal subtract/diff function that calls internal float diff */
  349. Sk.builtin.complex._c_diff = function (a, b) {
  350. var r, i; // Py_Float
  351. r = a.real.nb$subtract.call(a.real, b.real);
  352. i = a.imag.nb$subtract.call(a.imag, b.imag);
  353. return new Sk.builtin.complex(r, i);
  354. };
  355. Sk.builtin.complex.prototype.nb$subtract = function (other) {
  356. var result; // Py_complex
  357. var a, b; // Py_complex
  358. a = Sk.builtin.complex.check_number_or_complex(this);
  359. b = Sk.builtin.complex.check_number_or_complex(other);
  360. result = Sk.builtin.complex._c_diff(a, b);
  361. return result;
  362. };
  363. Sk.builtin.complex.prototype.nb$multiply = function (other) {
  364. var real;
  365. var imag;
  366. var a, b; // Py_complex
  367. a = this;
  368. b = Sk.builtin.complex.check_number_or_complex(other);
  369. real = a.real.v * b.real.v - a.imag.v * b.imag.v;
  370. imag = a.real.v * b.imag.v + a.imag.v * b.real.v;
  371. return new Sk.builtin.complex(new Sk.builtin.float_(real), new Sk.builtin.float_(imag));
  372. };
  373. /**
  374. * Otherwise google closure complains about ZeroDivisionError not being
  375. * defined
  376. * @suppress {missingProperties}
  377. *
  378. * implementation based on complexobject.c:c_quot
  379. */
  380. Sk.builtin.complex.prototype.nb$divide = function (other) {
  381. var real;
  382. var imag;
  383. other = Sk.builtin.complex.check_number_or_complex(other);
  384. var ratio;
  385. var denom;
  386. // other == b
  387. var breal = other.real.v;
  388. var bimag = other.imag.v;
  389. // this == a
  390. var areal = this.real.v;
  391. var aimag = this.imag.v;
  392. var abs_breal = Math.abs(breal);
  393. var abs_bimag = Math.abs(bimag);
  394. if (abs_breal >= abs_bimag) {
  395. // divide tops and bottom by breal
  396. if (abs_breal === 0.0) {
  397. throw new Sk.builtin.ZeroDivisionError("complex division by zero");
  398. } else {
  399. ratio = bimag / breal;
  400. denom = breal + bimag * ratio;
  401. real = (areal + aimag * ratio) / denom;
  402. imag = (aimag - areal * ratio) / denom;
  403. }
  404. } else if (abs_bimag >= abs_breal) {
  405. // divide tops and bottom by b.imag
  406. ratio = breal / bimag;
  407. denom = breal * ratio + bimag;
  408. goog.asserts.assert(bimag !== 0.0);
  409. real = (areal * ratio + aimag) / denom;
  410. imag = (aimag * ratio - areal) / denom;
  411. } else {
  412. // At least one of b.real or b.imag is a NaN
  413. real = NaN;
  414. imag = NaN;
  415. }
  416. return new Sk.builtin.complex(new Sk.builtin.float_(real), new Sk.builtin.float_(imag));
  417. };
  418. Sk.builtin.complex.prototype.nb$floor_divide = function (other) {
  419. throw new Sk.builtin.TypeError("can't take floor of complex number.");
  420. };
  421. Sk.builtin.complex.prototype.nb$remainder = function (other) {
  422. throw new Sk.builtin.TypeError("can't mod complex numbers.");
  423. };
  424. /**
  425. * @param {?Object=} z, modulo operation
  426. */
  427. Sk.builtin.complex.prototype.nb$power = function (other, z) {
  428. var p;
  429. var exponent;
  430. var int_exponent;
  431. var a, b;
  432. // none is allowed
  433. if (z != null && !Sk.builtin.checkNone(z)) {
  434. throw new Sk.builtin.ValueError("complex modulo");
  435. }
  436. a = this;
  437. b = Sk.builtin.complex.check_number_or_complex(other);
  438. exponent = b;
  439. int_exponent = b.real.v | 0; // js convert to int
  440. if (exponent.imag.v === 0.0 && exponent.real.v === int_exponent) {
  441. p = Sk.builtin.complex.c_powi(a, int_exponent);
  442. } else {
  443. p = Sk.builtin.complex.c_pow(a, exponent);
  444. }
  445. return p;
  446. };
  447. // power of complex a and complex exponent b
  448. Sk.builtin.complex.c_pow = function (a, b) {
  449. var real, imag; // Py_complex
  450. var vabs;
  451. var len;
  452. var at;
  453. var phase;
  454. // other == b
  455. var breal = b.real.v;
  456. var bimag = b.imag.v;
  457. // this == a
  458. var areal = a.real.v;
  459. var aimag = a.imag.v;
  460. if (breal === 0.0 && bimag === 0.0) {
  461. real = 1.0;
  462. imag = 0.0;
  463. } else if (areal === 0.0 && aimag === 0.0) {
  464. if(bimag !== 0.0 || breal < 0.0) {
  465. throw new Sk.builtin.ZeroDivisionError("complex division by zero");
  466. }
  467. real = 0.0;
  468. imag = 0.0;
  469. } else {
  470. vabs = Math.hypot(areal, aimag);
  471. len = Math.pow(vabs, breal);
  472. at = Math.atan2(aimag, areal);
  473. phase = at * breal;
  474. if(bimag !== 0.0) {
  475. len /= Math.exp(at * bimag);
  476. phase += bimag * Math.log(vabs);
  477. }
  478. real = len * Math.cos(phase);
  479. imag = len * Math.sin(phase);
  480. }
  481. return new Sk.builtin.complex(new Sk.builtin.float_(real), new Sk.builtin.float_(imag));
  482. };
  483. // power of complex x and integer exponent n
  484. Sk.builtin.complex.c_powi = function (x, n) {
  485. var cn; // Py_complex
  486. var c1;
  487. if (n > 100 || n < -100) {
  488. cn = new Sk.builtin.complex(new Sk.builtin.float_(n), new Sk.builtin.float_(0.0));
  489. return Sk.builtin.complex.c_pow(x, cn);
  490. } else if (n > 0) {
  491. return Sk.builtin.complex.c_powu(x, n);
  492. } else {
  493. // return c_quot(c_1,c_powu(x,-n));
  494. c1 = new Sk.builtin.complex(new Sk.builtin.float_(1.0), new Sk.builtin.float_(0.0));
  495. return c1.nb$divide(Sk.builtin.complex.c_powu(x,-n));
  496. }
  497. };
  498. Sk.builtin.complex.c_powu = function (x, n) {
  499. var r, p; // Py_complex
  500. var mask = 1;
  501. r = new Sk.builtin.complex(new Sk.builtin.float_(1.0), new Sk.builtin.float_(0.0));
  502. p = x;
  503. while (mask > 0 && n >= mask) {
  504. if (n & mask) {
  505. r = r.nb$multiply(p);
  506. }
  507. mask <<= 1;
  508. p = p.nb$multiply(p);
  509. }
  510. return r;
  511. };
  512. Sk.builtin.complex.prototype.nb$inplace_add = Sk.builtin.complex.prototype.nb$add;
  513. Sk.builtin.complex.prototype.nb$inplace_subtract = Sk.builtin.complex.prototype.nb$subtract;
  514. Sk.builtin.complex.prototype.nb$inplace_multiply = Sk.builtin.complex.prototype.nb$multiply;
  515. Sk.builtin.complex.prototype.nb$inplace_divide = Sk.builtin.complex.prototype.nb$divide;
  516. Sk.builtin.complex.prototype.nb$inplace_remainder = Sk.builtin.complex.prototype.nb$remainder;
  517. Sk.builtin.complex.prototype.nb$inplace_floor_divide = Sk.builtin.complex.prototype.nb$floor_divide;
  518. Sk.builtin.complex.prototype.nb$inplace_power = Sk.builtin.complex.prototype.nb$power;
  519. Sk.builtin.complex.prototype.nb$negative = function () {
  520. var real;
  521. var imag;
  522. // this == a
  523. var areal = this.real.v;
  524. var aimag = this.imag.v;
  525. real = -areal;
  526. imag = -aimag;
  527. return new Sk.builtin.complex(new Sk.builtin.float_(real), new Sk.builtin.float_(imag));
  528. };
  529. Sk.builtin.complex.prototype.nb$positive = function () {
  530. return Sk.builtin.complex.check_number_or_complex(this);
  531. };
  532. /**
  533. * check if op is instance of complex or a sub-type
  534. */
  535. Sk.builtin.complex._complex_check = function (op) {
  536. if (op === undefined) {
  537. return false;
  538. }
  539. if (op instanceof Sk.builtin.complex || (op.tp$name && op.tp$name === "complex")) {
  540. return true;
  541. }
  542. // check if type of ob is a subclass
  543. if (Sk.builtin.issubclass(new Sk.builtin.type(op), Sk.builtin.complex)) {
  544. return true;
  545. }
  546. return false;
  547. };
  548. Sk.builtin.complex.prototype.tp$richcompare = function (w, op) {
  549. var result;
  550. var equal;
  551. var i;
  552. if (op !== "Eq" && op !== "NotEq") {
  553. if(Sk.builtin.checkNumber(w) || Sk.builtin.complex._complex_check(w)) {
  554. throw new Sk.builtin.TypeError("no ordering relation is defined for complex numbers");
  555. }
  556. return Sk.builtin.NotImplemented.NotImplemented$;
  557. }
  558. // assert(PyComplex_Check(v)));
  559. i = Sk.builtin.complex.check_number_or_complex(this);
  560. var _real = i.tp$getattr("real").v;
  561. var _imag = i.tp$getattr("imag").v;
  562. if (Sk.builtin.checkInt(w)) {
  563. /* Check for 0.0 imaginary part first to avoid the rich
  564. * comparison when possible.
  565. */
  566. // if true, the complex number has just a real part
  567. if (_imag === 0.0) {
  568. equal = Sk.misceval.richCompareBool(new Sk.builtin.float_(_real), w, op);
  569. result = new Sk.builtin.bool( equal);
  570. return result;
  571. } else {
  572. equal = false;
  573. }
  574. } else if (Sk.builtin.checkFloat(w)) {
  575. equal = (_real === Sk.builtin.float_.PyFloat_AsDouble(w) && _imag === 0.0);
  576. } else if (Sk.builtin.complex._complex_check(w)) {
  577. // ToDo: figure if we need to call to_complex
  578. var w_real = w.tp$getattr("real").v;
  579. var w_imag = w.tp$getattr("imag").v;
  580. equal = _real === w_real && _imag === w_imag;
  581. } else {
  582. return Sk.builtin.NotImplemented.NotImplemented$;
  583. }
  584. // invert result if op == NotEq
  585. if(op === "NotEq") {
  586. equal = !equal;
  587. }
  588. // wrap as bool
  589. result = new Sk.builtin.bool( equal);
  590. return result;
  591. };
  592. // Despite what jshint may want us to do, these two functions need to remain
  593. // as == and != Unless you modify the logic of numberCompare do not change
  594. // these.
  595. Sk.builtin.complex.prototype.__eq__ = function (me, other) {
  596. return Sk.builtin.complex.prototype.tp$richcompare.call(me, other, "Eq");
  597. };
  598. Sk.builtin.complex.prototype.__ne__ = function (me, other) {
  599. return Sk.builtin.complex.prototype.tp$richcompare.call(me, other, "NotEq");
  600. };
  601. /**
  602. * Do we really need to implement those? Otherwise I can't find in Sk.abstr a place where this particular
  603. * expcetion is thrown.git co
  604. */
  605. Sk.builtin.complex.prototype.__lt__ = function (me, other) {
  606. throw new Sk.builtin.TypeError("unorderable types: " + Sk.abstr.typeName(me) + " < " + Sk.abstr.typeName(other));
  607. };
  608. Sk.builtin.complex.prototype.__le__ = function (me, other) {
  609. throw new Sk.builtin.TypeError("unorderable types: " + Sk.abstr.typeName(me) + " <= " + Sk.abstr.typeName(other));
  610. };
  611. Sk.builtin.complex.prototype.__gt__ = function (me, other) {
  612. throw new Sk.builtin.TypeError("unorderable types: " + Sk.abstr.typeName(me) + " > " + Sk.abstr.typeName(other));
  613. };
  614. Sk.builtin.complex.prototype.__ge__ = function (me, other) {
  615. throw new Sk.builtin.TypeError("unorderable types: " + Sk.abstr.typeName(me) + " >= " + Sk.abstr.typeName(other));
  616. };
  617. Sk.builtin.complex.prototype.__float__ = function (self) {
  618. throw new Sk.builtin.TypeError("can't convert complex to float");
  619. };
  620. Sk.builtin.complex.prototype.__int__ = function (self) {
  621. throw new Sk.builtin.TypeError("can't convert complex to int");
  622. };
  623. Sk.builtin.complex.prototype._internalGenericGetAttr = Sk.builtin.object.prototype.GenericGetAttr;
  624. /**
  625. * Custom getattr impl. to get the c.real and c.imag to work. Though we should
  626. * consider to implement tp$members that always are attributs on the class and
  627. * will be used in the genericgetattr method.
  628. * Would be super easy to implement the readonly stuff too.
  629. *
  630. */
  631. Sk.builtin.complex.prototype.tp$getattr = function (name) {
  632. if (name != null && (Sk.builtin.checkString(name) || typeof name === "string")) {
  633. var _name = name;
  634. // get javascript string
  635. if (Sk.builtin.checkString(name)) {
  636. _name = Sk.ffi.remapToJs(name);
  637. }
  638. if (_name === "real" || _name === "imag") {
  639. return this[_name];
  640. }
  641. }
  642. // if we have not returned yet, try the genericgetattr
  643. return this._internalGenericGetAttr(name);
  644. };
  645. Sk.builtin.complex.prototype.tp$setattr = function (name, value) {
  646. if (name != null && (Sk.builtin.checkString(name) || typeof name === "string")) {
  647. var _name = name;
  648. // get javascript string
  649. if (Sk.builtin.checkString(name)) {
  650. _name = Sk.ffi.remapToJs(name);
  651. }
  652. if (_name === "real" || _name === "imag") {
  653. throw new Sk.builtin.AttributeError("readonly attribute");
  654. }
  655. }
  656. // builtin: --> all is readonly (I am not happy with this)
  657. throw new Sk.builtin.AttributeError("'complex' object attribute '" + name + "' is readonly");
  658. };
  659. /**
  660. * Internal format function for repr and str
  661. * It is not intended for __format__ calls
  662. *
  663. * This functions assumes, that v is always instance of Sk.builtin.complex
  664. */
  665. Sk.builtin.complex.complex_format = function (v, precision, format_code){
  666. function copysign (a, b) {
  667. return b < 0 ? -Math.abs(a) : Math.abs(a);
  668. }
  669. if (v == null || !Sk.builtin.complex._complex_check(v)) {
  670. throw new Error("Invalid internal method call: Sk.complex.complex_format() called with invalid value type.");
  671. }
  672. var result; // PyObject
  673. var pre = "";
  674. var im = "";
  675. var re = null;
  676. var lead = "";
  677. var tail = "";
  678. if (v.real.v === 0.0 && copysign(1.0, v.real.v) == 1.0) {
  679. re = "";
  680. im = Sk.builtin.complex.PyOS_double_to_string(v.imag.v, format_code, precision, 0, null);
  681. // im = v.imag.v;
  682. } else {
  683. /* Format imaginary part with sign, real part without */
  684. pre = Sk.builtin.complex.PyOS_double_to_string(v.real.v, format_code, precision, 0, null);
  685. re = pre;
  686. im = Sk.builtin.complex.PyOS_double_to_string(v.imag.v, format_code, precision, Sk.builtin.complex.PyOS_double_to_string.Py_DTSF_SIGN, null);
  687. if (v.imag.v === 0 && 1/v.imag.v === -Infinity && im && im[0] !== "-"){
  688. im = "-" + im; // force negative zero sign
  689. }
  690. lead = "(";
  691. tail = ")";
  692. }
  693. result = "" + lead + re + im + "j" + tail; // concat all parts
  694. return new Sk.builtin.str(result);
  695. };
  696. Sk.builtin.complex.prototype["$r"] = function () {
  697. return Sk.builtin.complex.complex_format(this, 0, "r");
  698. };
  699. Sk.builtin.complex.prototype.tp$str = function () {
  700. return Sk.builtin.complex.complex_format(this, null, "g"); // g, 12 == Py_Float_STR_PRECISION
  701. };
  702. /**
  703. * https://hg.python.org/cpython/file/3cf2990d19ab/Objects/complexobject.c#l907
  704. * also see _PyComplex_FormatAdvanced
  705. *
  706. * We currently use the signature (self, format_spec) instead of (self, args). So we do
  707. * not need to unwrap the args.
  708. */
  709. Sk.builtin.complex.prototype.__format__ = new Sk.builtin.func(function (self, format_spec){
  710. var result; // PyObject
  711. if (format_spec == null) {
  712. return null;
  713. }
  714. if (Sk.builtin.checkString(format_spec)) {
  715. result = Sk.builtin.complex._PyComplex_FormatAdvanced(self, format_spec);
  716. return result;
  717. }
  718. throw new Sk.builtin.TypeError("__format__ requires str or unicode");
  719. });
  720. Sk.builtin.complex._PyComplex_FormatAdvanced = function(self, format_spec) {
  721. throw new Sk.builtin.NotImplementedError("__format__ is not implemented for complex type.");
  722. };
  723. /**
  724. Return true if float or double are is neither infinite nor NAN, else false
  725. Value is already a Javascript object
  726. */
  727. Sk.builtin.complex._is_finite = function (val) {
  728. return !isNaN(val) && val !== Infinity && val !== -Infinity;
  729. };
  730. Sk.builtin.complex._is_infinity = function (val) {
  731. return val === Infinity || val === -Infinity;
  732. };
  733. /**
  734. * @suppress {missingProperties}
  735. */
  736. Sk.builtin.complex.prototype.__abs__ = new Sk.builtin.func(function (self) {
  737. var result;
  738. var _real = self.real.v;
  739. var _imag = self.imag.v;
  740. if (!Sk.builtin.complex._is_finite(_real) || !Sk.builtin.complex._is_finite(_imag)) {
  741. /* C99 rules: if either the real or the imaginary part is an
  742. infinity, return infinity, even if the other part is a
  743. NaN.
  744. */
  745. if (Sk.builtin.complex._is_infinity(_real)) {
  746. result = Math.abs(_real);
  747. return new Sk.builtin.float_(result);
  748. }
  749. if (Sk.builtin.complex._is_infinity(_imag)) {
  750. result = Math.abs(_imag);
  751. return new Sk.builtin.float_(result);
  752. }
  753. /* either the real or imaginary part is a NaN,
  754. and neither is infinite. Result should be NaN. */
  755. return new Sk.builtin.float_(NaN);
  756. }
  757. result = Math.hypot(_real, _imag);
  758. if (!Sk.builtin.complex._is_finite(result)) {
  759. throw new Sk.builtin.OverflowError("absolute value too large");
  760. }
  761. return new Sk.builtin.float_(result);
  762. });
  763. Sk.builtin.complex.prototype.__bool__ = new Sk.builtin.func(function (self) {
  764. return new Sk.builtin.bool( self.tp$getattr("real").v || self.tp$getattr("real").v);
  765. });
  766. Sk.builtin.complex.prototype.__truediv__ = new Sk.builtin.func(function (self, other){
  767. Sk.builtin.pyCheckArgs("__truediv__", arguments, 1, 1, true);
  768. return self.nb$divide.call(self, other);
  769. });
  770. Sk.builtin.complex.prototype.__hash__ = new Sk.builtin.func(function (self){
  771. Sk.builtin.pyCheckArgs("__hash__", arguments, 0, 0, true);
  772. return self.tp$hash.call(self);
  773. });
  774. Sk.builtin.complex.prototype.__add__ = new Sk.builtin.func(function (self, other){
  775. Sk.builtin.pyCheckArgs("__add__", arguments, 1, 1, true);
  776. return self.nb$add.call(self, other);
  777. });
  778. Sk.builtin.complex.prototype.__repr__ = new Sk.builtin.func(function (self){
  779. Sk.builtin.pyCheckArgs("__repr__", arguments, 0, 0, true);
  780. return self["r$"].call(self);
  781. });
  782. Sk.builtin.complex.prototype.__str__ = new Sk.builtin.func(function (self){
  783. Sk.builtin.pyCheckArgs("__str__", arguments, 0, 0, true);
  784. return self.tp$str.call(self);
  785. });
  786. Sk.builtin.complex.prototype.__sub__ = new Sk.builtin.func(function (self, other){
  787. Sk.builtin.pyCheckArgs("__sub__", arguments, 1, 1, true);
  788. return self.nb$subtract.call(self, other);
  789. });
  790. Sk.builtin.complex.prototype.__mul__ = new Sk.builtin.func(function (self, other){
  791. Sk.builtin.pyCheckArgs("__mul__", arguments, 1, 1, true);
  792. return self.nb$multiply.call(self, other);
  793. });
  794. Sk.builtin.complex.prototype.__div__ = new Sk.builtin.func(function (self, other){
  795. Sk.builtin.pyCheckArgs("__div__", arguments, 1, 1, true);
  796. return self.nb$divide.call(self, other);
  797. });
  798. Sk.builtin.complex.prototype.__floordiv__ = new Sk.builtin.func(function (self, other){
  799. Sk.builtin.pyCheckArgs("__floordiv__", arguments, 1, 1, true);
  800. return self.nb$floor_divide.call(self, other);
  801. });
  802. Sk.builtin.complex.prototype.__mod__ = new Sk.builtin.func(function (self, other){
  803. Sk.builtin.pyCheckArgs("__mod__", arguments, 1, 1, true);
  804. return self.nb$remainder.call(self, other);
  805. });
  806. Sk.builtin.complex.prototype.__pow__ = new Sk.builtin.func(function (self, other, z){
  807. Sk.builtin.pyCheckArgs("__pow__", arguments, 1, 2, true);
  808. return self.nb$power.call(self, other, z);
  809. });
  810. Sk.builtin.complex.prototype.__neg__ = new Sk.builtin.func(function (self){
  811. Sk.builtin.pyCheckArgs("__neg__", arguments, 0, 0, true);
  812. return self.nb$negative.call(self);
  813. });
  814. Sk.builtin.complex.prototype.__pos__ = new Sk.builtin.func(function (self){
  815. Sk.builtin.pyCheckArgs("__pos__", arguments, 0, 0, true);
  816. return self.nb$positive.call(self);
  817. });
  818. Sk.builtin.complex.prototype.conjugate = new Sk.builtin.func(function (self){
  819. Sk.builtin.pyCheckArgs("conjugate", arguments, 0, 0, true);
  820. var _imag = self.imag.v;
  821. _imag = -_imag;
  822. return new Sk.builtin.complex(self.real, new Sk.builtin.float_(_imag));
  823. });
  824. // deprecated
  825. Sk.builtin.complex.prototype.__divmod__ = new Sk.builtin.func(function (self, other){
  826. Sk.builtin.pyCheckArgs("__divmod__", arguments, 1, 1, true);
  827. var div, mod; // Py_complex
  828. var d, m, z; // PyObject
  829. var a, b; // Py_complex
  830. a = Sk.builtin.complex.check_number_or_complex(self);
  831. b = Sk.builtin.complex.check_number_or_complex(other);
  832. div = a.nb$divide.call(a, b); // the raw divisor value
  833. div.real = new Sk.builtin.float_(Math.floor(div.real.v));
  834. div.imag = new Sk.builtin.float_(0.0);
  835. mod = a.nb$subtract.call(a, b.nb$multiply.call(b, div));
  836. z = new Sk.builtin.tuple([div, mod]);
  837. return z;
  838. });
  839. Sk.builtin.complex.prototype.__getnewargs__ = new Sk.builtin.func(function (self){
  840. Sk.builtin.pyCheckArgs("__getnewargs__", arguments, 0, 0, true);
  841. return new Sk.builtin.tuple([self.real, self.imag]);
  842. });
  843. Sk.builtin.complex.prototype.__nonzero__ = new Sk.builtin.func(function (self){
  844. Sk.builtin.pyCheckArgs("__nonzero__", arguments, 0, 0, true);
  845. if(self.real.v !== 0.0 || self.imag.v !== 0.0) {
  846. return Sk.builtin.bool.true$;
  847. } else {
  848. return Sk.builtin.bool.false$;
  849. }
  850. });
  851. // ToDo: think about inplace methods too
  852. goog.exportSymbol("Sk.builtin.complex", Sk.builtin.complex);
  853. /**
  854. * Convert a double val to a string using supplied format_code, precision, and flags.
  855. *
  856. * format_code must be one of 'e', 'E', 'f', 'F', 'g', 'G' or 'r'. For 'r', the supplied precision must be 0 and is ignored. The 'r' format code specifies the standard repr() format.
  857. *
  858. * flags can be zero or more of the values Py_DTSF_SIGN, Py_DTSF_ADD_DOT_0, or Py_DTSF_ALT, or-ed together:
  859. *
  860. * Py_DTSF_SIGN means to always precede the returned string with a sign character, even if val is non-negative.
  861. * Py_DTSF_ADD_DOT_0 means to ensure that the returned string will not look like an integer.
  862. * Py_DTSF_ALT means to apply “alternate” formatting rules. See the documentation for the PyOS_snprintf() '#' specifier for details.
  863. * If ptype is non-NULL, then the value it points to will be set to one of Py_DTST_FINITE, Py_DTST_INFINITE, or Py_DTST_NAN, signifying that val is a finite number, an
  864. * infinite number, or not a number, respectively.
  865. */
  866. Sk.builtin.complex.PyOS_double_to_string = function(val, format_code, precision, flags, type) {
  867. var format;
  868. var buf;
  869. var t;
  870. var exp;
  871. var upper = false;
  872. // Validate format code, and map upper and lower case
  873. switch(format_code) {
  874. case "e": /* exponent */
  875. case "f": /* fixed */
  876. case "g": /* general */
  877. break;
  878. case "E":
  879. upper = true;
  880. format_code = "e";
  881. break;
  882. case "F":
  883. upper = true;
  884. format_code = "f";
  885. break;
  886. case "r": /* repr format */
  887. // Supplied precision is unused, must be 0.
  888. if(precision !== 0) {
  889. throw new Error("Bad internall call"); // only happens when somebody messes up calling this in js
  890. }
  891. // repr() precision is 17 significant decimal digits
  892. precision = 17;
  893. format_code = "g";
  894. break;
  895. default:
  896. throw new Error("Bad internall call");
  897. }
  898. // no need for buffer size calculation like in cpython
  899. // Handle nan and inf
  900. if(isNaN(val)) {
  901. buf = "nan";
  902. t = Sk.builtin.complex.PyOS_double_to_string.Py_DTST_NAN;
  903. } else if (val === Infinity) {
  904. buf = "inf";
  905. t = Sk.builtin.complex.PyOS_double_to_string.Py_DTST_INFINITE;
  906. } else if (val === -Infinity) {
  907. buf = "-inf";
  908. t = Sk.builtin.complex.PyOS_double_to_string.Py_DTST_INFINITE;
  909. } else {
  910. t = Sk.builtin.complex.PyOS_double_to_string.Py_DTST_FINITE;
  911. if(flags & Sk.builtin.complex.PyOS_double_to_string.Py_DTSF_ADD_DOT_0) {
  912. format_code = "g"; // "Z"; _PyOS_ascii_formatd converts "Z" to "g"
  913. }
  914. // ToDo: call snprintf here
  915. // ToDo: call ascii_formatd
  916. var format_str = "%";
  917. format_str += flags & Sk.builtin.complex.PyOS_double_to_string.Py_DTSF_ALT ? "#" : "";
  918. if(precision != null) {
  919. format_str += ".";
  920. format_str += precision;
  921. }
  922. format_str += format_code;
  923. format_str = new Sk.builtin.str(format_str);
  924. /**
  925. * We cann call nb$remainder with val, because it gets unwrapped and it doesn't matter if it is
  926. * already a javascript number. If we do not pass a float, we can't distinguish between ints and floats
  927. * and therefore we can't adjust the sign of the zero accordingly
  928. */
  929. buf = format_str.nb$remainder(new Sk.builtin.float_(val));
  930. buf = buf.v; // get javascript string
  931. }
  932. /**
  933. * Add sign when requested. It's convenient (esp. when formatting complex numbers) to
  934. * include sign even for inf and nan.
  935. */
  936. if(flags & Sk.builtin.complex.PyOS_double_to_string.Py_DTSF_SIGN && buf[0] !== "-") {
  937. buf = "+" + buf;
  938. }
  939. if(upper) {
  940. // Convert to upper case
  941. buf = buf.toUpperCase();
  942. }
  943. return buf;
  944. };
  945. /* PyOS_double_to_string's "flags" parameter can be set to 0 or more of: */
  946. Sk.builtin.complex.PyOS_double_to_string.Py_DTSF_SIGN = 0x01; // always add the sign
  947. Sk.builtin.complex.PyOS_double_to_string.Py_DTSF_ADD_DOT_0 = 0x02; // if the result is an integer add ".0"
  948. Sk.builtin.complex.PyOS_double_to_string.Py_DTSF_ALT = 0x04; // "alternate" formatting. it's format_code specific
  949. /* PyOS_double_to_string's "type", if non-NULL, will be set to one of: */
  950. Sk.builtin.complex.PyOS_double_to_string.Py_DTST_FINITE = 0;
  951. Sk.builtin.complex.PyOS_double_to_string.Py_DTST_INFINITE = 1;
  952. Sk.builtin.complex.PyOS_double_to_string.Py_DTST_NAN = 2;