mirror of
https://github.com/python/cpython.git
synced 2025-07-12 13:55:34 +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.
|
||||
\end{funcdesc}
|
||||
|
||||
\begin{funcdesc}{compile}{string, filename, kind\optional{,
|
||||
\begin{funcdesc}{compile}{string, filename, kind\optional{,
|
||||
flags\optional{, dont_inherit}}}
|
||||
Compile the \var{string} into a code object. Code objects can be
|
||||
executed by an \keyword{exec} statement or evaluated by a call to
|
||||
|
@ -408,7 +408,7 @@ raised.
|
|||
\begin{funcdesc}{locals}{}
|
||||
Return a dictionary representing the current local symbol table.
|
||||
\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.
|
||||
\end{funcdesc}
|
||||
|
||||
|
@ -478,7 +478,7 @@ the interpreter.
|
|||
ignored). If the file cannot be opened, \exception{IOError} is
|
||||
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
|
||||
for improved portability. (It's useful even on systems which don't
|
||||
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
|
||||
delivered. For example, \code{10**2} returns \code{100}, but
|
||||
\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
|
||||
would raise an exception.)
|
||||
Python 2.2. In Python 2.1 and before, if both arguments were of integer
|
||||
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}
|
||||
|
||||
\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
|
||||
corresponding symbol table are undefined.\footnote{
|
||||
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.}
|
||||
\end{funcdesc}
|
||||
|
||||
|
|
|
@ -22,8 +22,4 @@ The number in both columns should match.
|
|||
-3L -3L
|
||||
-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.,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.,1), -2.): raise TestFailed, 'pow(-2.,1)'
|
||||
#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.,0), 1.): raise TestFailed, 'pow(-2.,0)'
|
||||
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.,3), -8.): raise TestFailed, 'pow(-2.,3)'
|
||||
|
||||
from types import FloatType
|
||||
for x in 2, 2L, 2.0:
|
||||
for y in 10, 10L, 10.0:
|
||||
for z in 1000, 1000L, 1000.0:
|
||||
if fcmp(pow(x, y, z), 24.0):
|
||||
raise TestFailed, 'pow(%s, %s, %s)' % (x, y, z)
|
||||
if isinstance(x, FloatType) or \
|
||||
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'
|
||||
if range(3) != [0, 1, 2]: raise TestFailed, 'range(3)'
|
||||
|
|
|
@ -314,10 +314,19 @@ def test_auto_overflow():
|
|||
checkit(x, '**', y)
|
||||
|
||||
for z in special:
|
||||
if z != 0:
|
||||
expected = pow(longx, longy, long(z))
|
||||
got = pow(x, y, z)
|
||||
checkit('pow', x, y, '%', z)
|
||||
if z != 0 :
|
||||
if y >= 0:
|
||||
expected = pow(longx, longy, long(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
|
||||
|
||||
|
|
|
@ -64,6 +64,15 @@ def powtest(type):
|
|||
for j in range(jl, jh+1):
|
||||
for k in range(kl, kh+1):
|
||||
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)):
|
||||
raise ValueError, "pow(" +str(i)+ "," +str(j)+ \
|
||||
"," +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
|
||||
|
||||
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
|
||||
|
||||
for i in range(-10, 11):
|
||||
|
@ -112,8 +117,3 @@ for i in range(-10, 11):
|
|||
if j >= 0 and k != 0:
|
||||
o = 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
|
||||
|
||||
- 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
|
||||
more, generally naming all attributes of an object, and all attributes
|
||||
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)
|
||||
{
|
||||
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
|
||||
* long integers. Maybe something clever with logarithms could be done.
|
||||
* [AMK]
|
||||
*/
|
||||
|
||||
if ((PyObject *)z != Py_None) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"3rd argument to floating pow() must be None");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CONVERT_TO_DOUBLE(v, iv);
|
||||
CONVERT_TO_DOUBLE(w, iw);
|
||||
|
||||
|
@ -538,16 +540,6 @@ float_pow(PyObject *v, PyObject *w, PyObject *z)
|
|||
PyErr_SetFromErrno(PyExc_OverflowError);
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -575,6 +575,11 @@ int_pow(PyIntObject *v, PyIntObject *w, PyIntObject *z)
|
|||
CONVERT_TO_LONG(v, iv);
|
||||
CONVERT_TO_LONG(w, iw);
|
||||
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
|
||||
this calls float_pow() which converts its
|
||||
arguments to double. */
|
||||
|
|
|
@ -1598,12 +1598,17 @@ long_pow(PyObject *v, PyObject *w, PyObject *x)
|
|||
|
||||
size_b = b->ob_size;
|
||||
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(b);
|
||||
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);
|
||||
}
|
||||
z = (PyLongObject *)PyLong_FromLong(1L);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue