Index: 0.27/Include/abstract.h
--- 0.27/Include/abstract.h Sun, 03 Sep 2000 19:51:56 -0400 nas (python/n/35_abstract.h 1.1.1.4 644)
+++ 0.26(w)/Include/abstract.h Sun, 12 Nov 2000 16:04:50 -0500 nas (python/n/35_abstract.h 1.1.1.4 644)
@@ -470,6 +470,17 @@
 
        */
 
+     DL_IMPORT(PyObject *) PyNumber_Compare(PyObject *o1, PyObject *o2);
+
+       /*
+	  Returns the result of comparing o1 and o2, or null on failure.
+	  This is the equivalent of the Python expression: cmp(o1,o2)
+
+	  XXX This should take a third argument as per the rich comparison
+	  proposal.
+
+       */
+
      DL_IMPORT(PyObject *) PyNumber_Add(PyObject *o1, PyObject *o2);
 
        /*
Index: 0.27/Include/classobject.h
--- 0.27/Include/classobject.h Sun, 03 Sep 2000 19:51:56 -0400 nas (python/n/40_classobjec 1.4 644)
+++ 0.26(w)/Include/classobject.h Sun, 12 Nov 2000 15:56:16 -0500 nas (python/n/40_classobjec 1.4 644)
@@ -59,14 +59,6 @@
 
 extern DL_IMPORT(int) PyClass_IsSubclass(PyObject *, PyObject *);
 
-extern DL_IMPORT(PyObject *) PyInstance_DoBinOp(PyObject *, PyObject *,
-                                                char *, char *,
-                                                PyObject * (*)(PyObject *,
-                                                               PyObject *));
-
-extern DL_IMPORT(int)
-PyInstance_HalfBinOp(PyObject *, PyObject *, char *, PyObject **,
-			PyObject * (*)(PyObject *, PyObject *), int);
 
 #ifdef __cplusplus
 }
Index: 0.27/Include/object.h
--- 0.27/Include/object.h Mon, 25 Sep 2000 22:16:58 -0400 nas (python/o/18_object.h 1.1.3.6 644)
+++ 0.26(w)/Include/object.h Sun, 12 Nov 2000 16:05:58 -0500 nas (python/o/18_object.h 1.1.3.6 644)
@@ -119,6 +119,11 @@
 typedef int (*traverseproc)(PyObject *, visitproc, void *);
 
 typedef struct {
+	/* For old style numbers all arguments are guaranteed to be of the
+	   object's type (modulo coercion hacks that is); new style numbers
+	   should check both arguments for proper type and implement the
+	   necessary conversions in the slots themselves. */
+
 	binaryfunc nb_add;
 	binaryfunc nb_subtract;
 	binaryfunc nb_multiply;
@@ -153,6 +158,12 @@
 	binaryfunc nb_inplace_and;
 	binaryfunc nb_inplace_xor;
 	binaryfunc nb_inplace_or;
+
+	/* New style number slots; these are only used the
+	   Py_TPFLAGS_NEWSTYLENUMBER flag is set */
+
+	binaryfunc nb_cmp; /* XXX this should be richcmpfunc */
+
 } PyNumberMethods;
 
 typedef struct {
@@ -322,6 +333,9 @@
 /* PySequenceMethods and PyNumberMethods contain in-place operators */
 #define Py_TPFLAGS_HAVE_INPLACEOPS (1L<<3)
 
+/* PyNumberMethods do their own coercion */
+#define Py_TPFLAGS_NEWSTYLENUMBER (1L<<4)
+
 #define Py_TPFLAGS_DEFAULT  (Py_TPFLAGS_HAVE_GETCHARBUFFER | \
                              Py_TPFLAGS_HAVE_SEQUENCE_IN | \
                              Py_TPFLAGS_HAVE_INPLACEOPS)
@@ -434,6 +448,26 @@
 
 #define Py_None (&_Py_NoneStruct)
 
+/*
+Py_NotImplemented is a singleton used to signal that an operation is
+not implemented for a given type combination.
+*/
+
+extern DL_IMPORT(PyObject) _Py_NotImplementedStruct; /* Don't use this directly */
+
+#define Py_NotImplemented (&_Py_NotImplementedStruct)
+
+/* Coercion debugging printf */
+/*#define COERCION_DEBUG*/
+#ifdef COERCION_DEBUG
+# ifndef DPRINTF    
+#  define DPRINTF if (Py_DebugFlag) printf
+# endif
+#else
+# ifndef DPRINTF    
+#  define DPRINTF if (0) printf
+# endif
+#endif
 
 /*
 A common programming style in Python requires the forward declaration
Index: 0.27/Objects/abstract.c
--- 0.27/Objects/abstract.c Thu, 05 Oct 2000 18:42:16 -0400 nas (python/E/14_abstract.c 1.1.1.6 644)
+++ 0.26(w)/Objects/abstract.c Sun, 12 Nov 2000 15:40:15 -0500 nas (python/E/14_abstract.c 1.1.1.6 644)
@@ -1,7 +1,12 @@
 /* Abstract Object Interface (many thanks to Jim Fulton) */
 
+
 #include "Python.h"
 #include <ctype.h>
+#include "structmember.h" /* we need the offsetof() macro from there */
+
+#define NEW_STYLE_NUMBER(o) PyType_HasFeature((o)->ob_type, \
+				Py_TPFLAGS_NEWSTYLENUMBER)
 
 /* Shorthands to return certain errors */
 
@@ -281,108 +286,439 @@
 
 /* Binary operators */
 
-#define BINOP(v, w, opname, ropname, thisfunc) \
-	if (PyInstance_Check(v) || PyInstance_Check(w)) \
-		return PyInstance_DoBinOp(v, w, opname, ropname, thisfunc)
+/* New style number protocol support */
 
