Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(692)

Side by Side Diff: Objects/complexobject.c

Issue 33084: [issue1580] Use shorter float repr when possible (Closed) Base URL: http://svn.python.org/view/*checkout*/python/branches/py3k/
Patch Set: Include extra files dtoa.c, dtoa.h and formatfloat_testcases.txt Created 14 years, 11 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 1
2 /* Complex object implementation */ 2 /* Complex object implementation */
3 3
4 /* Borrows heavily from floatobject.c */ 4 /* Borrows heavily from floatobject.c */
5 5
6 /* Submitted by Jim Hugunin */ 6 /* Submitted by Jim Hugunin */
7 7
8 #include "Python.h" 8 #include "Python.h"
9 #include "structmember.h" 9 #include "structmember.h"
10 10
11 #ifdef HAVE_IEEEFP_H 11 #ifdef HAVE_IEEEFP_H
12 #include <ieeefp.h> 12 #include <ieeefp.h>
13 #endif 13 #endif
14 14
15 #ifndef WITHOUT_COMPLEX 15 #ifndef WITHOUT_COMPLEX
16 16
17 /* Precisions used by repr() and str(), respectively.
18
19 The repr() precision (17 significant decimal digits) is the minimal number
20 that is guaranteed to have enough precision so that if the number is read
21 back in the exact same binary value is recreated. This is true for IEEE
22 floating point by design, and also happens to work for all other modern
23 hardware.
24
25 The str() precision is chosen so that in most cases, the rounding noise
26 created by various operations is suppressed, while giving plenty of
27 precision for practical use.
28 */
29
30 #define PREC_REPR 17
31 #define PREC_STR 12
32
33 /* elementary operations on complex numbers */ 17 /* elementary operations on complex numbers */
34 18
35 static Py_complex c_1 = {1., 0.}; 19 static Py_complex c_1 = {1., 0.};
36 20
37 Py_complex 21 Py_complex
38 c_sum(Py_complex a, Py_complex b) 22 c_sum(Py_complex a, Py_complex b)
39 { 23 {
40 Py_complex r; 24 Py_complex r;
41 r.real = a.real + b.real; 25 r.real = a.real + b.real;
42 r.imag = a.imag + b.imag; 26 r.imag = a.imag + b.imag;
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 } 322 }
339 } 323 }
340 324
341 static void 325 static void
342 complex_dealloc(PyObject *op) 326 complex_dealloc(PyObject *op)
343 { 327 {
344 op->ob_type->tp_free(op); 328 op->ob_type->tp_free(op);
345 } 329 }
346 330
347 331
348 static void 332 static PyObject *
349 complex_to_buf(char *buf, int bufsz, PyComplexObject *v, int precision) 333 complex_format(PyComplexObject *v, char format_code)
350 { 334 {
351 » char format[32]; 335 PyObject *result = NULL;
352 » if (v->cval.real == 0.) { 336 Py_ssize_t len;
353 » » if (!Py_IS_FINITE(v->cval.imag)) { 337 char *buf;
354 » » » if (Py_IS_NAN(v->cval.imag)) 338
355 » » » » strncpy(buf, "nan*j", 6); 339 /* If these are non-NULL, they'll need to be freed. */
356 » » » else if (copysign(1, v->cval.imag) == 1) 340 char *pre = NULL;
357 » » » » strncpy(buf, "inf*j", 6); 341 char *pim = NULL;
358 » » » else 342
359 » » » » strncpy(buf, "-inf*j", 7); 343 /* These do not need to be freed. They're either aliases for pim
360 » » } 344 and pre, or pointers to constants. */
361 » » else { 345 char *re = NULL;
362 » » » PyOS_snprintf(format, sizeof(format), "%%.%ig", precisio n); 346 char *im = NULL;
363 » » » PyOS_ascii_formatd(buf, bufsz - 1, format, v->cval.imag) ; 347 char *lead = "";
364 » » » strncat(buf, "j", 1); 348 char *tail = "";
365 » » } 349
366 » } else { 350
367 » » char re[64], im[64]; 351 if (v->cval.real == 0.) {
368 » » /* Format imaginary part with sign, real part without */ 352 re = "";
369 » » if (!Py_IS_FINITE(v->cval.real)) { 353 if (!Py_IS_FINITE(v->cval.imag)) {
370 » » » if (Py_IS_NAN(v->cval.real)) 354 if (Py_IS_NAN(v->cval.imag))
371 » » » » strncpy(re, "nan", 4); 355 im = "nan*";
372 » » » /* else if (copysign(1, v->cval.real) == 1) */ 356 else if (copysign(1, v->cval.imag) == 1)
373 » » » else if (v->cval.real > 0) 357 im = "inf*";
374 » » » » strncpy(re, "inf", 4); 358 else
375 » » » else 359 im = "-inf*";
376 » » » » strncpy(re, "-inf", 5); 360 }
377 » » } 361 else {
378 » » else { 362 pim = PyOS_double_to_string(v->cval.imag, format_code, 0, 0);
379 » » » PyOS_snprintf(format, sizeof(format), "%%.%ig", precisio n); 363 if (!pim) {
380 » » » PyOS_ascii_formatd(re, sizeof(re), format, v->cval.real) ; 364 PyErr_NoMemory();
381 » » } 365 goto done;
382 » » if (!Py_IS_FINITE(v->cval.imag)) { 366 }
383 » » » if (Py_IS_NAN(v->cval.imag)) 367 im = pim;
384 » » » » strncpy(im, "+nan*", 6); 368 }
385 » » » /* else if (copysign(1, v->cval.imag) == 1) */ 369 } else {
386 » » » else if (v->cval.imag > 0) 370 /* Format imaginary part with sign, real part without */
387 » » » » strncpy(im, "+inf*", 6); 371 if (!Py_IS_FINITE(v->cval.real)) {
388 » » » else 372 if (Py_IS_NAN(v->cval.real))
389 » » » » strncpy(im, "-inf*", 6); 373 re = "nan";
390 » » } 374 /* else if (copysign(1, v->cval.real) == 1) */
391 » » else { 375 else if (v->cval.real > 0)
392 » » » PyOS_snprintf(format, sizeof(format), "%%+.%ig", precisi on); 376 re = "inf";
393 » » » PyOS_ascii_formatd(im, sizeof(im), format, v->cval.imag) ; 377 else
394 » » } 378 re = "-inf";
395 » » PyOS_snprintf(buf, bufsz, "(%s%sj)", re, im); 379 }
396 » } 380 else {
381 pre = PyOS_double_to_string(v->cval.real, format_code, 0, 0);
382 if (!pre) {
383 PyErr_NoMemory();
384 goto done;
385 }
386 re = pre;
387 }
388
389 if (!Py_IS_FINITE(v->cval.imag)) {
390 if (Py_IS_NAN(v->cval.imag))
391 im = "+nan*";
392 /* else if (copysign(1, v->cval.imag) == 1) */
393 else if (v->cval.imag > 0)
394 im = "+inf*";
395 else
396 im = "-inf*";
397 }
398 else {
399 pim = PyOS_double_to_string(v->cval.imag, format_code,
400 0, Py_DTSF_SIGN);
401 if (!pim) {
402 PyErr_NoMemory();
403 goto done;
404 }
405 im = pim;
406 }
407 lead = "(";
408 tail = ")";
409 }
410 /* Alloc the final buffer. Add one for the "j" in the format string, and
411 one for the trailing zero. */
412 len = strlen(lead) + strlen(re) + strlen(im) + strlen(tail) + 2;
413 buf = PyMem_Malloc(len);
Nick Coghlan 2009/04/09 10:52:04 Where does buf get freed?
ericvsmith 2009/04/09 11:44:20 Good catch. I'll fix that.
414 if (!buf) {
415 PyErr_NoMemory();
416 goto done;
417 }
418 PyOS_snprintf(buf, len, "%s%s%sj%s", lead, re, im, tail);
419 result = PyUnicode_FromString(buf);
420 done:
421 PyMem_Free(pim);
422 PyMem_Free(pre);
423
424 return result;
397 } 425 }
398 426
399 static PyObject * 427 static PyObject *
400 complex_repr(PyComplexObject *v) 428 complex_repr(PyComplexObject *v)
401 { 429 {
402 » char buf[100]; 430 return complex_format(v, 'r');
403 » complex_to_buf(buf, sizeof(buf), v, PREC_REPR);
404 » return PyUnicode_FromString(buf);
405 } 431 }
406 432
407 static PyObject * 433 static PyObject *
408 complex_str(PyComplexObject *v) 434 complex_str(PyComplexObject *v)
409 { 435 {
410 » char buf[100]; 436 return complex_format(v, 's');
411 » complex_to_buf(buf, sizeof(buf), v, PREC_STR);
412 » return PyUnicode_FromString(buf);
413 } 437 }
414 438
415 static long 439 static long
416 complex_hash(PyComplexObject *v) 440 complex_hash(PyComplexObject *v)
417 { 441 {
418 long hashreal, hashimag, combined; 442 long hashreal, hashimag, combined;
419 hashreal = _Py_HashDouble(v->cval.real); 443 hashreal = _Py_HashDouble(v->cval.real);
420 if (hashreal == -1) 444 if (hashreal == -1)
421 return -1; 445 return -1;
422 hashimag = _Py_HashDouble(v->cval.imag); 446 hashimag = _Py_HashDouble(v->cval.imag);
(...skipping 691 matching lines...) Expand 10 before | Expand all | Expand 10 after
1114 0, /* tp_descr_get */ 1138 0, /* tp_descr_get */
1115 0, /* tp_descr_set */ 1139 0, /* tp_descr_set */
1116 0, /* tp_dictoffset */ 1140 0, /* tp_dictoffset */
1117 0, /* tp_init */ 1141 0, /* tp_init */
1118 PyType_GenericAlloc, /* tp_alloc */ 1142 PyType_GenericAlloc, /* tp_alloc */
1119 complex_new, /* tp_new */ 1143 complex_new, /* tp_new */
1120 PyObject_Del, /* tp_free */ 1144 PyObject_Del, /* tp_free */
1121 }; 1145 };
1122 1146
1123 #endif 1147 #endif
OLDNEW

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b