I think that the number of double dispatching methods needed is far fewer than n^2 for n arithmetic classes.
In Kyma, we currently have a hierarchy of 94 classes of "arithmetic" objects, of which about 18 have substantially different behavior (and are not abstract).
To implement double dispatched addition, for example, we needed about 90 methods: 17 implementors of #+, and 71 implementors of #sumFromXXXX:, where XXXX is some class name.
You can greatly reduce the number of methods by taking advantage of the "receiver" superclass hierarchy using "forwarding" double dispatching methods. For example, #sumFromSmallInteger: is defined in ArithmeticObject (the abstract superclass of all of these objects) to resend the message as #sumFromInteger:; that message is defined to resend as #sumFromNumber:; that message resends #sumFromScalar:, etc. working up the class hierarchy of the receiver.
Only in those classes that need to distinguish between adding themselves to SmallIntegers and Numbers, for instance, need to implement both #sumFromSmallInteger: and #sumFromNumber:.
Kurt Hebel
squeak-dev@lists.squeakfoundation.org