-PyObject *
-PyNumber_Or(PyObject *v, PyObject *w)
-{
-	BINOP(v, w, "__or__", "__ror__", PyNumber_Or);
-	if (v->ob_type->tp_as_number != NULL) {
-		PyObject *x = NULL;
-		PyObject * (*f)(PyObject *, PyObject *) = NULL;
-		if (PyNumber_Coerce(&v, &w) != 0)
-			return NULL;
-		if (v->ob_type->tp_as_number != NULL &&
-		    (f = v->ob_type->tp_as_number->nb_or) != NULL)
-			x = (*f)(v, w);
+#define NB_SLOT(x) offsetof(PyNumberMethods,x)
+#define NB_BINOP(nb_methods,slot) \
+		((binaryfunc*)(& ((char*)nb_methods)[slot] ))
+#define NB_TERNOP(nb_methods,slot) \
+		((ternaryfunc*)(& ((char*)nb_methods)[slot] ))
+
+/* Forward declarations for new slot emulators. */
+
+static PyObject *_PyNumber_OldstyleCompare(PyObject *v, PyObject *w);
+
+/*
+  Calling scheme used for binary operations:
+
+  v	w	Action
+  -------------------------------------------------------------------
+  new	new	v.op(v,w), w.op(v,w)
+  new	old	v.op(v,w), coerce(v,w), v.op(v,w)
+  old	new	w.op(v,w), coerce(v,w), v.op(v,w)
+  old	old	coerce(v,w), v.op(v,w)
+
+  Legend:
+  -------
+  * new == new style number
+  * old == old style number
+  * Action indicates the order in which operations are tried until either
+    a valid result is produced or an error occurs.
+
+ */
+
+static PyObject *
+_PyNumber_BinaryOperation(PyObject *v,
+			  PyObject *w,
+			  const int op_slot,
+			  const char *operation)
+{
+	PyNumberMethods *mv, *mw;
+	register PyObject *x;
+	register binaryfunc *slot;
+	int c;
+	
+	DPRINTF("_PyNumber_BinaryOperation(%s at 0x%lx, %s at 0x%lx,"
+		" %i,%s);\n",
+		v->ob_type->tp_name,(long)v,
+		w->ob_type->tp_name,(long)w,op_slot,operation);
+
+	/* First try: v.op(v,w) */
+	mv = v->ob_type->tp_as_number;
+	if (mv != NULL) {
+		DPRINTF(" Trying first number\n");
+		if (NEW_STYLE_NUMBER(v)) {
+			DPRINTF("  is a new style number\n");
+			slot = NB_BINOP(mv,op_slot);
+			if (*slot) {
+				x = (*slot)(v,w);
+				if (x != Py_NotImplemented)
+					return x;
+				/* Can't do it... fall through */
+				Py_DECREF(x);
+				DPRINTF("  operation not implemented\n");
+			}
+			else
+				DPRINTF("  slot not implemented\n");
+		}
+		else
+			DPRINTF("  is an old style number\n");
+	}
+	else
+	    DPRINTF(" First argument is not a number\n");
+
+	/* Then try: w.op(v,w) */
+	mw = w->ob_type->tp_as_number;
+	if (mw != NULL) {
+		DPRINTF(" Trying second number\n"); 
+		if (NEW_STYLE_NUMBER(w)) {
+			DPRINTF("  is a new style number\n");
+			slot = NB_BINOP(mw,op_slot);
+			if (*slot) {
+				x = (*slot)(v,w);
+				if (x != Py_NotImplemented)
+					return x;
+				/* Can't do it... fall through */
+				Py_DECREF(x);
+				DPRINTF("  operation not implemented\n");
+			}
+			else
+				DPRINTF("  slot not implemented\n");
+			/* If both arguments are new style numbers and
+			   don't implement the requested operation,
+			   then we have bad operands. */
+			if (NEW_STYLE_NUMBER(v))
+				goto badOperands;
+		}
+		else
+			DPRINTF("  is an old style number\n");
+	}
+	else
+	    DPRINTF(" Second argument is not a number\n");
+
+	/* When using old coercion, make sure that the requested slot
+	   is available on old style numbers or use an emulation. */
+	if (op_slot > NB_SLOT(nb_hex)) {
+
+	    /* Emulation hooks: */
+	    if (op_slot == NB_SLOT(nb_cmp))
+		return _PyNumber_OldstyleCompare(v,w);
+
+	    goto badOperands;
+	}
+	
+	DPRINTF(" Reverting to old style coercion\n");
+	
+	c = PyNumber_CoerceEx(&v, &w);
+	if (c < 0)
+		return NULL;
+	if (c == 0) {
+		DPRINTF("  which gives: (%s at 0x%lx) "
+			"%s (%s at 0x%lx)\n",
+			v->ob_type->tp_name,(long)v,operation,
+			w->ob_type->tp_name,(long)w);
+		if (v->ob_type->tp_as_number != NULL) {
+			slot = NB_BINOP(v->ob_type->tp_as_number,
+					op_slot);
+			if (*slot) {
+				x = (*slot)(v, w);
+				Py_DECREF(v);
+				Py_DECREF(w);
+				return x;
+			}
+		}
+		/* PyNumber_CoerceEx has incremented the ref counts */
 		Py_DECREF(v);
 		Py_DECREF(w);
-		if (f != NULL)
-			return x;
 	}
-	return type_error("bad operand type(s) for |");
+	/* if (c == 1), we fall through and report an error;
+	   ref counts are not incremented by PyNumber_CoerceEx
+	   in this case */
+
+ badOperands:
+	PyErr_Format(PyExc_TypeError, "bad operand type(s) for %s",operation);
+	return NULL;
 }
 
-PyObject *
-PyNumber_Xor(PyObject *v, PyObject *w)
-{
-	BINOP(v, w, "__xor__", "__rxor__", PyNumber_Xor);
-	if (v->ob_type->tp_as_number != NULL) {
-		PyObject *x = NULL;
-		PyObject * (*f)(PyObject *, PyObject *) = NULL;
-		if (PyNumber_Coerce(&v, &w) != 0)
-			return NULL;
-		if (v->ob_type->tp_as_number != NULL &&
-		    (f = v->ob_type->tp_as_number->nb_xor) != NULL)
-			x = (*f)(v, w);
+/*
+  Calling scheme used for ternary operations:
+
+  v	w	z	Action
+  -------------------------------------------------------------------
+  new	new	new	v.op(v,w,z), w.op(v,w,z), z.op(v,w,z)
+  new	old	new	v.op(v,w,z), z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
+  old	new	new	w.op(v,w,z), z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
+  old	old	new	z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
+  new	new	old	v.op(v,w,z), w.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
+  new	old	old	v.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
+  old	new	old	w.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
+  old	old	old	coerce(v,w,z), v.op(v,w,z)
+
+  Legend:
+  -------
+  * new == new style number
+  * old == old style number
+  * Action indicates the order in which operations are tried until either
+    a valid result is produced or an error occurs.
+  * coerce(v,w,z) actually does: coerce(v,w), coerce(v,z), coerce(w,z) and
+    only if z != Py_None; if z == Py_None, then it is treated as absent
+    variable and only coerce(v,w) is tried.
+
+ */
+
+static PyObject *
+_PyNumber_TernaryOperation(PyObject *v,
+			   PyObject *w,
+			   PyObject *z,
+			   const int op_slot,
+			   const char *operation)
+{
+	PyNumberMethods *mv, *mw, *mz;
+	register PyObject *x = NULL;
+	register ternaryfunc *slot;
+	
+	DPRINTF("_PyNumber_TernaryOperation(%s at 0x%lx, "
+		"%s at 0x%lx, %s at 0x%lx, %i,%s);\n",
+		v->ob_type->tp_name,(long)v,
+		w->ob_type->tp_name,(long)w,
+		z->ob_type->tp_name,(long)z,
+		op_slot,operation);
+
+	/* First try: v.op(v,w,z) */
+	mv = v->ob_type->tp_as_number;
+	if (mv != NULL) {
+		DPRINTF(" Trying first number\n");
+		if (NEW_STYLE_NUMBER(v)) {
+			DPRINTF("  is a new style number\n");
+			slot = NB_TERNOP(mv,op_slot);
+			if (*slot) {
+				x = (*slot)(v,w,z);
+				if (x != Py_NotImplemented)
+					return x;
+				/* Can't do it... fall through */
+				Py_DECREF(x);
+				DPRINTF("  operation not implemented\n");
+			}
+			else
+				DPRINTF("  slot not implemented\n");
+		}
+		else
+			DPRINTF("  is an old style number\n");
+	}
+	else
+	    DPRINTF(" First argument is not a number\n");
+
+	/* Next try: w.op(v,w,z) */
+	mw = w->ob_type->tp_as_number;
+	if (mw != NULL) {
+		DPRINTF(" Trying second number\n"); 
+		if (NEW_STYLE_NUMBER(w)) {
+			DPRINTF("  is a new style number\n");
+			slot = NB_TERNOP(mw,op_slot);
+			if (*slot) {
+				x = (*slot)(v,w,z);
+				if (x != Py_NotImplemented)
+					return x;
+				/* Can't do it... fall through */
+				Py_DECREF(x);
+				DPRINTF("  operation not implemented\n");
+			}
+			else
+				DPRINTF("  slot not implemented\n");
+		}
+		else
+			DPRINTF("  is an old style number\n");
+	}
+	else
+	    DPRINTF(" Second argument is not a number\n");
+
+	/* Finally try: z.op(v,w,z) */
+	mz = z->ob_type->tp_as_number;
+	if (mz != NULL) {
+		DPRINTF(" Trying third number\n"); 
+		if (NEW_STYLE_NUMBER(z)) {
+			DPRINTF("  is a new style number\n");
+			slot = NB_TERNOP(mz,op_slot);
+			if (*slot) {
+				x = (*slot)(v,w,z);
+				if (x != Py_NotImplemented)
+					return x;
+				/* Can't do it... fall through */
+				Py_DECREF(x);
+				DPRINTF("  operation not implemented\n");
+			}
+			else
+				DPRINTF("  slot not implemented\n");
+			/* If all three arguments are new style numbers and
+			   don't implement the requested operation,
+			   then we have bad operands. */
+			if (NEW_STYLE_NUMBER(v) && NEW_STYLE_NUMBER(w)) {
+				goto badOperands;
+			}
+		}
+		else
+			DPRINTF("  is an old style number\n");
+	}
+	else
+	    DPRINTF(" Third argument is not a number\n");
+
+	/* Revert to old style number coercion */
+	{
+		PyObject *v1,*z1,*w2,*z2;
+		int c;
+		
+		DPRINTF(" Reverting to old style coercion\n");
+
+		/* When using old coercion, make sure that the requested
+		   slot is available on old style numbers. */
+		if (op_slot > NB_SLOT(nb_hex))
+			goto badOperands;
+		
+		c = PyNumber_Coerce(&v, &w);
+		if (c != 0)
+			goto error3;
+
+		/* Special case: if the third argument is None, it is
+		   treated as absent argument and not coerced. */
+		if (z == Py_None) {
+			DPRINTF("  special case: third argument is None\n");
+			if (v->ob_type->tp_as_number) {
+				slot = NB_TERNOP(v->ob_type->tp_as_number,
+						 op_slot);
+				if (*slot)
+					x = (*slot)(v, w, z);
+				else
+					c = -1;
+			}
+			else
+				c = -1;
+			goto error2;
+		}
+		v1 = v;
+		z1 = z;
+		c = PyNumber_Coerce(&v1, &z1);
+		if (c != 0)
+			goto error2;
+		w2 = w;
+		z2 = z1;
+		c = PyNumber_Coerce(&w2, &z2);
+		if (c != 0)
+			goto error1;
+
+		if (v1->ob_type->tp_as_number != NULL) {
+			slot = NB_TERNOP(v1->ob_type->tp_as_number,
+					 op_slot);
+			if (*slot)
+				x = (*slot)(v1, w2, z2);
+			else
+				c = -1;
+		}
+		else
+			c = -1;
+
+		Py_DECREF(w2);
+		Py_DECREF(z2);
+	error1:
+		Py_DECREF(v1);
+		Py_DECREF(z1);
+	error2:
 		Py_DECREF(v);
 		Py_DECREF(w);
-		if (f != NULL)
+	error3:
+		if (c >= 0)
 			return x;
 	}
-	return type_error("bad operand type(s) for ^");
+	
+ badOperands:
+	PyErr_Format(PyExc_TypeError, "bad operand type(s) for %s",operation);
+	return NULL;
+}
+
+/* XXX I should really wait for David Ascher to help on this one, but
+   to make the patch work *now*, I'll just use this for the time being: */
+
+/* Emulate old method for comparing numeric types using coercion and
+   tp_compare. If coercion doesn't work, we use the type names as
+   comparison basis (like PyObject_Compare() does too). */
+
+static PyObject *
+_PyNumber_OldstyleCompare(PyObject *v, 
+			  PyObject *w)
+{
+    int err;
+    char *vname, *wname;
+
+    DPRINTF("_PyNumber_OldstyleCompare(%s at 0x%lx, %s at 0x%lx);\n",
+	    v->ob_type->tp_name,(long)v,
+	    w->ob_type->tp_name,(long)w);
+    err = PyNumber_CoerceEx(&v, &w);
+    if (err < 0)
+	    return NULL;
+    else if (err == 0 && v->ob_type->tp_compare) {
+	    int cmp;
+	    
+	    cmp = (*v->ob_type->tp_compare)(v, w);
+	    /* XXX Test for errors ? Looks like C types cannot raise
+	       exceptions in the compare slot... */
+	    Py_DECREF(v);
+	    Py_DECREF(w);
+	    DPRINTF(" compare slot returned: %i",cmp);
+	    return PyInt_FromLong(cmp);
+    }
+    DPRINTF(" using type names for comparison\n");
+    /* Numerical types compare smaller than all other types */
+    if (v->ob_type->tp_as_number) {
+	    vname = "";
+    } else {
+	    vname = v->ob_type->tp_name;
+    }
+    if (w->ob_type->tp_as_number) {
+	    wname = "";
+    } else {
+	    wname = w->ob_type->tp_name;
+    }
+    return PyInt_FromLong(strcmp(vname, wname));
+}
+
+PyObject *
+PyNumber_Compare(PyObject *v, PyObject *w)
+{
+	DPRINTF("PyNumber_Compare(%s at 0x%lx, %s at 0x%lx);\n",
+		v->ob_type->tp_name,(long)v,
+		w->ob_type->tp_name,(long)w);
+	return _PyNumber_BinaryOperation(v,w,
+					 NB_SLOT(nb_cmp),
+					 "cmp()");
+}
+
+PyObject *
+PyNumber_Or(PyObject *v, PyObject *w)
+{
+	return _PyNumber_BinaryOperation(v,w,
+					 NB_SLOT(nb_or),
+					 "|");
+}
+
+PyObject *
+PyNumber_Xor(PyObject *v, PyObject *w)
+{
+	return _PyNumber_BinaryOperation(v,w,
+					 NB_SLOT(nb_xor),
+					 "^");
 }
 
 PyObject *
 PyNumber_And(PyObject *v, PyObject *w)
 {
-	BINOP(v, w, "__and__", "__rand__", PyNumber_And);
-	if (v->ob_type->tp_as_number != NULL) {
-		PyObject *x = NULL;
-		PyObject * (*f)(PyObject *, PyObject *) = NULL;
-		if (PyNumber_Coerce(&v, &w) != 0)
-			return NULL;
-		if (v->ob_type->tp_as_number != NULL &&
-		    (f = v->ob_type->tp_as_number->nb_and) != NULL)
-			x = (*f)(v, w);
-		Py_DECREF(v);
-		Py_DECREF(w);
-		if (f != NULL)
-			return x;
-	}
-	return type_error("bad operand type(s) for &");
+	return _PyNumber_BinaryOperation(v,w,
+					 NB_SLOT(nb_and),
+					 "&");
 }
 
 PyObject *
 PyNumber_Lshift(PyObject *v, PyObject *w)
 {
-	BINOP(v, w, "__lshift__", "__rlshift__", PyNumber_Lshift);
-	if (v->ob_type->tp_as_number != NULL) {
-		PyObject *x = NULL;
-		PyObject * (*f)(PyObject *, PyObject *) = NULL;
-		if (PyNumber_Coerce(&v, &w) != 0)
-			return NULL;
-		if (v->ob_type->tp_as_number != NULL &&
-		    (f = v->ob_type->tp_as_number->nb_lshift) != NULL)
-			x = (*f)(v, w);
-		Py_DECREF(v);
-		Py_DECREF(w);
-		if (f != NULL)
-			return x;
-	}
-	return type_error("bad operand type(s) for <<");
+	return _PyNumber_BinaryOperation(v,w,
+					 NB_SLOT(nb_lshift),
+					 "<<");
 }
 
 PyObject *
 PyNumber_Rshift(PyObject *v, PyObject *w)
 {
-	BINOP(v, w, "__rshift__", "__rrshift__", PyNumber_Rshift);
-	if (v->ob_type->tp_as_number != NULL) {
-		PyObject *x = NULL;
-		PyObject * (*f)(PyObject *, PyObject *) = NULL;
-		if (PyNumber_Coerce(&v, &w) != 0)
-			return NULL;
-		if (v->ob_type->tp_as_number != NULL &&
-		    (f = v->ob_type->tp_as_number->nb_rshift) != NULL)
-			x = (*f)(v, w);
-		Py_DECREF(v);
-		Py_DECREF(w);
-		if (f != NULL)
-			return x;
-	}
-	return type_error("bad operand type(s) for >>");
+	return _PyNumber_BinaryOperation(v,w,
+					 NB_SLOT(nb_rshift),
+					 ">>");
 }
 
 PyObject *
@@ -390,44 +726,26 @@
 {
 	PySequenceMethods *m;
 
-	BINOP(v, w, "__add__", "__radd__", PyNumber_Add);
 	m = v->ob_type->tp_as_sequence;
-	if (m && m->sq_concat)
-		return (*m->sq_concat)(v, w);
-	else if (v->ob_type->tp_as_number != NULL) {
-		PyObject *x = NULL;
-		PyObject * (*f)(PyObject *, PyObject *) = NULL;
-		if (PyNumber_Coerce(&v, &w) != 0)
-			return NULL;
-		if (v->ob_type->tp_as_number != NULL &&
-		    (f = v->ob_type->tp_as_number->nb_add) != NULL)
-			x = (*f)(v, w);
-		Py_DECREF(v);
-		Py_DECREF(w);
-		if (f != NULL)
-			return x;
-	}
-	return type_error("bad operand type(s) for +");
+	if (m && m->sq_concat) {
+		PyObject *x;
+		x = (*m->sq_concat)(v, w);
+		if (x != NULL) 
+			return x;
+		/* Fall through and give the nb_add slot a chance... */
+		PyErr_Clear();
+	}
+	return _PyNumber_BinaryOperation(v,w,
+					 NB_SLOT(nb_add),
+					 "+");
 }
 
 PyObject *
 PyNumber_Subtract(PyObject *v, PyObject *w)
 {
-	BINOP(v, w, "__sub__", "__rsub__", PyNumber_Subtract);
-	if (v->ob_type->tp_as_number != NULL) {
-		PyObject *x = NULL;
-		PyObject * (*f)(PyObject *, PyObject *) = NULL;
-		if (PyNumber_Coerce(&v, &w) != 0)
-			return NULL;
-		if (v->ob_type->tp_as_number != NULL &&
-		    (f = v->ob_type->tp_as_number->nb_subtract) != NULL)
-			x = (*f)(v, w);
-		Py_DECREF(v);
-		Py_DECREF(w);
-		if (f != NULL)
-			return x;
-	}
-	return type_error("bad operand type(s) for -");
+	return _PyNumber_BinaryOperation(v,w,
+					 NB_SLOT(nb_subtract),
+					 "-");
 }
 
 PyObject *
@@ -436,9 +754,8 @@
 	PyTypeObject *tp = v->ob_type;
 	PySequenceMethods *m;
 
-	BINOP(v, w, "__mul__", "__rmul__", PyNumber_Multiply);
-	if (tp->tp_as_number != NULL &&
-	    w->ob_type->tp_as_sequence != NULL) {
+	if (tp->tp_as_number != NULL && w->ob_type->tp_as_sequence != NULL &&
+			w->ob_type->tp_as_sequence->sq_repeat) {
 		/* number*sequence -- swap v and w */
 		PyObject *tmp = v;
 		v = w;
@@ -446,17 +763,9 @@
 		tp = v->ob_type;
 	}
 	if (tp->tp_as_number != NULL) {
-		PyObject *x = NULL;
-		PyObject * (*f)(PyObject *, PyObject *) = NULL;
-		if (PyNumber_Coerce(&v, &w) != 0)
-			return NULL;
-		if (v->ob_type->tp_as_number != NULL &&
-		    (f = v->ob_type->tp_as_number->nb_multiply) != NULL)
-			x = (*f)(v, w);
-		Py_DECREF(v);
-		Py_DECREF(w);
-		if (f != NULL)
-			return x;
+		return _PyNumber_BinaryOperation(v,w,
+						 NB_SLOT(nb_multiply),
+						 "*");
 	}
 	m = tp->tp_as_sequence;
 	if (m && m->sq_repeat) {
@@ -482,21 +791,9 @@
 PyObject *
 PyNumber_Divide(PyObject *v, PyObject *w)
 {
-	BINOP(v, w, "__div__", "__rdiv__", PyNumber_Divide);
-	if (v->ob_type->tp_as_number != NULL) {
-		PyObject *x = NULL;
-		PyObject * (*f)(PyObject *, PyObject *) = NULL;
-		if (PyNumber_Coerce(&v, &w) != 0)
-			return NULL;
-		if (v->ob_type->tp_as_number != NULL &&
-		    (f = v->ob_type->tp_as_number->nb_divide) != NULL)
-			x = (*f)(v, w);
-		Py_DECREF(v);
-		Py_DECREF(w);
-		if (f != NULL)
-			return x;
-	}
-	return type_error("bad operand type(s) for /");
+	return _PyNumber_BinaryOperation(v,w,
+					 NB_SLOT(nb_divide),
+					 "/");
 }
 
 PyObject *
@@ -506,142 +803,40 @@
 		return PyString_Format(v, w);
 	else if (PyUnicode_Check(v))
 		return PyUnicode_Format(v, w);
-	BINOP(v, w, "__mod__", "__rmod__", PyNumber_Remainder);
-	if (v->ob_type->tp_as_number != NULL) {
-		PyObject *x = NULL;
-		PyObject * (*f)(PyObject *, PyObject *) = NULL;
-		if (PyNumber_Coerce(&v, &w) != 0)
-			return NULL;
-		if (v->ob_type->tp_as_number != NULL &&
-		    (f = v->ob_type->tp_as_number->nb_remainder) != NULL)
-			x = (*f)(v, w);
-		Py_DECREF(v);
-		Py_DECREF(w);
-		if (f != NULL)
-			return x;
-	}
-	return type_error("bad operand type(s) for %");
+	return _PyNumber_BinaryOperation(v,w,
+					 NB_SLOT(nb_remainder),
+					 "%");
 }
 
 PyObject *
 PyNumber_Divmod(PyObject *v, PyObject *w)
 {
-	BINOP(v, w, "__divmod__", "__rdivmod__", PyNumber_Divmod);
-	if (v->ob_type->tp_as_number != NULL) {
-		PyObject *x = NULL;
-		PyObject * (*f)(PyObject *, PyObject *) = NULL;
-		if (PyNumber_Coerce(&v, &w) != 0)
-			return NULL;
-		if (v->ob_type->tp_as_number != NULL &&
-		    (f = v->ob_type->tp_as_number->nb_divmod) != NULL)
-			x = (*f)(v, w);
-		Py_DECREF(v);
-		Py_DECREF(w);
-		if (f != NULL)
-			return x;
-	}
-	return type_error("bad operand type(s) for divmod()");
-}
-
-/* Power (binary or ternary) */
-
-static PyObject *
-do_pow(PyObject *v, PyObject *w)
-{
-	PyObject *res;
-	PyObject * (*f)(PyObject *, PyObject *, PyObject *);
-	BINOP(v, w, "__pow__", "__rpow__", do_pow);
-	if (v->ob_type->tp_as_number == NULL ||
-	    w->ob_type->tp_as_number == NULL) {
-		PyErr_SetString(PyExc_TypeError,
-				"pow(x, y) requires numeric arguments");
-		return NULL;
-	}
-	if (PyNumber_Coerce(&v, &w) != 0)
-		return NULL;
-	if (v->ob_type->tp_as_number != NULL &&
-	    (f = v->ob_type->tp_as_number->nb_power) != NULL)
-		res = (*f)(v, w, Py_None);
-	else
-		res = type_error("pow(x, y) not defined for these operands");
-	Py_DECREF(v);
-	Py_DECREF(w);
-	return res;
+	return _PyNumber_BinaryOperation(v,w,
+					 NB_SLOT(nb_divmod),
+					 "divmod()");
 }
 
 PyObject *
 PyNumber_Power(PyObject *v, PyObject *w, PyObject *z)
 {
-	PyObject *res;
-	PyObject *v1, *z1, *w2, *z2;
-	PyObject * (*f)(PyObject *, PyObject *, PyObject *);
-
-	if (z == Py_None)
-		return do_pow(v, w);
-	/* XXX The ternary version doesn't do class instance coercions */
-	if (PyInstance_Check(v))
-		return v->ob_type->tp_as_number->nb_power(v, w, z);
-	if (v->ob_type->tp_as_number == NULL ||
-	    z->ob_type->tp_as_number == NULL ||
-	    w->ob_type->tp_as_number == NULL) {
-		return type_error("pow(x, y, z) requires numeric arguments");
-	}
-	if (PyNumber_Coerce(&v, &w) != 0)
-		return NULL;
-	res = NULL;
-	v1 = v;
-	z1 = z;
-	if (PyNumber_Coerce(&v1, &z1) != 0)
-		goto error2;
-	w2 = w;
-	z2 = z1;
- 	if (PyNumber_Coerce(&w2, &z2) != 0)
-		goto error1;
-	if (v->ob_type->tp_as_number != NULL &&
-	    (f = v1->ob_type->tp_as_number->nb_power) != NULL)
-		res = (*f)(v1, w2, z2);
-	else
-		res = type_error(
-			"pow(x, y, z) not defined for these operands");
-	Py_DECREF(w2);
-	Py_DECREF(z2);
-  error1:
-	Py_DECREF(v1);
-	Py_DECREF(z1);
-  error2:
-	Py_DECREF(v);
-	Py_DECREF(w);
-	return res;
+	return _PyNumber_TernaryOperation(v,w,z,
+					  NB_SLOT(nb_power),
+					  "** or pow()");
 }
 
 /* Binary in-place operators */
 
 /* The in-place operators are defined to fall back to the 'normal',
-   non in-place operations, if the in-place methods are not in place, and to
-   take class instances into account. This is how it is supposed to work:
+   non in-place operations, if the in-place methods are not in place.
 
-   - If the left-hand-side object (the first argument) is an
-     instance object, try to let PyInstance_HalfBinOp() handle it.  Pass the
-     non in-place variant of the function as callback, because it will only
-     be used if the left-hand object is changed by coercion.
-
-   - Otherwise, if the left hand object is not an instance object, it has
-     the appropriate struct members, and they are filled, call the
-     appropriate function and return the result. No coercion is done on the
-     arguments; the left-hand object is the one the operation is performed
-     on, and it's up to the function to deal with the right-hand object.
+   - If the left hand object has the appropriate struct members, and
+     they are filled, call the appropriate function and return the
+     result.  No coercion is done on the arguments; the left-hand object
+     is the one the operation is performed on, and it's up to the
+     function to deal with the right-hand object.
      
    - Otherwise, in-place modification is not supported. Handle it exactly as
-     a non in-place operation of the same kind:
-
-     - If either object is an instance, let PyInstance_DoBinOp() handle it.
-     
-     - Otherwise, both arguments are C types. If the left-hand object has
-       the appropriate struct members filled, coerce, call the
-       appropriate function, and return the result.
-  
-     - Otherwise, we are out of options: raise a type error specific to
-       augmented assignment.
+     a non in-place operation of the same kind.
 
    */
 
@@ -651,174 +846,78 @@
 PyNumber_InPlaceOr(PyObject *v, PyObject *w)
 {
 	PyObject * (*f)(PyObject *, PyObject *) = NULL;
-	PyObject *x = NULL;
 
-	if (PyInstance_Check(v)) {
-		if (PyInstance_HalfBinOp(v, w, "__ior__", &x,
-					 PyNumber_Or, 0) <= 0)
-			return x;
-	}
-	else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
+	if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
 		 (f = v->ob_type->tp_as_number->nb_inplace_or) != NULL)
 		return (*f)(v, w);
 
-	BINOP(v, w, "__or__", "__ror__", PyNumber_Or);
-
-	if (v->ob_type->tp_as_number != NULL) {
-		if (PyNumber_Coerce(&v, &w) != 0)
-			return NULL;
-		if (v->ob_type->tp_as_number != NULL &&
-		    (f = v->ob_type->tp_as_number->nb_or) != NULL)
-			x = (*f)(v, w);
-		Py_DECREF(v);
-		Py_DECREF(w);
-		if (f != NULL)
-			return x;
-	}
-
-	return type_error("bad operand type(s) for |=");
+	return _PyNumber_BinaryOperation(v,w,
+					 NB_SLOT(nb_or),
+					 "|=");
 }
 
 PyObject *
 PyNumber_InPlaceXor(PyObject *v, PyObject *w)
 {
 	PyObject * (*f)(PyObject *, PyObject *) = NULL;
-	PyObject *x = NULL;
 
-	if (PyInstance_Check(v)) {
-		if (PyInstance_HalfBinOp(v, w, "__ixor__", &x,
-					 PyNumber_Xor, 0) <= 0)
-			return x;
-	}
-	else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
+	if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
 		 (f = v->ob_type->tp_as_number->nb_inplace_xor) != NULL)
 		return (*f)(v, w);
 
-	BINOP(v, w, "__xor__", "__rxor__", PyNumber_Xor);
-
-	if (v->ob_type->tp_as_number != NULL) {
-		if (PyNumber_Coerce(&v, &w) != 0)
-			return NULL;
-		if (v->ob_type->tp_as_number != NULL &&
-		    (f = v->ob_type->tp_as_number->nb_xor) != NULL)
-			x = (*f)(v, w);
-		Py_DECREF(v);
-		Py_DECREF(w);
-		if (f != NULL)
-			return x;
-	}
-
-	return type_error("bad operand type(s) for ^=");
+	return _PyNumber_BinaryOperation(v,w,
+					 NB_SLOT(nb_xor),
+					 "^=");
 }
 
 PyObject *
 PyNumber_InPlaceAnd(PyObject *v, PyObject *w)
 {
 	PyObject * (*f)(PyObject *, PyObject *) = NULL;
-	PyObject *x = NULL;
 
-	if (PyInstance_Check(v)) {
-		if (PyInstance_HalfBinOp(v, w, "__iand__", &x,
-					 PyNumber_And, 0) <= 0)
-			return x;
-	}
-	else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
+	if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
 		 (f = v->ob_type->tp_as_number->nb_inplace_and) != NULL)
 		return (*f)(v, w);
 
-	BINOP(v, w, "__and__", "__rand__", PyNumber_And);
-
-	if (v->ob_type->tp_as_number != NULL) {
-		if (PyNumber_Coerce(&v, &w) != 0)
-			return NULL;
-		if (v->ob_type->tp_as_number != NULL &&
-		    (f = v->ob_type->tp_as_number->nb_and) != NULL)
-			x = (*f)(v, w);
-		Py_DECREF(v);
-		Py_DECREF(w);
-		if (f != NULL)
-			return x;
-	}
-
-	return type_error("bad operand type(s) for &=");
+	return _PyNumber_BinaryOperation(v,w,
+					 NB_SLOT(nb_and),
+					 "&=");
 }
 
 PyObject *
 PyNumber_InPlaceLshift(PyObject *v, PyObject *w)
 {
 	PyObject * (*f)(PyObject *, PyObject *) = NULL;
-	PyObject *x = NULL;
 
-	if (PyInstance_Check(v)) {
-		if (PyInstance_HalfBinOp(v, w, "__ilshift__", &x,
-					PyNumber_Lshift, 0) <= 0)
-			return x;
-	}
-	else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
+	if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
 		 (f = v->ob_type->tp_as_number->nb_inplace_lshift) != NULL)
 		return (*f)(v, w);
 
-	BINOP(v, w, "__lshift__", "__rlshift__", PyNumber_Lshift);
-
-	if (v->ob_type->tp_as_number != NULL) {
-		if (PyNumber_Coerce(&v, &w) != 0)
-			return NULL;
-		if (v->ob_type->tp_as_number != NULL &&
-		    (f = v->ob_type->tp_as_number->nb_lshift) != NULL)
-			x = (*f)(v, w);
-		Py_DECREF(v);
-		Py_DECREF(w);
-		if (f != NULL)
-			return x;
-	}
-
-	return type_error("bad operand type(s) for <<=");
+	return _PyNumber_BinaryOperation(v,w,
+					 NB_SLOT(nb_lshift),
+					 "<<=");
 }
 
 PyObject *
 PyNumber_InPlaceRshift(PyObject *v, PyObject *w)
 {
 	PyObject * (*f)(PyObject *, PyObject *) = NULL;
-	PyObject *x = NULL;
 
-	if (PyInstance_Check(v)) {
-		if (PyInstance_HalfBinOp(v, w, "__irshift__", &x,
-					PyNumber_Rshift, 0) <= 0)
-			return x;
-	}
-	else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
+	if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
 		 (f = v->ob_type->tp_as_number->nb_inplace_rshift) != NULL)
 		return (*f)(v, w);
 
-	BINOP(v, w, "__rshift__", "__rrshift__", PyNumber_Rshift);
-
-	if (v->ob_type->tp_as_number != NULL) {
-		if (PyNumber_Coerce(&v, &w) != 0)
-			return NULL;
-		if (v->ob_type->tp_as_number != NULL &&
-		    (f = v->ob_type->tp_as_number->nb_rshift) != NULL)
-			x = (*f)(v, w);
-		Py_DECREF(v);
-		Py_DECREF(w);
-		if (f != NULL)
-			return x;
-	}
-
-	return type_error("bad operand type(s) for >>=");
+	return _PyNumber_BinaryOperation(v,w,
+					 NB_SLOT(nb_rshift),
+					 ">>=");
 }
 
 PyObject *
 PyNumber_InPlaceAdd(PyObject *v, PyObject *w)
 {
 	PyObject * (*f)(PyObject *, PyObject *) = NULL;
-	PyObject *x = NULL;
 
-	if (PyInstance_Check(v)) {
-		if (PyInstance_HalfBinOp(v, w, "__iadd__", &x,
-					 PyNumber_Add, 0) <= 0)
-			return x;
-	}
-	else if (HASINPLACE(v)) {
+	if (HASINPLACE(v)) {
 		if (v->ob_type->tp_as_sequence != NULL)
 			f = v->ob_type->tp_as_sequence->sq_inplace_concat;
 		if (f == NULL && v->ob_type->tp_as_number != NULL)
@@ -827,60 +926,29 @@
 			return (*f)(v, w);
 	}
 
-	BINOP(v, w, "__add__", "__radd__", PyNumber_Add);
-
 	if (v->ob_type->tp_as_sequence != NULL) {
 		f = v->ob_type->tp_as_sequence->sq_concat;
 		if (f != NULL)
 			return (*f)(v, w);
 	}
-	if (v->ob_type->tp_as_number != NULL) {
-		if (PyNumber_Coerce(&v, &w) != 0)
-			return NULL;
-		if (v->ob_type->tp_as_number != NULL) {
-			f = v->ob_type->tp_as_number->nb_add;
-			if (f != NULL)
-				x = (*f)(v, w);
-		}
-		Py_DECREF(v);
-		Py_DECREF(w);
-		if (f != NULL)
-			return x;
-	}
 
-	return type_error("bad operand type(s) for +=");
+	return _PyNumber_BinaryOperation(v,w,
+					 NB_SLOT(nb_add),
+					 "+=");
 }
 
 PyObject *
 PyNumber_InPlaceSubtract(PyObject *v, PyObject *w)
 {
 	PyObject * (*f)(PyObject *, PyObject *) = NULL;
-	PyObject *x = NULL;
 
-	if (PyInstance_Check(v)) {
-		if (PyInstance_HalfBinOp(v, w, "__isub__", &x,
-					PyNumber_Subtract, 0) <= 0)
-			return x;
-	}
-	else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
+	if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
 		 (f = v->ob_type->tp_as_number->nb_inplace_subtract) != NULL)
 		return (*f)(v, w);
 
-	BINOP(v, w, "__sub__", "__rsub__", PyNumber_Subtract);
-
-	if (v->ob_type->tp_as_number != NULL) {
-		if (PyNumber_Coerce(&v, &w) != 0)
-			return NULL;
-		if (v->ob_type->tp_as_number != NULL &&
-		    (f = v->ob_type->tp_as_number->nb_subtract) != NULL)
-			x = (*f)(v, w);
-		Py_DECREF(v);
-		Py_DECREF(w);
-		if (f != NULL)
-			return x;
-	}
-
-	return type_error("bad operand type(s) for -=");
+	return _PyNumber_BinaryOperation(v,w,
+					 NB_SLOT(nb_subtract),
+					 "-=");
 }
 
 PyObject *
