Edinburgh Speech Tools  2.4-release
 All Classes Functions Variables Typedefs Enumerations Enumerator Friends Pages
EST_TMatrix.cc
1  /*************************************************************************/
2  /* */
3  /* Centre for Speech Technology Research */
4  /* University of Edinburgh, UK */
5  /* Copyright (c) 1995,1996 */
6  /* All Rights Reserved. */
7  /* */
8  /* Permission is hereby granted, free of charge, to use and distribute */
9  /* this software and its documentation without restriction, including */
10  /* without limitation the rights to use, copy, modify, merge, publish, */
11  /* distribute, sublicense, and/or sell copies of this work, and to */
12  /* permit persons to whom this work is furnished to do so, subject to */
13  /* the following conditions: */
14  /* 1. The code must retain the above copyright notice, this list of */
15  /* conditions and the following disclaimer. */
16  /* 2. Any modifications must be clearly marked as such. */
17  /* 3. Original authors' names are not deleted. */
18  /* 4. The authors' names are not used to endorse or promote products */
19  /* derived from this software without specific prior written */
20  /* permission. */
21  /* */
22  /* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */
23  /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
24  /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
25  /* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */
26  /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
27  /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
28  /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
29  /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
30  /* THIS SOFTWARE. */
31  /* */
32  /*************************************************************************/
33  /* */
34  /* Author : Paul Taylor */
35  /* Rewritten : Richard Caley */
36  /* ------------------------------------------------------------------- */
37  /* Template EST_TMatrix Class */
38  /* */
39  /*************************************************************************/
40 
41 #include "EST_TMatrix.h"
42 #include <fstream>
43 #include <iostream>
44 #include "EST_bool.h"
45 #include "EST_matrix_support.h"
46 #include "EST_TVector.h"
47 #include "EST_cutils.h"
48 #include "EST_error.h"
49 
50 /* Construction and destruction
51  */
52 
53 template<class T>
55 {
57  p_num_rows = 0;
58  p_row_step=0;
59 }
60 
61 template<class T>
63 {
64  default_vals();
65 }
66 
67 template<class T>
69 {
70  default_vals();
71  copy(in);
72 }
73 
74 template<class T>
75 EST_TMatrix<T>::EST_TMatrix(int rows, int cols)
76 {
77  default_vals();
78  resize(rows, cols);
79 }
80 
81 template<class T>
82 EST_TMatrix<T>::EST_TMatrix(int rows, int cols,
83  T *memory, int offset, int free_when_destroyed)
84 {
85  default_vals();
86  set_memory(memory, offset, rows, cols, free_when_destroyed);
87 }
88 
89 template<class T>
91 {
92  p_num_rows = 0;
93  p_row_step=0;
94 }
95 
96 /* Basic access
97  */
98 
99 template<class T>
100 T &EST_TMatrix<T>::a_check(int row, int col)
101 {
102 
103  if (!EST_matrix_bounds_check(row, col, num_rows(), num_columns(), FALSE))
104  return *this->error_return;
105 
106  return a_no_check(row,col);
107 }
108 
109 /* Since we know a() itself doesn't change the matrix, we can cast away
110  * the const here. Isn't the C++ syntax beautiful!
111  */
112 template<class T>
113 const T &EST_TMatrix<T>::a_check(int row, int col) const
114 {
115  return ((EST_TMatrix<T> *)this)->a(row,col);
116 }
117 
118 template<class T>
120 {
121 
122  set_values(a.p_memory,
123  a.p_row_step, a.p_column_step,
124  0, a.num_rows(),
125  0, a.num_columns());
126 }
127 
128 template<class T>
129 void EST_TMatrix<T>::set_values(const T *data,
130  int r_step, int c_step,
131  int start_r, int num_r,
132  int start_c, int num_c
133  )
134 {
135  for(int r=start_r, i=0, rp=0; i< num_r; i++, r++, rp+=r_step)
136  for(int c=start_c, j=0, cp=0; j< num_c; j++, c++, cp+=c_step)
137  a_no_check(r,c) = data[rp+cp];
138 }
139 
140 template<class T>
141 void EST_TMatrix<T>::get_values(T *data,
142  int r_step, int c_step,
143  int start_r, int num_r,
144  int start_c, int num_c
145  ) const
146 {
147  for(int r=start_r, i=0, rp=0; i< num_r; i++, r++, rp+=r_step)
148  for(int c=start_c, j=0, cp=0; j< num_c; j++, c++, cp+=c_step)
149  data[rp+cp] = a_no_check(r,c);
150 }
151 
152 template<class T>
154 {
155  resize(a.num_rows(), a.num_columns(), 0);
156  copy_data(a);
157 }
158 
159 template<class T>
161 {
162  copy(in);
163  return *this;
164 }
165 
166 template<class T>
168 {
169  if (in.num_columns() != num_columns())
170  EST_error("Can't add rows with differnet number of columns (%d vs %d)",
171  in.num_columns(),
172  num_columns()
173  );
174  else
175  {
176  int old_num_rows = num_rows();
177  resize(num_rows()+in.num_rows(), num_columns(), TRUE);
178 
179  for(int i=old_num_rows, i1=0; i<num_rows(); i++, i1++)
180  for(int j=0; j<num_columns(); j++)
181  a(i,j) = in.a(i1,j);
182 
183  }
184  return *this;
185 }
186 
187 template<class T>
189 {
190  if (in.num_rows() != num_rows())
191  EST_error("Can't add columns with differnet number of rows (%d vs %d)",
192  in.num_rows(),
193  num_rows()
194  );
195  else
196  {
197  int old_num_columns = num_columns();
198  resize(num_columns()+in.num_columns(), num_rows(), TRUE);
199 
200  for(int i=old_num_columns, i1=0; i<num_columns(); i++, i1++)
201  for(int j=0; j<num_rows(); j++)
202  a(i,j) = in.a(i1,j);
203 
204  }
205  return *this;
206 }
207 
208 template<class T>
209 void EST_TMatrix<T>::just_resize(int new_rows,
210  int new_cols,
211  T** old_vals)
212 {
213  T *new_m;
214 
215  if (num_rows() != new_rows || num_columns() != new_cols || this->p_memory == NULL )
216  {
217  if (this->p_sub_matrix)
218  EST_error("Attempt to resize Sub-Matrix");
219 
220  if (new_cols < 0 || new_rows < 0)
221  EST_error("Attempt to resize matrix to negative size: %d x %d",
222  new_rows,
223  new_cols);
224 
225 
226  new_m = new T[new_rows*new_cols];
227 
228  if (this->p_memory != NULL)
229  {
230  if (old_vals != NULL)
231  *old_vals = this->p_memory;
232  else if (!this->p_sub_matrix)
233  delete [] (this->p_memory-this->p_offset);
234  }
235 
236  p_num_rows = new_rows;
237  this->p_num_columns = new_cols;
238  this->p_offset=0;
239  p_row_step=this->p_num_columns;
240  this->p_column_step=1;
241 
242  this->p_memory = new_m;
243  }
244  else
245  *old_vals = this->p_memory;
246 
247 }
248 
249 template<class T>
250 void EST_TMatrix<T>::resize(int new_rows, int new_cols, int set)
251 {
252  int i,j;
253  T * old_vals = this->p_memory;
254  int old_rows = num_rows();
255  int old_cols = num_columns();
256  int old_row_step = p_row_step;
257  int old_offset = this->p_offset;
258  int old_column_step = this->p_column_step;
259 
260  if (new_rows<0)
261  new_rows = old_rows;
262  if (new_cols<0)
263  new_cols = old_cols;
264 
265  just_resize(new_rows, new_cols, &old_vals);
266 
267  if (set)
268  {
269  int copy_r = 0;
270  int copy_c = 0;
271 
272  if (old_vals != NULL)
273  {
274  copy_r = Lof(num_rows(), old_rows);
275  copy_c = Lof(num_columns(), old_cols);
276 
277  set_values(old_vals,
278  old_row_step, old_column_step,
279  0, copy_r,
280  0, copy_c);
281  }
282  else
283  {
284  copy_r = old_rows;
285  copy_c = old_cols;
286  }
287 
288  for(i=0; i<copy_r; i++)
289  for(j=copy_c; j<new_cols; j++)
290  a_no_check(i,j) = *this->def_val;
291 
292  for(i=copy_r; i<new_rows; i++)
293  for(j=0; j<new_cols; j++)
294  a_no_check(i,j) = *this->def_val;
295  }
296 
297  if (old_vals && old_vals != this->p_memory && !this->p_sub_matrix)
298  delete [] (old_vals-old_offset);
299 }
300 
301 template<class T>
302 bool EST_TMatrix<T>::have_rows_before(int n) const
303 {
304  return this->p_offset >= n*p_row_step;
305 }
306 
307 template<class T>
308 bool EST_TMatrix<T>::have_columns_before(int n) const
309 {
310  return this->p_offset >= n*this->p_column_step;
311 }
312 
313 template<class T>
314 void EST_TMatrix<T>::fill(const T &v)
315 {
316  int i, j;
317  for (i = 0; i < num_rows(); ++i)
318  for (j = 0; j < num_columns(); ++j)
319  fast_a_m(i,j) = v;
320 }
321 
322 
323 template<class T>
324 EST_write_status EST_TMatrix<T>::save(const EST_String &filename) const
325 {
326  int i, j;
327  ostream *outf;
328  if (filename == "-" || filename == "")
329  outf = &cout;
330  else
331  outf = new ofstream(filename);
332 
333  for (i = 0; i < num_rows(); ++i)
334  {
335  for (j = 0; j < num_columns(); ++j)
336  {
337  *outf
338 #if 0
339  << "{" <<i<<","<<j
340  <<",m="<<((int)this->p_memory)<<","
341  <<"r'="<<((int)((T *) mx_move_pointer_f(this->p_memory, sizeof(T)*p_row_step, i)))<<","
342  <<"r="<<((int)mx_move_pointer(this->p_memory, T, p_row_step, i))<<","
343  <<"c="<<((int)mx_move_pointer(this->p_memory, T, this->p_column_step, j))<<","
344  <<((int)(&fast_a_m_gcc(i,j)))
345  <<"}"
346 #endif
347  << a_no_check(i,j) << "\t";
348  }
349  *outf << endl;
350  }
351 
352  if (outf != &cout)
353  delete outf;
354 
355  return write_ok;
356 }
357 
358 template<class T>
359 EST_read_status
361 {
362  // this function can only be written if we can find a way of parsing
363  // an unknown type;
364  (void) filename;
365  EST_error("Matrix loading not implemented yet.");
366  return misc_read_error;
367 
368 }
369 
370 template<class T>
371 void EST_TMatrix<T>::set_memory(T *buffer, int offset,
372  int rows, int columns,
373  int free_when_destroyed)
374 {
375  EST_TVector<T>::set_memory(buffer, offset, columns, free_when_destroyed);
376  p_num_rows = rows;
377  p_row_step = columns;
378 }
379 
380 template<class T>
381 void EST_TMatrix<T>::copy_row(int r, T *buf,
382  int offset, int num) const
383 {
384  int to = num >= 0 ? offset + num : num_columns();
385 
386  if (!EST_matrix_bounds_check(r, 0, num_rows(), num_columns(), FALSE))
387  {
388  if (num_rows()>0)
389  r=0;
390  else
391  return;
392  }
393 
394  for (int j = offset; j < to; j++)
395  buf[j-offset] = fast_a_m(r, j);
396 }
397 
398 template<class T>
400  int offset, int num) const
401 {
402  int to = num >= 0 ? offset + num : num_columns();
403 
404  if (!EST_matrix_bounds_check(r, 0, num_rows(), num_columns(), FALSE))
405  {
406  if (num_rows()>0)
407  r=0;
408  else
409  return;
410  }
411 
412  buf.resize(to - offset);
413 
414  for (int j = offset; j < to; j++)
415  buf[j - offset] = fast_a_m(r, j);
416 }
417 
418 
419 template<class T>
420 void EST_TMatrix<T>::copy_column(int c, T *buf,
421  int offset, int num) const
422 {
423  if (num_rows() == 0)
424  return;
425 
426  int to = num >= 0 ? offset + num : num_rows();
427 
428  if (!EST_matrix_bounds_check(0, c, num_rows(), num_columns(), FALSE))
429  {
430  if (num_columns()>0)
431  c=0;
432  else
433  return;
434  }
435 
436  for (int i = offset; i < to; i++)
437  buf[i-offset] = fast_a_m(i, c);
438 }
439 
440 
441 template<class T>
443  int offset, int num) const
444 {
445  if (num_rows() == 0)
446  return;
447 
448  int to = num >= 0 ? offset + num : num_rows();
449 
450  if (!EST_matrix_bounds_check(0, c, num_rows(), num_columns(), FALSE))
451  {
452  if( num_columns()>0 )
453  c=0;
454  else
455  return;
456  }
457 
458  buf.resize(to - offset);
459 
460  for (int i = offset; i < to; i++)
461  buf[i-offset] = fast_a_m(i, c);
462 }
463 
464 
465 template<class T>
466 void EST_TMatrix<T>::set_row(int r, const T *buf, int offset, int num)
467 {
468  int to = num>=0?offset+num:num_columns();
469 
470  if (!EST_matrix_bounds_check(r, 0, num_rows(), num_columns(), TRUE))
471  return;
472 
473  for(int j=offset; j<to; j++)
474  fast_a_m(r, j) = buf[j-offset];
475 }
476 
477 template<class T>
478 void EST_TMatrix<T>::set_column(int c, const T *buf, int offset, int num)
479 {
480  int to = num>=0?offset+num:num_rows();
481 
482  if (!EST_matrix_bounds_check(0, c, num_rows(), num_columns(), TRUE))
483  return;
484 
485  for(int i=offset; i<to; i++)
486  fast_a_m(i, c) = buf[i-offset];
487 }
488 
489 template<class T>
490 void EST_TMatrix<T>::set_row(int r,
491  const EST_TMatrix<T> &from, int from_r, int from_offset,
492  int offset, int num)
493 {
494  int to = num>=0?offset+num:num_columns();
495 
496  if (!EST_matrix_bounds_check(r, 0, num_rows(), num_columns(), TRUE))
497  return;
498 
499  if (!EST_matrix_bounds_check(from_r, 0, from.num_rows(), from.num_columns(), FALSE))
500  {
501  if (from.num_rows()>0)
502  from_r=0;
503  else
504  return;
505  }
506 
507  for(int j=offset; j<to; j++)
508  fast_a_m(r, j) = from.fast_a_m(from_r, (j-offset)+from_offset);
509 }
510 
511 template<class T>
512 void EST_TMatrix<T>::set_column(int c,
513  const EST_TMatrix<T> &from, int from_c, int from_offset,
514  int offset, int num)
515 {
516  int to = num>=0?offset+num:num_rows();
517 
518  if (!EST_matrix_bounds_check(0, c, num_rows(), num_columns(), TRUE))
519  return;
520 
521  if (!EST_matrix_bounds_check(0, from_c, from.num_rows(), from.num_columns(), FALSE))
522  {
523  if (from.num_columns()>0)
524  from_c=0;
525  else
526  return;
527  }
528 
529  for(int i=offset; i<to; i++)
530  fast_a_m(i, c) = from.fast_a_m((i-offset)+from_offset, from_c);
531 }
532 
533 template<class T>
534 void EST_TMatrix<T>::row(EST_TVector<T> &rv, int r, int start_c, int len)
535 {
536  if (len < 0)
537  len = num_columns()-start_c;
538 
539  if (!EST_matrix_bounds_check(r, 1, start_c, len, num_rows(), num_columns(), 0))
540  return;
541 
542  if (rv.p_memory != NULL && ! rv.p_sub_matrix)
543  delete [] (rv.p_memory - rv.p_offset);
544 
545  rv.p_sub_matrix = TRUE;
546  rv.p_num_columns = len;
547  rv.p_offset = this->p_offset + start_c*this->p_column_step + r*p_row_step;
548  rv.p_memory = this->p_memory - this->p_offset + rv.p_offset;
549 // cout << "mrow: mem: " << rv.p_memory << " (" << (int)rv.p_memory << ")\n";
550 // cout << "mrow: ofset: " << rv.p_offset << " (" << (int)rv.p_offset << ")\n";
551 
552  rv.p_column_step=this->p_column_step;
553 }
554 
555 template<class T>
556 void EST_TMatrix<T>::column(EST_TVector<T> &cv, int c, int start_r, int len)
557 {
558  if (len < 0)
559  len = num_rows()-start_r;
560 
561  if (!EST_matrix_bounds_check(start_r, len, c, 1,num_rows(), num_columns(), 0))
562  return;
563 
564  if (cv.p_memory != NULL && ! cv.p_sub_matrix)
565  delete [] (cv.p_memory - cv.p_offset);
566 
567  cv.p_sub_matrix = TRUE;
568  cv.p_num_columns = len;
569  cv.p_offset = this->p_offset + c*this->p_column_step + start_r*p_row_step;
570  cv.p_memory = this->p_memory - this->p_offset + cv.p_offset;
571 // cout << "mcol: mem: " << cv.p_memory << " (" << (int)cv.p_memory << ")\n";
572 // cout << "mcol: offset: " << cv.p_offset << " (" << (int)cv.p_offset << ")\n";
573 
574  cv.p_column_step=p_row_step;
575 }
576 
577 template<class T>
579  int r, int len_r, int c, int len_c)
580 {
581  if (len_r < 0)
582  len_r = num_rows()-r;
583  if (len_c < 0)
584  len_c = num_columns()-c;
585 
586  if (!EST_matrix_bounds_check(r, len_r, c, len_c, num_rows(), num_columns(), 0))
587  return;
588 
589  if (sm.p_memory != NULL && ! sm.p_sub_matrix)
590  delete [] (sm.p_memory - sm.p_offset);
591 
592  sm.p_sub_matrix = TRUE;
593  sm.p_offset = this->p_offset + c*this->p_column_step + r*p_row_step;
594  sm.p_memory = this->p_memory - this->p_offset + sm.p_offset;
595  sm.p_row_step=p_row_step;
596  sm.p_column_step=this->p_column_step;
597  sm.p_num_rows = len_r;
598  sm.p_num_columns = len_c;
599 
600 }
601