Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
Pyston
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
Pyston
Commits
e98abcb2
Commit
e98abcb2
authored
Jan 11, 2016
by
Marius Wachtler
1
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1040 from Daetalus/complex_improvements_2
Add missing complex attributes
parents
2526c94e
fb612f83
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
377 additions
and
673 deletions
+377
-673
from_cpython/Include/complexobject.h
from_cpython/Include/complexobject.h
+0
-4
from_cpython/Objects/complexobject.c
from_cpython/Objects/complexobject.c
+32
-16
src/runtime/complex.cpp
src/runtime/complex.cpp
+295
-653
src/runtime/types.h
src/runtime/types.h
+4
-0
test/tests/complex.py
test/tests/complex.py
+46
-0
No files found.
from_cpython/Include/complexobject.h
View file @
e98abcb2
...
...
@@ -39,14 +39,10 @@ PyComplexObject represents a complex number with double-precision
real and imaginary parts.
*/
// Pyston change: this is not our object format
#if 0
typedef
struct
{
PyObject_HEAD
Py_complex
cval
;
}
PyComplexObject
;
#endif
typedef
struct
_PyComplexObject
PyComplexObject
;
// Pyston change: this is not a static object any more
// PyAPI_DATA(PyTypeObject) PyComplex_Type;
...
...
from_cpython/Objects/complexobject.c
View file @
e98abcb2
...
...
@@ -215,8 +215,6 @@ c_abs(Py_complex z)
return
result
;
}
// Pyston changes: comment this out
#if 0
static
PyObject
*
complex_subtype_from_c_complex
(
PyTypeObject
*
type
,
Py_complex
cval
)
{
...
...
@@ -356,14 +354,18 @@ PyComplex_AsCComplex(PyObject *op)
}
}
// Pyston changes: comment this out
#if 0
static void
complex_dealloc(PyObject *op)
{
op->ob_type->tp_free(op);
}
#endif
static PyObject *
// Pyston change: make no static
PyObject
*
complex_format
(
PyComplexObject
*
v
,
int
precision
,
char
format_code
)
{
PyObject
*
result
=
NULL
;
...
...
@@ -426,6 +428,8 @@ complex_format(PyComplexObject *v, int precision, char format_code)
return
result
;
}
// Pyston changes: comment this out
#if 0
static int
complex_print(PyComplexObject *v, FILE *fp, int flags)
{
...
...
@@ -788,8 +792,10 @@ complex_coerce(PyObject **pv, PyObject **pw)
}
return 1; /* Can't do it */
}
#endif
static PyObject *
// Pyston change: make no static
PyObject
*
complex_richcompare
(
PyObject
*
v
,
PyObject
*
w
,
int
op
)
{
PyObject
*
res
;
...
...
@@ -858,6 +864,8 @@ complex_richcompare(PyObject *v, PyObject *w, int op)
return
Py_NotImplemented
;
}
// Pyston change: comment this out
#if 0
static PyObject *
complex_int(PyObject *v)
{
...
...
@@ -907,8 +915,10 @@ PyDoc_STRVAR(complex__format__doc,
"complex.__format__() -> str\n"
"\n"
"Convert to a string according to format_spec.");
#endif
static PyObject *
// Pyston changes: make no static
PyObject
*
complex__format__
(
PyObject
*
self
,
PyObject
*
args
)
{
PyObject
*
format_spec
;
...
...
@@ -952,7 +962,6 @@ PyDoc_STRVAR(complex_is_finite_doc,
"complex.is_finite() -> bool\n"
"\n"
"Returns True if the real and the imaginary part is finite.");
#endif
static PyMethodDef complex_methods[] = {
{"conjugate", (PyCFunction)complex_conjugate, METH_NOARGS,
...
...
@@ -974,6 +983,7 @@ static PyMemberDef complex_members[] = {
"the imaginary part of a complex number"},
{0},
};
#endif
static
PyObject
*
complex_subtype_from_string
(
PyTypeObject
*
type
,
PyObject
*
v
)
...
...
@@ -1136,22 +1146,26 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v)
return
NULL
;
}
static PyObject *
complex_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *r, *i, *tmp;
// Pyston changes: change the API, make it no static
// and let complex_new accept unpacked arguments
PyObject
*
complex_new
(
PyTypeObject
*
type
,
PyObject
*
r
,
PyObject
*
i
)
{
PyObject
*
tmp
;
PyNumberMethods
*
nbr
,
*
nbi
=
NULL
;
Py_complex
cr
,
ci
;
int
own_r
=
0
;
int
cr_is_complex
=
0
;
int
ci_is_complex
=
0
;
static char *kwlist[] = {"real", "imag", 0};
r = Py_False;
i = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO:complex", kwlist,
&r, &i))
return NULL;
/* Pyston changes: comment this out, pyston don't use tuple arg.
static char *kwlist[] = {"real", "imag", 0};
r = Py_False;
i = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO:complex", kwlist,
&r, &i))
return NULL;
*/
/* Special-case for a single argument when type(arg) is complex. */
if
(
PyComplex_CheckExact
(
r
)
&&
i
==
NULL
&&
...
...
@@ -1269,6 +1283,8 @@ complex_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return
complex_subtype_from_doubles
(
type
,
cr
.
real
,
ci
.
real
);
}
// Pyston changes: comment this out
#if 0
PyDoc_STRVAR(complex_doc,
"complex(real[, imag]) -> complex number\n"
"\n"
...
...
src/runtime/complex.cpp
View file @
e98abcb2
...
...
@@ -22,227 +22,162 @@
#include "runtime/types.h"
extern
"C"
PyObject
*
complex_pow
(
PyObject
*
v
,
PyObject
*
w
,
PyObject
*
z
)
noexcept
;
extern
"C"
PyObject
*
complex_new
(
PyTypeObject
*
type
,
PyObject
*
r
,
PyObject
*
i
)
noexcept
;
extern
"C"
Py_complex
PyComplex_AsCComplex
(
PyObject
*
op
)
noexcept
;
extern
"C"
PyObject
*
complex_format
(
PyComplexObject
*
v
,
int
precision
,
char
format_code
)
noexcept
;
extern
"C"
PyObject
*
complex_richcompare
(
PyObject
*
v
,
PyObject
*
w
,
int
op
)
noexcept
;
extern
"C"
PyObject
*
complex__format__
(
PyObject
*
self
,
PyObject
*
args
)
noexcept
;
namespace
pyston
{
static
inline
void
raiseDivZeroExc
()
{
raiseExcHelper
(
ZeroDivisionError
,
"complex divide by zero"
);
}
extern
"C"
Box
*
createPureImaginary
(
double
i
)
{
return
new
BoxedComplex
(
0.0
,
i
);
}
static
PyObject
*
try_complex_special_method
(
PyObject
*
op
)
noexcept
{
PyObject
*
f
;
static
PyObject
*
complexstr
;
if
(
complexstr
==
NULL
)
{
complexstr
=
PyString_InternFromString
(
"__complex__"
);
if
(
complexstr
==
NULL
)
return
NULL
;
}
if
(
PyInstance_Check
(
op
))
{
f
=
PyObject_GetAttr
(
op
,
complexstr
);
if
(
f
==
NULL
)
{
if
(
PyErr_ExceptionMatches
(
PyExc_AttributeError
))
PyErr_Clear
();
else
return
NULL
;
}
}
else
{
f
=
_PyObject_LookupSpecial
(
op
,
"__complex__"
,
&
complexstr
);
if
(
f
==
NULL
&&
PyErr_Occurred
())
return
NULL
;
}
if
(
f
!=
NULL
)
{
PyObject
*
res
=
PyObject_CallFunctionObjArgs
(
f
,
NULL
);
Py_DECREF
(
f
);
return
res
;
}
return
NULL
;
}
extern
"C"
Py_complex
PyComplex_AsCComplex
(
PyObject
*
op
)
noexcept
{
Py_complex
cv
;
PyObject
*
newop
=
NULL
;
assert
(
op
);
/* If op is already of type PyComplex_Type, return its value */
if
(
PyComplex_Check
(
op
))
{
cv
.
real
=
((
BoxedComplex
*
)
op
)
->
real
;
cv
.
imag
=
((
BoxedComplex
*
)
op
)
->
imag
;
return
cv
;
}
/* If not, use op's __complex__ method, if it exists */
/* return -1 on failure */
cv
.
real
=
-
1.
;
cv
.
imag
=
0.
;
newop
=
try_complex_special_method
(
op
);
if
(
newop
)
{
if
(
!
PyComplex_Check
(
newop
))
{
PyErr_SetString
(
PyExc_TypeError
,
"__complex__ should return a complex object"
);
Py_DECREF
(
newop
);
return
cv
;
}
cv
.
real
=
((
BoxedComplex
*
)
newop
)
->
real
;
cv
.
imag
=
((
BoxedComplex
*
)
newop
)
->
imag
;
Py_DECREF
(
newop
);
return
cv
;
}
else
if
(
PyErr_Occurred
())
{
return
cv
;
}
/* If neither of the above works, interpret op as a float giving the
real part of the result, and fill in the imaginary part as 0. */
else
{
/* PyFloat_AsDouble will return -1 on failure */
cv
.
real
=
PyFloat_AsDouble
(
op
);
return
cv
;
}
}
extern
"C"
double
PyComplex_RealAsDouble
(
PyObject
*
op
)
noexcept
{
if
(
PyComplex_Check
(
op
))
{
return
static_cast
<
BoxedComplex
*>
(
op
)
->
real
;
}
else
{
return
PyFloat_AsDouble
(
op
);
static
Box
*
toComplex
(
Box
*
self
)
noexcept
{
BoxedComplex
*
r
;
if
(
self
==
NULL
)
{
return
new
BoxedComplex
(
0.0
,
0.0
);
}
}
extern
"C"
double
PyComplex_ImagAsDouble
(
PyObject
*
op
)
noexcept
{
if
(
PyComplex_Check
(
op
))
{
return
static_cast
<
BoxedComplex
*>
(
op
)
->
imag
;
if
(
PyComplex_Check
(
self
))
{
r
=
(
BoxedComplex
*
)
self
;
}
else
if
(
PyInt_Check
(
self
))
{
r
=
new
BoxedComplex
(
static_cast
<
BoxedInt
*>
(
self
)
->
n
,
0.0
);
}
else
if
(
PyFloat_Check
(
self
))
{
r
=
new
BoxedComplex
((
static_cast
<
BoxedFloat
*>
(
PyNumber_Float
(
self
)))
->
d
,
0.0
);
}
else
if
(
PyLong_Check
(
self
))
{
double
real
=
PyLong_AsDouble
(
self
);
if
(
real
==
-
1
&&
PyErr_Occurred
())
throwCAPIException
();
r
=
new
BoxedComplex
(
real
,
0.0
);
}
else
{
return
0.0
;
return
NotImplemented
;
}
return
r
;
}
extern
"C"
PyObject
*
PyComplex_FromDoubles
(
double
real
,
double
imag
)
noexcept
{
r
eturn
new
BoxedComplex
(
real
,
imag
);
static
inline
void
raiseDivZeroExc
()
{
r
aiseExcHelper
(
ZeroDivisionError
,
"complex division by zero"
);
}
extern
"C"
PyObject
*
PyComplex_FromCComplex
(
Py_complex
val
)
noexcept
{
return
new
BoxedComplex
(
val
.
real
,
val
.
imag
);
extern
"C"
Box
*
createPureImaginary
(
double
i
)
{
return
new
BoxedComplex
(
0.0
,
i
);
}
// addition
extern
"C"
Box
*
complexAddComplex
(
BoxedComplex
*
lhs
,
BoxedComplex
*
rhs
)
{
assert
(
lhs
->
cls
==
complex_cls
);
assert
(
rhs
->
cls
==
complex_cls
);
assert
(
PyComplex_Check
(
lhs
)
);
assert
(
PyComplex_Check
(
rhs
)
);
return
boxComplex
(
lhs
->
real
+
rhs
->
real
,
lhs
->
imag
+
rhs
->
imag
);
}
extern
"C"
Box
*
complexAddFloat
(
BoxedComplex
*
lhs
,
BoxedFloat
*
rhs
)
{
assert
(
lhs
->
cls
==
complex_cls
);
assert
(
rhs
->
cls
==
float_cls
);
assert
(
PyComplex_Check
(
lhs
)
);
assert
(
PyFloat_Check
(
rhs
)
);
return
boxComplex
(
lhs
->
real
+
rhs
->
d
,
lhs
->
imag
);
}
extern
"C"
Box
*
complexAddInt
(
BoxedComplex
*
lhs
,
BoxedInt
*
rhs
)
{
assert
(
lhs
->
cls
==
complex_cls
);
assert
(
PyComplex_Check
(
lhs
)
);
assert
(
PyInt_Check
(
rhs
));
return
boxComplex
(
lhs
->
real
+
(
double
)
rhs
->
n
,
lhs
->
imag
);
}
extern
"C"
Box
*
complexAdd
(
BoxedComplex
*
lhs
,
Box
*
rhs
)
{
assert
(
lhs
->
cls
==
complex_cls
);
if
(
PyInt_Check
(
rhs
))
{
return
complexAddInt
(
lhs
,
static_cast
<
BoxedInt
*>
(
rhs
));
}
else
if
(
rhs
->
cls
==
float_cls
)
{
return
complexAddFloat
(
lhs
,
static_cast
<
BoxedFloat
*>
(
rhs
));
}
else
if
(
rhs
->
cls
==
complex_cls
)
{
return
complexAddComplex
(
lhs
,
static_cast
<
BoxedComplex
*>
(
rhs
));
}
else
{
extern
"C"
Box
*
complexAdd
(
BoxedComplex
*
lhs
,
Box
*
_rhs
)
{
if
(
!
PyComplex_Check
(
lhs
))
raiseExcHelper
(
TypeError
,
"descriptor '__add__' requires a 'complex' object but received a '%s'"
,
getTypeName
(
lhs
));
Box
*
rhs
=
toComplex
(
_rhs
);
if
(
rhs
==
NotImplemented
)
return
NotImplemented
;
}
BoxedComplex
*
rhs_complex
=
static_cast
<
BoxedComplex
*>
(
rhs
);
return
complexAddComplex
(
lhs
,
rhs_complex
);
}
// subtraction
extern
"C"
Box
*
complexSubComplex
(
BoxedComplex
*
lhs
,
BoxedComplex
*
rhs
)
{
assert
(
lhs
->
cls
==
complex_cls
);
assert
(
rhs
->
cls
==
complex_cls
);
assert
(
PyComplex_Check
(
lhs
)
);
assert
(
PyComplex_Check
(
rhs
)
);
return
boxComplex
(
lhs
->
real
-
rhs
->
real
,
lhs
->
imag
-
rhs
->
imag
);
}
extern
"C"
Box
*
complexSubFloat
(
BoxedComplex
*
lhs
,
BoxedFloat
*
rhs
)
{
assert
(
lhs
->
cls
==
complex_cls
);
assert
(
rhs
->
cls
==
float_cls
);
assert
(
PyComplex_Check
(
lhs
)
);
assert
(
PyFloat_Check
(
rhs
)
);
return
boxComplex
(
lhs
->
real
-
rhs
->
d
,
lhs
->
imag
);
}
extern
"C"
Box
*
complexSubInt
(
BoxedComplex
*
lhs
,
BoxedInt
*
rhs
)
{
assert
(
lhs
->
cls
==
complex_cls
);
assert
(
PyComplex_Check
(
lhs
)
);
assert
(
PyInt_Check
(
rhs
));
return
boxComplex
(
lhs
->
real
-
(
double
)
rhs
->
n
,
lhs
->
imag
);
}
extern
"C"
Box
*
complexSub
(
BoxedComplex
*
lhs
,
Box
*
rhs
)
{
assert
(
lhs
->
cls
==
complex_cls
);
if
(
PyInt_Check
(
rhs
))
{
return
complexSubInt
(
lhs
,
static_cast
<
BoxedInt
*>
(
rhs
));
}
else
if
(
rhs
->
cls
==
float_cls
)
{
return
complexSubFloat
(
lhs
,
static_cast
<
BoxedFloat
*>
(
rhs
));
}
else
if
(
rhs
->
cls
==
complex_cls
)
{
return
complexSubComplex
(
lhs
,
static_cast
<
BoxedComplex
*>
(
rhs
));
}
else
{
extern
"C"
Box
*
complexSub
(
BoxedComplex
*
lhs
,
Box
*
_rhs
)
{
if
(
!
PyComplex_Check
(
lhs
))
raiseExcHelper
(
TypeError
,
"descriptor '__sub__' requires a 'complex' object but received a '%s'"
,
getTypeName
(
lhs
));
Box
*
rhs
=
toComplex
(
_rhs
);
if
(
rhs
==
NotImplemented
)
return
NotImplemented
;
}
BoxedComplex
*
rhs_complex
=
static_cast
<
BoxedComplex
*>
(
rhs
);
return
complexSubComplex
(
lhs
,
rhs_complex
);
}
extern
"C"
Box
*
complexRSub
(
BoxedComplex
*
_
lhs
,
Box
*
_rhs
)
{
if
(
!
PyComplex_Check
(
_
lhs
))
extern
"C"
Box
*
complexRSub
(
BoxedComplex
*
lhs
,
Box
*
_rhs
)
{
if
(
!
PyComplex_Check
(
lhs
))
raiseExcHelper
(
TypeError
,
"descriptor '__rsub__' requires a 'complex' object but received a '%s'"
,
getTypeName
(
_lhs
));
BoxedComplex
*
lhs
=
new
BoxedComplex
(
0.0
,
0.0
);
if
(
PyInt_Check
(
_rhs
))
{
lhs
->
real
=
(
static_cast
<
BoxedInt
*>
(
_rhs
))
->
n
;
}
else
if
(
_rhs
->
cls
==
float_cls
)
{
lhs
->
real
=
(
static_cast
<
BoxedFloat
*>
(
_rhs
))
->
d
;
}
else
if
(
_rhs
->
cls
==
complex_cls
)
{
lhs
=
static_cast
<
BoxedComplex
*>
(
_rhs
);
}
else
{
getTypeName
(
lhs
));
Box
*
rhs
=
toComplex
(
_rhs
);
if
(
rhs
==
NotImplemented
)
return
NotImplemented
;
}
return
complexSubComplex
(
lhs
,
_lhs
);
BoxedComplex
*
rhs_complex
=
static_cast
<
BoxedComplex
*>
(
rhs
);
return
complexSubComplex
(
rhs_complex
,
lhs
);
}
// multiplication
extern
"C"
Box
*
complexMulComplex
(
BoxedComplex
*
lhs
,
BoxedComplex
*
rhs
)
{
assert
(
lhs
->
cls
==
complex_cls
);
assert
(
rhs
->
cls
==
complex_cls
);
assert
(
PyComplex_Check
(
lhs
)
);
assert
(
PyComplex_Check
(
rhs
)
);
return
boxComplex
(
lhs
->
real
*
rhs
->
real
-
lhs
->
imag
*
rhs
->
imag
,
lhs
->
real
*
rhs
->
imag
+
lhs
->
imag
*
rhs
->
real
);
}
extern
"C"
Box
*
complexMulFloat
(
BoxedComplex
*
lhs
,
BoxedFloat
*
rhs
)
{
assert
(
lhs
->
cls
==
complex_cls
);
assert
(
rhs
->
cls
==
float_cls
);
assert
(
PyComplex_Check
(
lhs
)
);
assert
(
PyFloat_Check
(
rhs
)
);
return
boxComplex
(
lhs
->
real
*
rhs
->
d
,
lhs
->
imag
*
rhs
->
d
);
}
extern
"C"
Box
*
complexMulInt
(
BoxedComplex
*
lhs
,
BoxedInt
*
rhs
)
{
assert
(
lhs
->
cls
==
complex_cls
);
assert
(
PyComplex_Check
(
lhs
)
);
assert
(
PyInt_Check
(
rhs
));
return
boxComplex
(
lhs
->
real
*
(
double
)
rhs
->
n
,
lhs
->
imag
*
(
double
)
rhs
->
n
);
}
extern
"C"
Box
*
complexMul
(
BoxedComplex
*
lhs
,
Box
*
rhs
)
{
assert
(
lhs
->
cls
==
complex_cls
);
if
(
PyInt_Check
(
rhs
))
{
return
complexMulInt
(
lhs
,
static_cast
<
BoxedInt
*>
(
rhs
));
}
else
if
(
rhs
->
cls
==
float_cls
)
{
return
complexMulFloat
(
lhs
,
static_cast
<
BoxedFloat
*>
(
rhs
));
}
else
if
(
rhs
->
cls
==
complex_cls
)
{
return
complexMulComplex
(
lhs
,
static_cast
<
BoxedComplex
*>
(
rhs
));
}
else
{
extern
"C"
Box
*
complexMul
(
BoxedComplex
*
lhs
,
Box
*
_rhs
)
{
if
(
!
PyComplex_Check
(
lhs
))
raiseExcHelper
(
TypeError
,
"descriptor '__mul__' requires a 'complex' object but received a '%s'"
,
getTypeName
(
lhs
));
Box
*
rhs
=
toComplex
(
_rhs
);
if
(
rhs
==
NotImplemented
)
return
NotImplemented
;
}
BoxedComplex
*
rhs_complex
=
static_cast
<
BoxedComplex
*>
(
rhs
);
return
complexMulComplex
(
lhs
,
rhs_complex
);
}
// division
...
...
@@ -250,7 +185,7 @@ Box* complexDivComplex(BoxedComplex* lhs, BoxedComplex* rhs) {
if
(
!
PyComplex_Check
(
lhs
))
raiseExcHelper
(
TypeError
,
"descriptor '__div__' requires a 'complex' object but received a '%s'"
,
getTypeName
(
lhs
));
assert
(
rhs
->
cls
==
complex_cls
);
assert
(
PyComplex_Check
(
rhs
)
);
double
real_f
,
imag_f
;
const
double
abs_breal
=
rhs
->
real
<
0
?
-
rhs
->
real
:
rhs
->
real
;
...
...
@@ -299,36 +234,72 @@ extern "C" Box* complexDivInt(BoxedComplex* lhs, BoxedInt* rhs) {
return
boxComplex
(
lhs
->
real
/
(
double
)
rhs
->
n
,
lhs
->
imag
/
(
double
)
rhs
->
n
);
}
extern
"C"
Box
*
complexDiv
(
BoxedComplex
*
lhs
,
Box
*
rhs
)
{
extern
"C"
Box
*
complexDiv
(
BoxedComplex
*
lhs
,
Box
*
_
rhs
)
{
if
(
!
PyComplex_Check
(
lhs
))
raiseExcHelper
(
TypeError
,
"descriptor '__div__' requires a 'complex' object but received a '%s'"
,
getTypeName
(
lhs
));
Box
*
rhs
=
toComplex
(
_rhs
);
if
(
rhs
==
NotImplemented
)
return
NotImplemented
;
BoxedComplex
*
rhs_complex
=
static_cast
<
BoxedComplex
*>
(
rhs
);
return
complexDivComplex
(
lhs
,
rhs_complex
);
}
extern
"C"
Box
*
complexRDiv
(
BoxedComplex
*
lhs
,
Box
*
_rhs
)
{
if
(
!
PyComplex_Check
(
lhs
))
raiseExcHelper
(
TypeError
,
"descriptor '__rdiv__' requires a 'complex' object but received a '%s'"
,
getTypeName
(
lhs
));
Box
*
rhs
=
toComplex
(
_rhs
);
if
(
rhs
==
NotImplemented
)
return
NotImplemented
;
BoxedComplex
*
rhs_complex
=
static_cast
<
BoxedComplex
*>
(
rhs
);
return
complexDivComplex
(
rhs_complex
,
lhs
);
}
Box
*
complexTruediv
(
BoxedComplex
*
lhs
,
Box
*
rhs
)
{
if
(
!
PyComplex_Check
(
lhs
))
raiseExcHelper
(
TypeError
,
"descriptor '__truediv__' requires a 'complex' object but received a '%s'"
,
getTypeName
(
lhs
));
if
(
PyInt_Check
(
rhs
))
{
return
complexDivInt
(
lhs
,
static_cast
<
BoxedInt
*>
(
rhs
));
}
else
if
(
rhs
->
cls
==
float_cls
)
{
}
else
if
(
PyFloat_Check
(
rhs
)
)
{
return
complexDivFloat
(
lhs
,
static_cast
<
BoxedFloat
*>
(
rhs
));
}
else
if
(
rhs
->
cls
==
complex_cls
)
{
}
else
if
(
PyComplex_Check
(
rhs
)
)
{
return
complexDivComplex
(
lhs
,
static_cast
<
BoxedComplex
*>
(
rhs
));
}
else
if
(
PyLong_Check
(
rhs
))
{
double
res
=
PyLong_AsDouble
(
rhs
);
if
(
res
==
-
1
&&
PyErr_Occurred
())
throwCAPIException
();
return
complexDivFloat
(
lhs
,
(
BoxedFloat
*
)
boxFloat
(
res
));
}
else
{
return
NotImplemented
;
}
}
extern
"C"
Box
*
complexRDiv
(
BoxedComplex
*
_lhs
,
Box
*
_rhs
)
{
if
(
!
PyComplex_Check
(
_lhs
))
raiseExcHelper
(
TypeError
,
"descriptor '__rdiv__' requires a 'complex' object but received a '%s'"
,
getTypeName
(
_lhs
));
BoxedComplex
*
lhs
=
new
BoxedComplex
(
0.0
,
0.0
);
if
(
PyInt_Check
(
_rhs
))
{
lhs
->
real
=
(
static_cast
<
BoxedInt
*>
(
_rhs
))
->
n
;
}
else
if
(
_rhs
->
cls
==
float_cls
)
{
lhs
->
real
=
(
static_cast
<
BoxedFloat
*>
(
_rhs
))
->
d
;
}
else
if
(
_rhs
->
cls
==
complex_cls
)
{
lhs
=
static_cast
<
BoxedComplex
*>
(
_rhs
);
}
else
{
Box
*
complexRTruediv
(
BoxedComplex
*
lhs
,
Box
*
_rhs
)
{
if
(
!
PyComplex_Check
(
lhs
))
raiseExcHelper
(
TypeError
,
"descriptor '__rtruediv__' requires a 'complex' object but received a '%s'"
,
getTypeName
(
lhs
));
if
(
_rhs
==
None
)
return
NotImplemented
;
}
return
complexDivComplex
(
lhs
,
_lhs
);
Box
*
rhs
=
toComplex
(
_rhs
);
if
(
rhs
==
NotImplemented
)
return
NotImplemented
;
BoxedComplex
*
rhs_complex
=
static_cast
<
BoxedComplex
*>
(
rhs
);
return
complexDivComplex
(
rhs_complex
,
lhs
);
}
Box
*
complexPos
(
BoxedComplex
*
self
)
{
...
...
@@ -338,65 +309,13 @@ Box* complexPos(BoxedComplex* self) {
return
PyComplex_FromDoubles
(
self
->
real
,
self
->
imag
);
}
// str and repr
Box
*
complex_fmt
(
double
r
,
double
i
,
int
precision
,
char
format_code
)
noexcept
{
PyObject
*
result
=
NULL
;
/* If these are non-NULL, they'll need to be freed. */
char
*
pre
=
NULL
;
char
*
im
=
NULL
;
/* These do not need to be freed. re is either an alias
for pre or a pointer to a constant. lead and tail
are pointers to constants. */
std
::
string
lead
=
""
;
std
::
string
tail
=
""
;
std
::
string
re
=
""
;
std
::
string
result_str
;
if
(
r
==
0.
&&
copysign
(
1.0
,
r
)
==
1.0
)
{
re
=
""
;
im
=
PyOS_double_to_string
(
i
,
format_code
,
precision
,
0
,
NULL
);
if
(
!
im
)
{
PyErr_NoMemory
();
goto
done
;
}
}
else
{
/* Format imaginary part with signr part without */
pre
=
PyOS_double_to_string
(
r
,
format_code
,
precision
,
0
,
NULL
);
if
(
!
pre
)
{
PyErr_NoMemory
();
goto
done
;
}
re
=
std
::
string
(
pre
);
im
=
PyOS_double_to_string
(
i
,
format_code
,
precision
,
Py_DTSF_SIGN
,
NULL
);
if
(
!
im
)
{
PyErr_NoMemory
();
goto
done
;
}
lead
=
"("
;
tail
=
")"
;
}
/* Alloc the final buffer. Add one for the "j" in the format string,
and one for the trailing zero. */
result_str
=
lead
+
std
::
string
(
re
)
+
std
::
string
(
im
)
+
"j"
+
tail
;
result
=
PyString_FromString
(
result_str
.
c_str
());
done:
PyMem_Free
(
im
);
PyMem_Free
(
pre
);
return
result
;
}
static
void
_addFunc
(
const
char
*
name
,
ConcreteCompilerType
*
rtn_type
,
void
*
complex_func
,
void
*
float_func
,
void
*
int_func
,
void
*
boxed_func
)
{
FunctionMetadata
*
md
=
new
FunctionMetadata
(
2
,
false
,
false
);
md
->
addVersion
(
complex_func
,
rtn_type
,
{
BOXED_COMPLEX
,
BOXED_COMPLEX
});
md
->
addVersion
(
float_func
,
rtn_type
,
{
BOXED_COMPLEX
,
BOXED_FLOAT
});
md
->
addVersion
(
int_func
,
rtn_type
,
{
BOXED_COMPLEX
,
BOXED_INT
});
md
->
addVersion
(
boxed_func
,
UNKNOWN
,
{
BOXED_COMPLEX
,
UNKNOWN
});
md
->
addVersion
(
boxed_func
,
UNKNOWN
,
{
UNKNOWN
,
UNKNOWN
});
complex_cls
->
giveAttr
(
name
,
new
BoxedFunction
(
md
));
}
...
...
@@ -411,21 +330,19 @@ Box* complexPow(BoxedComplex* lhs, Box* _rhs, Box* mod) {
return
res
;
}
Box
*
complexR
pow
(
BoxedComplex
*
_
lhs
,
Box
*
_rhs
)
{
if
(
!
PyComplex_Check
(
_
lhs
))
Box
*
complexR
Pow
(
BoxedComplex
*
lhs
,
Box
*
_rhs
)
{
if
(
!
PyComplex_Check
(
lhs
))
raiseExcHelper
(
TypeError
,
"descriptor '__rpow__' requires a 'complex' object but received a '%s'"
,
getTypeName
(
_lhs
));
BoxedComplex
*
lhs
=
new
BoxedComplex
(
0.0
,
0.0
);
if
(
PyInt_Check
(
_rhs
))
{
lhs
->
real
=
(
static_cast
<
BoxedInt
*>
(
_rhs
))
->
n
;
}
else
if
(
_rhs
->
cls
==
float_cls
)
{
lhs
->
real
=
(
static_cast
<
BoxedFloat
*>
(
_rhs
))
->
d
;
}
else
if
(
_rhs
->
cls
==
complex_cls
)
{
lhs
=
static_cast
<
BoxedComplex
*>
(
_rhs
);
}
else
{
getTypeName
(
lhs
));
Box
*
rhs
=
toComplex
(
_rhs
);
if
(
rhs
==
NotImplemented
)
return
NotImplemented
;
}
return
complexPow
(
lhs
,
_lhs
,
None
);
BoxedComplex
*
rhs_complex
=
static_cast
<
BoxedComplex
*>
(
rhs
);
return
complexPow
(
rhs_complex
,
lhs
,
None
);
}
Box
*
complexHash
(
BoxedComplex
*
self
)
{
...
...
@@ -517,398 +434,164 @@ Box* complexStr(BoxedComplex* self) {
if
(
!
PyComplex_Check
(
self
))
raiseExcHelper
(
TypeError
,
"descriptor '__str__' requires a 'complex' object but received a '%s'"
,
getTypeName
(
self
));
Box
*
r
=
complex_fmt
(
self
->
real
,
self
->
imag
,
12
,
'g'
);
Box
*
r
=
complex_format
((
PyComplexObject
*
)
self
,
12
,
'g'
);
if
(
!
r
)
{
throwCAPIException
();
}
return
r
;
}
Box
*
complex
Repr
(
BoxedComplex
*
self
)
{
Box
*
complex
Int
(
BoxedComplex
*
self
)
{
if
(
!
PyComplex_Check
(
self
))
raiseExcHelper
(
TypeError
,
"descriptor '__
repr
__' requires a 'complex' object but received a '%s'"
,
raiseExcHelper
(
TypeError
,
"descriptor '__
int
__' requires a 'complex' object but received a '%s'"
,
getTypeName
(
self
));
Box
*
r
=
complex_fmt
(
self
->
real
,
self
->
imag
,
16
,
'g'
);
if
(
!
r
)
{
throwCAPIException
();
}
return
r
;
}
static
PyObject
*
complex_subtype_from_string
(
PyObject
*
v
)
noexcept
{
const
char
*
s
,
*
start
;
char
*
end
;
double
x
=
0.0
,
y
=
0.0
,
z
;
int
got_bracket
=
0
;
#ifdef Py_USING_UNICODE
char
*
s_buffer
=
NULL
;
#endif
Py_ssize_t
len
;
if
(
PyString_Check
(
v
))
{
s
=
PyString_AS_STRING
(
v
);
len
=
PyString_GET_SIZE
(
v
);
}
#ifdef Py_USING_UNICODE
else
if
(
PyUnicode_Check
(
v
))
{
s_buffer
=
(
char
*
)
PyMem_MALLOC
(
PyUnicode_GET_SIZE
(
v
)
+
1
);
if
(
s_buffer
==
NULL
)
return
PyErr_NoMemory
();
if
(
PyUnicode_EncodeDecimal
(
PyUnicode_AS_UNICODE
(
v
),
PyUnicode_GET_SIZE
(
v
),
s_buffer
,
NULL
))
goto
error
;
s
=
s_buffer
;
len
=
strlen
(
s
);
}
#endif
else
if
(
PyObject_AsCharBuffer
(
v
,
&
s
,
&
len
))
{
PyErr_SetString
(
PyExc_TypeError
,
"complex() arg is not a string"
);
return
NULL
;
}
/* position on first nonblank */
start
=
s
;
while
(
Py_ISSPACE
(
*
s
))
s
++
;
if
(
*
s
==
'('
)
{
/* Skip over possible bracket from repr(). */
got_bracket
=
1
;
s
++
;
while
(
Py_ISSPACE
(
*
s
))
s
++
;
}
/* a valid complex string usually takes one of the three forms:
<float> - real part only
<float>j - imaginary part only
<float><signed-float>j - real and imaginary parts
where <float> represents any numeric string that's accepted by the
float constructor (including 'nan', 'inf', 'infinity', etc.), and
<signed-float> is any string of the form <float> whose first
character is '+' or '-'.
For backwards compatibility, the extra forms
<float><sign>j
<sign>j
j
raiseExcHelper
(
TypeError
,
"can't convert complex to int"
);
}
are also accepted, though support for these forms may be removed from
a future version of Python.
*/
Box
*
complexFloat
(
BoxedComplex
*
self
)
{
if
(
!
PyComplex_Check
(
self
))
raiseExcHelper
(
TypeError
,
"descriptor '__float__' requires a 'complex' object but received a '%s'"
,
getTypeName
(
self
));
/* first look for forms starting with <float> */
z
=
PyOS_string_to_double
(
s
,
&
end
,
NULL
);
if
(
z
==
-
1.0
&&
PyErr_Occurred
())
{
if
(
PyErr_ExceptionMatches
(
PyExc_ValueError
))
PyErr_Clear
();
else
goto
error
;
}
if
(
end
!=
s
)
{
/* all 4 forms starting with <float> land here */
s
=
end
;
if
(
*
s
==
'+'
||
*
s
==
'-'
)
{
/* <float><signed-float>j | <float><sign>j */
x
=
z
;
y
=
PyOS_string_to_double
(
s
,
&
end
,
NULL
);
if
(
y
==
-
1.0
&&
PyErr_Occurred
())
{
if
(
PyErr_ExceptionMatches
(
PyExc_ValueError
))
PyErr_Clear
();
else
goto
error
;
}
if
(
end
!=
s
)
/* <float><signed-float>j */
s
=
end
;
else
{
/* <float><sign>j */
y
=
*
s
==
'+'
?
1.0
:
-
1.0
;
s
++
;
}
if
(
!
(
*
s
==
'j'
||
*
s
==
'J'
))
goto
parse_error
;
s
++
;
}
else
if
(
*
s
==
'j'
||
*
s
==
'J'
)
{
/* <float>j */
s
++
;
y
=
z
;
}
else
/* <float> */
x
=
z
;
}
else
{
/* not starting with <float>; must be <sign>j or j */
if
(
*
s
==
'+'
||
*
s
==
'-'
)
{
/* <sign>j */
y
=
*
s
==
'+'
?
1.0
:
-
1.0
;
s
++
;
}
else
/* j */
y
=
1.0
;
if
(
!
(
*
s
==
'j'
||
*
s
==
'J'
))
goto
parse_error
;
s
++
;
}
raiseExcHelper
(
TypeError
,
"can't convert complex to float"
);
}
/* trailing whitespace and closing bracket */
while
(
Py_ISSPACE
(
*
s
))
s
++
;
if
(
got_bracket
)
{
/* if there was an opening parenthesis, then the corresponding
closing parenthesis should be right here */
if
(
*
s
!=
')'
)
goto
parse_error
;
s
++
;
while
(
Py_ISSPACE
(
*
s
))
s
++
;
}
Box
*
complexLong
(
BoxedComplex
*
self
)
{
if
(
!
PyComplex_Check
(
self
))
raiseExcHelper
(
TypeError
,
"descriptor '__long__' requires a 'complex' object but received a '%s'"
,
getTypeName
(
self
));
/* we should now be at the end of the string */
if
(
s
-
start
!=
len
)
goto
parse_error
;
#ifdef Py_USING_UNICODE
if
(
s_buffer
)
PyMem_FREE
(
s_buffer
);
#endif
return
new
BoxedComplex
(
x
,
y
);
parse_error:
PyErr_SetString
(
PyExc_ValueError
,
"complex() arg is a malformed string"
);
error:
#ifdef Py_USING_UNICODE
if
(
s_buffer
)
PyMem_FREE
(
s_buffer
);
#endif
return
NULL
;
raiseExcHelper
(
TypeError
,
"can't convert complex to long"
);
}
Box
*
complexRepr
(
BoxedComplex
*
self
)
{
if
(
!
PyComplex_Check
(
self
))
raiseExcHelper
(
TypeError
,
"descriptor '__repr__' requires a 'complex' object but received a '%s'"
,
getTypeName
(
self
));
static
Box
*
to_complex
(
Box
*
self
)
noexcept
{
BoxedComplex
*
r
;
if
(
self
==
None
||
self
==
NULL
)
{
return
new
BoxedComplex
(
0.0
,
0.0
);
}
static
BoxedString
*
complex_str
=
internStringImmortal
(
"__complex__"
);
if
(
PyComplex_Check
(
self
)
&&
!
PyObject_HasAttr
((
PyObject
*
)
self
,
complex_str
))
{
r
=
(
BoxedComplex
*
)
self
;
}
else
if
(
PyInt_Check
(
self
))
{
r
=
new
BoxedComplex
(
static_cast
<
BoxedInt
*>
(
self
)
->
n
,
0.0
);
}
else
if
(
PyFloat_Check
(
self
))
{
r
=
new
BoxedComplex
((
static_cast
<
BoxedFloat
*>
(
PyNumber_Float
(
self
)))
->
d
,
0.0
);
}
else
if
(
self
->
cls
==
long_cls
)
{
r
=
new
BoxedComplex
(
PyLong_AsDouble
(
self
),
0.0
);
}
else
{
return
NotImplemented
;
Box
*
r
=
complex_format
((
PyComplexObject
*
)
self
,
16
,
'g'
);
if
(
!
r
)
{
throwCAPIException
();
}
return
r
;
}
template
<
ExceptionStyle
S
>
static
Box
*
try_special_method
(
Box
*
self
)
noexcept
(
S
==
CAPI
)
{
if
(
self
==
None
||
self
==
NULL
)
{
return
None
;
}
static
BoxedString
*
float_str
=
internStringImmortal
(
"__float__"
);
if
(
PyObject_HasAttr
((
PyObject
*
)
self
,
float_str
))
{
Box
*
r_f
=
callattrInternal
<
S
,
NOT_REWRITABLE
>
(
self
,
float_str
,
CLASS_ONLY
,
NULL
,
ArgPassSpec
(
0
),
NULL
,
NULL
,
NULL
,
NULL
,
NULL
);
if
(
!
PyFloat_Check
(
r_f
))
{
if
(
S
==
CAPI
)
{
if
(
!
PyErr_Occurred
())
PyErr_Format
(
PyExc_TypeError
,
"__float__ returned non-float (type %.200s)"
,
r_f
->
cls
->
tp_name
);
return
NULL
;
}
else
{
raiseExcHelper
(
TypeError
,
"__float__ returned non-float (type %.200s)"
,
r_f
->
cls
->
tp_name
);
}
}
return
(
BoxedFloat
*
)
r_f
;
}
static
BoxedString
*
complex_str
=
internStringImmortal
(
"__complex__"
);
if
(
PyObject_HasAttr
((
PyObject
*
)
self
,
complex_str
))
{
Box
*
r
=
callattrInternal
<
S
,
NOT_REWRITABLE
>
(
self
,
complex_str
,
CLASS_OR_INST
,
NULL
,
ArgPassSpec
(
0
),
NULL
,
NULL
,
NULL
,
NULL
,
NULL
);
if
(
!
r
)
{
if
(
S
==
CAPI
)
{
if
(
!
PyErr_Occurred
())
PyErr_Format
(
TypeError
,
"complex() argument must be a string or a number, not '%s'
\n
"
,
getTypeName
(
self
));
return
NULL
;
}
else
{
raiseExcHelper
(
TypeError
,
"complex() argument must be a string or a number, not '%s'
\n
"
,
getTypeName
(
self
));
}
}
if
(
!
PyComplex_Check
(
r
))
{
if
(
S
==
CAPI
)
{
PyErr_Format
(
TypeError
,
"__complex__ returned non-complex (type %s)"
,
r
->
cls
->
tp_name
);
return
NULL
;
}
else
raiseExcHelper
(
TypeError
,
"__complex__ returned non-complex (type %s)"
,
r
->
cls
->
tp_name
);
}
return
static_cast
<
BoxedComplex
*>
(
r
);
template
<
ExceptionStyle
S
>
Box
*
complexNew
(
BoxedClass
*
cls
,
Box
*
real
,
Box
*
imag
)
noexcept
(
S
==
CAPI
)
{
if
(
real
==
NULL
)
{
real
=
Py_False
;
imag
=
NULL
;
}
return
None
;
Box
*
res
=
complex_new
(
cls
,
real
,
imag
);
if
(
S
==
CXX
&&
res
==
NULL
)
throwCAPIException
();
return
res
;
}
template
<
ExceptionStyle
S
>
Box
*
_complexNew
(
Box
*
real
,
Box
*
imag
)
noexcept
(
S
==
CAPI
)
{
// handle str and unicode
if
(
real
!=
None
&&
real
!=
NULL
)
{
if
(
PyString_Check
(
real
)
||
PyUnicode_Check
(
real
))
{
if
(
imag
!=
None
&&
imag
!=
NULL
)
{
raiseExcHelper
(
TypeError
,
"complex() can't take second arg if first is a string"
);
}
Box
*
res
=
complex_subtype_from_string
(
real
);
if
(
res
==
NULL
)
{
throwCAPIException
();
}
return
res
;
}
}
Box
*
complexDivmodComplex
(
BoxedComplex
*
lhs
,
Box
*
_rhs
)
{
if
(
PyErr_Warn
(
PyExc_DeprecationWarning
,
"complex divmod(), // and % are deprecated"
)
<
0
)
throwCAPIException
();
if
(
real
!=
None
&&
real
!=
NULL
&&
real
->
cls
==
complex_cls
&&
(
imag
==
NULL
||
imag
==
None
))
{
return
static_cast
<
BoxedComplex
*>
(
real
);
}
Box
*
rhs
=
toComplex
(
_rhs
);
Box
*
_real
=
try_special_method
<
S
>
(
real
);
Box
*
_imag
=
try_special_method
<
S
>
(
imag
)
;
if
(
rhs
==
NotImplemented
)
return
NotImplemented
;
if
(
_real
!=
None
&&
_real
!=
NULL
)
{
real
=
_real
;
}
BoxedComplex
*
rhs_complex
=
static_cast
<
BoxedComplex
*>
(
rhs
);
if
(
_imag
!=
None
&&
_imag
!=
NULL
)
{
imag
=
_imag
;
if
(
rhs_complex
->
real
==
0.0
&&
rhs_complex
->
imag
==
0.0
)
{
raiseExcHelper
(
ZeroDivisionError
,
"complex divmod()"
)
;
}
double
real_f
,
imag_f
;
bool
real_is_complex
=
false
,
imag_is_complex
=
false
;
if
(
real
==
None
||
real
==
NULL
)
{
real_f
=
0.0
;
}
else
if
(
PyComplex_Check
(
real
))
{
real_f
=
((
BoxedComplex
*
)
real
)
->
real
;
real_is_complex
=
true
;
}
else
{
real_f
=
((
BoxedFloat
*
)
PyNumber_Float
(
real
))
->
d
;
}
if
(
imag
==
None
||
imag
==
NULL
)
{
imag_f
=
0.0
;
}
else
if
(
PyComplex_Check
(
imag
))
{
imag_f
=
((
BoxedComplex
*
)
imag
)
->
real
;
imag_is_complex
=
true
;
}
else
{
imag_f
=
((
BoxedFloat
*
)
PyNumber_Float
(
imag
))
->
d
;
}
BoxedComplex
*
div
=
(
BoxedComplex
*
)
complexDiv
(
lhs
,
rhs_complex
);
/* The raw divisor value. */
div
->
real
=
floor
(
div
->
real
);
/* Use the floor of the real part. */
div
->
imag
=
0.0
;
BoxedComplex
*
mod
=
(
BoxedComplex
*
)
complexSubComplex
(
lhs
,
(
BoxedComplex
*
)
complexMulComplex
(
rhs_complex
,
div
));
Box
*
res
=
BoxedTuple
::
create
({
div
,
mod
});
return
res
;
}
if
(
imag_is_complex
)
{
real_f
-=
((
BoxedComplex
*
)
imag
)
->
imag
;
}
Box
*
complexDivmod
(
BoxedComplex
*
lhs
,
Box
*
rhs
)
{
if
(
!
PyComplex_Check
(
lhs
))
raiseExcHelper
(
TypeError
,
"descriptor '__divmod__' requires a 'complex' object but received a '%s'"
,
getTypeName
(
lhs
));
if
(
real_is_complex
)
{
imag_f
+=
((
BoxedComplex
*
)
real
)
->
imag
;
}
if
(
rhs
==
None
)
return
NotImplemented
;
return
new
BoxedComplex
(
real_f
,
imag_f
);
return
complexDivmodComplex
(
lhs
,
rhs
);
}
template
<
ExceptionStyle
S
>
Box
*
complexNew
(
BoxedClass
*
_cls
,
Box
*
_real
,
Box
*
_imag
)
noexcept
(
S
==
CAPI
)
{
if
(
!
isSubclass
(
_cls
->
cls
,
type_cls
))
{
if
(
S
==
CAPI
)
{
PyErr_Format
(
TypeError
,
"complex.__new__(X): X is not a type object (%s)"
,
getTypeName
(
_cls
));
return
NULL
;
}
else
raiseExcHelper
(
TypeError
,
"complex.__new__(X): X is not a type object (%s)"
,
getTypeName
(
_cls
));
}
BoxedClass
*
cls
=
static_cast
<
BoxedClass
*>
(
_cls
);
if
(
PyComplex_Check
(
cls
))
{
if
(
S
==
CAPI
)
{
PyErr_Format
(
TypeError
,
"complex.__new__(%s): %s is not a subtype of complex"
,
getNameOfClass
(
cls
),
getNameOfClass
(
cls
));
return
NULL
;
}
else
raiseExcHelper
(
TypeError
,
"complex.__new__(%s): %s is not a subtype of complex"
,
getNameOfClass
(
cls
),
getNameOfClass
(
cls
));
}
// check second argument
if
(
_imag
!=
NULL
&&
(
PyString_Check
(
_imag
)
||
PyUnicode_Check
(
_imag
)))
{
if
(
S
==
CAPI
)
{
PyErr_Format
(
TypeError
,
"complex() second arg can't be a string"
);
return
NULL
;
}
else
raiseExcHelper
(
TypeError
,
"complex() second arg can't be a string"
);
}
Box
*
complexRDivmod
(
BoxedComplex
*
lhs
,
Box
*
_rhs
)
{
if
(
!
PyComplex_Check
(
lhs
))
raiseExcHelper
(
TypeError
,
"descriptor '__rdivmod__' requires a 'complex' object but received a '%s'"
,
getTypeName
(
lhs
));
// we can't use None as default value, because complex(None) should raise TypeError,
// but complex() should return `0j`. So use NULL as default value.
// Here check we pass complex(None, None), complex(None)
// or complex(imag=None) to the constructor
if
((
_real
==
None
)
&&
(
_imag
==
None
||
_imag
==
NULL
))
{
raiseExcHelper
(
TypeError
,
"complex() argument must be a string or number"
);
}
if
(
_rhs
==
None
)
return
NotImplemented
;
if
(
cls
==
complex_cls
)
return
_complexNew
<
S
>
(
_real
,
_imag
);
Box
*
rhs
=
toComplex
(
_rhs
);
BoxedComplex
*
r
=
(
BoxedComplex
*
)
_complexNew
<
S
>
(
_real
,
_imag
);
if
(
rhs
==
NotImplemented
)
return
NotImplemented
;
if
(
!
r
)
{
assert
(
S
==
CAPI
);
return
NULL
;
}
BoxedComplex
*
rhs_complex
=
static_cast
<
BoxedComplex
*>
(
rhs
);
return
new
(
_cls
)
BoxedComplex
(
r
->
real
,
r
->
imag
);
return
complexDivmodComplex
(
rhs_complex
,
lhs
);
}
extern
"C"
Box
*
complexDivmod
(
BoxedComplex
*
lhs
,
BoxedComplex
*
rhs
)
{
if
(
!
PyComplex_Check
(
lhs
))
raiseExcHelper
(
TypeError
,
"descriptor '__divmod__' requires a 'complex' object but received a '%s'"
,
getTypeName
(
lhs
));
Box
*
complexModComplex
(
BoxedComplex
*
lhs
,
Box
*
_rhs
)
{
if
(
PyErr_Warn
(
PyExc_DeprecationWarning
,
"complex divmod(), // and % are deprecated"
)
<
0
)
return
NULL
;
Box
*
res
=
toComplex
(
_rhs
);
if
(
res
==
NotImplemented
)
{
return
NotImplemented
;
}
BoxedComplex
*
rhs
=
(
BoxedComplex
*
)
res
;
if
(
rhs
->
real
==
0.0
&&
rhs
->
imag
==
0.0
)
{
raiseExcHelper
(
ZeroDivisionError
,
"complex
divmod()
"
);
raiseExcHelper
(
ZeroDivisionError
,
"complex
remainder
"
);
}
BoxedComplex
*
div
=
(
BoxedComplex
*
)
complexDiv
(
lhs
,
rhs
);
/* The raw divisor value. */
div
->
real
=
floor
(
div
->
real
);
/* Use the floor of the real part. */
div
->
imag
=
0.0
;
BoxedComplex
*
mod
=
(
BoxedComplex
*
)
complexSubComplex
(
lhs
,
(
BoxedComplex
*
)
complexMulComplex
(
rhs
,
div
));
Box
*
res
=
BoxedTuple
::
create
({
div
,
mod
});
return
res
;
return
mod
;
}
extern
"C"
Box
*
complexMod
(
BoxedComplex
*
lhs
,
Box
*
_
rhs
)
{
Box
*
complexMod
(
BoxedComplex
*
lhs
,
Box
*
rhs
)
{
if
(
!
PyComplex_Check
(
lhs
))
raiseExcHelper
(
TypeError
,
"descriptor '__mod__' requires a 'complex' object but received a '%s'"
,
getTypeName
(
lhs
));
if
(
PyErr_Warn
(
PyExc_DeprecationWarning
,
"complex divmod(), // and % are deprecated"
)
<
0
)
return
NULL
;
Box
*
res
=
to_complex
(
_rhs
);
if
(
res
==
NotImplemented
)
{
if
(
rhs
==
None
)
return
NotImplemented
;
}
BoxedComplex
*
rhs
=
(
BoxedComplex
*
)
res
;
return
complexModComplex
(
lhs
,
rhs
);
}
if
(
rhs
->
real
==
0.0
&&
rhs
->
imag
==
0.0
)
{
raiseExcHelper
(
ZeroDivisionError
,
"complex remainder"
);
}
Box
*
complexRMod
(
BoxedComplex
*
lhs
,
Box
*
_rhs
)
{
if
(
!
PyComplex_Check
(
lhs
))
raiseExcHelper
(
TypeError
,
"descriptor '__rmod__' requires a 'complex' object but received a '%s'"
,
getTypeName
(
lhs
));
BoxedComplex
*
div
=
(
BoxedComplex
*
)
complexDiv
(
lhs
,
rhs
);
/* The raw divisor value. */
div
->
real
=
floor
(
div
->
real
);
/* Use the floor of the real part. */
div
->
imag
=
0.0
;
BoxedComplex
*
mod
=
(
BoxedComplex
*
)
complexSubComplex
(
lhs
,
(
BoxedComplex
*
)
complexMulComplex
(
rhs
,
div
));
return
mod
;
if
(
_rhs
==
None
)
return
NotImplemented
;
Box
*
rhs
=
toComplex
(
_rhs
);
if
(
rhs
==
NotImplemented
)
return
NotImplemented
;
BoxedComplex
*
rhs_complex
=
static_cast
<
BoxedComplex
*>
(
rhs
);
return
complexModComplex
(
rhs_complex
,
lhs
);
}
extern
"C"
Box
*
complexFloordiv
(
BoxedComplex
*
lhs
,
Box
*
_rhs
)
{
...
...
@@ -916,68 +599,38 @@ extern "C" Box* complexFloordiv(BoxedComplex* lhs, Box* _rhs) {
raiseExcHelper
(
TypeError
,
"descriptor '__floordiv__' requires a 'complex' object but received a '%s'"
,
getTypeName
(
lhs
));
Box
*
res
=
to_complex
(
_rhs
);
if
(
res
==
NotImplemented
)
{
if
(
_rhs
==
None
)
return
NotImplemented
;
Box
*
rhs
=
toComplex
(
_rhs
);
if
(
rhs
==
NotImplemented
)
{
return
NotImplemented
;
}
BoxedComplex
*
rhs
=
(
BoxedComplex
*
)
res
;
BoxedTuple
*
t
=
(
BoxedTuple
*
)
complexDivmod
(
lhs
,
rhs
);
BoxedComplex
*
rhs_complex
=
(
BoxedComplex
*
)
rhs
;
BoxedTuple
*
t
=
(
BoxedTuple
*
)
complexDivmod
(
lhs
,
rhs_complex
);
return
t
->
elts
[
0
];
}
static
PyObject
*
complex_richcompare
(
PyObject
*
v
,
PyObject
*
w
,
int
op
)
noexcept
{
PyObject
*
res
;
int
equal
;
if
(
op
!=
Py_EQ
&&
op
!=
Py_NE
)
{
/* for backwards compatibility, comparisons with non-numbers return
* NotImplemented. Only comparisons with core numeric types raise
* TypeError.
*/
if
(
PyInt_Check
(
w
)
||
PyLong_Check
(
w
)
||
PyFloat_Check
(
w
)
||
PyComplex_Check
(
w
))
{
PyErr_SetString
(
PyExc_TypeError
,
"no ordering relation is defined "
"for complex numbers"
);
return
NULL
;
}
return
Py_NotImplemented
;
}
Box
*
complexRFloordiv
(
BoxedComplex
*
lhs
,
Box
*
_rhs
)
{
if
(
!
PyComplex_Check
(
lhs
))
raiseExcHelper
(
TypeError
,
"descriptor '__rfloordiv__' requires a 'complex' object but received a '%s'"
,
getTypeName
(
lhs
));
assert
(
PyComplex_Check
(
v
));
BoxedComplex
*
lhs
=
static_cast
<
BoxedComplex
*>
(
v
);
if
(
PyInt_Check
(
w
)
||
PyLong_Check
(
w
))
{
/* Check for 0->g0 imaginary part first to avoid the rich
* comparison when possible->g
*/
if
(
lhs
->
imag
==
0.0
)
{
PyObject
*
j
,
*
sub_res
;
j
=
PyFloat_FromDouble
(
lhs
->
real
);
if
(
j
==
NULL
)
return
NULL
;
sub_res
=
PyObject_RichCompare
(
j
,
w
,
op
);
Py_DECREF
(
j
);
return
sub_res
;
}
else
{
equal
=
0
;
}
}
else
if
(
PyFloat_Check
(
w
))
{
equal
=
(
lhs
->
real
==
PyFloat_AsDouble
(
w
)
&&
lhs
->
imag
==
0.0
);
}
else
if
(
PyComplex_Check
(
w
))
{
BoxedComplex
*
rhs
=
static_cast
<
BoxedComplex
*>
(
w
);
equal
=
(
lhs
->
real
==
rhs
->
real
&&
lhs
->
imag
==
rhs
->
imag
);
}
else
{
return
Py_NotImplemented
;
}
if
(
_rhs
==
None
)
return
NotImplemented
;
if
(
equal
==
(
op
==
Py_EQ
))
res
=
Py_True
;
else
res
=
Py_False
;
Box
*
rhs
=
toComplex
(
_rhs
);
Py_INCREF
(
res
);
return
res
;
if
(
rhs
==
NotImplemented
)
{
return
NotImplemented
;
}
BoxedComplex
*
rhs_complex
=
(
BoxedComplex
*
)
rhs
;
BoxedTuple
*
t
=
(
BoxedTuple
*
)
complexDivmod
(
rhs_complex
,
lhs
);
return
t
->
elts
[
0
];
}
extern
"C"
Box
*
complexEq
(
BoxedComplex
*
lhs
,
Box
*
rhs
)
{
...
...
@@ -1068,31 +721,6 @@ PyObject* complex_neg(PyComplexObject* v) {
return
PyComplex_FromDoubles
(
-
self
->
real
,
-
self
->
imag
);
}
// Pyston change: make not static
PyObject
*
complex__format__
(
PyObject
*
self
,
PyObject
*
args
)
{
PyObject
*
format_spec
;
if
(
!
PyArg_ParseTuple
(
args
,
"O:__format__"
,
&
format_spec
))
return
NULL
;
if
(
PyBytes_Check
(
format_spec
))
return
_PyComplex_FormatAdvanced
(
self
,
PyBytes_AS_STRING
(
format_spec
),
PyBytes_GET_SIZE
(
format_spec
));
if
(
PyUnicode_Check
(
format_spec
))
{
/* Convert format_spec to a str */
PyObject
*
result
;
PyObject
*
str_spec
=
PyObject_Str
(
format_spec
);
if
(
str_spec
==
NULL
)
return
NULL
;
result
=
_PyComplex_FormatAdvanced
(
self
,
PyBytes_AS_STRING
(
str_spec
),
PyBytes_GET_SIZE
(
str_spec
));
Py_DECREF
(
str_spec
);
return
result
;
}
PyErr_SetString
(
PyExc_TypeError
,
"__format__ requires str or unicode"
);
return
NULL
;
}
static
PyMethodDef
complex_methods
[]
=
{
{
"__format__"
,
(
PyCFunction
)
complex__format__
,
METH_VARARGS
,
NULL
},
};
...
...
@@ -1101,10 +729,10 @@ void setupComplex() {
static
PyNumberMethods
complex_as_number
;
complex_cls
->
tp_as_number
=
&
complex_as_number
;
auto
complex_new
=
FunctionMetadata
::
create
((
void
*
)
complexNew
<
CXX
>
,
UNKNOWN
,
3
,
false
,
false
,
ParamNames
({
""
,
"real"
,
"imag"
},
""
,
""
),
CXX
);
complex_new
->
addVersion
((
void
*
)
complexNew
<
CAPI
>
,
UNKNOWN
,
CAPI
);
complex_cls
->
giveAttr
(
"__new__"
,
new
BoxedFunction
(
complex_new
,
{
NULL
,
NULL
}));
auto
complex_new
_func
=
FunctionMetadata
::
create
((
void
*
)
complexNew
<
CXX
>
,
UNKNOWN
,
3
,
false
,
false
,
ParamNames
({
""
,
"real"
,
"imag"
},
""
,
""
),
CXX
);
complex_new
_func
->
addVersion
((
void
*
)
complexNew
<
CAPI
>
,
UNKNOWN
,
CAPI
);
complex_cls
->
giveAttr
(
"__new__"
,
new
BoxedFunction
(
complex_new
_func
,
{
NULL
,
NULL
}));
_addFunc
(
"__add__"
,
BOXED_COMPLEX
,
(
void
*
)
complexAddComplex
,
(
void
*
)
complexAddFloat
,
(
void
*
)
complexAddInt
,
(
void
*
)
complexAdd
);
...
...
@@ -1126,16 +754,21 @@ void setupComplex() {
complex_cls
->
giveAttr
(
"__rdiv__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
complexRDiv
,
UNKNOWN
,
2
)));
complex_cls
->
giveAttr
(
"__pow__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
complexPow
,
UNKNOWN
,
3
,
false
,
false
),
{
None
}));
complex_cls
->
giveAttr
(
"__rpow__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
complexR
p
ow
,
UNKNOWN
,
2
)));
complex_cls
->
giveAttr
(
"__rpow__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
complexR
P
ow
,
UNKNOWN
,
2
)));
complex_cls
->
giveAttr
(
"__mod__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
complexMod
,
UNKNOWN
,
2
)));
complex_cls
->
giveAttr
(
"__divmod__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
complexDivmod
,
BOXED_TUPLE
,
2
)));
complex_cls
->
giveAttr
(
"__rmod__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
complexRMod
,
UNKNOWN
,
2
)));
complex_cls
->
giveAttr
(
"__divmod__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
complexDivmod
,
UNKNOWN
,
2
)));
complex_cls
->
giveAttr
(
"__rdivmod__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
complexRDivmod
,
UNKNOWN
,
2
)));
complex_cls
->
giveAttr
(
"__floordiv__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
complexFloordiv
,
UNKNOWN
,
2
)));
complex_cls
->
giveAttr
(
"__rfloordiv__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
complexRFloordiv
,
UNKNOWN
,
2
)));
complex_cls
->
giveAttr
(
"__truediv__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
complexDivComplex
,
BOXED_COMPLEX
,
2
)));
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
complexTruediv
,
UNKNOWN
,
2
)));
complex_cls
->
giveAttr
(
"__rtruediv__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
complexRTruediv
,
UNKNOWN
,
2
)));
complex_cls
->
giveAttr
(
"conjugate"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
complexConjugate
,
BOXED_COMPLEX
,
1
)));
complex_cls
->
giveAttr
(
"__coerce__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
complexCoerce
,
UNKNOWN
,
2
)));
...
...
@@ -1154,11 +787,20 @@ void setupComplex() {
complex_cls
->
giveAttr
(
"__pos__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
complexPos
,
BOXED_COMPLEX
,
1
)));
complex_cls
->
giveAttr
(
"__hash__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
complexHash
,
BOXED_INT
,
1
)));
complex_cls
->
giveAttr
(
"__str__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
complexStr
,
STR
,
1
)));
complex_cls
->
giveAttr
(
"__int__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
complexInt
,
UNKNOWN
,
1
)));
complex_cls
->
giveAttr
(
"__float__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
complexFloat
,
UNKNOWN
,
1
)));
complex_cls
->
giveAttr
(
"__long__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
complexLong
,
UNKNOWN
,
1
)));
complex_cls
->
giveAttr
(
"__repr__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
complexRepr
,
STR
,
1
)));
complex_cls
->
giveAttr
(
"real"
,
new
BoxedMemberDescriptor
(
BoxedMemberDescriptor
::
DOUBLE
,
offsetof
(
BoxedComplex
,
real
)));
complex_cls
->
giveAttr
(
"imag"
,
new
BoxedMemberDescriptor
(
BoxedMemberDescriptor
::
DOUBLE
,
offsetof
(
BoxedComplex
,
imag
)));
complex_cls
->
giveAttr
(
"__doc__"
,
boxString
(
"complex(real[, imag]) -> complex number
\n
"
"
\n
"
"Create a complex number from a real part and an optional imaginary part.
\n
"
"This is equivalent to (real + imag*1j) where imag defaults to 0."
));
for
(
auto
&
md
:
complex_methods
)
{
complex_cls
->
giveAttr
(
md
.
ml_name
,
new
BoxedMethodDescriptor
(
&
md
,
complex_cls
));
}
...
...
src/runtime/types.h
View file @
e98abcb2
...
...
@@ -390,6 +390,10 @@ public:
DEFAULT_CLASS_SIMPLE
(
complex_cls
);
};
static_assert
(
sizeof
(
BoxedComplex
)
==
sizeof
(
PyComplexObject
),
""
);
static_assert
(
offsetof
(
BoxedComplex
,
real
)
==
offsetof
(
PyComplexObject
,
cval
.
real
),
""
);
static_assert
(
offsetof
(
BoxedComplex
,
imag
)
==
offsetof
(
PyComplexObject
,
cval
.
imag
),
""
);
class
BoxedBool
:
public
BoxedInt
{
public:
BoxedBool
(
bool
b
)
__attribute__
((
visibility
(
"default"
)))
:
BoxedInt
(
b
?
1
:
0
)
{}
...
...
test/tests/complex.py
View file @
e98abcb2
...
...
@@ -22,3 +22,49 @@ try:
complex
(
1
,
1.0
).
real
=
1
except
TypeError
,
e
:
print
e
class
C
(
complex
):
pass
print
(
1j
-
C
(
1
))
print
(
1j
+
C
(
1
))
print
(
1j
*
C
(
1
))
print
(
1j
/
C
(
1
))
class
C1
(
complex
):
def
__complex__
(
self
):
return
1j
print
(
C1
(
1
)
+
1j
)
print
(
C1
(
1
)
-
1j
)
print
(
C1
(
1
)
*
1j
)
print
(
C1
(
1
)
/
1j
)
types
=
[
int
,
float
,
long
]
for
_type
in
types
:
try
:
_type
(
1j
)
except
TypeError
as
e
:
print
(
e
.
message
)
data
=
[
"-1j"
,
"0j"
,
"1j"
,
"5+5j"
,
"5-5j"
,
"5"
,
"5L"
,
"5.5"
,
"
\
"
5
\
"
"
,
"None"
,
]
operations
=
[
"__mod__"
,
"__rmod__"
,
"__divmod__"
,
"__rdivmod__"
,
"__truediv__"
,
"__rtruediv__"
,
"__floordiv__"
,
"__rfloordiv__"
,
]
for
x
in
data
:
for
y
in
data
:
for
operation
in
operations
:
try
:
print
(
eval
(
"complex.{op}({arg1}, {arg2})"
.
format
(
op
=
operation
,
arg1
=
x
,
arg2
=
y
)))
except
Exception
as
e
:
print
(
e
.
message
)
Boxiang Sun
@Daetalus
mentioned in commit
c2bac556
·
Sep 08, 2016
mentioned in commit
c2bac556
mentioned in commit c2bac55610136628467e002ba1b8a0ee99389168
Toggle commit list
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment