/*
Copyright (C) 2001-2008, The Perl Foundation.
$Id: /mirror/trunk/src/pmc/multiarray.pmc 26316 2008-03-11T09:50:21.102015Z allison  $

=head1 NAME

src/pmc/multiarray.pmc - Multi-dimensional Array

=head1 DESCRIPTION

C<MultiArray> extends C<Array> to provide a multi-dimensional array.

This is one way for calculating offsets in 2 dimensional space.

MULTIDIM CALC OFFSET

Algorithm:

    i + j*Ni + k*Ni*Nj + l*Ni*Nj*Nk ...

where i, j, k, l... are coordinates in a multidimensional space and
Ni, Nj, Nk... are the lengths of the dimensions.

Limitations: the array can only expand in the last dimension The first
(n-1) dimensions of a n-dimensional array are fixed and layed out at
array creation.

=head2 Functions

=over 4

=cut

*/

#include "parrot/parrot.h"

/*

=item C<static INTVAL calc_offset(PARROT_INTERP, List *list, PMC *key)>

Calculates the offset for C<*key>.

=cut

*/

static INTVAL calc_offset(PARROT_INTERP, List*list, PMC *key)
{
    PMC   *dim  = VTABLE_get_pmc_keyed_int(interp, list->user_data, 1);
    INTVAL l    = key_integer(interp, key);
    INTVAL ninj = 1;

    for (; dim ; dim = key_next(interp, dim)) {
        key = key_next(interp, key);

        if (!key)
            break;

        ninj *= key_integer(interp, dim);
        l    += key_integer(interp, key) * ninj;
    }

    return l;
}

pmclass MultiArray extends Array need_ext provides array {

/*

=item C<void init()>

Overrides the default in C<Array>. There is no initialization.

=cut

*/

    VTABLE void init() {
        /* override default in Array - no init */
    }

/*

=item C<INTVAL get_integer_keyed(PMC *key)>

Returns the integer value for C<*key>.

=cut

*/

    VTABLE INTVAL get_integer_keyed(PMC *key) {
        INTVAL ix = calc_offset(INTERP, (List *)PMC_data(SELF), key);
        return SELF.get_integer_keyed_int(ix);
    }

/*

=item C<FLOATVAL get_number_keyed(PMC *key)>

Returns the floating-point number value for C<*key>.

=cut

*/

    VTABLE FLOATVAL get_number_keyed(PMC *key) {
        INTVAL ix = calc_offset(INTERP, (List *)PMC_data(SELF), key);
        return SELF.get_number_keyed_int(ix);
    }

/*

=item C<STRING *get_string_keyed(PMC *key)>

Returns the Parrot string value for C<*key>.

=cut

*/

    VTABLE STRING *get_string_keyed(PMC *key) {
        INTVAL ix = calc_offset(INTERP, (List *)PMC_data(SELF), key);
        return SELF.get_string_keyed_int(ix);
    }

/*

=item C<PMC *get_pmc_keyed(PMC *key)>

Returns the PMC value for C<*key>.

=cut

*/

    VTABLE PMC *get_pmc_keyed(PMC *key) {
        INTVAL ix = calc_offset(INTERP, (List *)PMC_data(SELF), key);
        return SELF.get_pmc_keyed_int(ix);
    }

/*

=item C<void set_integer_keyed(PMC *key, INTVAL value)>

Sets the integer value C<value> at C<*key>.

=cut

*/

    VTABLE void set_integer_keyed(PMC *key, INTVAL value) {
        INTVAL ix = calc_offset(INTERP, (List *)PMC_data(SELF), key);
        SELF.set_integer_keyed_int(ix, value);
    }

/*

=item C<void set_number_keyed(PMC *key, FLOATVAL value)>

Sets the floating-point number value C<value> at C<*key>.

=cut

*/

    VTABLE void set_number_keyed(PMC *key, FLOATVAL value) {
        INTVAL ix = calc_offset(INTERP, (List *)PMC_data(SELF), key);
        SELF.set_number_keyed_int(ix, value);
    }

/*

=item C<void set_string_keyed(PMC *key, STRING *value)>

Sets the Parrot string value C<value> at C<*key>.

=cut

*/

    VTABLE void set_string_keyed(PMC *key, STRING *value) {
        INTVAL ix = calc_offset(INTERP, (List *)PMC_data(SELF), key);
        SELF.set_string_keyed_int(ix, value);
    }

/*

=item C<void set_pmc_keyed(PMC *dest_key, PMC *src)>

Unimplemented.

=cut

*/

    VTABLE void set_pmc_keyed(PMC *dest_key, PMC *src) {
        /* XXX array ??? */
    }
}

/*

=back

=head1 HISTORY

Initial revision by Josef Hook <joh@stacken.kth.se>

1.6 Based on list.c by Leopold Toetsch <lt@toetsch.at>

=cut

*/

/*
 * Local variables:
 *   c-file-style: "parrot"
 * End:
 * vim: expandtab shiftwidth=4:
 */
