Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
cpython
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
cpython
Commits
8d87dc0c
Kaydet (Commit)
8d87dc0c
authored
Eki 25, 2009
tarafından
Mark Dickinson
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Issue #1087418: Small performance boost for bitwise operations on longs.
Initial patch by Gregory Smith; some tweaks added.
üst
f1ca811a
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
102 additions
and
66 deletions
+102
-66
NEWS
Misc/NEWS
+2
-0
longobject.c
Objects/longobject.c
+100
-66
No files found.
Misc/NEWS
Dosyayı görüntüle @
8d87dc0c
...
@@ -12,6 +12,8 @@ What's New in Python 2.7 alpha 1
...
@@ -12,6 +12,8 @@ What's New in Python 2.7 alpha 1
Core and Builtins
Core and Builtins
-----------------
-----------------
- Issue #1087418: Boost performance of bitwise operations for longs.
- Issue #1722344: threading._shutdown() is now called in Py_Finalize(), which
- Issue #1722344: threading._shutdown() is now called in Py_Finalize(), which
fixes the problem of some exceptions being thrown at shutdown when the
fixes the problem of some exceptions being thrown at shutdown when the
interpreter is killed. Patch by Adam Olsen.
interpreter is killed. Patch by Adam Olsen.
...
...
Objects/longobject.c
Dosyayı görüntüle @
8d87dc0c
...
@@ -3411,6 +3411,22 @@ lshift_error:
...
@@ -3411,6 +3411,22 @@ lshift_error:
return
(
PyObject
*
)
z
;
return
(
PyObject
*
)
z
;
}
}
/* Compute two's complement of digit vector a[0:m], writing result to
z[0:m]. The digit vector a need not be normalized, but should not
be entirely zero. a and z may point to the same digit vector. */
static
void
v_complement
(
digit
*
z
,
digit
*
a
,
Py_ssize_t
m
)
{
Py_ssize_t
i
;
digit
carry
=
1
;
for
(
i
=
0
;
i
<
m
;
++
i
)
{
carry
+=
a
[
i
]
^
PyLong_MASK
;
z
[
i
]
=
carry
&
PyLong_MASK
;
carry
>>=
PyLong_SHIFT
;
}
assert
(
carry
==
0
);
}
/* Bitwise and/xor/or operations */
/* Bitwise and/xor/or operations */
...
@@ -3419,104 +3435,122 @@ long_bitwise(PyLongObject *a,
...
@@ -3419,104 +3435,122 @@ long_bitwise(PyLongObject *a,
int
op
,
/* '&', '|', '^' */
int
op
,
/* '&', '|', '^' */
PyLongObject
*
b
)
PyLongObject
*
b
)
{
{
digit
maska
,
maskb
;
/* 0 or PyLong_MASK */
int
nega
,
negb
,
negz
;
int
negz
;
Py_ssize_t
size_a
,
size_b
,
size_z
,
i
;
Py_ssize_t
size_a
,
size_b
,
size_z
,
i
;
PyLongObject
*
z
;
PyLongObject
*
z
;
digit
diga
,
digb
;
PyObject
*
v
;
if
(
Py_SIZE
(
a
)
<
0
)
{
/* Bitwise operations for negative numbers operate as though
a
=
(
PyLongObject
*
)
long_invert
(
a
);
on a two's complement representation. So convert arguments
if
(
a
==
NULL
)
from sign-magnitude to two's complement, and convert the
result back to sign-magnitude at the end. */
/* If a is negative, replace it by its two's complement. */
size_a
=
ABS
(
Py_SIZE
(
a
));
nega
=
Py_SIZE
(
a
)
<
0
;
if
(
nega
)
{
z
=
_PyLong_New
(
size_a
);
if
(
z
==
NULL
)
return
NULL
;
return
NULL
;
maska
=
PyLong_MASK
;
v_complement
(
z
->
ob_digit
,
a
->
ob_digit
,
size_a
);
a
=
z
;
}
}
else
{
else
/* Keep reference count consistent. */
Py_INCREF
(
a
);
Py_INCREF
(
a
);
maska
=
0
;
}
/* Same for b. */
if
(
Py_SIZE
(
b
)
<
0
)
{
size_b
=
ABS
(
Py_SIZE
(
b
));
b
=
(
PyLongObject
*
)
long_invert
(
b
);
negb
=
Py_SIZE
(
b
)
<
0
;
if
(
b
==
NULL
)
{
if
(
negb
)
{
z
=
_PyLong_New
(
size_b
);
if
(
z
==
NULL
)
{
Py_DECREF
(
a
);
Py_DECREF
(
a
);
return
NULL
;
return
NULL
;
}
}
maskb
=
PyLong_MASK
;
v_complement
(
z
->
ob_digit
,
b
->
ob_digit
,
size_b
);
b
=
z
;
}
}
else
{
else
Py_INCREF
(
b
);
Py_INCREF
(
b
);
maskb
=
0
;
/* Swap a and b if necessary to ensure size_a >= size_b. */
if
(
size_a
<
size_b
)
{
z
=
a
;
a
=
b
;
b
=
z
;
size_z
=
size_a
;
size_a
=
size_b
;
size_b
=
size_z
;
negz
=
nega
;
nega
=
negb
;
negb
=
negz
;
}
}
negz
=
0
;
/* JRH: The original logic here was to allocate the result value (z)
as the longer of the two operands. However, there are some cases
where the result is guaranteed to be shorter than that: AND of two
positives, OR of two negatives: use the shorter number. AND with
mixed signs: use the positive number. OR with mixed signs: use the
negative number.
*/
switch
(
op
)
{
switch
(
op
)
{
case
'^'
:
case
'^'
:
if
(
maska
!=
maskb
)
{
negz
=
nega
^
negb
;
maska
^=
PyLong_MASK
;
size_z
=
size_a
;
negz
=
-
1
;
}
break
;
break
;
case
'&'
:
case
'&'
:
if
(
maska
&&
maskb
)
{
negz
=
nega
&
negb
;
op
=
'|'
;
size_z
=
negb
?
size_a
:
size_b
;
maska
^=
PyLong_MASK
;
maskb
^=
PyLong_MASK
;
negz
=
-
1
;
}
break
;
break
;
case
'|'
:
case
'|'
:
if
(
maska
||
maskb
)
{
negz
=
nega
|
negb
;
op
=
'&'
;
size_z
=
negb
?
size_b
:
size_a
;
maska
^=
PyLong_MASK
;
maskb
^=
PyLong_MASK
;
negz
=
-
1
;
}
break
;
break
;
default:
PyErr_BadArgument
();
return
NULL
;
}
}
/* JRH: The original logic here was to allocate the result value (z)
/* We allow an extra digit if z is negative, to make sure that
as the longer of the two operands. However, there are some cases
the final two's complement of z doesn't overflow. */
where the result is guaranteed to be shorter than that: AND of two
z
=
_PyLong_New
(
size_z
+
negz
);
positives, OR of two negatives: use the shorter number. AND with
mixed signs: use the positive number. OR with mixed signs: use the
negative number. After the transformations above, op will be '&'
iff one of these cases applies, and mask will be non-0 for operands
whose length should be ignored.
*/
size_a
=
Py_SIZE
(
a
);
size_b
=
Py_SIZE
(
b
);
size_z
=
op
==
'&'
?
(
maska
?
size_b
:
(
maskb
?
size_a
:
MIN
(
size_a
,
size_b
)))
:
MAX
(
size_a
,
size_b
);
z
=
_PyLong_New
(
size_z
);
if
(
z
==
NULL
)
{
if
(
z
==
NULL
)
{
Py_DECREF
(
a
);
Py_DECREF
(
a
);
Py_DECREF
(
b
);
Py_DECREF
(
b
);
return
NULL
;
return
NULL
;
}
}
for
(
i
=
0
;
i
<
size_z
;
++
i
)
{
/* Compute digits for overlap of a and b. */
diga
=
(
i
<
size_a
?
a
->
ob_digit
[
i
]
:
0
)
^
maska
;
switch
(
op
)
{
digb
=
(
i
<
size_b
?
b
->
ob_digit
[
i
]
:
0
)
^
maskb
;
case
'&'
:
switch
(
op
)
{
for
(
i
=
0
;
i
<
size_b
;
++
i
)
case
'&'
:
z
->
ob_digit
[
i
]
=
diga
&
digb
;
break
;
z
->
ob_digit
[
i
]
=
a
->
ob_digit
[
i
]
&
b
->
ob_digit
[
i
];
case
'|'
:
z
->
ob_digit
[
i
]
=
diga
|
digb
;
break
;
break
;
case
'^'
:
z
->
ob_digit
[
i
]
=
diga
^
digb
;
break
;
case
'|'
:
}
for
(
i
=
0
;
i
<
size_b
;
++
i
)
z
->
ob_digit
[
i
]
=
a
->
ob_digit
[
i
]
|
b
->
ob_digit
[
i
];
break
;
case
'^'
:
for
(
i
=
0
;
i
<
size_b
;
++
i
)
z
->
ob_digit
[
i
]
=
a
->
ob_digit
[
i
]
^
b
->
ob_digit
[
i
];
break
;
default:
PyErr_BadArgument
();
return
NULL
;
}
/* Copy any remaining digits of a, inverting if necessary. */
if
(
op
==
'^'
&&
negb
)
for
(;
i
<
size_z
;
++
i
)
z
->
ob_digit
[
i
]
=
a
->
ob_digit
[
i
]
^
PyLong_MASK
;
else
if
(
i
<
size_z
)
memcpy
(
&
z
->
ob_digit
[
i
],
&
a
->
ob_digit
[
i
],
(
size_z
-
i
)
*
sizeof
(
digit
));
/* Complement result if negative. */
if
(
negz
)
{
Py_SIZE
(
z
)
=
-
(
Py_SIZE
(
z
));
z
->
ob_digit
[
size_z
]
=
PyLong_MASK
;
v_complement
(
z
->
ob_digit
,
z
->
ob_digit
,
size_z
+
1
);
}
}
Py_DECREF
(
a
);
Py_DECREF
(
a
);
Py_DECREF
(
b
);
Py_DECREF
(
b
);
z
=
long_normalize
(
z
);
return
(
PyObject
*
)
long_normalize
(
z
);
if
(
negz
==
0
)
return
(
PyObject
*
)
z
;
v
=
long_invert
(
z
);
Py_DECREF
(
z
);
return
v
;
}
}
static
PyObject
*
static
PyObject
*
...
...
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