@@ -888,14 +956,8 @@
 {
 	PyObject * (*f)(PyObject *, PyObject *) = NULL;
 	PyObject * (*g)(PyObject *, int) = NULL;
-	PyObject *x = NULL;
 
-	if (PyInstance_Check(v)) {
-		if (PyInstance_HalfBinOp(v, w, "__imul__", &x,
-					PyNumber_Multiply, 0) <= 0)
-			return x;
-	}
-	else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
+	if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
 		 (f = v->ob_type->tp_as_number->nb_inplace_multiply) != NULL)
 		return (*f)(v, w);
 	else if (v->ob_type->tp_as_sequence != NULL && HASINPLACE(v) &&
@@ -917,18 +979,10 @@
 		return (*g)(v, (int)mul_value);
 	}
 
-	BINOP(v, w, "__mul__", "__rmul__", PyNumber_Multiply);
-
 	if (v->ob_type->tp_as_number != NULL) {
-		if (PyNumber_Coerce(&v, &w) != 0)
-			return NULL;
-		if (v->ob_type->tp_as_number != NULL &&
-		    (f = v->ob_type->tp_as_number->nb_multiply) != NULL)
-			x = (*f)(v, w);
-		Py_DECREF(v);
-		Py_DECREF(w);
-		if (f != NULL)
-			return x;
+		return _PyNumber_BinaryOperation(v,w,
+						 NB_SLOT(nb_multiply),
+						 "*=");
 	}
 	else if (v->ob_type->tp_as_sequence != NULL &&
 		 (g = v->ob_type->tp_as_sequence->sq_repeat) != NULL) {
@@ -955,46 +1009,22 @@
 PyNumber_InPlaceDivide(PyObject *v, PyObject *w)
 {
 	PyObject * (*f)(PyObject *, PyObject *) = NULL;
-	PyObject *x = NULL;
 
-	if (PyInstance_Check(v)) {
-		if (PyInstance_HalfBinOp(v, w, "__idiv__", &x,
-					PyNumber_Divide, 0) <= 0)
-			return x;
-	}
-	else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
+	if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
 		 (f = v->ob_type->tp_as_number->nb_inplace_divide) != NULL)
 		return (*f)(v, w);
 
-	BINOP(v, w, "__div__", "__rdiv__", PyNumber_Divide);
-
-	if (v->ob_type->tp_as_number != NULL) {
-		if (PyNumber_Coerce(&v, &w) != 0)
-			return NULL;
-		if (v->ob_type->tp_as_number != NULL &&
-		    (f = v->ob_type->tp_as_number->nb_divide) != NULL)
-			x = (*f)(v, w);
-		Py_DECREF(v);
-		Py_DECREF(w);
-		if (f != NULL)
-			return x;
-	}
-
-	return type_error("bad operand type(s) for /=");
+	return _PyNumber_BinaryOperation(v,w,
+					 NB_SLOT(nb_divide),
+					 "/=");
 }
 
 PyObject *
 PyNumber_InPlaceRemainder(PyObject *v, PyObject *w)
 {
 	PyObject * (*f)(PyObject *, PyObject *) = NULL;
-	PyObject *x = NULL;
 
-	if (PyInstance_Check(v)) {
-		if (PyInstance_HalfBinOp(v, w, "__imod__", &x,
-					PyNumber_Remainder, 0) <= 0)
-			return x;
-	}
-	else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
+	if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
 		 (f = v->ob_type->tp_as_number->nb_inplace_remainder) != NULL)
 		return (*f)(v, w);
 
