Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 32f453e

Browse files
committed
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
1 parent 5d2b77c commit 32f453e

9 files changed

Lines changed: 79 additions & 49 deletions

File tree

Doc/lib/libfuncs.tex

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ \section{Built-in Functions \label{built-in-funcs}}
118118
operations.
119119
\end{funcdesc}
120120

121-
\begin{funcdesc}{compile}{string, filename, kind\optional{,
121+
\begin{funcdesc}{compile}{string, filename, kind\optional{,
122122
flags\optional{, dont_inherit}}}
123123
Compile the \var{string} into a code object. Code objects can be
124124
executed by an \keyword{exec} statement or evaluated by a call to
@@ -408,7 +408,7 @@ \section{Built-in Functions \label{built-in-funcs}}
408408
\begin{funcdesc}{locals}{}
409409
Return a dictionary representing the current local symbol table.
410410
\strong{Warning:} The contents of this dictionary should not be
411-
modified; changes may not affect the values of local variables used by
411+
modified; changes may not affect the values of local variables used by
412412
the interpreter.
413413
\end{funcdesc}
414414

@@ -478,7 +478,7 @@ \section{Built-in Functions \label{built-in-funcs}}
478478
ignored). If the file cannot be opened, \exception{IOError} is
479479
raised.
480480

481-
If \var{mode} is omitted, it defaults to \code{'r'}. When opening a
481+
If \var{mode} is omitted, it defaults to \code{'r'}. When opening a
482482
binary file, you should append \code{'b'} to the \var{mode} value
483483
for improved portability. (It's useful even on systems which don't
484484
treat binary and text files differently, where it serves as
@@ -519,8 +519,14 @@ \section{Built-in Functions \label{built-in-funcs}}
519519
case, all arguments are converted to float and a float result is
520520
delivered. For example, \code{10**2} returns \code{100}, but
521521
\code{10**-2} returns \code{0.01}. (This last feature was added in
522-
Python 2.2. In Python 2.1 and before, a negative second argument
523-
would raise an exception.)
522+
Python 2.2. In Python 2.1 and before, if both arguments were of integer
523+
types and the second argument was negative, an exception was raised.)
524+
If the second argument is negative, the third argument must be omitted.
525+
If \var{z} is present, \var{x} and \var{y} must be of integer types,
526+
and \var{y} must be non-negative. (This restriction was added in
527+
Python 2.2. In Python 2.1 and before, floating 3-argument \code{pow()}
528+
returned platform-dependent results depending on floating-point
529+
rounding accidents.)
524530
\end{funcdesc}
525531

526532
\begin{funcdesc}{range}{\optional{start,} stop\optional{, step}}
@@ -731,7 +737,7 @@ \section{Built-in Functions \label{built-in-funcs}}
731737
The returned dictionary should not be modified: the effects on the
732738
corresponding symbol table are undefined.\footnote{
733739
In the current implementation, local variable bindings cannot
734-
normally be affected this way, but variables retrieved from
740+
normally be affected this way, but variables retrieved from
735741
other scopes (such as modules) can be. This may change.}
736742
\end{funcdesc}
737743

Lib/test/output/test_pow

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,4 @@ The number in both columns should match.
2222
-3L -3L
2323
-7L -7L
2424

25-
3.0 3.0
26-
-5.0 -5.0
27-
-1.0 -1.0
28-
-7.0 -7.0
2925

Lib/test/test_b2.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -82,17 +82,28 @@
8282
if fcmp(pow(2.,20), 1024.*1024.): raise TestFailed, 'pow(2.,20)'
8383
if fcmp(pow(2.,30), 1024.*1024.*1024.): raise TestFailed, 'pow(2.,30)'
8484
#
85-
# XXX These don't work -- negative float to the float power...
86-
#if fcmp(pow(-2.,0), 1.): raise TestFailed, 'pow(-2.,0)'
87-
#if fcmp(pow(-2.,1), -2.): raise TestFailed, 'pow(-2.,1)'
88-
#if fcmp(pow(-2.,2), 4.): raise TestFailed, 'pow(-2.,2)'
89-
#if fcmp(pow(-2.,3), -8.): raise TestFailed, 'pow(-2.,3)'
90-
#
85+
if fcmp(pow(-2.,0), 1.): raise TestFailed, 'pow(-2.,0)'
86+
if fcmp(pow(-2.,1), -2.): raise TestFailed, 'pow(-2.,1)'
87+
if fcmp(pow(-2.,2), 4.): raise TestFailed, 'pow(-2.,2)'
88+
if fcmp(pow(-2.,3), -8.): raise TestFailed, 'pow(-2.,3)'
89+
90+
from types import FloatType
9191
for x in 2, 2L, 2.0:
9292
for y in 10, 10L, 10.0:
9393
for z in 1000, 1000L, 1000.0:
94-
if fcmp(pow(x, y, z), 24.0):
95-
raise TestFailed, 'pow(%s, %s, %s)' % (x, y, z)
94+
if isinstance(x, FloatType) or \
95+
isinstance(y, FloatType) or \
96+
isinstance(z, FloatType):
97+
try:
98+
pow(x, y, z)
99+
except TypeError:
100+
pass
101+
else:
102+
raise TestFailed("3-arg float pow() should have "
103+
"raised TypeError %r" % (x, y, z))
104+
else:
105+
if fcmp(pow(x, y, z), 24.0):
106+
raise TestFailed, 'pow(%s, %s, %s)' % (x, y, z)
96107

97108
print 'range'
98109
if range(3) != [0, 1, 2]: raise TestFailed, 'range(3)'

Lib/test/test_long.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -314,10 +314,19 @@ def checkit(*args):
314314
checkit(x, '**', y)
315315

316316
for z in special:
317-
if z != 0:
318-
expected = pow(longx, longy, long(z))
319-
got = pow(x, y, z)
320-
checkit('pow', x, y, '%', z)
317+
if z != 0 :
318+
if y >= 0:
319+
expected = pow(longx, longy, long(z))
320+
got = pow(x, y, z)
321+
checkit('pow', x, y, '%', z)
322+
else:
323+
try:
324+
pow(longx, longy, long(z))
325+
except TypeError:
326+
pass
327+
else:
328+
raise TestFailed("pow%r should have raised "
329+
"TypeError" % ((longx, longy, long(z))))
321330

322331
# ---------------------------------------------------------------- do it
323332

Lib/test/test_pow.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,15 @@ def powtest(type):
6464
for j in range(jl, jh+1):
6565
for k in range(kl, kh+1):
6666
if k != 0:
67+
if type == float or j < 0:
68+
try:
69+
pow(type(i),j,k)
70+
except TypeError:
71+
pass
72+
else:
73+
raise TestFailed("expected TypeError from "
74+
"pow%r" % ((type(i), j, k)))
75+
continue
6776
if compare(pow(type(i),j,k), pow(type(i),j)% type(k)):
6877
raise ValueError, "pow(" +str(i)+ "," +str(j)+ \
6978
"," +str(k)+ ") != pow(" +str(i)+ "," + \
@@ -96,10 +105,6 @@ def powtest(type):
96105
print `pow(5L,2) % -8`, `pow(5L,2,-8)`
97106
print
98107

99-
print pow(3.0,3.0) % 8, pow(3.0,3.0,8)
100-
print pow(3.0,3.0) % -8, pow(3.0,3.0,-8)
101-
print pow(3.0,2) % -2, pow(3.0,2,-2)
102-
print pow(5.0,2) % -8, pow(5.0,2,-8)
103108
print
104109

105110
for i in range(-10, 11):
@@ -112,8 +117,3 @@ def powtest(type):
112117
if j >= 0 and k != 0:
113118
o = pow(long(i),j) % k
114119
n = pow(long(i),j,k)
115-
if o != n: print 'Long mismatch:', i,j,k
116-
if i >= 0 and k != 0:
117-
o = pow(float(i),j) % k
118-
n = pow(float(i),j,k)
119-
if o != n: print 'Float mismatch:', i,j,k

Misc/NEWS

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ What's New in Python 2.2a3?
33

44
Core
55

6+
- The 3-argument builtin pow() no longer allows a third non-None argument
7+
if either of the first two arguments is a float, or if both are of
8+
integer types and the second argument is negative (in which latter case
9+
the arguments are converted to float, so this is really the same
10+
restriction).
11+
612
- The builtin dir() now returns more information, and sometimes much
713
more, generally naming all attributes of an object, and all attributes
814
reachable from the object via its class, and from its class's base

Objects/floatobject.c

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -492,11 +492,13 @@ static PyObject *
492492
float_pow(PyObject *v, PyObject *w, PyObject *z)
493493
{
494494
double iv, iw, ix;
495-
/* XXX Doesn't handle overflows if z!=None yet; it may never do so :(
496-
* The z parameter is really only going to be useful for integers and
497-
* long integers. Maybe something clever with logarithms could be done.
498-
* [AMK]
499-
*/
495+
496+
if ((PyObject *)z != Py_None) {
497+
PyErr_SetString(PyExc_TypeError,
498+
"3rd argument to floating pow() must be None");
499+
return NULL;
500+
}
501+
500502
CONVERT_TO_DOUBLE(v, iv);
501503
CONVERT_TO_DOUBLE(w, iw);
502504

@@ -538,16 +540,6 @@ float_pow(PyObject *v, PyObject *w, PyObject *z)
538540
PyErr_SetFromErrno(PyExc_OverflowError);
539541
return NULL;
540542
}
541-
if ((PyObject *)z != Py_None) {
542-
double iz;
543-
CONVERT_TO_DOUBLE(z, iz);
544-
PyFPE_START_PROTECT("pow", return 0)
545-
ix = fmod(ix, iz); /* XXX To Be Rewritten */
546-
if (ix != 0 && ((iv < 0 && iz > 0) || (iv > 0 && iz < 0) )) {
547-
ix += iz;
548-
}
549-
PyFPE_END_PROTECT(ix)
550-
}
551543
return PyFloat_FromDouble(ix);
552544
}
553545

