SHOGUN  3.2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SGNDArray.cpp
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 3 of the License, or
5  * (at your option) any later version.
6  *
7  * Written (W) 2012 Fernando José Iglesias García
8  * Written (W) 2010,2012 Soeren Sonnenburg
9  * Copyright (C) 2010 Berlin Institute of Technology
10  * Copyright (C) 2012 Soeren Sonnenburg
11  */
12 
13 #include <shogun/lib/common.h>
14 #include <shogun/lib/SGNDArray.h>
16 
17 namespace shogun
18 {
19 
20 template<class T> SGNDArray<T>::SGNDArray() :
22 {
23  init_data();
24 }
25 
26 template<class T> SGNDArray<T>::SGNDArray(T* a, index_t* d, index_t nd, bool ref_counting) :
27  SGReferencedData(ref_counting)
28 {
29  array = a;
30  dims = d;
31  num_dims = nd;
32  len_array = 1;
33  for (int32_t i=0; i<num_dims; i++)
34  len_array *= dims[i];
35 
36  REQUIRE(len_array>0, "Length of array (%d) must be greater than 0\n", len_array);
37 }
38 
39 template<class T> SGNDArray<T>::SGNDArray(index_t* d, index_t nd, bool ref_counting) :
40  SGReferencedData(ref_counting), dims(d), num_dims(nd)
41 {
42  len_array = 1;
43  for (int32_t i=0; i<num_dims; i++)
44  len_array *= dims[i];
45 
46  REQUIRE(len_array>0, "Length of array (%d) must be greater than 0\n", len_array);
47  array = SG_MALLOC(T, len_array);
48 }
49 
50 template<class T> SGNDArray<T>::SGNDArray(const SGVector<index_t> dimensions, bool ref_counting) :
51  SGReferencedData(ref_counting)
52 {
53  num_dims = dimensions.size();
54  dims = SG_MALLOC(index_t, num_dims);
55 
56  len_array = 1;
57  for (int32_t i=0; i<num_dims; i++)
58  {
59  dims[i] = dimensions[i];
60  len_array *= dims[i];
61  }
62 
63  REQUIRE(len_array>0, "Length of array (%d) must be greater than 0\n", len_array);
64  array = SG_MALLOC(T, len_array);
65 }
66 
67 template<class T> SGNDArray<T>::SGNDArray(const SGNDArray &orig) :
68  SGReferencedData(orig)
69 {
70  copy_data(orig);
71 }
72 
73 template<class T> SGNDArray<T>::~SGNDArray()
74 {
75  unref();
76 }
77 
78 template<class T> void SGNDArray<T>::copy_data(const SGReferencedData &orig)
79 {
80  array = ((SGNDArray*)(&orig))->array;
81  dims = ((SGNDArray*)(&orig))->dims;
82  num_dims = ((SGNDArray*)(&orig))->num_dims;
83  len_array = ((SGNDArray*)(&orig))->len_array;
84 }
85 
86 template<class T> void SGNDArray<T>::init_data()
87 {
88  array = NULL;
89  dims = NULL;
90  num_dims = 0;
91  len_array = 0;
92 }
93 
94 template<class T> void SGNDArray<T>::free_data()
95 {
96  SG_FREE(array);
97  SG_FREE(dims);
98 
99  array = NULL;
100  dims = NULL;
101  num_dims = 0;
102  len_array = 0;
103 }
104 
105 template<class T> SGNDArray<T> SGNDArray<T>::clone() const
106 {
107  SGNDArray<T> array_clone(get_dimensions());
108  memcpy(array_clone.array, array, sizeof(T)*len_array);
109  return array_clone;
110 }
111 
113 {
114  SGVector<index_t> dimensions(num_dims);
115 
116  for (int32_t i = 0; i < num_dims; i++)
117  dimensions[i] = dims[i];
118 
119  return dimensions;
120 }
121 
122 template<class T> void SGNDArray<T>::transpose_matrix(index_t matIdx) const
123 {
124  REQUIRE(array && dims, "Array is empty.\n");
125  REQUIRE(num_dims > 2, "Number of dimensions (%d) must be greater than 2.\n", num_dims);
126  REQUIRE(dims[2] > matIdx, "Provided index (%d) is out of range, must be smaller than %d\n", matIdx, dims[2]);
127 
128  T aux;
129  // Index to acces directly the elements of the matrix of interest
130  int64_t idx = int64_t(matIdx)*int64_t(dims[0])*dims[1];
131 
132  for (int64_t i=0; i<dims[0]; i++)
133  for (int64_t j=0; j<i-1; j++)
134  {
135  aux = array[idx + i + j*dims[0]];
136  array[idx + i + j*dims[0]] = array[idx + j + i*dims[0]];
137  array[idx + j + i*dims[1]] = aux;
138  }
139 
140  // Swap the sizes of the two first dimensions
141  index_t auxDim = dims[0];
142  dims[0] = dims[1];
143  dims[1] = auxDim;
144 }
145 
146 template<class T> void SGNDArray<T>::set_const(T const_elem)
147 {
148  for (index_t i = 0; i < len_array; i++)
149  array[i] = const_elem;
150 }
151 
152 template<class T>
154 {
155  for (index_t i = 0; i < len_array; i++)
156  array[i] *= val;
157 
158  return (*this);
159 }
160 
161 template<>
163 {
165  return (*this);
166 }
167 
168 template<>
170 {
172  return (*this);
173 }
174 
175 template<class T>
177 {
178  REQUIRE(len_array == ndarray.len_array,
179  "The length of the given array (%d) does not match the length of internal array (%d).\n", ndarray.len_array, len_array);
180  REQUIRE(num_dims == ndarray.num_dims,
181  "The provided number of dimensions (%d) does not match the internal number of dimensions (%d).\n", ndarray.num_dims, num_dims);
182 
183  for (index_t i = 0; i < len_array; i++)
184  array[i] += ndarray.array[i];
185 
186  return (*this);
187 }
188 
189 template<>
191 {
193  return (*this);
194 }
195 
196 template<>
198 {
200  return (*this);
201 }
202 
203 template<class T>
205 {
206  REQUIRE(len_array == ndarray.len_array,
207  "The length of the given array (%d) does not match the length of internal array (%d).\n", ndarray.len_array, len_array);
208  REQUIRE(num_dims == ndarray.num_dims,
209  "The provided number of dimensions (%d) does not match the internal number of dimensions (%d).\n", ndarray.num_dims, num_dims);
210 
211  for (index_t i = 0; i < len_array; i++)
212  array[i] -= ndarray.array[i];
213 
214  return (*this);
215 }
216 
217 template<>
219 {
221  return (*this);
222 }
223 
224 template<>
226 {
228  return (*this);
229 }
230 
231 template<class T>
232 T SGNDArray<T>::max_element(int32_t &max_at)
233 {
234  REQUIRE(len_array > 0, "Length of the array (%d) must be greater than 0.\n", len_array);
235 
236  T m = array[0];
237  max_at = 0;
238 
239  for (int32_t i = 1; i < len_array; i++)
240  {
241  if (array[i] >= m)
242  {
243  max_at = i;
244  m = array[i];
245  }
246  }
247 
248  return m;
249 }
250 
251 template<>
252 bool SGNDArray<bool>::max_element(int32_t &max_at)
253 {
255  return false;
256 }
257 
258 template<>
259 char SGNDArray<char>::max_element(int32_t &max_at)
260 {
262  return '\0';
263 }
264 
265 template<class T>
267 {
268  int32_t y = 0;
269  int32_t fact = 1;
270 
271  REQUIRE(index.size() == num_dims,
272  "Provided number of dimensions (%d) does not match internal number of dimensions (%d).\n", index.size(), num_dims);
273 
274  for (int32_t i = num_dims - 1; i >= 0; i--)
275  {
276  REQUIRE(index[i] < dims[i], "Provided index (%d) on dimension %d must be smaller than %d. \n", index[i], i, dims[i]);
277 
278  y += index[i] * fact;
279  fact *= dims[i];
280  }
281 
282  return array[y];
283 }
284 
285 template<class T>
287 {
288  REQUIRE(curr_index.size() == num_dims,
289  "The provided number of dimensions (%d) does not match the internal number of dimensions (%d).\n", curr_index.size(), num_dims);
290 
291  for (int32_t i = num_dims - 1; i >= 0; i--)
292  {
293  curr_index[i]++;
294 
295  if (curr_index[i] < dims[i])
296  break;
297 
298  curr_index[i] = 0;
299  }
300 }
301 
302 template<class T>
304 {
305  // TODO: A nice implementation would be a function like repmat in matlab
306  REQUIRE(axes.size() <= 2,
307  "Provided axes size (%d) must be smaller than 2.\n", axes.size());
308  REQUIRE(num_dims <= 2,
309  "Number of dimensions (%d) must be smaller than 2. Only 1-d and 2-d array can be expanded currently.\n", num_dims);
310 
311  // Initialize indices in big array to zeros
312  SGVector<index_t> inds_big(big_array.num_dims);
313  inds_big.zero();
314 
315  // Replicate the small array to the big one.
316  // Go over the big one by one and take the corresponding value
317  T* data_big = &big_array.array[0];
318  for (int32_t vi = 0; vi < big_array.len_array; vi++)
319  {
320  int32_t y = 0;
321 
322  if (axes.size() == 1)
323  {
324  y = inds_big[axes[0]];
325  }
326  else if (axes.size() == 2)
327  {
328  int32_t ind1 = axes[0];
329  int32_t ind2 = axes[1];
330  y = inds_big[ind1] * dims[1] + inds_big[ind2];
331  }
332 
333  *data_big = array[y];
334  data_big++;
335 
336  // Move to the next index
337  big_array.next_index(inds_big);
338  }
339 }
340 
341 template class SGNDArray<bool>;
342 template class SGNDArray<char>;
343 template class SGNDArray<int8_t>;
344 template class SGNDArray<uint8_t>;
345 template class SGNDArray<int16_t>;
346 template class SGNDArray<uint16_t>;
347 template class SGNDArray<int32_t>;
348 template class SGNDArray<uint32_t>;
349 template class SGNDArray<int64_t>;
350 template class SGNDArray<uint64_t>;
351 template class SGNDArray<float32_t>;
352 template class SGNDArray<float64_t>;
353 template class SGNDArray<floatmax_t>;
354 }

SHOGUN Machine Learning Toolbox - Documentation