This is a bit embarrassing.
>>> import catacomb as C
>>> x = C.MP(5)
>>> x == 5.1
True
>>> x < 5.1
False
>>> r = x/2
>>> r
5/2
>>> r == 2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: an integer is required
>>> r == 2.5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: an integer is required
>>> r*1.0
5/2
>>> r*1.1
5/2
>>> r*2.0
5
>>> r*2.5
5
Fix this nonsense.
* Change the `obvious' arithmetic operators so that they notice that
one of the operands is a float. Handle this by converting to a
Python bignum and letting Python handle the arithmetic. The result
is a float, which seems sensible inexact contagion.
* Introduce a rich-comparison method which also detects a float
operand and hands off to Python. Python seems to get this right,
comparing the float to the bignum in its full precision, so that's a
win.
* Also, modify the `IntRat' code to apply inexact contagion in the
same way. Comparisons may be imperfect here, but that's
surprisingly hard to get right.
The new results:
>>> import catacomb as C
>>> x = C.MP(5)
>>> x == 5.1
False
>>> x < 5.1
True
>>> r = x/2
>>> r
5/2
>>> r == 2
False
>>> r == 2.5
True
>>> r*1.0
2.5
>>> r*1.1
2.75
>>> r*2.0
5.0
>>> r*2.5
6.25
return (0);
}
+PyObject *enrich_compare(int op, int cmp)
+{
+ int r = -1;
+
+ switch (op) {
+ case Py_LT: r = cmp < 0; break;
+ case Py_LE: r = cmp <= 0; break;
+ case Py_EQ: r = cmp == 0; break;
+ case Py_NE: r = cmp != 0; break;
+ case Py_GE: r = cmp >= 0; break;
+ case Py_GT: r = cmp > 0; break;
+ default: assert(0);
+ }
+ return (getbool(r));
+}
+
/*----- Saving and restoring exceptions ----------------------------------*/
void report_lost_exception_v(struct excinfo *exc,
extern PyObject *abstract_pynew(PyTypeObject *, PyObject *, PyObject *);
/* A `tp_new' function which refuses to make the object. */
+extern PyObject *enrich_compare(int /*op*/, int /*cmp*/);
+ /* Use a traditional compare-against-zero comparison result CMP to answer a
+ * modern Python `tp_richcompare' operation OP.
+ */
+
#ifndef CONVERT_CAREFULLY
# define CONVERT_CAREFULLY(newty, expty, obj) \
(!sizeof(*(expty *)0 = (obj)) + (/*unconst*/ newty)(obj))