mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
New restriction on pow(x, y, z): If z is not None, x and y must be of
integer types, and y must be >= 0. See discussion at http://sf.net/tracker/index.php?func=detail&aid=457066&group_id=5470&atid=105470
This commit is contained in:
parent
5d2b77cf31
commit
32f453eaa4
9 changed files with 79 additions and 49 deletions
|
@ -118,7 +118,7 @@ class instances are callable if they have a \method{__call__()} method.
|
||||||
operations.
|
operations.
|
||||||
\end{funcdesc}
|
\end{funcdesc}
|
||||||
|
|
||||||
\begin{funcdesc}{compile}{string, filename, kind\optional{,
|
\begin{funcdesc}{compile}{string, filename, kind\optional{,
|
||||||
flags\optional{, dont_inherit}}}
|
flags\optional{, dont_inherit}}}
|
||||||
Compile the \var{string} into a code object. Code objects can be
|
Compile the \var{string} into a code object. Code objects can be
|
||||||
executed by an \keyword{exec} statement or evaluated by a call to
|
executed by an \keyword{exec} statement or evaluated by a call to
|
||||||
|
@ -408,7 +408,7 @@ raised.
|
||||||
\begin{funcdesc}{locals}{}
|
\begin{funcdesc}{locals}{}
|
||||||
Return a dictionary representing the current local symbol table.
|
Return a dictionary representing the current local symbol table.
|
||||||
\strong{Warning:} The contents of this dictionary should not be
|
\strong{Warning:} The contents of this dictionary should not be
|
||||||
modified; changes may not affect the values of local variables used by
|
modified; changes may not affect the values of local variables used by
|
||||||
the interpreter.
|
the interpreter.
|
||||||
\end{funcdesc}
|
\end{funcdesc}
|
||||||
|
|
||||||
|
@ -478,7 +478,7 @@ the interpreter.
|
||||||
ignored). If the file cannot be opened, \exception{IOError} is
|
ignored). If the file cannot be opened, \exception{IOError} is
|
||||||
raised.
|
raised.
|
||||||
|
|
||||||
If \var{mode} is omitted, it defaults to \code{'r'}. When opening a
|
If \var{mode} is omitted, it defaults to \code{'r'}. When opening a
|
||||||
binary file, you should append \code{'b'} to the \var{mode} value
|
binary file, you should append \code{'b'} to the \var{mode} value
|
||||||
for improved portability. (It's useful even on systems which don't
|
for improved portability. (It's useful even on systems which don't
|
||||||
treat binary and text files differently, where it serves as
|
treat binary and text files differently, where it serves as
|
||||||
|
@ -519,8 +519,14 @@ the interpreter.
|
||||||
case, all arguments are converted to float and a float result is
|
case, all arguments are converted to float and a float result is
|
||||||
delivered. For example, \code{10**2} returns \code{100}, but
|
delivered. For example, \code{10**2} returns \code{100}, but
|
||||||
\code{10**-2} returns \code{0.01}. (This last feature was added in
|
\code{10**-2} returns \code{0.01}. (This last feature was added in
|
||||||
Python 2.2. In Python 2.1 and before, a negative second argument
|
Python 2.2. In Python 2.1 and before, if both arguments were of integer
|
||||||
would raise an exception.)
|
types and the second argument was negative, an exception was raised.)
|
||||||
|
If the second argument is negative, the third argument must be omitted.
|
||||||
|
If \var{z} is present, \var{x} and \var{y} must be of integer types,
|
||||||
|
and \var{y} must be non-negative. (This restriction was added in
|
||||||
|
Python 2.2. In Python 2.1 and before, floating 3-argument \code{pow()}
|
||||||
|
returned platform-dependent results depending on floating-point
|
||||||
|
rounding accidents.)
|
||||||
\end{funcdesc}
|
\end{funcdesc}
|
||||||
|
|
||||||
\begin{funcdesc}{range}{\optional{start,} stop\optional{, step}}
|
\begin{funcdesc}{range}{\optional{start,} stop\optional{, step}}
|
||||||
|
@ -731,7 +737,7 @@ returns a dictionary corresponding to the object's symbol table.
|
||||||
The returned dictionary should not be modified: the effects on the
|
The returned dictionary should not be modified: the effects on the
|
||||||
corresponding symbol table are undefined.\footnote{
|
corresponding symbol table are undefined.\footnote{
|
||||||
In the current implementation, local variable bindings cannot
|
In the current implementation, local variable bindings cannot
|
||||||
normally be affected this way, but variables retrieved from
|
normally be affected this way, but variables retrieved from
|
||||||
other scopes (such as modules) can be. This may change.}
|
other scopes (such as modules) can be. This may change.}
|
||||||
\end{funcdesc}
|
\end{funcdesc}
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,4 @@ The number in both columns should match.
|
||||||
-3L -3L
|
-3L -3L
|
||||||
-7L -7L
|
-7L -7L
|
||||||
|
|
||||||
3.0 3.0
|
|
||||||
-5.0 -5.0
|
|
||||||
-1.0 -1.0
|
|
||||||
-7.0 -7.0
|
|
||||||
|
|
||||||
|
|
|
@ -82,17 +82,28 @@ if fcmp(pow(2.,10), 1024.): raise TestFailed, 'pow(2.,10)'
|
||||||
if fcmp(pow(2.,20), 1024.*1024.): raise TestFailed, 'pow(2.,20)'
|
if fcmp(pow(2.,20), 1024.*1024.): raise TestFailed, 'pow(2.,20)'
|
||||||
if fcmp(pow(2.,30), 1024.*1024.*1024.): raise TestFailed, 'pow(2.,30)'
|
if fcmp(pow(2.,30), 1024.*1024.*1024.): raise TestFailed, 'pow(2.,30)'
|
||||||
#
|
#
|
||||||
# XXX These don't work -- negative float to the float power...
|
if fcmp(pow(-2.,0), 1.): raise TestFailed, 'pow(-2.,0)'
|
||||||
#if fcmp(pow(-2.,0), 1.): raise TestFailed, 'pow(-2.,0)'
|
if fcmp(pow(-2.,1), -2.): raise TestFailed, 'pow(-2.,1)'
|
||||||
#if fcmp(pow(-2.,1), -2.): raise TestFailed, 'pow(-2.,1)'
|
if fcmp(pow(-2.,2), 4.): raise TestFailed, 'pow(-2.,2)'
|
||||||
#if fcmp(pow(-2.,2), 4.): raise TestFailed, 'pow(-2.,2)'
|
if fcmp(pow(-2.,3), -8.): raise TestFailed, 'pow(-2.,3)'
|
||||||
#if fcmp(pow(-2.,3), -8.): raise TestFailed, 'pow(-2.,3)'
|
|
||||||
#
|
from types import FloatType
|
||||||
for x in 2, 2L, 2.0:
|
for x in 2, 2L, 2.0:
|
||||||
for y in 10, 10L, 10.0:
|
for y in 10, 10L, 10.0:
|
||||||
for z in 1000, 1000L, 1000.0:
|
for z in 1000, 1000L, 1000.0:
|
||||||
if fcmp(pow(x, y, z), 24.0):
|
if isinstance(x, FloatType) or \
|
||||||
raise TestFailed, 'pow(%s, %s, %s)' % (x, y, z)
|
isinstance(y, FloatType) or \
|
||||||
|
isinstance(z, FloatType):
|
||||||
|
try:
|
||||||
|
pow(x, y, z)
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise TestFailed("3-arg float pow() should have "
|
||||||
|
"raised TypeError %r" % (x, y, z))
|
||||||
|
else:
|
||||||
|
if fcmp(pow(x, y, z), 24.0):
|
||||||
|
raise TestFailed, 'pow(%s, %s, %s)' % (x, y, z)
|
||||||
|
|
||||||
print 'range'
|
print 'range'
|
||||||
if range(3) != [0, 1, 2]: raise TestFailed, 'range(3)'
|
if range(3) != [0, 1, 2]: raise TestFailed, 'range(3)'
|
||||||
|
|
|
@ -314,10 +314,19 @@ def test_auto_overflow():
|
||||||
checkit(x, '**', y)
|
checkit(x, '**', y)
|
||||||
|
|
||||||
for z in special:
|
for z in special:
|
||||||
if z != 0:
|
if z != 0 :
|
||||||
expected = pow(longx, longy, long(z))
|
if y >= 0:
|
||||||
got = pow(x, y, z)
|
expected = pow(longx, longy, long(z))
|
||||||
checkit('pow', x, y, '%', z)
|
got = pow(x, y, z)
|
||||||
|
checkit('pow', x, y, '%', z)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
pow(longx, longy, long(z))
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise TestFailed("pow%r should have raised "
|
||||||
|
"TypeError" % ((longx, longy, long(z))))
|
||||||
|
|
||||||
# ---------------------------------------------------------------- do it
|
# ---------------------------------------------------------------- do it
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,15 @@ def powtest(type):
|
||||||
for j in range(jl, jh+1):
|
for j in range(jl, jh+1):
|
||||||
for k in range(kl, kh+1):
|
for k in range(kl, kh+1):
|
||||||
if k != 0:
|
if k != 0:
|
||||||
|
if type == float or j < 0:
|
||||||
|
try:
|
||||||
|
pow(type(i),j,k)
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise TestFailed("expected TypeError from "
|
||||||
|
"pow%r" % ((type(i), j, k)))
|
||||||
|
continue
|
||||||
if compare(pow(type(i),j,k), pow(type(i),j)% type(k)):
|
if compare(pow(type(i),j,k), pow(type(i),j)% type(k)):
|
||||||
raise ValueError, "pow(" +str(i)+ "," +str(j)+ \
|
raise ValueError, "pow(" +str(i)+ "," +str(j)+ \
|
||||||
"," +str(k)+ ") != pow(" +str(i)+ "," + \
|
"," +str(k)+ ") != pow(" +str(i)+ "," + \
|
||||||
|
@ -96,10 +105,6 @@ print `pow(-3L,3L) % -8`, `pow(-3L,3L,-8)`
|
||||||
print `pow(5L,2) % -8`, `pow(5L,2,-8)`
|
print `pow(5L,2) % -8`, `pow(5L,2,-8)`
|
||||||
print
|
print
|
||||||
|
|
||||||
print pow(3.0,3.0) % 8, pow(3.0,3.0,8)
|
|
||||||
print pow(3.0,3.0) % -8, pow(3.0,3.0,-8)
|
|
||||||
print pow(3.0,2) % -2, pow(3.0,2,-2)
|
|
||||||
print pow(5.0,2) % -8, pow(5.0,2,-8)
|
|
||||||
print
|
print
|
||||||
|
|
||||||
for i in range(-10, 11):
|
for i in range(-10, 11):
|
||||||
|
@ -112,8 +117,3 @@ for i in range(-10, 11):
|
||||||
if j >= 0 and k != 0:
|
if j >= 0 and k != 0:
|
||||||
o = pow(long(i),j) % k
|
o = pow(long(i),j) % k
|
||||||
n = pow(long(i),j,k)
|
n = pow(long(i),j,k)
|
||||||
if o != n: print 'Long mismatch:', i,j,k
|
|
||||||
if i >= 0 and k != 0:
|
|
||||||
o = pow(float(i),j) % k
|
|
||||||
n = pow(float(i),j,k)
|
|
||||||
if o != n: print 'Float mismatch:', i,j,k
|
|
||||||
|
|
|
@ -3,6 +3,12 @@ What's New in Python 2.2a3?
|
||||||
|
|
||||||
Core
|
Core
|
||||||
|
|
||||||
|
- The 3-argument builtin pow() no longer allows a third non-None argument
|
||||||
|
if either of the first two arguments is a float, or if both are of
|
||||||
|
integer types and the second argument is negative (in which latter case
|
||||||
|
the arguments are converted to float, so this is really the same
|
||||||
|
restriction).
|
||||||
|
|
||||||
- The builtin dir() now returns more information, and sometimes much
|
- The builtin dir() now returns more information, and sometimes much
|
||||||
more, generally naming all attributes of an object, and all attributes
|
more, generally naming all attributes of an object, and all attributes
|
||||||
reachable from the object via its class, and from its class's base
|
reachable from the object via its class, and from its class's base
|
||||||
|
|
|
@ -492,11 +492,13 @@ static PyObject *
|
||||||
float_pow(PyObject *v, PyObject *w, PyObject *z)
|
float_pow(PyObject *v, PyObject *w, PyObject *z)
|
||||||
{
|
{
|
||||||
double iv, iw, ix;
|
double iv, iw, ix;
|
||||||
/* XXX Doesn't handle overflows if z!=None yet; it may never do so :(
|
|
||||||
* The z parameter is really only going to be useful for integers and
|
if ((PyObject *)z != Py_None) {
|
||||||
* long integers. Maybe something clever with logarithms could be done.
|
PyErr_SetString(PyExc_TypeError,
|
||||||
* [AMK]
|
"3rd argument to floating pow() must be None");
|
||||||
*/
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
CONVERT_TO_DOUBLE(v, iv);
|
CONVERT_TO_DOUBLE(v, iv);
|
||||||
CONVERT_TO_DOUBLE(w, iw);
|
CONVERT_TO_DOUBLE(w, iw);
|
||||||
|
|
||||||
|
@ -538,16 +540,6 @@ float_pow(PyObject *v, PyObject *w, PyObject *z)
|
||||||
PyErr_SetFromErrno(PyExc_OverflowError);
|
PyErr_SetFromErrno(PyExc_OverflowError);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if ((PyObject *)z != Py_None) {
|
|
||||||
double iz;
|
|
||||||
CONVERT_TO_DOUBLE(z, iz);
|
|
||||||
PyFPE_START_PROTECT("pow", return 0)
|
|
||||||
ix = fmod(ix, iz); /* XXX To Be Rewritten */
|
|
||||||
if (ix != 0 && ((iv < 0 && iz > 0) || (iv > 0 && iz < 0) )) {
|
|
||||||
ix += iz;
|
|
||||||
}
|
|
||||||
PyFPE_END_PROTECT(ix)
|
|
||||||
}
|
|
||||||
return PyFloat_FromDouble(ix);
|
return PyFloat_FromDouble(ix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -575,6 +575,11 @@ int_pow(PyIntObject *v, PyIntObject *w, PyIntObject *z)
|
||||||
CONVERT_TO_LONG(v, iv);
|
CONVERT_TO_LONG(v, iv);
|
||||||
CONVERT_TO_LONG(w, iw);
|
CONVERT_TO_LONG(w, iw);
|
||||||
if (iw < 0) {
|
if (iw < 0) {
|
||||||
|
if ((PyObject *)z != Py_None) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "integer pow() arg "
|
||||||
|
"3 must not be specified when arg 2 is < 0");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
/* Return a float. This works because we know that
|
/* Return a float. This works because we know that
|
||||||
this calls float_pow() which converts its
|
this calls float_pow() which converts its
|
||||||
arguments to double. */
|
arguments to double. */
|
||||||
|
|
|
@ -1598,12 +1598,17 @@ long_pow(PyObject *v, PyObject *w, PyObject *x)
|
||||||
|
|
||||||
size_b = b->ob_size;
|
size_b = b->ob_size;
|
||||||
if (size_b < 0) {
|
if (size_b < 0) {
|
||||||
/* Return a float. This works because we know that
|
|
||||||
this calls float_pow() which converts its
|
|
||||||
arguments to double. */
|
|
||||||
Py_DECREF(a);
|
Py_DECREF(a);
|
||||||
Py_DECREF(b);
|
Py_DECREF(b);
|
||||||
Py_DECREF(c);
|
Py_DECREF(c);
|
||||||
|
if (x != Py_None) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "integer pow() arg "
|
||||||
|
"3 must not be specified when arg 2 is < 0");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* Return a float. This works because we know that
|
||||||
|
this calls float_pow() which converts its
|
||||||
|
arguments to double. */
|
||||||
return PyFloat_Type.tp_as_number->nb_power(v, w, x);
|
return PyFloat_Type.tp_as_number->nb_power(v, w, x);
|
||||||
}
|
}
|
||||||
z = (PyLongObject *)PyLong_FromLong(1L);
|
z = (PyLongObject *)PyLong_FromLong(1L);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue