Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
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
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
cython
Commits
99d47bff
Commit
99d47bff
authored
9 years ago
by
Stefan Behnel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
optimise division with constant floats
parent
20a10e73
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
220 additions
and
5 deletions
+220
-5
CHANGES.rst
CHANGES.rst
+1
-1
Cython/Compiler/Optimize.py
Cython/Compiler/Optimize.py
+10
-1
Cython/Utility/Optimize.c
Cython/Utility/Optimize.c
+9
-3
tests/run/float_division.pyx
tests/run/float_division.pyx
+200
-0
No files found.
CHANGES.rst
View file @
99d47bff
...
...
@@ -17,7 +17,7 @@ Features added
* Optimisations for PyLong are enabled in Py2.7 (not only Py3.x).
* Adding/subtracting constant Python floats and small integers is faster.
* Adding/subtracting
/dividing
constant Python floats and small integers is faster.
* Binary and/or/xor/rshift operations and division/modulus with small
constant Python integers are faster.
...
...
This diff is collapsed.
Click to expand it.
Cython/Compiler/Optimize.py
View file @
99d47bff
...
...
@@ -2831,6 +2831,9 @@ class OptimizeBuiltinCalls(Visitor.NodeRefCleanupMixin,
def
_handle_simple_method_object___truediv__
(
self
,
node
,
function
,
args
,
is_unbound_method
):
return
self
.
_optimise_num_div
(
'TrueDivide'
,
node
,
function
,
args
,
is_unbound_method
)
def
_handle_simple_method_object___div__
(
self
,
node
,
function
,
args
,
is_unbound_method
):
return
self
.
_optimise_num_div
(
'Divide'
,
node
,
function
,
args
,
is_unbound_method
)
def
_optimise_num_div
(
self
,
operator
,
node
,
function
,
args
,
is_unbound_method
):
if
len
(
args
)
!=
2
or
not
args
[
1
].
has_constant_result
()
or
args
[
1
].
constant_result
==
0
:
return
node
...
...
@@ -2850,6 +2853,12 @@ class OptimizeBuiltinCalls(Visitor.NodeRefCleanupMixin,
def
_handle_simple_method_float___sub__
(
self
,
node
,
function
,
args
,
is_unbound_method
):
return
self
.
_optimise_num_binop
(
'Subtract'
,
node
,
function
,
args
,
is_unbound_method
)
def
_handle_simple_method_float___truediv__
(
self
,
node
,
function
,
args
,
is_unbound_method
):
return
self
.
_optimise_num_binop
(
'TrueDivide'
,
node
,
function
,
args
,
is_unbound_method
)
def
_handle_simple_method_float___div__
(
self
,
node
,
function
,
args
,
is_unbound_method
):
return
self
.
_optimise_num_binop
(
'Divide'
,
node
,
function
,
args
,
is_unbound_method
)
def
_optimise_num_binop
(
self
,
operator
,
node
,
function
,
args
,
is_unbound_method
):
"""
Optimise math operators for (likely) float or small integer operations.
...
...
@@ -2880,7 +2889,7 @@ class OptimizeBuiltinCalls(Visitor.NodeRefCleanupMixin,
is_float
=
isinstance
(
numval
,
ExprNodes
.
FloatNode
)
if
is_float
:
if
operator
not
in
(
'Add'
,
'Subtract'
,
'TrueDivide'
):
if
operator
not
in
(
'Add'
,
'Subtract'
,
'TrueDivide'
,
'Divide'
):
return
node
elif
abs
(
numval
.
constant_result
)
>
2
**
30
:
return
node
...
...
This diff is collapsed.
Click to expand it.
Cython/Utility/Optimize.c
View file @
99d47bff
...
...
@@ -490,7 +490,7 @@ fallback:
static
PyObject
*
__Pyx_PyInt_
{{
op
}}{{
order
}}(
PyObject
*
op1
,
PyObject
*
op2
,
long
intval
,
int
inplace
);
/*proto*/
#else
#define __Pyx_PyInt_{{op}}{{order}}(op1, op2, intval, inplace) \
(
(inplace ? PyNumber_InPlace{{op}} : PyNumber_{{op}})
(op1, op2))
(
inplace ? PyNumber_InPlace{{op}}(op1, op2) : PyNumber_{{op}}
(op1, op2))
#endif
/////////////// PyIntBinop ///////////////
...
...
@@ -639,7 +639,9 @@ static PyObject* __Pyx_PyInt_{{op}}{{order}}(PyObject *op1, PyObject *op2, CYTHO
static
PyObject
*
__Pyx_PyFloat_
{{
op
}}{{
order
}}(
PyObject
*
op1
,
PyObject
*
op2
,
double
floatval
,
int
inplace
);
/*proto*/
#else
#define __Pyx_PyFloat_{{op}}{{order}}(op1, op2, floatval, inplace) \
((inplace ? PyNumber_InPlace{{op}} : PyNumber_{{op}})(op1, op2))
{{if op == 'Divide'}}((inplace ? __Pyx_PyNumber_InPlaceDivide(op1, op2) : __Pyx_PyNumber_Divide(op1, op2)))
{{
else
}}(
inplace
?
PyNumber_InPlace
{{
op
}}(
op1
,
op2
)
:
PyNumber_
{{
op
}}(
op1
,
op2
))
{{
endif
}}
#endif
/////////////// PyFloatBinop ///////////////
...
...
@@ -648,7 +650,7 @@ static PyObject* __Pyx_PyFloat_{{op}}{{order}}(PyObject *op1, PyObject *op2, dou
#if CYTHON_COMPILING_IN_CPYTHON
{{
py
:
from
Cython
.
Utility
import
pylong_join
}}
{{
py
:
pyval
,
fval
=
(
'
op2
'
,
'b'
)
if
order
==
'
CObj
'
else
(
'
op1
'
,
'a'
)
}}
{{
py
:
c_op
=
{
'
Add
'
:
'+'
,
'
Subtract
'
:
'-'
,
'
TrueDivide
'
:
'/'
}[
op
]
}}
{{
py
:
c_op
=
{
'
Add
'
:
'+'
,
'
Subtract
'
:
'-'
,
'
TrueDivide
'
:
'/'
,
'
Divide
'
:
'/'
}[
op
]
}}
static
PyObject
*
__Pyx_PyFloat_
{{
op
}}{{
order
}}(
PyObject
*
op1
,
PyObject
*
op2
,
double
floatval
,
int
inplace
)
{
const
double
{{
'a'
if
order
==
'
CObj
'
else
'b'
}}
=
floatval
;
...
...
@@ -699,7 +701,11 @@ static PyObject* __Pyx_PyFloat_{{op}}{{order}}(PyObject *op1, PyObject *op2, dou
if
(
unlikely
({{
fval
}}
==
-
1
.
0
&&
PyErr_Occurred
()))
return
NULL
;
#endif
}
else
{
{{
if
op
==
'
Divide
'
}}
return
(
inplace
?
__Pyx_PyNumber_InPlaceDivide
(
op1
,
op2
)
:
__Pyx_PyNumber_Divide
(
op1
,
op2
));
{{
else
}}
return
(
inplace
?
PyNumber_InPlace
{{
op
}}
:
PyNumber_
{{
op
}})(
op1
,
op2
);
{{
endif
}}
}
// copied from floatobject.c in Py3.5:
...
...
This diff is collapsed.
Click to expand it.
tests/run/float_division.pyx
0 → 100644
View file @
99d47bff
# mode: run
# tag: division
def
int_by_float
():
"""
>>> int_by_float()
0.5
"""
return
1
/
2.0
def
float_by_int
():
"""
>>> float_by_int()
2.0
"""
return
2.0
/
1
def
float_by_float
():
"""
>>> float_by_float()
1.5
"""
return
3.0
/
2.0
def
div_1_by
(
x
):
"""
>>> div_1_by(1.0)
1.0
>>> div_1_by(2.0)
0.5
>>> div_1_by(0.5)
2.0
>>> 1.0 / float('inf')
0.0
>>> div_1_by(float('inf'))
0.0
>>> div_1_by(float('-inf'))
-0.0
>>> div_1_by(float('nan'))
nan
"""
return
1.0
/
x
def
div_by_2
(
x
):
"""
>>> div_by_2(1.0)
0.5
>>> float('inf') / 2.0
inf
>>> div_by_2(float('inf'))
inf
>>> div_by_2(float('-inf'))
-inf
>>> float('nan') / 2.0
nan
>>> div_by_2(float('nan'))
nan
"""
return
x
/
2.0
def
div_by_neg_2
(
x
):
"""
>>> div_by_neg_2(1.0)
-0.5
>>> div_by_neg_2(-1.0)
0.5
>>> (-2**14) / (-2.0)
8192.0
>>> div_by_neg_2(-2**14)
8192.0
>>> (-2**52) / (-2.0)
2251799813685248.0
>>> div_by_neg_2(-2**52)
2251799813685248.0
>>> (-2**53-1) / (-2.0)
4503599627370496.0
>>> div_by_neg_2(-2**53-1)
4503599627370496.0
>>> float('inf') / -2.0
-inf
>>> div_by_neg_2(float('inf'))
-inf
>>> div_by_neg_2(float('-inf'))
inf
>>> float('nan') / -2.0
nan
>>> div_by_neg_2(float('nan'))
nan
"""
return
x
/
-
2.0
def
div_neg_2_by
(
x
):
"""
>>> div_neg_2_by(1.0)
-2.0
>>> div_neg_2_by(-1)
2.0
>>> div_neg_2_by(-2.0)
1.0
>>> div_neg_2_by(-2)
1.0
>>> -2.0 / float('inf')
-0.0
>>> div_neg_2_by(float('inf'))
-0.0
>>> div_neg_2_by(float('-inf'))
0.0
>>> float('nan') / -2.0
nan
>>> div_neg_2_by(float('nan'))
nan
"""
return
(
-
2.0
)
/
x
def
div_by_nan
(
x
):
"""
>>> 1.0 / float('nan')
nan
>>> div_by_nan(1.0)
nan
>>> float('nan') / float('nan')
nan
>>> div_by_nan(float('nan'))
nan
>>> float('inf') / float('nan')
nan
>>> div_by_nan(float('inf'))
nan
"""
return
x
/
float
(
"nan"
)
def
div_nan_by
(
x
):
"""
>>> float('nan') / 1.0
nan
>>> div_nan_by(1.0)
nan
>>> float('nan') / float('nan')
nan
>>> div_nan_by(float('nan'))
nan
"""
return
float
(
"nan"
)
/
x
def
div_by_inf
(
x
):
"""
>>> 1 / float('inf')
0.0
>>> div_by_inf(1)
0.0
>>> 1.0 / float('inf')
0.0
>>> div_by_inf(1.0)
0.0
>>> div_by_inf(float('inf'))
nan
"""
return
x
/
float
(
"inf"
)
def
div_inf_by
(
x
):
"""
>>> float('inf') / 1.0
inf
>>> div_inf_by(1.0)
inf
>>> float('inf') / float('nan')
nan
>>> div_inf_by(float('nan'))
nan
>>> float('inf') / float('-inf')
nan
>>> div_inf_by(float('-inf'))
nan
"""
return
float
(
"inf"
)
/
x
def
div_neg_inf_by
(
x
):
"""
>>> float('-inf') / 1.0
-inf
>>> div_neg_inf_by(1.0)
-inf
>>> float('-inf') / -1.0
inf
>>> div_neg_inf_by(-1.0)
inf
"""
return
float
(
"-inf"
)
/
x
This diff is collapsed.
Click to expand it.
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