Chaim Frenkel <[EMAIL PROTECTED]> wrote:

> I would have wanted to limit the vtbl to self manipulation functions.
> Set, get, convert, etc. Cross object operations would/should be
> outside the realm of the object. (It seems like trying to lift yourself
> by the bootstraps.)

There is a certainly a cleaness and elegance in only including unary
operators in the vtable; however, allowing binary ops allows efficiency
when both ops are of the same type, which is a common case.
For example,  consider an add where both ops are of type bigint.
if this is done by the BigInt add function, it is likely to be fast and
efficent, being able to access the internal representation of arbitrary
sized integers.

When they are different types.....

and Buddha Buck <[EMAIL PROTECTED]> wrote:

> I seem to remember a suggestion made a long time ago that would have the 
> vtable include methods to convert to the "standard types", so that if the 
> calls were b->vtable->add(b,a) (and both operands had to be passed in; this 
> is C we're talking about, not C++ or perl.  OO has to be done manually), 
> then the add routine would do a->vtable->fetchint(a) to get the appropriate 
> value.  Or something like that.  Have I confused something?

That was probably me. (Which means it was probsbly a daft proposal,
and everyone rightly ignored it ;-)
The basic idea was that all numeric SV types must provide methods
that extract their vlaue as an integer or float of a size (abitrarily large)
specified by the caller, the format of which is a Perl standard.
For example, one might say:

buf = malloc(25);
sv->get_float_representation(buf,20,5)
which demands that sv fill buf with 20 bytes of mantissa and 5 bytes of
exponent. Somewhere in the perl API spec says how a manitissa and exponent
should be laid out (eg sign bit, NaN etc). This format may not relate
to any particualr hardware representaion of f/p numbers.

When Perl is asked to evaluate $huge_real + $small_int,
it calls huge_real_sv->add(huge_real_sv, small_int_sv).
At this point, the add function checks whether it's seconbd operand
is also a huge_real. If it were, it would directly access the internals of
of both ops, and and efficienty calculate the result. Since it's not,
and since it knows preactically nothing about the type of the second op,
it asks the 2nd op to return its value as a 'big enough' float - where
'big enough' is chosen by huge_real.

This is a relatively slow and inefficient method, but does allow for
interoperability of any 2 arbitrary 3rd-party numberic data types, especially
oversided ones.
You might also want to add a few methods to return the value in standard
int/float represenations for efficiency. So, in total, you might have the
following methods say:

get_int(), get_float(), get_double(),
get_float_representation(buf,msize,esize),
get_int_representation(buf,size),

I think the problem with the sv->add[type]() approach is
that it doesnt cope with bizarre numeric tpyes easily.

So, I would replace

addend->vtable->(add[typeof adder])(adder)

with

addend->vtable->add(addend,adder)

where the standard num's add() function looks like:

num_add(SV*a, *b) {
        if (a->vtable == b->vtable) {
                c = a->value + b->value // efficient
        } else {
                c = a->value + b->get_float(); // slower - dont know type of b
        }
}

while the add method of a user-defined 256-bit integer type might look
roughly like:

int256_add(SV*a, *b) {
        if (a->vtable == b->vtable) {
                p = b->value;
        } else {
                p = malloc(32);
                b->get_int_representation(p,32);
        }
        for (i=0; i<32/sizeof(int); i++) {
                c[i] = a->value[i] + p[i];
                // plus stuff to do with carry
        }
}







Reply via email to