namespace sc {
#define Array2_declare(Type) \
class Array2 ## Type { \
  protected: \
    int _length0; \
    int _length1; \
    int _managed; \
    Type * _array; \
  public: \
    Array2 ## Type():_length0(0),_length1(0),_array(0) {} \
    Array2 ## Type(const Array2 ## Type &a): _length0(0),_length1(0),_array(0) { \
        operator=(a); \
      } \
    Array2 ## Type(Type* data,int size0,int size1): \
      _length0(size0),_length1(size1),_managed(0),_array(data) {} \
    Array2 ## Type(int size0,int size1): _length0(0),_length1(0),_array(0) { \
        set_lengths(size0,size1); \
      } \
    ~Array2 ## Type() { clear(); } \
    int length0() const { return _length0; }; \
    int length1() const { return _length1; }; \
    void clear() { set_lengths(0,0); } \
    void set_lengths(int size0,int size1) { \
        if (_managed && _array) delete[] _array; \
        _managed = 1; \
        if (size0*size1) _array = new Type [ size0*size1 ]; \
        else _array = 0; \
        _length0 = size0; \
        _length1 = size1; \
      } \
    Array2 ## Type& operator = (const Array2 ## Type & s) { \
        if (_managed && _array) delete[] _array; \
        _managed = 1; \
        _length0 = s._length0; \
        _length1 = s._length1; \
        if (_length0*_length1) _array = new Type [ _length0*_length1 ]; \
        else _array = 0; \
        for (int i=0; i<_length0*_length1; i++) { \
            _array[i] = s._array[i]; \
          } \
        return (*this); \
      } \
    Type& operator() (int i,int j) { \
        if (i<0 || i>=_length0 || j<0 || j>=_length1) { \
            ExEnv::err0() << "Array2::operator()(" << i << "," << j << "): " \
                 << "out of range (" << _length0 << "," << _length1 \
                 << ",)" << std::endl; \
            abort(); \
          }; \
        return _array[i*_length1+j]; \
      } \
    const Type& operator() (int i,int j) const { \
        if (i<0 || i>=_length0 || j<0 || j>=_length1) { \
            ExEnv::err0() << "Array2::operator()(" << i << "," << j << "): " \
                 << "out of range (" << _length0 << "," << _length1 \
                 << ",)" << std::endl; \
            abort(); \
          }; \
        return _array[i*_length1+j]; \
      } \
};
}
