// runtime system for dprog programs.

#ifndef CXX_DPROG_HH
#define CXX_DPROG_HH

#include <vector>
#include <cstdarg>
#include <cassert>

#include <iostream>

namespace dprog {

    // two-dimensional matrix (optimization compared to n-dim. matrix)
    template <typename T>
    class Matrix2 {
	T *_array;
	size_t _array_size;	// mainly for debugging
	size_t _row_size;

	Matrix2();
	Matrix2(Matrix2&);

    public:
	Matrix2(size_t rows, size_t cols) {
	    _row_size = cols;	// there are "cols" columns in each row
	    _array_size = rows * cols;
	    _array = new T[_array_size];
	}

	~Matrix2() {
	    delete[] _array;
	}

	T &cell(int i, int j) {
	    assert(i >= 0);
	    assert(j >= 0);

	    size_t offset = i*_row_size + j;
	    assert(offset < _array_size);
	    return *(_array + offset);
	}
    };
	    
	

    // n-dimensional matrix
    template <typename T>
    class Matrix {
	std::vector<size_t> _scale;
	T *_array;
	size_t _array_size;	// mainly for debugging

	Matrix();
	Matrix(Matrix&);

    public:
	Matrix(size_t dim, ...) {

	    va_list args;
	    va_start(args, dim);

	    std::vector<size_t> dimensions;
	    size_t size = 1;
	    for (size_t i = dim; i > 0; --i)
		{
		    size_t d = va_arg(args, size_t);
		    size *= d;
		    dimensions.push_back(d);
		}
	    va_end(args);

	    std::vector<size_t>::iterator i;
	    size_t scale = size;
	    for (i = dimensions.begin(); i != dimensions.end(); ++i)
		{
		    scale /= *i;
		    _scale.push_back(scale);
		}
	    
	    _array = new T[size];
	    _array_size = size;
	}
	~Matrix() {
	    delete[] _array;
	}

	T &cell(...) {
	    va_list args;
	    va_start(args, this);

	    size_t offset = 0;
	    std::vector<size_t>::const_iterator i;
	    for (i = _scale.begin(); i != _scale.end(); ++i)
		{
		    size_t idx = va_arg(args, size_t);
		    offset += idx*(*i);
		}

	    va_end(args);

	    assert(offset < _array_size);

	    return *(_array + offset);
	}
    };
};

#endif // CXX_DPROG_HH


syntax highlighted by Code2HTML, v. 0.9.1