1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
|
//array.hpp
//This header defines the array class which allows for the creation
//of dynamic arrays with any given dimension or type.
#pragma once
#ifndef MULTIDIM_ARRAY
#define MULTIDIM_ARRAY
#include <stdexcept>
#include <cstdarg>
template<typename T,typename SizeType=unsigned>
class array{
protected:
SizeType num_dimensions;//number of dimensions
SizeType data_size;//size of data (in elements)
SizeType* dimensions;//array of dimension sizes
T* data;//the data
static void memcpy(T* dst,T* src,SizeType len){
if(dst==src){
return;}
SizeType x=0;
while(x<len){
*dst=*src;
++dst;
++src;
++x;}}
static void memmove(T* dst,T* src,SizeType len){
if(dst==src){
return;}
SizeType x=0;
if(dst<src){
while(x<len){
*dst=*src;
++dst;
++src;
++x;}}
else{
dst+=len;
src+=len;
while(x<len){
*dst=*src;
--dst;
--src;
++x;}}}
public:
//accesor methods
inline SizeType numdim() const{
return num_dimensions;}
inline SizeType dimsize(SizeType n) const{
if(n>=num_dimensions){
throw std::out_of_range("array::dimsize(SizeType) const");}
return dimensions[n];}
//use to get data directly from data array
inline T& operator[](SizeType x){
if(x>=datasize){
throw std::out_of_range("array::operator[]");}
return data[x];}
inline const T& operator[](SizeType x) const{
if(x>=datasize){
throw std::out_of_range("array::operator[](SizeType) const");}
return data[x];}
//constructor
//no arguments
array(){
num_dimensions=0;
data_size=0;
dimensions=NULL;
data=NULL;}
//array(number of dimensions,<dimension sizes>...)
array(SizeType ndim,...){
num_dimensions=ndim;
if(ndim==0){
throw dimensionless_array("array::array(SizeType,...)");}
else{
dimensions=new SizeType[ndim];
va_list args;
va_start(args,ndim);
SizeType size=1;
for(int a=0;a<ndim;++a){
dimensions[a]=va_arg(args,T);
if(dimensions[a]==0){
--a;
--ndim;
continue;}
size*=dimensions[a];}
data=new T[size];
data_size=size;
va_end(args);}}
//destrctor
~array(){
delete[] dimensions;
delete[] data;}
//returns a reference to the element at the given position
//operator()(x,y,z,...)
T& operator()(SizeType x,...){
SizeType index,pos=x,dim=1,a=1;
va_list args;
va_start(args,x);
for(;a<num_dimensions;++a){
if((index=va_arg(args,SizeType))>=dimensions[a]){
printf("num_dimensions: %inindex: %indimensions[a]: %in",num_dimensions,index,dimensions[a]);
throw std::out_of_range("array::operator()(SizeType,...)");}
dim*=dimensions[a];
pos+=index*dim;}
va_end(args);
return data[pos];}
const T& operator()(SizeType x,...) const{
SizeType index,pos=x,dim=1,a=1;
va_list args;
va_start(args,x);
for(;a<num_dimensions;++a){
if((index=va_arg(args,SizeType))>=dimensions[a]){
throw std::out_of_range("array::operator()(SizeType,...) const");}
dim*=dimensions[a];
pos+=index*dim;}
va_end(args);
return data[pos];}
//resizes the array, even with different dimensions
//resize(number of dimensions (0 for current),<dimension sizes>...)
//TODO: fix this function so that it keeps old data
SizeType resize(SizeType ndim,...){
if(ndim==0){
throw std::invalid_argument("Array resized to 0 dimensions in array::resize(SizeType,...)");}
SizeType a,x,y,size=1,mwidth;
SizeType* ndimen=new SizeType[ndim];
T* ndata;
va_list args;
va_start(args,ndim);
for(a=0;a<ndim;++a){
ndimen[a]=va_arg(args,SizeType);
//make sure that there isn't a size 0 dimension
if(ndimen[a]==0){
delete[] ndimen;
printf("DEBUG");
throw std::invalid_argument("Passed a 0-length dimension in array::resize(SizeType,...)");}
size*=ndimen[a];}
ndata=new T[size];
mwidth=(dimensions[0]<ndimen[0]?dimensions[0]:ndimen[0]);
x=0;
y=0;
//copy the data to the new buffer
while(x<data_size && y<size){
memcpy(ndata+y,data+x,mwidth);
x+=dimensions[0];
y+=ndimen[0];}
//fill in the rest of the variables
delete[] dimensions;
dimensions=ndimen;
num_dimensions=ndim;
data_size=size;
delete[] data;
data=ndata;
return data_size;}
//returns the size in bytes of the contained data
inline SizeType datasize() const{
return data_size*sizeof(T);}
//returns the number of elements contained
inline SizeType size() const{
return data_size;}
//operators
array<T,SizeType>& operator=(const array<T,SizeType>& rhs){
delete[] data;
data=new T[rhs.data_size];
data_size=rhs.data_size;
delete[] dimensions;
dimensions=new T[rhs.num_dimensions];
num_dimensions=rhs.num_dimensions;
memcpy(data,rhs.data,data_size);
return *this;}
template<typename U>
bool operator==(const array<U>& rhs) const{
SizeType x;
for(x=0;x<len;++x){
if(data[x]=rhs.data[x]){
return false;}}
return true;}
template<typename U>
inline bool operator!=(const array<U>& rhs) const{
return !(*this==rhs);}};
#endif
|