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
2be06383
Commit
2be06383
authored
Jun 03, 2015
by
Kevin Modzelewski
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #549 from tjhance/float_pow
Float pow
parents
1eb99619
b569aed6
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
84 additions
and
46 deletions
+84
-46
from_cpython/Objects/floatobject.c
from_cpython/Objects/floatobject.c
+53
-24
src/runtime/float.cpp
src/runtime/float.cpp
+20
-22
src/runtime/int.cpp
src/runtime/int.cpp
+2
-0
test/tests/float.py
test/tests/float.py
+9
-0
No files found.
from_cpython/Objects/floatobject.c
View file @
2be06383
...
...
@@ -820,11 +820,14 @@ float_floor_div(PyObject *v, PyObject *w)
x is not an infinity or nan. */
#define DOUBLE_IS_ODD_INTEGER(x) (fmod(fabs(x), 2.0) == 1.0)
static
PyObject
*
inline
int
float_pow_unboxed
(
double
iv
,
double
iw
,
double
*
res
);
// pyston change: split this up into float_pow and and float_pow_unboxed
PyObject
*
float_pow
(
PyObject
*
v
,
PyObject
*
w
,
PyObject
*
z
)
{
double
iv
,
iw
,
ix
;
int
negate_result
=
0
;
double
iv
,
iw
,
res
;
int
err
;
if
((
PyObject
*
)
z
!=
Py_None
)
{
PyErr_SetString
(
PyExc_TypeError
,
"pow() 3rd argument not "
...
...
@@ -835,15 +838,32 @@ float_pow(PyObject *v, PyObject *w, PyObject *z)
CONVERT_TO_DOUBLE
(
v
,
iv
);
CONVERT_TO_DOUBLE
(
w
,
iw
);
err
=
float_pow_unboxed
(
iv
,
iw
,
&
res
);
if
(
err
)
{
return
NULL
;
}
else
{
return
PyFloat_FromDouble
(
res
);
}
}
int
float_pow_unboxed
(
double
iv
,
double
iw
,
double
*
res
)
{
double
ix
;
int
negate_result
=
0
;
/* Sort out special cases here instead of relying on pow() */
if
(
iw
==
0
)
{
/* v**0 is 1, even 0**0 */
return
PyFloat_FromDouble
(
1
.
0
);
*
res
=
1
.
0
;
return
0
;
}
if
(
Py_IS_NAN
(
iv
))
{
/* nan**w = nan, unless w == 0 */
return
PyFloat_FromDouble
(
iv
);
*
res
=
iv
;
return
0
;
}
if
(
Py_IS_NAN
(
iw
))
{
/* v**nan = nan, unless v == 1; 1**nan = 1 */
return
PyFloat_FromDouble
(
iv
==
1
.
0
?
1
.
0
:
iw
);
*
res
=
(
iv
==
1
.
0
?
1
.
0
:
iw
);
return
0
;
}
if
(
Py_IS_INFINITY
(
iw
))
{
/* v**inf is: 0.0 if abs(v) < 1; 1.0 if abs(v) == 1; inf if
...
...
@@ -853,12 +873,16 @@ float_pow(PyObject *v, PyObject *w, PyObject *z)
* abs(v) > 1 (including case where v infinite)
*/
iv
=
fabs
(
iv
);
if
(
iv
==
1
.
0
)
return
PyFloat_FromDouble
(
1
.
0
);
else
if
((
iw
>
0
.
0
)
==
(
iv
>
1
.
0
))
return
PyFloat_FromDouble
(
fabs
(
iw
));
/* return inf */
else
return
PyFloat_FromDouble
(
0
.
0
);
if
(
iv
==
1
.
0
)
{
*
res
=
1
.
0
;
return
0
;
}
else
if
((
iw
>
0
.
0
)
==
(
iv
>
1
.
0
))
{
*
res
=
fabs
(
iw
);
return
0
;
}
else
{
*
res
=
0
.
0
;
return
0
;
}
}
if
(
Py_IS_INFINITY
(
iv
))
{
/* (+-inf)**w is: inf for w positive, 0 for w negative; in
...
...
@@ -866,11 +890,13 @@ float_pow(PyObject *v, PyObject *w, PyObject *z)
* an odd integer.
*/
int
iw_is_odd
=
DOUBLE_IS_ODD_INTEGER
(
iw
);
if
(
iw
>
0
.
0
)
return
PyFloat_FromDouble
(
iw_is_odd
?
iv
:
fabs
(
iv
));
else
return
PyFloat_FromDouble
(
iw_is_odd
?
copysign
(
0
.
0
,
iv
)
:
0
.
0
);
if
(
iw
>
0
.
0
)
{
*
res
=
(
iw_is_odd
?
iv
:
fabs
(
iv
));
return
0
;
}
else
{
*
res
=
(
iw_is_odd
?
copysign
(
0
.
0
,
iv
)
:
0
.
0
);
return
0
;
}
}
if
(
iv
==
0
.
0
)
{
/* 0**w is: 0 for w positive, 1 for w zero
(already dealt with above), and an error
...
...
@@ -880,10 +906,11 @@ float_pow(PyObject *v, PyObject *w, PyObject *z)
PyErr_SetString
(
PyExc_ZeroDivisionError
,
"0.0 cannot be raised to a "
"negative power"
);
return
NULL
;
return
1
;
}
/* use correct sign if iw is odd */
return
PyFloat_FromDouble
(
iw_is_odd
?
iv
:
0
.
0
);
*
res
=
(
iw_is_odd
?
iv
:
0
.
0
);
return
0
;
}
if
(
iv
<
0
.
0
)
{
...
...
@@ -893,7 +920,7 @@ float_pow(PyObject *v, PyObject *w, PyObject *z)
if
(
iw
!=
floor
(
iw
))
{
PyErr_SetString
(
PyExc_ValueError
,
"negative number "
"cannot be raised to a fractional power"
);
return
NULL
;
return
1
;
}
/* iw is an exact integer, albeit perhaps a very large
* one. Replace iv by its absolute value and remember
...
...
@@ -915,7 +942,8 @@ float_pow(PyObject *v, PyObject *w, PyObject *z)
* happen to be representable in a *C* integer. That's a
* bug.
*/
return
PyFloat_FromDouble
(
negate_result
?
-
1
.
0
:
1
.
0
);
*
res
=
(
negate_result
?
-
1
.
0
:
1
.
0
);
return
0
;
}
/* Now iv and iw are finite, iw is nonzero, and iv is
...
...
@@ -923,7 +951,7 @@ float_pow(PyObject *v, PyObject *w, PyObject *z)
* the platform pow to step in and do the rest.
*/
errno
=
0
;
PyFPE_START_PROTECT
(
"pow"
,
return
NULL
)
PyFPE_START_PROTECT
(
"pow"
,
return
1
)
ix
=
pow
(
iv
,
iw
);
PyFPE_END_PROTECT
(
ix
)
Py_ADJUST_ERANGE1
(
ix
);
...
...
@@ -936,9 +964,10 @@ float_pow(PyObject *v, PyObject *w, PyObject *z)
*/
PyErr_SetFromErrno
(
errno
==
ERANGE
?
PyExc_OverflowError
:
PyExc_ValueError
);
return
NULL
;
return
1
;
}
return
PyFloat_FromDouble
(
ix
);
*
res
=
ix
;
return
0
;
}
#undef DOUBLE_IS_ODD_INTEGER
...
...
src/runtime/float.cpp
View file @
2be06383
...
...
@@ -30,6 +30,8 @@ extern "C" PyObject* float_fromhex(PyObject* cls, PyObject* arg) noexcept;
extern
"C"
PyObject
*
float_as_integer_ratio
(
PyObject
*
v
,
PyObject
*
unused
)
noexcept
;
extern
"C"
PyObject
*
float_is_integer
(
PyObject
*
v
)
noexcept
;
extern
"C"
PyObject
*
float__format__
(
PyObject
*
v
)
noexcept
;
extern
"C"
PyObject
*
float_pow
(
PyObject
*
v
,
PyObject
*
w
,
PyObject
*
z
)
noexcept
;
extern
"C"
int
float_pow_unboxed
(
double
iv
,
double
iw
,
double
*
res
)
noexcept
;
namespace
pyston
{
...
...
@@ -95,10 +97,6 @@ extern "C" double mod_float_float(double lhs, double rhs) {
return
r
;
}
extern
"C"
double
pow_float_float
(
double
lhs
,
double
rhs
)
{
return
pow
(
lhs
,
rhs
);
}
extern
"C"
double
div_float_float
(
double
lhs
,
double
rhs
)
{
raiseDivZeroExcIfZero
(
rhs
);
return
lhs
/
rhs
;
...
...
@@ -426,35 +424,35 @@ extern "C" Box* floatRMod(BoxedFloat* lhs, Box* rhs) {
}
}
extern
"C"
Box
*
floatPow
(
BoxedFloat
*
lhs
,
Box
*
rhs
,
Box
*
mod
)
{
Box
*
res
=
float_pow
(
lhs
,
rhs
,
mod
);
if
(
!
res
)
{
throwCAPIException
();
}
return
res
;
}
extern
"C"
Box
*
floatPowFloat
(
BoxedFloat
*
lhs
,
BoxedFloat
*
rhs
,
Box
*
mod
=
None
)
{
// TODO to specialize this, need to account for all the special cases in float_pow
assert
(
lhs
->
cls
==
float_cls
);
assert
(
rhs
->
cls
==
float_cls
);
if
(
mod
!=
None
)
raiseExcHelper
(
TypeError
,
"pow() 3rd argument not allowed unless all arguments are integers"
);
return
boxFloat
(
pow
(
lhs
->
d
,
rhs
->
d
));
return
floatPow
(
lhs
,
rhs
,
mod
);
}
extern
"C"
Box
*
floatPowInt
(
BoxedFloat
*
lhs
,
BoxedInt
*
rhs
,
Box
*
mod
=
None
)
{
// TODO to specialize this, need to account for all the special cases in float_pow
assert
(
lhs
->
cls
==
float_cls
);
assert
(
isSubclass
(
rhs
->
cls
,
int_cls
));
if
(
mod
!=
None
)
raiseExcHelper
(
TypeError
,
"pow() 3rd argument not allowed unless all arguments are integers"
);
return
boxFloat
(
pow
(
lhs
->
d
,
rhs
->
n
));
return
floatPow
(
lhs
,
rhs
,
mod
);
}
extern
"C"
Box
*
floatPow
(
BoxedFloat
*
lhs
,
Box
*
rhs
,
Box
*
mod
)
{
assert
(
lhs
->
cls
==
float_cls
);
if
(
mod
!=
None
)
raiseExcHelper
(
TypeError
,
"pow() 3rd argument not allowed unless all arguments are integers"
);
if
(
isSubclass
(
rhs
->
cls
,
int_cls
))
{
return
floatPowInt
(
lhs
,
static_cast
<
BoxedInt
*>
(
rhs
));
}
else
if
(
rhs
->
cls
==
float_cls
)
{
return
floatPowFloat
(
lhs
,
static_cast
<
BoxedFloat
*>
(
rhs
));
}
else
if
(
rhs
->
cls
==
long_cls
)
{
return
boxFloat
(
pow
(
lhs
->
d
,
PyLong_AsDouble
(
rhs
)));
extern
"C"
double
pow_float_float
(
double
lhs
,
double
rhs
)
{
double
res
;
int
err
=
float_pow_unboxed
(
lhs
,
rhs
,
&
res
);
if
(
err
)
{
throwCAPIException
();
}
else
{
return
NotImplemented
;
return
res
;
}
}
...
...
src/runtime/int.cpp
View file @
2be06383
...
...
@@ -31,6 +31,8 @@
#include "runtime/types.h"
#include "runtime/util.h"
extern
"C"
PyObject
*
float_pow
(
PyObject
*
v
,
PyObject
*
w
,
PyObject
*
z
)
noexcept
;
namespace
pyston
{
extern
"C"
long
PyInt_GetMax
()
noexcept
{
...
...
test/tests/float.py
View file @
2be06383
...
...
@@ -65,3 +65,12 @@ print (0.5).as_integer_ratio()
print
(
0.5
).
is_integer
()
print
(
1.0
).
is_integer
()
print
1.0
.
__hash__
(),
1.1
.
__hash__
(),
-
1.1
.
__hash__
()
print
1.0
**
(
10
**
100
)
print
(
-
1.0
)
**
(
10
**
100
)
print
(
-
1.0
)
**
(
10
**
100
+
1
)
print
0.0
**
0.0
try
:
0.0
**
(
-
1.0
)
except
ZeroDivisionError
as
e
:
print
e
.
message
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