@@ -1003,108 +1033,26 @@
 	else if (PyUnicode_Check(v))
 		return PyUnicode_Format(v, w);
 
-	BINOP(v, w, "__mod__", "__rmod__", PyNumber_Remainder);
-
-	if (v->ob_type->tp_as_number != NULL) {
-		if (PyNumber_Coerce(&v, &w) != 0)
-			return NULL;
-		if ((f = v->ob_type->tp_as_number->nb_remainder) != NULL)
-			x = (*f)(v, w);
-		Py_DECREF(v);
-		Py_DECREF(w);
-		if (f != NULL)
-			return x;
-	}
-
-	return type_error("bad operand type(s) for %=");
+	return _PyNumber_BinaryOperation(v,w,
+					 NB_SLOT(nb_remainder),
+					 "%=");
 }
 
 
-/* In-place Power (binary or ternary, for API consistency) */
-
-static PyObject *
-do_inplace_pow(PyObject *v, PyObject *w)
-{
-	PyObject * (*f)(PyObject *, PyObject *, PyObject *) = NULL;
-	PyObject *x = NULL;
-
-	if (PyInstance_Check(v)) {
-		if (PyInstance_HalfBinOp(v, w, "__ipow__", &x, do_pow, 0) <= 0)
-			return x;
-	}
-	else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
-		 (f = v->ob_type->tp_as_number->nb_inplace_power) != NULL)
-		return (*f)(v, w, Py_None);
-
-	BINOP(v, w, "__pow__", "__rpow__", do_pow);
-
-	if (v->ob_type->tp_as_number == NULL ||
-	    w->ob_type->tp_as_number == NULL) {
-		return type_error("bad operand type(s) for **=");
-	}
-	if (PyNumber_Coerce(&v, &w) != 0)
-		return NULL;
-	if ((f = v->ob_type->tp_as_number->nb_power) != NULL)
-		x = (*f)(v, w, Py_None);
-	else
-		x = type_error("bad operand type(s) for **=");
-	Py_DECREF(v);
-	Py_DECREF(w);
-	return x;
-}
-
 PyObject *
 PyNumber_InPlacePower(PyObject *v, PyObject *w, PyObject *z)
 {
-	PyObject *res;
-	PyObject *v1, *z1, *w2, *z2, *oldv;
-	PyObject * (*f)(PyObject *, PyObject *, PyObject *);
-
-	if (z == Py_None)
-		return do_inplace_pow(v, w);
-	/* XXX The ternary version doesn't do class instance coercions */
-	if (PyInstance_Check(v))
-		return v->ob_type->tp_as_number->nb_inplace_power(v, w, z);
-	if (v->ob_type->tp_as_number == NULL ||
-	    z->ob_type->tp_as_number == NULL ||
-	    w->ob_type->tp_as_number == NULL) {
-		return type_error(
-			"(inplace) pow(x, y, z) requires numeric arguments");
-	}
-	oldv = v;
-	Py_INCREF(oldv);
-	res = NULL;
-	if (PyNumber_Coerce(&v, &w) != 0)
-		goto error3;
-	v1 = v;
-	z1 = z;
-	if (PyNumber_Coerce(&v1, &z1) != 0)
-		goto error2;
-	w2 = w;
-	z2 = z1;
- 	if (PyNumber_Coerce(&w2, &z2) != 0)
-		goto error1;
-	if (oldv == v1 && HASINPLACE(v1) &&
-	    v->ob_type->tp_as_number != NULL &&
-	    (f = v1->ob_type->tp_as_number->nb_inplace_power) != NULL)
-		res = (*f)(v1, w2, z2);
-	else if (v1->ob_type->tp_as_number != NULL &&
-		 (f = v1->ob_type->tp_as_number->nb_power) != NULL)
-		res = (*f)(v1, w2, z2);
-	else
-		res = type_error(
-		     "(inplace) pow(x, y, z) not defined for these operands");
-	Py_DECREF(w2);
-	Py_DECREF(z2);
-  error1:
-	Py_DECREF(v1);
-	Py_DECREF(z1);
-  error2:
-	Py_DECREF(v);
-	Py_DECREF(w);
-  error3:
-	Py_DECREF(oldv);
-	return res;
+	if (HASINPLACE(v) &&
+	    v->ob_type->tp_as_number->nb_inplace_power != NULL) {
+		return _PyNumber_TernaryOperation(v,w,z,
+						  NB_SLOT(nb_inplace_power),
+						  "**=");
+	}
+	else {
+		return _PyNumber_TernaryOperation(v,w,z,
+						  NB_SLOT(nb_power),
+						  "**=");
+	}
 }
 
 