Objects/intobject.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,11 @@ int_pow(PyIntObject *v, PyIntObject *w, PyIntObject *z)
575575
CONVERT_TO_LONG(v, iv);
576576
CONVERT_TO_LONG(w, iw);
577577
if (iw < 0) {
578+
if ((PyObject *)z != Py_None) {
579+
PyErr_SetString(PyExc_TypeError, "integer pow() arg "
580+
"3 must not be specified when arg 2 is < 0");
581+
return NULL;
582+
}
578583
/* Return a float. This works because we know that
579584
this calls float_pow() which converts its
580585
arguments to double. */

Objects/longobject.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1598,12 +1598,17 @@ long_pow(PyObject *v, PyObject *w, PyObject *x)
15981598

15991599
size_b = b->ob_size;
16001600
if (size_b < 0) {
1601-
/* Return a float. This works because we know that
1602-
this calls float_pow() which converts its
1603-
arguments to double. */
16041601
Py_DECREF(a);
16051602
Py_DECREF(b);
16061603
Py_DECREF(c);
1604+
if (x != Py_None) {
1605+
PyErr_SetString(PyExc_TypeError, "integer pow() arg "
1606+
"3 must not be specified when arg 2 is < 0");
1607+
return NULL;
1608+
}
1609+
/* Return a float. This works because we know that
1610+
this calls float_pow() which converts its
1611+
arguments to double. */
16071612
return PyFloat_Type.tp_as_number->nb_power(v, w, x);
16081613
}
16091614
z = (PyLongObject *)PyLong_FromLong(1L);

0 commit comments

Comments
 (0)