Added the images for test.
[pom.git] / array.h
1
2 //////////////////////////////////////////////////////////////////////////////////
3 // This program is free software: you can redistribute it and/or modify         //
4 // it under the terms of the version 3 of the GNU General Public License        //
5 // as published by the Free Software Foundation.                                //
6 //                                                                              //
7 // This program is distributed in the hope that it will be useful, but          //
8 // WITHOUT ANY WARRANTY; without even the implied warranty of                   //
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU             //
10 // General Public License for more details.                                     //
11 //                                                                              //
12 // You should have received a copy of the GNU General Public License            //
13 // along with this program. If not, see <http://www.gnu.org/licenses/>.         //
14 //                                                                              //
15 // Written by Francois Fleuret                                                  //
16 // (C) Ecole Polytechnique Federale de Lausanne                                 //
17 // Contact <pom@epfl.ch> for comments & bug reports                             //
18 //////////////////////////////////////////////////////////////////////////////////
19
20 #ifndef ARRAY_H
21 #define ARRAY_H
22
23 #include <iostream>
24 #include <string.h>
25 #include <stdlib.h>
26
27 using namespace std;
28
29 #include "misc.h"
30
31 template<class T>
32 class Array {
33 public:
34   int width, height;
35   // [i][j] is faster on i386 CPU than [i + j * width]
36   T *content;
37   T **heads;
38
39   inline void resize(int w, int h) {
40     delete[] content;
41     delete[] heads;
42     width = w; height = h;
43     content = new T[width * height];
44     heads = new T *[width];
45     for(int i = 0; i < width; i++) heads[i] = content + i * height;
46   }
47
48   inline int get_width() const { return width; }
49   inline int get_height() const { return height; }
50
51   inline Array() : width(0), height(0), content(0), heads(0) { }
52
53   inline Array(int w, int h) : width(w), height(h) {
54     content = new T[width * height];
55     heads = new T *[width];
56     for(int i = 0; i < width; i++) heads[i] = content + i * height;
57   }
58
59   inline Array(const Array &a) : width(a.width), height(a.height) {
60     content = new T[width * height];
61     heads = new T *[width];
62     for(int i = 0; i < width; i++) heads[i] = content + i * height;
63     memcpy(content, a.content, height * width * sizeof(T));
64   }
65
66   inline ~Array() { delete[] content; delete[] heads; }
67
68   inline Array &operator = (const Array &a) {
69     if(this != &a) {
70       if(a.width != width || a.height != height) resize(a.width, a.height);
71       if(width > 0 && height > 0) memcpy(content, a.content, height * width * sizeof(T));
72     }
73     return *this;
74   }
75
76   inline Array& clear() {
77     memset(content, 0, height * width * sizeof(T));
78     return *this;
79   }
80
81   inline T dot(const Array &a) {
82     ASSERT(width == a.width && height == a.height, "Size mismatch in Array::dot");
83     T *u1 = content, *u2 = a.content;
84     T s = 0;
85     for(int i = 0; i < width * height; i++) s += *(u1++) * *(u2++);
86     return s;
87   }
88
89   inline T sum_square() {
90     T *u = content;
91     T s = 0;
92     for(int i = 0; i < width * height; i++) { s += *u * *u; u++; }
93     return s;
94   }
95
96   inline T sum() {
97     T *u = content;
98     T s = 0;
99     for(int i = 0; i < width * height; i++) s += *(u++);
100     return s;
101   }
102
103   inline T &operator () (int i, int j) {
104     ASSERT(i >= 0 && i < width && j >= 0 && j < height, "Index out of bounds in Array::operator ()");
105     return heads[i][j];
106   }
107
108   inline T operator () (int i, int j) const {
109     ASSERT(i >= 0 && i < width && j >= 0 && j < height, "Index out of bounds in Array::operator () const");
110     return heads[i][j];
111   }
112
113   inline void print(std::ostream &os) const {
114     for(int i = 0; i < width; i++) for(int j = 0; j < height; j++)
115       os << heads[i][j] << ((i < width-1) ? ' ' : '\n');
116   }
117
118   inline void print_for_gnuplot(std::ostream &os) const {
119     for(int i = 0; i < width; i++) {
120       for(int j = 0; j < height; j++)
121         os << i << " " << j << " " << heads[i][j] << "\n";
122       os << "\n";
123     }
124   }
125
126   inline T l2distance(const Array<T> &m) {
127     ASSERT(m.width == width && m.height == height, "Array size mismatch");
128     T r = 0;
129     for(int i = 0; i < width * height; i++) r += (m.content[i] - content[i]) * (m.content[i] - content[i]);
130     return r;
131   }
132 };
133
134 template<class T>
135 std::ostream &operator << (std::ostream &os, const Array<T> &v) { v.print(os); return os; }
136
137 #endif