Index: 0.27/Objects/classobject.c
--- 0.27/Objects/classobject.c Sat, 11 Nov 2000 21:24:02 -0500 nas (python/E/16_classobjec 1.1.2.2.2.1.2.1.1.8 644)
+++ 0.26(w)/Objects/classobject.c Sun, 12 Nov 2000 15:59:25 -0500 nas (python/E/16_classobjec 1.1.2.2.2.1.2.1.1.8 644)
@@ -4,6 +4,7 @@
 #include "Python.h"
 #include "structmember.h"
 
+
 /* Forward */
 static PyObject *class_lookup(PyClassObject *, PyObject *,
 			      PyClassObject **);
@@ -755,11 +756,18 @@
 	return res;
 }
 
+/* XXX these should be removed which rich comparisons are implemented */
+static PyObject *
+do_binop(PyObject *v, PyObject *w, char *opname, char *ropname,
+                   PyObject * (*thisfunc)(PyObject *, PyObject *));
+static int
+do_halfbinop(PyObject *v, PyObject *w, char *opname,PyObject **r_result,
+		PyObject * (*thisfunc)(PyObject *, PyObject *), int swapped);
+
 static PyObject *
 instance_compare1(PyObject *inst, PyObject *other)
 {
-	return PyInstance_DoBinOp(inst, other, "__cmp__", "__rcmp__",
-			     instance_compare1);
+	return do_binop(inst, other, "__cmp__", "__rcmp__", instance_compare1);
 }
 
 static int
@@ -785,6 +793,14 @@
 	return 0;
 }
 
