Variable Dimension Array

Finally, after months of putting this project off, I figured out a simple algorithm that makes the resize function work! I tested it and was overjoyed to see it working as it should.

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 

What do you guys think?
Last edited on
Here's some simple documentation:

array<class T,class SizeType=unsigned> - T is the type that the array holds and SizeType is the type that the array uses to keep track of sizes (dimension lengths, indices, etc.)

array() - Create an empty array

array(SizeType dim,...) - Create an array with dim dimensions and the given dimension lengths (Note: passing 0 for dim or a 0-length dimension will raise an exception)

numdim() - Returns the number of dimensions in the array

dimsize(SizeType n) - Returns the size of the nth dimension

T& operator[](SizeType x) - Returns the value at index x in the data array (always 1d)

T& operator()(SizeType x,...) - Returns the value at the given indices

resize(SizeType ndim,...) - Resizes the array to hold ndim dimensions and the given dimension lengths (Note: passing 0 for dim or a 0-length dimension will raise an exception)

datasize() - Returns the size, in bytes, of the data

size() - Returns the size, in elements, of the data

array& operator=(const array& rhs) - Sets the array's data equal to rhs

bool operator==(const array& rhs) - Returns if the two arrays contain the same values

bool operator!=(const array& rhs) - Returns if the two arrays do not contain the same values
Anyone?
Topic archived. No new replies allowed.