Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #ifndef SMALLMATRIX_TYPE_HPP
00013 #define SMALLMATRIX_TYPE_HPP
00014
00015 #include "alloc_func.hpp"
00016 #include "mem_func.hpp"
00017
00039 template <typename T>
00040 class SmallMatrix {
00041 protected:
00042 T *data;
00043 uint width;
00044 uint height;
00045 uint capacity;
00046
00047 public:
00048
00049 SmallMatrix() : data(NULL), width(0), height(0), capacity(0) {}
00050
00055 SmallMatrix(const SmallMatrix &other) : data(NULL), width(0), height(0), capacity(0)
00056 {
00057 this->Assign(other);
00058 }
00059
00060 ~SmallMatrix()
00061 {
00062 free(this->data);
00063 }
00064
00069 SmallMatrix &operator=(const SmallMatrix &other)
00070 {
00071 this->Assign(other);
00072 return *this;
00073 }
00074
00078 inline void Assign(const SmallMatrix &other)
00079 {
00080 if (&other == this) return;
00081
00082 this->height = other.Height();
00083 this->width = other.Width();
00084 uint num_items = this->width * this->height;
00085 if (num_items > this->capacity) {
00086 this->capacity = num_items;
00087 free(this->data);
00088 this->data = MallocT<T>(num_items);
00089 MemCpyT(this->data, other[0], num_items);
00090 } else if (num_items > 0) {
00091 MemCpyT(this->data, other[0], num_items);
00092 }
00093 }
00094
00098 inline void Clear()
00099 {
00100
00101
00102
00103 this->width = 0;
00104 }
00105
00109 inline void Reset()
00110 {
00111 this->height = 0;
00112 this->width = 0;
00113 this->capacity = 0;
00114 free(this->data);
00115 this->data = NULL;
00116 }
00117
00121 inline void Compact()
00122 {
00123 uint capacity = this->height * this->width;
00124 if (capacity >= this->capacity) return;
00125 this->capacity = capacity;
00126 this->data = ReallocT(this->data, this->capacity);
00127 }
00128
00133 void EraseColumn(uint x)
00134 {
00135 if (x < --this->width) {
00136 MemCpyT<T>(this->data + x * this->height,
00137 this->data + this->width * this->height,
00138 this->height);
00139 }
00140 }
00141
00147 void EraseColumnPreservingOrder(uint x, uint count = 1)
00148 {
00149 if (count == 0) return;
00150 assert(x < this->width);
00151 assert(x + count <= this->width);
00152 this->width -= count;
00153 uint to_move = (this->width - x) * this->height;
00154 if (to_move > 0) {
00155 MemMoveT(this->data + x * this->height,
00156 this->data + (x + count) * this->height, to_move);
00157 }
00158 }
00159
00164 void EraseRow(uint y)
00165 {
00166 if (y < this->height - 1) {
00167 for (uint x = 0; x < this->width; ++x) {
00168 this->data[x * this->height + y] =
00169 this->data[(x + 1) * this->height - 1];
00170 }
00171 }
00172 this->Resize(this->width, this->height - 1);
00173 }
00174
00180 void EraseRowPreservingOrder(uint y, uint count = 1)
00181 {
00182 if (this->height > count + y) {
00183 for (uint x = 0; x < this->width; ++x) {
00184 MemMoveT(this->data + x * this->height + y,
00185 this->data + x * this->height + y + count,
00186 this->height - count - y);
00187 }
00188 }
00189 this->Resize(this->width, this->height - count);
00190 }
00191
00196 inline void AppendRow(uint to_add = 1)
00197 {
00198 this->Resize(this->width, to_add + this->height);
00199 }
00200
00205 inline void AppendColumn(uint to_add = 1)
00206 {
00207 this->Resize(to_add + this->width, this->height);
00208 }
00209
00216 inline void Resize(uint new_width, uint new_height)
00217 {
00218 uint new_capacity = new_width * new_height;
00219 T *new_data = NULL;
00220 void (*copy)(T *dest, const T *src, size_t count) = NULL;
00221 if (new_capacity > this->capacity) {
00222
00223 new_data = MallocT<T>(new_capacity);
00224 copy = &MemCpyT<T>;
00225 } else {
00226
00227 new_data = this->data;
00228 copy = &MemMoveT<T>;
00229 }
00230 if (this->height != new_height || new_data != this->data) {
00231 if (this->height > 0) {
00232 if (new_height > this->height) {
00233
00234
00235 for (uint x = this->width; x > 0; --x) {
00236 if (x * new_height > new_capacity) continue;
00237 (*copy)(new_data + (x - 1) * new_height,
00238 this->data + (x - 1) * this->height,
00239 min(this->height, new_height));
00240 }
00241 } else {
00242
00243 for (uint x = 0; x < this->width; ++x) {
00244 if ((x + 1) * new_height > new_capacity) break;
00245 (*copy)(new_data + x * new_height,
00246 this->data + x * this->height,
00247 min(this->height, new_height));
00248 }
00249 }
00250 }
00251 this->height = new_height;
00252 if (new_data != this->data) {
00253 free(this->data);
00254 this->data = new_data;
00255 this->capacity = new_capacity;
00256 }
00257 }
00258 this->width = new_width;
00259 }
00260
00261 inline uint Height() const
00262 {
00263 return this->height;
00264 }
00265
00266 inline uint Width() const
00267 {
00268 return this->width;
00269 }
00270
00278 inline const T &Get(uint x, uint y) const
00279 {
00280 assert(x < this->width && y < this->height);
00281 return this->data[x * this->height + y];
00282 }
00283
00291 inline T &Get(uint x, uint y)
00292 {
00293 assert(x < this->width && y < this->height);
00294 return this->data[x * this->height + y];
00295 }
00296
00303 inline const T *operator[](uint x) const
00304 {
00305 assert(x < this->width);
00306 return this->data + x * this->height;
00307 }
00308
00315 inline T *operator[](uint x)
00316 {
00317 assert(x < this->width);
00318 return this->data + x * this->height;
00319 }
00320 };
00321
00322 #endif