+/*
+static PyObject *
+instance_cmp(PyObject *inst, PyObject *other)
+{
+	return PyInt_FromLong(instance_compare(inst, other));
+}
+*/
+
 static long
 instance_hash(PyInstanceObject *inst)
 {
@@ -1188,16 +1204,16 @@
 
 /* Implement a binary operator involving at least one class instance. */
 
-PyObject *
-PyInstance_DoBinOp(PyObject *v, PyObject *w, char *opname, char *ropname,
+static PyObject *
+do_binop(PyObject *v, PyObject *w, char *opname, char *ropname,
                    PyObject * (*thisfunc)(PyObject *, PyObject *))
 {
 	char buf[256];
 	PyObject *result = NULL;
 
-	if (PyInstance_HalfBinOp(v, w, opname, &result, thisfunc, 0) <= 0)
+	if (do_halfbinop(v, w, opname, &result, thisfunc, 0) <= 0)
 		return result;
-	if (PyInstance_HalfBinOp(w, v, ropname, &result, thisfunc, 1) <= 0)
+	if (do_halfbinop(w, v, ropname, &result, thisfunc, 1) <= 0)
 		return result;
 	/* Sigh -- special case for comparisons */
 	if (strcmp(opname, "__cmp__") == 0) {
@@ -1221,8 +1237,8 @@
 
 static PyObject *coerce_obj;
 
-int
-PyInstance_HalfBinOp(PyObject *v, PyObject *w, char *opname, PyObject **r_result,
+static int
+do_halfbinop(PyObject *v, PyObject *w, char *opname, PyObject **r_result,
 		     PyObject * (*thisfunc)(PyObject *, PyObject *), int swapped)
 {
 	PyObject *func;
@@ -1298,6 +1314,48 @@
 	return *r_result == NULL ? -1 : 0;
 }
 
+#define HALF_BINOP(v, w, opname) \
+{ \
+	PyObject *func; \
+	PyObject *args; \
+	PyObject *result; \
+	if (PyInstance_Check(v)) { \
+		func = PyObject_GetAttrString(v, opname); \
+		if (func != NULL) { \
+			args = Py_BuildValue("(O)", w); \
+			if (args == NULL) { \
+				Py_DECREF(func); \
+				return NULL; \
+			} \
+			result = PyEval_CallObject(func, args); \
+			Py_DECREF(args); \
+			Py_DECREF(func); \
+			return result; \
+		} \
+		if (!PyErr_ExceptionMatches(PyExc_AttributeError)) \
+			return NULL; \
+		PyErr_Clear(); \
+	} \
+}
+	
+
+static PyObject *
+instance_binop(PyObject *v, PyObject *w, char *opname, char *r_opname)
+{
+	HALF_BINOP(v, w, opname);
+	HALF_BINOP(w, v, r_opname);
+	Py_INCREF(Py_NotImplemented);
+	return Py_NotImplemented;
+}
+
+static PyObject *
+instance_binop_inplace(PyObject *v, PyObject *w, char *iopname,
+		char *opname, char *r_opname)
+{
+	HALF_BINOP(v, w, iopname);
+	return instance_binop(v, w, opname, r_opname);
+}
+
 static int
 instance_coerce(PyObject **pv, PyObject **pw)
 {
@@ -1361,10 +1419,44 @@
 	return generic_unary_op(self, o); \
 }
 
+#define BINARY(f, m) \
+static PyObject *f(PyObject *v, PyObject *w) { \
+	return instance_binop(v, w, "__" m "__", "__r" m "__"); \
+}
+
+#define BINARY_INPLACE(f, m) \
+static PyObject *f(PyObject *v, PyObject *w) { \
+	return instance_binop_inplace(v, w, "__i" m "__", "__" m "__", \
+			"__r" m "__"); \
+}
+
 UNARY(instance_neg, "__neg__")
 UNARY(instance_pos, "__pos__")
 UNARY(instance_abs, "__abs__")
 
+BINARY(instance_or, "or")
+BINARY(instance_xor, "xor")
+BINARY(instance_and, "and")
+BINARY(instance_lshift, "lshift")
+BINARY(instance_rshift, "rshift")
+BINARY(instance_add, "add")
+BINARY(instance_sub, "sub")
+BINARY(instance_mul, "mul")
+BINARY(instance_div, "div")
+BINARY(instance_mod, "mod")
+BINARY(instance_divmod, "divmod")
+BINARY_INPLACE(instance_ior, "or")
+BINARY_INPLACE(instance_ixor, "xor")
+BINARY_INPLACE(instance_iand, "and")
+BINARY_INPLACE(instance_ilshift, "lshift")
+BINARY_INPLACE(instance_irshift, "rshift")
+BINARY_INPLACE(instance_iadd, "add")
+BINARY_INPLACE(instance_isub, "sub")
+BINARY_INPLACE(instance_imul, "mul")
+BINARY_INPLACE(instance_idiv, "div")
+BINARY_INPLACE(instance_imod, "mod")
+BINARY_INPLACE(instance_ipow, "pow")
+
 static int
 instance_nonzero(PyInstanceObject *self)
 {
@@ -1416,93 +1508,63 @@
 static PyObject *
 instance_pow(PyObject *v, PyObject *w, PyObject *z)
 {
-	/* XXX Doesn't do coercions... */
-	PyObject *func;
-	PyObject *args;
-	PyObject *result;
-	static PyObject *powstr;
-
-	if (powstr == NULL)
-		powstr = PyString_InternFromString("__pow__");
-	func = PyObject_GetAttr(v, powstr);
-	if (func == NULL)
-		return NULL;
-	args = Py_BuildValue("(OO)", w, z);
-	if (args == NULL) {
-		Py_DECREF(func);
-		return NULL;
-	}
-	result = PyEval_CallObject(func, args);
-	Py_DECREF(func);
-	Py_DECREF(args);
-	return result;
+	if (z != Py_None) {
+		Py_INCREF(Py_NotImplemented);
+		return Py_NotImplemented;
+	}
+	HALF_BINOP(v, w, "__pow__");
+	Py_INCREF(Py_NotImplemented);
+	return Py_NotImplemented;
 }
 
 static PyObject *
 instance_inplace_pow(PyObject *v, PyObject *w, PyObject *z)
 {
-	/* XXX Doesn't do coercions... */
-	PyObject *func;
-	PyObject *args;
-	PyObject *result;
-	static PyObject *ipowstr;
-
-	if (ipowstr == NULL)
-		ipowstr = PyString_InternFromString("__ipow__");
-	func = PyObject_GetAttr(v, ipowstr);
-	if (func == NULL) {
-		if (!PyErr_ExceptionMatches(PyExc_AttributeError))
-			return NULL;
-		PyErr_Clear();
-		return instance_pow(v, w, z);
+	if (z != Py_None) {
+		Py_INCREF(Py_NotImplemented);
+		return Py_NotImplemented;
 	}
-	args = Py_BuildValue("(OO)", w, z);
-	if (args == NULL) {
-		Py_DECREF(func);
-		return NULL;
-	}
-	result = PyEval_CallObject(func, args);
-	Py_DECREF(func);
-	Py_DECREF(args);
-	return result;
+	HALF_BINOP(v, w, "__ipow__");
+	return instance_pow(v, w, z);
 }
 
 
 static PyNumberMethods instance_as_number = {
-	0, /*nb_add*/
-	0, /*nb_subtract*/
-	0, /*nb_multiply*/
-	0, /*nb_divide*/
-	0, /*nb_remainder*/
-	0, /*nb_divmod*/
+	(binaryfunc)instance_add, /*nb_add*/
+	(binaryfunc)instance_sub, /*nb_subtract*/
+	(binaryfunc)instance_mul, /*nb_multiply*/
+	(binaryfunc)instance_div, /*nb_divide*/
+	(binaryfunc)instance_mod, /*nb_remainder*/
+	(binaryfunc)instance_divmod, /*nb_divmod*/
 	(ternaryfunc)instance_pow, /*nb_power*/
 	(unaryfunc)instance_neg, /*nb_negative*/
 	(unaryfunc)instance_pos, /*nb_positive*/
 	(unaryfunc)instance_abs, /*nb_absolute*/
 	(inquiry)instance_nonzero, /*nb_nonzero*/
 	(unaryfunc)instance_invert, /*nb_invert*/
-	0, /*nb_lshift*/
-	0, /*nb_rshift*/
-	0, /*nb_and*/
-	0, /*nb_xor*/
-	0, /*nb_or*/
+	(binaryfunc)instance_lshift, /*nb_lshift*/
+	(binaryfunc)instance_rshift, /*nb_rshift*/
+	(binaryfunc)instance_and, /*nb_and*/
+	(binaryfunc)instance_xor, /*nb_xor*/
+	(binaryfunc)instance_or, /*nb_or*/
 	(coercion)instance_coerce, /*nb_coerce*/
 	(unaryfunc)instance_int, /*nb_int*/
 	(unaryfunc)instance_long, /*nb_long*/
 	(unaryfunc)instance_float, /*nb_float*/
 	(unaryfunc)instance_oct, /*nb_oct*/
 	(unaryfunc)instance_hex, /*nb_hex*/
-	0, /*nb_inplace_add*/
-	0, /*nb_inplace_subtract*/
-	0, /*nb_inplace_multiply*/
-	0, /*nb_inplace_divide*/
-	0, /*nb_inplace_remainder*/
+	(binaryfunc)instance_iadd, /*nb_inplace_add*/
+	(binaryfunc)instance_isub, /*nb_inplace_subtract*/
+	(binaryfunc)instance_imul, /*nb_inplace_multiply*/
+	(binaryfunc)instance_idiv, /*nb_inplace_divide*/
+	(binaryfunc)instance_imod, /*nb_inplace_remainder*/
 	(ternaryfunc)instance_inplace_pow, /*nb_inplace_power*/
-	0, /*nb_inplace_lshift*/
-	0, /*nb_inplace_rshift*/
-	0, /*nb_inplace_and*/
-	0, /*nb_inplace_xor*/
-	0, /*nb_inplace_or*/
+	(binaryfunc)instance_ilshift, /*nb_inplace_lshift*/
+	(binaryfunc)instance_irshift, /*nb_inplace_rshift*/
+	(binaryfunc)instance_iand, /*nb_inplace_and*/
+	(binaryfunc)instance_ixor, /*nb_inplace_xor*/
+	(binaryfunc)instance_ior, /*nb_inplace_or*/
+	0 /*(binaryfunc)instance_cmp*/, /*nb_cmp*/
 };
 
 PyTypeObject PyInstance_Type = {
@@ -1526,7 +1588,7 @@
 	(getattrofunc)instance_getattr, /*tp_getattro*/
 	(setattrofunc)instance_setattr, /*tp_setattro*/
         0, /* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /*tp_flags*/
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC | Py_TPFLAGS_NEWSTYLENUMBER, /*tp_flags*/
 	0,		/* tp_doc */
 	(traverseproc)instance_traverse,	/* tp_traverse */
 };
Index: 0.27/Objects/floatobject.c
--- 0.27/Objects/floatobject.c Sat, 11 Nov 2000 21:24:02 -0500 nas (python/E/21_floatobjec 1.1.1.10 644)
+++ 0.26(w)/Objects/floatobject.c Sun, 12 Nov 2000 15:41:23 -0500 nas (python/E/21_floatobjec 1.1.1.10 644)
@@ -256,6 +256,38 @@
 	}
 }
 
+/* Macro and helper that convert PyObject obj to a C double and store
+   the value in dbl; this replaces the functionality of the coercion
+   slot function */
+
+#define CONVERT_TO_DOUBLE(obj,dbl)			\
+	if (PyFloat_Check(obj))				\
+		dbl = PyFloat_AS_DOUBLE(obj);		\
+	else if (convert_to_double(&(obj),&(dbl)) < 0)	\
+		return obj;
+
+static int
+convert_to_double(PyObject **v,
+		  double *dbl)
+{
+	register PyObject *obj = *v;
+	
+	if (PyInt_Check(obj)) {
+		*dbl = (double)PyInt_AS_LONG(obj);
+	}
+	else if (PyLong_Check(obj)) {
+		PyFPE_START_PROTECT("convert_to_double", {*v=NULL;return -1;})
+		*dbl = PyLong_AsDouble(obj);
+		PyFPE_END_PROTECT(result)
+	}
+	else {
+		Py_INCREF(Py_NotImplemented);
+		*v = Py_NotImplemented;
+		return -1;
+	}
+	return 0;
+}
+
 /* Precisions used by repr() and str(), respectively.
 
    The repr() precision (17 significant decimal digits) is the minimal number
@@ -314,6 +346,15 @@
 	return (i < j) ? -1 : (i > j) ? 1 : 0;
 }
 
+/* XXX Needed for the new style number compare slots */
+static PyObject *
+float_cmp(PyObject *v, PyObject *w)
+{
+	double a,b;
+	CONVERT_TO_DOUBLE(v,a);
+	CONVERT_TO_DOUBLE(w,b);
+	return PyInt_FromLong((a < b) ? -1 : (a > b) ? 1 : 0);
+}
 
 static long
 float_hash(PyFloatObject *v)
@@ -322,62 +363,69 @@
 }
 
 static PyObject *
-float_add(PyFloatObject *v, PyFloatObject *w)
+float_add(PyObject *v, PyObject *w)
 {
-	double result;
+	double a,b;
+	CONVERT_TO_DOUBLE(v,a);
+	CONVERT_TO_DOUBLE(w,b);
 	PyFPE_START_PROTECT("add", return 0)
-	result = v->ob_fval + w->ob_fval;
-	PyFPE_END_PROTECT(result)
-	return PyFloat_FromDouble(result);
+	a = a + b;
+	PyFPE_END_PROTECT(a)
+	return PyFloat_FromDouble(a);
 }
 
 static PyObject *
-float_sub(PyFloatObject *v, PyFloatObject *w)
+float_sub(PyObject *v, PyObject *w)
 {
-	double result;
+	double a,b;
+	CONVERT_TO_DOUBLE(v,a);
+	CONVERT_TO_DOUBLE(w,b);
 	PyFPE_START_PROTECT("subtract", return 0)
-	result = v->ob_fval - w->ob_fval;
-	PyFPE_END_PROTECT(result)
-	return PyFloat_FromDouble(result);
+	a = a - b;
+	PyFPE_END_PROTECT(a)
+	return PyFloat_FromDouble(a);
 }
 
 static PyObject *
-float_mul(PyFloatObject *v, PyFloatObject *w)
+float_mul(PyObject *v, PyObject *w)
 {
-	double result;
-
+	double a,b;
+	CONVERT_TO_DOUBLE(v,a);
+	CONVERT_TO_DOUBLE(w,b);
 	PyFPE_START_PROTECT("multiply", return 0)
-	result = v->ob_fval * w->ob_fval;
-	PyFPE_END_PROTECT(result)
-	return PyFloat_FromDouble(result);
+	a = a * b;
+	PyFPE_END_PROTECT(a)
+	return PyFloat_FromDouble(a);
 }
 
 static PyObject *
-float_div(PyFloatObject *v, PyFloatObject *w)
+float_div(PyObject *v, PyObject *w)
 {
-	double result;
-	if (w->ob_fval == 0) {
+	double a,b;
+	CONVERT_TO_DOUBLE(v,a);
+	CONVERT_TO_DOUBLE(w,b);
+	if (b == 0.0) {
 		PyErr_SetString(PyExc_ZeroDivisionError, "float division");
 		return NULL;
 	}
 	PyFPE_START_PROTECT("divide", return 0)
-	result = v->ob_fval / w->ob_fval;
-	PyFPE_END_PROTECT(result)
-	return PyFloat_FromDouble(result);
+	a = a / b;
+	PyFPE_END_PROTECT(a)
+	return PyFloat_FromDouble(a);
 }
 
 static PyObject *
-float_rem(PyFloatObject *v, PyFloatObject *w)
+float_rem(PyObject *v, PyObject *w)
 {
 	double vx, wx;
 	double mod;
-	wx = w->ob_fval;
+ 	CONVERT_TO_DOUBLE(v,vx);
+ 	CONVERT_TO_DOUBLE(w,wx);
 	if (wx == 0.0) {
 		PyErr_SetString(PyExc_ZeroDivisionError, "float modulo");
 		return NULL;
 	}
 	PyFPE_START_PROTECT("modulo", return 0)
-	vx = v->ob_fval;
 	mod = fmod(vx, wx);
 	/* note: checking mod*wx < 0 is incorrect -- underflows to
 	   0 if wx < sqrt(smallest nonzero double) */
@@ -389,17 +437,17 @@
 }
 
 static PyObject *
-float_divmod(PyFloatObject *v, PyFloatObject *w)
+float_divmod(PyObject *v, PyObject *w)
 {
 	double vx, wx;
 	double div, mod, floordiv;
-	wx = w->ob_fval;
+ 	CONVERT_TO_DOUBLE(v,vx);
+ 	CONVERT_TO_DOUBLE(w,wx);
 	if (wx == 0.0) {
 		PyErr_SetString(PyExc_ZeroDivisionError, "float divmod()");
 		return NULL;
 	}
 	PyFPE_START_PROTECT("divmod", return 0)
-	vx = v->ob_fval;
 	mod = fmod(vx, wx);
 	/* fmod is typically exact, so vx-mod is *mathematically* an
 	   exact multiple of wx.  But this is fp arithmetic, and fp
@@ -437,7 +485,7 @@
 }
 
 static PyObject *
-float_pow(PyFloatObject *v, PyObject *w, PyFloatObject *z)
+float_pow(PyObject *v, PyObject *w, PyObject *z)
 {
 	double iv, iw, ix;
 	long intw;
@@ -446,17 +494,18 @@
   * long integers.  Maybe something clever with logarithms could be done.
   * [AMK]
   */
-	iv = v->ob_fval;
-	iw = ((PyFloatObject *)w)->ob_fval;
+	CONVERT_TO_DOUBLE(v,iv);
+	CONVERT_TO_DOUBLE(w,iw);
 	intw = (long)iw;
 
 	/* Sort out special cases here instead of relying on pow() */
 	if (iw == 0) { 		/* x**0 is 1, even 0**0 */
 		PyFPE_START_PROTECT("pow", return NULL)
 		if ((PyObject *)z != Py_None) {
-			ix = fmod(1.0, z->ob_fval);
-			if (ix != 0 && z->ob_fval < 0)
-				ix += z->ob_fval;
+			double iz;
+			CONVERT_TO_DOUBLE(w,iz);
+			ix=fmod(1.0, iz);
+			if (ix!=0 && iz<0) ix+=iz;
 		}
 		else
 			ix = 1.0;
@@ -501,15 +550,14 @@
 		return NULL;
 	}
 	if ((PyObject *)z != Py_None) {
-		PyFPE_START_PROTECT("pow", return NULL)
-		ix = fmod(ix, z->ob_fval);	/* XXX To Be Rewritten */
-		if (ix != 0 &&
-		    ((iv < 0 && z->ob_fval > 0) ||
-		     (iv > 0 && z->ob_fval < 0)
-		    )) {
-		     ix += z->ob_fval;
+		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)
+  		PyFPE_END_PROTECT(ix)
 	}
 	return PyFloat_FromDouble(ix);
 }
@@ -611,6 +659,20 @@
 	(unaryfunc)float_float, /*nb_float*/
 	0,		/*nb_oct*/
 	0,		/*nb_hex*/
+	0,		/*nb_inplace_add*/
+	0,		/*nb_inplace_subtract*/
+	0,		/*nb_inplace_multiply*/
+	0,		/*nb_inplace_divide*/
+	0,		/*nb_inplace_remainder*/
+	0, 		/*nb_inplace_power*/
+	0,		/*nb_inplace_lshift*/
+	0,		/*nb_inplace_rshift*/
+	0,		/*nb_inplace_and*/
+	0,		/*nb_inplace_xor*/
+	0,		/*nb_inplace_or*/
+
+	/* New style slots: */
+	(binaryfunc)float_cmp, /*nb_cmp*/
 };
 
 PyTypeObject PyFloat_Type = {
@@ -631,6 +693,10 @@
 	(hashfunc)float_hash,	/*tp_hash*/
         0,			/*tp_call*/
         (reprfunc)float_str,	/*tp_str*/
+	0,			/*tp_getattro*/
+	0,			/*tp_setattro*/
+	0,			/*tp_as_buffer*/
+	Py_TPFLAGS_NEWSTYLENUMBER /*tp_flags*/
 };
 
 void
Index: 0.27/Objects/intobject.c
--- 0.27/Objects/intobject.c Sat, 11 Nov 2000 21:24:02 -0500 nas (python/E/24_intobject. 1.1.1.10 644)
+++ 0.26(w)/Objects/intobject.c Sun, 12 Nov 2000 14:15:10 -0500 nas (python/E/24_intobject. 1.1.1.10 644)
@@ -219,6 +219,19 @@
 
 /* Methods */
 
+/* Integers are seen as the "smallest" of all numeric types and thus
+   don't have any knowledge about conversion of other types to
+   integers. */
+
+#define CONVERT_TO_LONG(obj,lng)		\
+	if (PyInt_Check(obj)) {			\
+		lng = PyInt_AS_LONG(obj);	\
+	}					\
+	else {					\
+		Py_INCREF(Py_NotImplemented);	\
+		return Py_NotImplemented;	\
+	}
+
 /* ARGSUSED */
 static int
 int_print(PyIntObject *v, FILE *fp, int flags)
@@ -244,6 +257,16 @@
 	return (i < j) ? -1 : (i > j) ? 1 : 0;
 }
 
+/* XXX Needed for the new style number compare slots */
+static PyObject *
+int_cmp(PyObject *v, PyObject *w)
+{
+	register long a, b;
+	CONVERT_TO_LONG(v,a);
+	CONVERT_TO_LONG(w,b);
+	return PyInt_FromLong((a < b) ? -1 : (a > b) ? 1 : 0);
+}
+
 static long
 int_hash(PyIntObject *v)
 {
@@ -259,8 +282,8 @@
 int_add(PyIntObject *v, PyIntObject *w)
 {
 	register long a, b, x;
-	a = v->ob_ival;
-	b = w->ob_ival;
+	CONVERT_TO_LONG(v,a);
+	CONVERT_TO_LONG(w,b);
 	x = a + b;
 	if ((x^a) < 0 && (x^b) < 0)
 		return err_ovf("integer addition");
@@ -271,8 +294,8 @@
 int_sub(PyIntObject *v, PyIntObject *w)
 {
 	register long a, b, x;
-	a = v->ob_ival;
-	b = w->ob_ival;
+	CONVERT_TO_LONG(v,a);
+	CONVERT_TO_LONG(w,b);
 	x = a - b;
 	if ((x^a) < 0 && (x^~b) < 0)
 		return err_ovf("integer subtraction");
@@ -314,8 +337,8 @@
 	long a, b, ah, bh, x, y;
 	int s = 1;
 
-	a = v->ob_ival;
-	b = w->ob_ival;
+	CONVERT_TO_LONG(v,a);
+	CONVERT_TO_LONG(w,b);
 	ah = a >> (LONG_BIT/2);
 	bh = b >> (LONG_BIT/2);
 
@@ -408,11 +431,9 @@
 }
 
 static int
-i_divmod(register PyIntObject *x, register PyIntObject *y,
+i_divmod(register long xi, register long yi,
          long *p_xdivy, long *p_xmody)
 {
-	long xi = x->ob_ival;
-	long yi = y->ob_ival;
 	long xdivy, xmody;
 	
 	if (yi == 0) {
@@ -451,8 +472,11 @@
 static PyObject *
 int_div(PyIntObject *x, PyIntObject *y)
 {
+	long xi, yi;
 	long d, m;
-	if (i_divmod(x, y, &d, &m) < 0)
+	CONVERT_TO_LONG(x,xi);
+	CONVERT_TO_LONG(y,yi);
+	if (i_divmod(xi, yi, &d, &m) < 0)
 		return NULL;
 	return PyInt_FromLong(d);
 }
@@ -460,8 +484,11 @@
 static PyObject *
 int_mod(PyIntObject *x, PyIntObject *y)
 {
+	long xi, yi;
 	long d, m;
-	if (i_divmod(x, y, &d, &m) < 0)
+	CONVERT_TO_LONG(x,xi);
+	CONVERT_TO_LONG(y,yi);
+	if (i_divmod(xi, yi, &d, &m) < 0)
 		return NULL;
 	return PyInt_FromLong(m);
 }
@@ -469,8 +496,11 @@
 static PyObject *
 int_divmod(PyIntObject *x, PyIntObject *y)
 {
+	long xi, yi;
 	long d, m;
-	if (i_divmod(x, y, &d, &m) < 0)
+	CONVERT_TO_LONG(x,xi);
+	CONVERT_TO_LONG(y,yi);
+	if (i_divmod(xi, yi, &d, &m) < 0)
 		return NULL;
 	return Py_BuildValue("(ll)", d, m);
 }
@@ -480,8 +510,8 @@
 {
 #if 1
 	register long iv, iw, iz=0, ix, temp, prev;
-	iv = v->ob_ival;
-	iw = w->ob_ival;
+	CONVERT_TO_LONG(v,iv);
+	CONVERT_TO_LONG(w,iw);
 	if (iw < 0) {
 		if (iv)
 			PyErr_SetString(PyExc_ValueError,
@@ -492,7 +522,7 @@
 		return NULL;
 	}
  	if ((PyObject *)z != Py_None) {
-		iz = z->ob_ival;
+		CONVERT_TO_LONG(z,iz);
 		if (iz == 0) {
 			PyErr_SetString(PyExc_ValueError,
 					"pow() arg 3 cannot be 0");
@@ -531,27 +561,16 @@
 		}
 	}
 	if (iz) {
-	 	PyObject *t1, *t2;
-	 	long int div, mod;
-	 	t1=PyInt_FromLong(ix); 
-		t2=PyInt_FromLong(iz);
-	 	if (t1==NULL || t2==NULL ||
-	 		i_divmod((PyIntObject *)t1,
-				 (PyIntObject *)t2, &div, &mod)<0)
-		{
-		 	Py_XDECREF(t1);
-		 	Py_XDECREF(t2);
+	 	long div, mod;
+	 	if (i_divmod(ix, iz, &div, &mod) < 0)
 			return(NULL);
-		}
-		Py_DECREF(t1);
-		Py_DECREF(t2);
 	 	ix=mod;
 	}
 	return PyInt_FromLong(ix);
 #else
 	register long iv, iw, ix;
-	iv = v->ob_ival;
-	iw = w->ob_ival;
+	CONVERT_TO_LONG(v,iv);
+	CONVERT_TO_LONG(w,iw);
 	if (iw < 0) {
 		PyErr_SetString(PyExc_ValueError,
 				"integer to the negative power");
@@ -618,8 +637,8 @@
 int_lshift(PyIntObject *v, PyIntObject *w)
 {
 	register long a, b;
-	a = v->ob_ival;
-	b = w->ob_ival;
+	CONVERT_TO_LONG(v,a);
+	CONVERT_TO_LONG(w,b);
 	if (b < 0) {
 		PyErr_SetString(PyExc_ValueError, "negative shift count");
 		return NULL;
@@ -639,8 +658,8 @@
 int_rshift(PyIntObject *v, PyIntObject *w)
 {
 	register long a, b;
-	a = v->ob_ival;
-	b = w->ob_ival;
+	CONVERT_TO_LONG(v,a);
+	CONVERT_TO_LONG(w,b);
 	if (b < 0) {
 		PyErr_SetString(PyExc_ValueError, "negative shift count");
 		return NULL;
@@ -665,8 +684,8 @@
 int_and(PyIntObject *v, PyIntObject *w)
 {
 	register long a, b;
-	a = v->ob_ival;
-	b = w->ob_ival;
+	CONVERT_TO_LONG(v,a);
+	CONVERT_TO_LONG(w,b);
 	return PyInt_FromLong(a & b);
 }
 
@@ -674,8 +693,8 @@
 int_xor(PyIntObject *v, PyIntObject *w)
 {
 	register long a, b;
-	a = v->ob_ival;
-	b = w->ob_ival;
+	CONVERT_TO_LONG(v,a);
+	CONVERT_TO_LONG(w,b);
 	return PyInt_FromLong(a ^ b);
 }
 
@@ -683,8 +702,8 @@
 int_or(PyIntObject *v, PyIntObject *w)
 {
 	register long a, b;
-	a = v->ob_ival;
-	b = w->ob_ival;
+	CONVERT_TO_LONG(v,a);
+	CONVERT_TO_LONG(w,b);
 	return PyInt_FromLong(a | b);
 }
 
@@ -746,12 +765,15 @@
 	(binaryfunc)int_and, /*nb_and*/
 	(binaryfunc)int_xor, /*nb_xor*/
 	(binaryfunc)int_or, /*nb_or*/
-	0,		/*nb_coerce*/
+	0, 		/*nb_coerce*/
 	(unaryfunc)int_int, /*nb_int*/
 	(unaryfunc)int_long, /*nb_long*/
 	(unaryfunc)int_float, /*nb_float*/
 	(unaryfunc)int_oct, /*nb_oct*/
 	(unaryfunc)int_hex, /*nb_hex*/
+
+	/* New style slots: */
+	(binaryfunc)int_cmp, /*nb_cmp*/
 };
 
 PyTypeObject PyInt_Type = {
@@ -770,6 +792,12 @@
 	0,		/*tp_as_sequence*/
 	0,		/*tp_as_mapping*/
 	(hashfunc)int_hash, /*tp_hash*/
+        0,			/*tp_call*/
+        0,			/*tp_str*/
+	0,			/*tp_getattro*/
+	0,			/*tp_setattro*/
+	0,			/*tp_as_buffer*/
+	Py_TPFLAGS_NEWSTYLENUMBER /*tp_flags*/
 };
 
 void
Index: 0.27/Objects/object.c
--- 0.27/Objects/object.c Sat, 11 Nov 2000 21:24:02 -0500 nas (python/E/29_object.c 1.1.1.1.1.1.1.1.1.1.1.9 644)
+++ 0.26(w)/Objects/object.c Sun, 12 Nov 2000 16:02:37 -0500 nas (python/E/29_object.c 1.1.1.1.1.1.1.1.1.1.1.9 644)
@@ -311,14 +311,7 @@
 static PyObject *
 do_cmp(PyObject *v, PyObject *w)
 {
-	long c;
-	/* __rcmp__ actually won't be called unless __cmp__ isn't defined,
-	   because the check in cmpobject() reverses the objects first.
-	   This is intentional -- it makes no sense to define cmp(x,y)
-	   different than -cmp(y,x). */
-	if (PyInstance_Check(v) || PyInstance_Check(w))
-		return PyInstance_DoBinOp(v, w, "__cmp__", "__rcmp__", do_cmp);
-	c = PyObject_Compare(v, w);
+	long c = PyObject_Compare(v, w);
 	if (c && PyErr_Occurred())
 		return NULL;
 	return PyInt_FromLong(c);
@@ -402,8 +395,7 @@
 	if (v == w)
 		return 0;
 	if (PyInstance_Check(v) || PyInstance_Check(w)) {
-		PyObject *res;
-		int c;
+		int res, c;
 		if (!PyInstance_Check(v))
 			return -PyObject_Compare(w, v);
 		_PyCompareState_nesting++;
@@ -427,45 +419,34 @@
 				_PyCompareState_nesting--;
 				return -1;
 			}
-			res = do_cmp(v, w);
+			res = v->ob_type->tp_compare(v, w);
 			/* XXX DelItem shouldn't fail */
 			PyDict_DelItem(inprogress, pair);
 			Py_DECREF(pair);
 		} else {
-			res = do_cmp(v, w);
+			res = v->ob_type->tp_compare(v, w);
 		}
 		_PyCompareState_nesting--;
-		if (res == NULL)
-			return -1;
-		if (!PyInt_Check(res)) {
-			Py_DECREF(res);
-			PyErr_SetString(PyExc_TypeError,
-					"comparison did not return an int");
-			return -1;
-		}
-		c = PyInt_AsLong(res);
-		Py_DECREF(res);
-		return (c < 0) ? -1 : (c > 0) ? 1 : 0;	
+		return res;
 	}
 	if ((vtp = v->ob_type) != (wtp = w->ob_type)) {
 		char *vname = vtp->tp_name;
 		char *wname = wtp->tp_name;
-		if (vtp->tp_as_number != NULL && wtp->tp_as_number != NULL) {
-			int err;
-			err = PyNumber_CoerceEx(&v, &w);
-			if (err < 0)
+
+		if (vtp->tp_as_number != NULL || wtp->tp_as_number != NULL) {
+			PyObject *res;
+			int c;
+			res = PyNumber_Compare(v,w);
+			if (res == NULL)
 				return -1;
-			else if (err == 0) {
-				int cmp;
-				vtp = v->ob_type;
-				if (vtp->tp_compare == NULL)
-					cmp = (v < w) ? -1 : 1;
-				else
-					cmp = (*vtp->tp_compare)(v, w);
-				Py_DECREF(v);
-				Py_DECREF(w);
-				return cmp;
+			if (!PyInt_Check(res)) {
+			    PyErr_SetString(PyExc_TypeError,
+					"comparison did not return an int");
+			    return -1;
 			}
+			c = PyInt_AS_LONG(res);
+			Py_DECREF(res);
+			return (c < 0) ? -1 : (c > 0) ? 1 : 0;	
 		}
 		else if (PyUnicode_Check(v) || PyUnicode_Check(w)) {
 			int result = PyUnicode_Compare(v, w);
@@ -825,6 +806,9 @@
 	register PyObject *w = *pw;
 	int res;
 
+	DPRINTF("PyNumber_CoerceEx(%s at 0x%lx, %s at 0x%lx);\n",
+		v->ob_type->tp_name,(long)v,
+		w->ob_type->tp_name,(long)w);
 	if (v->ob_type == w->ob_type && !PyInstance_Check(v)) {
 		Py_INCREF(v);
 		Py_INCREF(w);
@@ -915,6 +899,38 @@
 
 PyObject _Py_NoneStruct = {
 	PyObject_HEAD_INIT(&PyNothing_Type)
+};
+
+/* NotImplemented is an object that can be used to signal that an
+   operation is not implemented for the given type combination. */
+
+static PyObject *
+NotImplemented_repr(op)
+	PyObject *op;
+{
+	return PyString_FromString("NotImplemented");
+}
+
+static PyTypeObject PyNotImplemented_Type = {
+	PyObject_HEAD_INIT(&PyType_Type)
+	0,
+	"NotImplemented",
+	0,
+	0,
+	0,		/*tp_dealloc*/ /*never called*/
+	0,		/*tp_print*/
+	0,		/*tp_getattr*/
+	0,		/*tp_setattr*/
+	0,		/*tp_compare*/
+	(reprfunc)NotImplemented_repr, /*tp_repr*/
+	0,		/*tp_as_number*/
+	0,		/*tp_as_sequence*/
+	0,		/*tp_as_mapping*/
+	0,		/*tp_hash */
+};
+
+PyObject _Py_NotImplementedStruct = {
+	PyObject_HEAD_INIT(&PyNotImplemented_Type)
 };
 
 
Index: 0.27/Python/bltinmodule.c
--- 0.27/Python/bltinmodule.c Sat, 11 Nov 2000 21:24:02 -0500 nas (python/G/36_bltinmodul 1.1.1.11 644)
+++ 0.26(w)/Python/bltinmodule.c Sun, 12 Nov 2000 00:24:40 -0500 nas (python/G/36_bltinmodul 1.1.1.11 644)
@@ -2266,6 +2266,9 @@
 		return NULL;
 	if (PyDict_SetItemString(dict, "Ellipsis", Py_Ellipsis) < 0)
 		return NULL;
+	if (PyDict_SetItemString(dict, "NotImplemented", 
+				 Py_NotImplemented) < 0)
+		return NULL;
 	debug = PyInt_FromLong(Py_OptimizeFlag == 0);
 	if (PyDict_SetItemString(dict, "__debug__", debug) < 0) {
 		Py_XDECREF(debug);
