/* Multiarray.pmc
 *  Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
 *  CVS Info
 *     $Id: multiarray.pmc,v 1.14 2003/08/28 13:17:01 leo Exp $
 *  Overview:
 *     These are the vtable functions for the Multiarray base class
 *  Data Structure and Algorithms:
 *   This is one way for calculating offsets in 2 dimensional space.
 *
 * MULTIDIM CALC OFFSET
 * Algoritm:
 *  i + j*Ni + k*Ni*Nj + l*Ni*Nj*Nk ...
 * where i,j,k,l are koordinates in a multdim space
 * and Ni,Nj,Nk .. are the length 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.
 *  History:
 *        	Initial revision by Josef Hook <joh@stacken.kth.se>
 *        1.6	Based on list.c by Leopold Toetsch <lt@toetsch.at>
 *
 *  Notes:
 *  References:
 */

#include "parrot/parrot.h"

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

    l = key_integer(interp, key);
    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 {

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

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


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

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

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

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

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

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

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