Gaia
descriptor.h
1 /*
2  * Copyright (C) 2006-2013 Music Technology Group - Universitat Pompeu Fabra
3  *
4  * This file is part of Gaia
5  *
6  * Gaia is free software: you can redistribute it and/or modify it under
7  * the terms of the GNU Affero General Public License as published by the Free
8  * Software Foundation (FSF), either version 3 of the License, or (at your
9  * option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14  * details.
15  *
16  * You should have received a copy of the Affero GNU General Public License
17  * version 3 along with this program. If not, see http://www.gnu.org/licenses/
18  */
19 
20 #ifndef GAIA_DESCRIPTOR_H
21 #define GAIA_DESCRIPTOR_H
22 
23 #include <QTextStream>
24 #include "types.h"
25 #include "gaiamath.h"
26 
27 namespace gaia2 {
28 
29 
30 // There are 3 solutions for the point structure:
31 //
32 // 1- Point = vector<(scope, UnscopedData)>, UnscopedData = vector<Descriptor>
33 // 2- Point = vector<SingleDescriptor>, SingleDescriptor = vector<(scope, Descriptor)>
34 // 3- Point = vector<vector<Descriptor> >, scope info stored apart, with maybe optional
35 // variable indicating whether we actually correspond to type 1 or 2
36 
37 
38 template <typename T>
39 class SingleValueMorphable : public Array<T> {
40  public:
41  SingleValueMorphable() : Array<T>(1, T()) {}
42  SingleValueMorphable(int size, const T& value) : Array<T>(size, value) {}
43  SingleValueMorphable(const T& value) : Array<T>(1, value) {}
44  SingleValueMorphable(const SingleValueMorphable& value) : Array<T>(value) {}
45  SingleValueMorphable(const T* arr, int size) : Array<T>(size) {
46  for (int i=0; i<size; i++) (*this)[i] = arr[i];
47  }
48  SingleValueMorphable(const std::vector<T>& v) : Array<T>((int)v.size()) {
49  for (uint i=0; i<v.size(); i++) (*this)[i] = v[i];
50  }
51 
52  protected:
53  // this constructor is made protected because it should not be called, as it
54  // creates confusion between a SVM of size n, or a SVM of size 1 & value n...
55  SingleValueMorphable(int ambiguous) {
56  throw GaiaException("Cannot call SingleValueMorphable::SVM(int) because it is ambiguous.");
57  }
58 
59  public:
60  SingleValueMorphable& operator=(const SingleValueMorphable& value) {
61  Array<T>::operator=(value);
62  return *this;
63  }
64 
65  SingleValueMorphable& operator=(const T& value) {
66  this->resize(1);
67  this->front() = value;
68  return *this;
69  }
70 
71  const T& toSingleValue() const {
72  if (this->size() != 1) {
73  throw GaiaException("Could not convert descriptor to single value (size=", this->size(), ")");
74  }
75  return this->at(0);
76  }
77 
78  // commented this automatic conversion because it actually causes a lot of
79  // ambiguities, and it is probably better to state explicitly when we want to
80  // convert from a SingleValueMorphable to a single value (catches errors earlier)
81  /*
82  operator const T&() const {
83  return toSingleValue();
84  }
85  */
86 
87  void checkSize(const SingleValueMorphable& rhs) const {
88  if (this->size() != rhs.size()) {
89  throw GaiaException("left-operand and right-operand do not have same size");
90  }
91  }
92 
93 
94 #define transferAssignmentOperator(OP) \
95  SingleValueMorphable& operator OP(const SingleValueMorphable& rhs) { \
96  checkSize(rhs); \
97  for (int i=0; i<this->size(); i++) { \
98  this->operator[](i) OP rhs.at(i); \
99  } \
100  return *this; \
101  }
102 
103  transferAssignmentOperator(+=);
104  transferAssignmentOperator(-=);
105  transferAssignmentOperator(*=);
106  transferAssignmentOperator(/=);
107 
108 #undef transferAssignmentOperator
109 
110 #define transferBinaryOperator(OP) \
111  SingleValueMorphable operator OP(const SingleValueMorphable& rhs) const { \
112  SingleValueMorphable result(*this); \
113  return result.operator OP##=(rhs); \
114  }
115 
116  transferBinaryOperator(+);
117  transferBinaryOperator(-);
118  transferBinaryOperator(*);
119  transferBinaryOperator(/);
120 
121 #undef transferBinaryOperator
122 
123 #define transferUnaryOperator(OP) \
124  SingleValueMorphable operator OP() const { \
125  SingleValueMorphable result(*this); \
126  for (int i=0; i<this->size(); i++) { \
127  result.operator[](i) = OP result.at(i); \
128  } \
129  return result; \
130  }
131 
132  transferUnaryOperator(-);
133 
134 #undef transferUnaryOperator
135 
136 #define transferAssignmentOperatorFromSingleValue(OP) \
137  SingleValueMorphable& operator OP(const T& x) { \
138  for (int i=0; i<this->size(); i++) { \
139  this->operator[](i) OP x; \
140  } \
141  return *this; \
142  }
143 
144  transferAssignmentOperatorFromSingleValue(+=);
145  transferAssignmentOperatorFromSingleValue(-=);
146  transferAssignmentOperatorFromSingleValue(*=);
147  transferAssignmentOperatorFromSingleValue(/=);
148 
149 #undef transferAssignmentOperatorFromSingleValue
150 
151 #define transferBinaryOperatorFromSingleValue(OP) \
152  SingleValueMorphable operator OP(const T& x) const { \
153  SingleValueMorphable result(*this); \
154  return result.operator OP##=(x); \
155  }
156 
157  transferBinaryOperatorFromSingleValue(+);
158  transferBinaryOperatorFromSingleValue(-);
159  transferBinaryOperatorFromSingleValue(*);
160  transferBinaryOperatorFromSingleValue(/);
161 
162 #undef transferBinaryOperatorFromSingleValue
163 
164 
165 #define transferComparison(OP) \
166  bool operator OP(const T& x) const { \
167  for (int i=0; i<this->size(); i++) { \
168  if (!(this->at(i) OP x)) return false; \
169  } \
170  return true; \
171  }
172 
173  transferComparison(<);
174  transferComparison(<=);
175  transferComparison(>);
176  transferComparison(>=);
177 
178 #undef transferComparison
179 
180  bool operator==(const Array<T>& x) const {
181  return Array<T>::operator==(x);
182  }
183 
184  bool operator==(const T& x) const {
185  return toSingleValue() == x;
186  }
187 
188  SingleValueMorphable& minimum(const SingleValueMorphable& rhs) {
189  checkSize(rhs);
190  for (int i=0; i<this->size(); i++) {
191  this->operator[](i) = std::min(this->at(i), rhs.at(i));
192  }
193  return *this;
194  }
195 
196  SingleValueMorphable& maximum(const SingleValueMorphable& rhs) {
197  checkSize(rhs);
198  for (int i=0; i<this->size(); i++) {
199  this->operator[](i) = std::max(this->at(i), rhs.at(i));
200  }
201  return *this;
202  }
203 
204  SingleValueMorphable& minimum(const T& minv) {
205  for (int i=0; i<this->size(); i++) {
206  this->operator[](i) = std::min(this->at(i), minv);
207  }
208  return *this;
209  }
210 
211  SingleValueMorphable& maximum(const T& maxv) {
212  for (int i=0; i<this->size(); i++) {
213  this->operator[](i) = std::max(this->at(i), maxv);
214  }
215  return *this;
216  }
217 
218 
219  bool isnan() const {
220  for (int i=0; i<this->size(); i++) {
221  if (gaia2::isnan(this->at(i))) return true;
222  }
223  return false;
224  }
225 
226  bool isinf() const {
227  for (int i=0; i<this->size(); i++) {
228  if (gaia2::isinf(this->at(i))) return true;
229  }
230  return false;
231  }
232 
233  SingleValueMorphable& inverse() {
234  for (int i=0; i<this->size(); i++) {
235  this->operator[](i) = (T)1.0 / this->at(i);
236  }
237  return *this;
238  }
239 
240  SingleValueMorphable& opposite() {
241  for (int i=0; i<this->size(); i++) {
242  this->operator[](i) = -this->at(i);
243  }
244  return *this;
245  }
246 
247  SingleValueMorphable& sqrt() {
248  for (int i=0; i<this->size(); i++) {
249  this->operator[](i) = std::sqrt(this->at(i));
250  }
251  return *this;
252  }
253 
254  SingleValueMorphable& abs() {
255  for (int i=0; i<this->size(); i++) {
256  this->operator[](i) = std::abs(this->at(i));
257  }
258  return *this;
259  }
260 
261  // only makes sense for RealDescriptor
262  T norm() const {
263  T result = 0;
264  for (int i=0; i<this->size(); i++) {
265  result += (*this)[i] * (*this)[i];
266  }
267  return std::sqrt(result);
268  }
269 
270  QString toString() const {
271  QString result;
272  QTextStream s(&result);
273 
274  if (this->size() == 1) s << this->at(0);
275  else if (this->size() == 0) s << "[]";
276  else {
277  s << "[ " << this->at(0);
278  for (int i=1; i<this->size(); i++) {
279  s << ", " << this->at(i);
280  }
281  s << " ]";
282  }
283  return result;
284  }
285 
286 };
287 
288 
289 template <typename T>
290 SingleValueMorphable<T> operator-(const T& x, const SingleValueMorphable<T>& y) {
291  return (y - x).opposite();
292 }
293 
294 template <typename T>
295 SingleValueMorphable<T> operator/(const T& x, const SingleValueMorphable<T>& y) {
296  return (y / x).inverse();
297 }
298 
299 template <typename T>
300 SingleValueMorphable<T> operator+(const T& x, const SingleValueMorphable<T>& y) {
301  return y + x;
302 }
303 
304 template <typename T>
305 SingleValueMorphable<T> operator*(const T& x, const SingleValueMorphable<T>& y) {
306  return y * x;
307 }
308 
309 template <typename T>
310 Stringifier& operator<<(Stringifier& out, const SingleValueMorphable<T>& array) {
311  return out << array.toString();
312 }
313 
317 
318 
319 template <>
320 inline RealDescriptor sqrt(const RealDescriptor& x) {
321  return RealDescriptor(x).sqrt();
322 }
323 
324 
325 } // namespace gaia2
326 
327 #endif // GAIA_DESCRIPTOR_H
Definition: descriptor.h:39
Definition: debugging.h:82
Main Gaia namespace, which contains all the library functions.
Definition: addfield.cpp:22
Exception class that can take up to 3 arguments of any type, which will be serialized into a QString ...
Definition: gaiaexception.h:46
Definition: types.h:73