1 // -*-C++-*-
2 
3 // Copyright (C) 2004
4 // Christian Stimming <stimming@tuhh.de>
5 
6 // Row-order modifications by Jacob (Jack) Gryn <jgryn at cs dot yorku dot ca>
7 
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Lesser General Public License as
10 // published by the Free Software Foundation; either version 2, or (at
11 // your option) any later version.
12 
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU Lesser General Public License for more details.
17 
18 // You should have received a copy of the GNU Lesser General Public License along
19 // with this library; see the file COPYING.  If not, write to the Free
20 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21 // USA.
22 
23 /** @file
24  * @brief General Dense Rectangular Matrix Class with float elements
25  */
26 
27 //      LAPACK++ (V. 1.1)
28 //      (C) 1992-1996 All Rights Reserved.
29 //
30 //      Lapack++ Rectangular Matrix Class
31 //
32 //      Dense (nonsingular) matrix, assumes no special structure or properties.
33 //
34 //      ) allows 2-d indexing
35 //      ) non-unit strides
36 //      ) deep (copy) assignment
37 //      ) std::cout << A.info()  prints out internal states of A
38 //      ) indexing via A(i,j) where i,j are either integers or
39 //              LaIndex
40 
41 #ifndef _LA_GEN_MAT_FLOAT_H_
42 #define _LA_GEN_MAT_FLOAT_H_
43 
44 #include "arch.h"
45 #include "lafnames.h"
46 #include VECTOR_FLOAT_H
47 #include LA_INDEX_H
48 
49 class LaGenMatComplex;
50 class LaGenMatDouble;
51 class LaGenMatFloat;
52 class LaGenMatInt;
53 class LaGenMatLongInt;
54 
55 
56 class DLLIMPORT LaGenMatFloat
57 {
58 public:
59     /** The type of the value elements. */
60     typedef float value_type;
61     /** Convenience typedef of this class to itself to make
62      * common function definitions easier. (New in
63      * lapackpp-2.4.5) */
64     typedef LaGenMatFloat matrix_type;
65     /** Internal wrapper type; don't use that in an
66      * application. */
67     typedef VectorFloat vec_type;
68 private:
69     vec_type     v;
70     LaIndex         ii[2];
71     int             dim[2];  // size of original matrix, not submatrix
72     int             sz[2];   // size of this submatrix
73     void init(int m, int n);
74     static int  debug_; // trace all entry and exits into methods and
75     // operators of this class.  This variable is
76     // explicitly initalized in lagenmatfloat.cc
77 
78     static int      *info_;   // print matrix info only, not values
79     //   originally 0, set to 1, and then
80     //   reset to 0 after use.
81     // use as in
82     //
83     //    std::cout << B.info() << std::endl;
84     //
85     // this *info_ member is unique in that it really isn't
86     // part of the matrix info, just a flag as to how
87     // to print it.   We've included in this beta release
88     // as part of our testing, but we do not expect it
89     // to be user accessable.
90     // It has to be declared as global static
91     // so that we may monitor expresssions like
92     // X::(const &X) and still utilize without violating
93     // the "const" condition.
94     // Because this *info_ is used at most one at a time,
95     // there is no harm in keeping only one copy of it,
96     // also, we do not need to malloc free space every time
97     // we call a matrix constructor.
98 
99 
100     int shallow_; // set flag to '0' in order to return matrices
101     // by value from functions without unecessary
102     // copying.
103 
104 
105     // users shouldn't be able to modify assignment semantics..
106     //
107     //LaGenMatFloat& shallow_assign();
108 
109 public:
110 
111 
112 
113     /*::::::::::::::::::::::::::*/
114 
115     /* Constructors/Destructors */
116 
117     /*::::::::::::::::::::::::::*/
118 
119 
120     LaGenMatFloat();
121     LaGenMatFloat(int, int);
122 
123     /** Constructs an \f$m\times n\f$ matrix by using the values
124      * from the one-dimensional C array \c v of length \c m*n.
125      *
126      * \note If \c row_ordering is \c false, then the data will \e
127      * not be copied but instead the C array will be shared
128      * (shallow copy). In that case, you must not delete the C
129      * array as long as you use this newly created matrix. Also,
130      * if you need a copy (deep copy), construct one matrix \c A
131      * by this constructor, and then copy this content into a
132      * second matrix by \c B.copy(A). On the other hand, if \c
133      * row_ordering is \c true, then the data will be copied
134      * immediately (deep copy).
135      *
136      * \param v The one-dimensional C array of size \c m*n whose
137      * data should be used. If \c row_ordering is \c false, then
138      * the data will \e not be copied but shared (shallow
139      * copy). If \c row_ordering is \c true, then the data will be
140      * copied (deep copy).
141      *
142      * \param m The number of rows in the new matrix.
143      *
144      * \param n The number of columns in the new matrix.
145      *
146      * \param row_ordering If \c false, then the C array is used
147      * in column-order, i.e. the first \c m elements of \c v are
148      * used as the first column of the matrix, the next \c m
149      * elements are the second column and so on. (This is the
150      * default and this is also the internal storage format in
151      * order to be compatible with the underlying Fortran
152      * subroutines.) If this is \c true, then the C array is used
153      * in row-order, i.e. the first \c n elements of \c v are used
154      * as the first row of the matrix, the next \c n elements are
155      * the second row and so on. (Internally, this is achieved by
156      * allocating a new copy of the array and copying the array
157      * into the internal ordering.)
158      */
159     LaGenMatFloat(float* v, int m, int n, bool row_ordering = false);
160 
161     /** Create a new matrix from an existing one by copying.
162      *
163      * Watch out! Due to the C++ "named return value optimization"
164      * you cannot use this as an alias for copy() when declaring a
165      * variable if the right-side is a return value of
166      * operator(). More precisely, you cannot write the following:
167      * \verbatim
168      LaGenMatFloat x( y(LaIndex(),LaIndex()) ); // erroneous reference copy!
169      \endverbatim
170      *
171      * Instead, if the initialization should create a new copy of
172      * the right-side matrix, you have to write it this way:
173      * \verbatim
174      LaGenMatFloat x( y(LaIndex(),LaIndex()).copy() ); // correct deep-copy
175      \endverbatim
176      *
177      * Or this way:
178      * \verbatim
179      LaGenMatFloat x;
180      x = y(LaIndex(),LaIndex()); // correct deep-copy
181      \endverbatim
182      */
183     LaGenMatFloat(const LaGenMatFloat&);
184     virtual ~LaGenMatFloat();
185 
186 
187     /** @name Information Predicates */
188     //@{
189     /** Returns true if this is an all-zero matrix. (New in
190      * lapackpp-2.4.5) */
191     bool is_zero() const;
192 
193     /** Returns true if this matrix is only a submatrix view of
194      * another (larger) matrix. (New in lapackpp-2.4.4) */
is_submatrixview()195     bool is_submatrixview() const
196     {
197         return size(0) != gdim(0) || size(1) != gdim(1);
198     };
199 
200     /** Returns true if this matrix has unit stride.
201      *
202      * This is a necessary condition for not being a submatrix
203      * view, but it's not sufficient. (New in lapackpp-2.4.4) */
has_unitstride()204     bool has_unitstride() const
205     {
206         return inc(0) == 1 && inc(1) == 1;
207     };
208 
209     /** Returns true if the given matrix \c mat is exactly equal
210      * to this object. (New in lapackpp-2.4.5) */
211     bool equal_to(const matrix_type& mat) const;
212     //@}
213 
214 
215     /*::::::::::::::::::::::::::::::::*/
216 
217     /*  Indices and access operations */
218 
219     /*::::::::::::::::::::::::::::::::*/
220 
221     inline int size(int d) const;   // submatrix size
222     /** Returns the number of columns, i.e. for a M x N matrix
223      * this returns N. New in lapackpp-2.4.4. */
cols()224     inline int cols() const
225     {
226         return size(1);
227     }
228     /** Returns the number of rows, i.e. for a M x N matrix this
229      * returns M. New in lapackpp-2.4.4. */
rows()230     inline int rows() const
231     {
232         return size(0);
233     }
234     inline int inc(int d) const;    // explicit increment
235     inline int gdim(int d) const;   // global dimensions
236     inline int start(int d) const;  // return ii[d].start()
237     inline int end(int d) const;    // return ii[d].end()
238     inline LaIndex index(int d) const;// index
239     inline int ref_count() const;
240     inline LaGenMatFloat& shallow_assign();
241     inline float* addr() const;       // begining addr of data space
242 
243     inline float& operator()(int i, int j);
244     inline const float& operator()(int i, int j) const;
245     LaGenMatFloat operator()(const LaIndex& I, const LaIndex& J) ;
246     LaGenMatFloat operator()(const LaIndex& I, const LaIndex& J) const;
247     /** Returns a submatrix view for the specified row \c k of
248      * this matrix.
249      *
250      * The returned object references still the same memory as
251      * this object, so if you modify elements, they will appear
252      * modified in both objects.  (New in lapackpp-2.4.6) */
253     LaGenMatFloat row(int k);
254     /** Returns a submatrix view for the specified row \c k of
255      * this matrix.
256      *
257      * The returned object references still the same memory as
258      * this object, so if you modify elements, they will appear
259      * modified in both objects.  (New in lapackpp-2.4.6) */
260     LaGenMatFloat row(int k) const;
261     /** Returns a submatrix view for the specified column \c k
262      * of this matrix.
263      *
264      * The returned object references still the same memory as
265      * this object, so if you modify elements, they will appear
266      * modified in both objects.  (New in lapackpp-2.4.6) */
267     LaGenMatFloat col(int k);
268     /** Returns a submatrix view for the specified column \c k
269      * of this matrix.
270      *
271      * The returned object references still the same memory as
272      * this object, so if you modify elements, they will appear
273      * modified in both objects.  (New in lapackpp-2.4.6) */
274     LaGenMatFloat col(int k) const;
275 
276     LaGenMatFloat& operator=(float s);
277     /** Release left-hand side (reclaiming memory space if
278      * possible) and copy elements of elements of \c s. Unline \c
279      * inject(), it does not require conformity, and previous
280      * references of left-hand side are unaffected.
281      *
282      * This is an alias for copy().
283      *
284      * Watch out! Due to the C++ "named return value optimization"
285      * you cannot use this as an alias for copy() when declaring a
286      * variable if the right-side is a return value of
287      * operator(). More precisely, you cannot write the following:
288      * \verbatim
289      LaGenMatFloat x = y(LaIndex(),LaIndex()); // erroneous reference copy!
290      \endverbatim
291      *
292      * Instead, if the initialization should create a new copy of
293      * the right-side matrix, you have to write it this way:
294      * \verbatim
295      LaGenMatFloat x = y(LaIndex(),LaIndex()).copy(); // correct deep-copy
296      \endverbatim
297      *
298      * Or this way:
299      * \verbatim
300      LaGenMatFloat x;
301      x = y(LaIndex(),LaIndex()); // correct deep-copy
302      \endverbatim
303      *
304      * Note: The manual for lapack++-1.1 claimed that this
305      * operator would be an alias for ref(), not for copy(),
306      * i.e. this operator creates a reference instead of a deep
307      * copy. However, since that confused many people, the
308      * behaviour was changed so that B=A will now create B as a
309      * deep copy instead of a reference. If you want a
310      * reference, please write B.ref(A) explicitly.
311      */
312     LaGenMatFloat& operator=(const LaGenMatFloat& s); //copy
313 
314     LaGenMatFloat& operator+=(float s);
315     LaGenMatFloat& add(float s);
316 
317     LaGenMatFloat& resize(int m, int n);
318     LaGenMatFloat& resize(const LaGenMatFloat& s);
319     LaGenMatFloat& ref(const LaGenMatFloat& s);
320     LaGenMatFloat& inject(const LaGenMatFloat& s);
321     LaGenMatFloat& copy(const LaGenMatFloat& s);
322 
323     /** Returns a newly allocated matrix that is an
324      * element-by-element copy of this matrix.
325      *
326      * New in lapackpp-2.5.2 */
327     LaGenMatFloat copy() const;
328 
329     /** @name Expensive access functions */
330     //@{
331     /** Returns a newly allocated large matrix that consists of
332      * \c M-by-N copies of the given matrix. (New in
333      * lapackpp-2.4.5.) */
334     matrix_type repmat (int M, int N) const;
335     /** Returns the trace, i.e. the sum of all diagonal elements
336      * of the matrix. (New in lapackpp-2.4.5) */
337     value_type trace () const;
338     /** Returns a newly allocated column vector of dimension \c
339      * Nx1 that contains the diagonal of the given matrix. (New
340      * in lapackpp-2.4.5) */
341     matrix_type diag () const;
342     //@}
343 
344 
shallow()345     inline int shallow() const      // read global shallow flag
346     {
347         return shallow_;
348     }
349     inline int debug() const;       // read global debug flag
350     inline int debug(int d);        // set global debug flag
info()351     inline const LaGenMatFloat& info() const
352     {
353         int *t = info_;
354         *t = 1;
355         return *this;
356     };
357 
358     //* I/O *//
359     friend DLLIMPORT std::ostream& operator<<(std::ostream&, const LaGenMatFloat&);
Info(std::ostream & s)360     std::ostream& Info(std::ostream& s) const
361     {
362         s << "Size: (" << size(0) << "x" << size(1) << ") " ;
363         s << "Indeces: " << ii[0] << " " << ii[1];
364         s << "#ref: " << ref_count() << "addr: " << addr() << std::endl;
365         return s;
366     };
367 
368     /** @name Matrix type conversions */
369     //@{
370     /** Convert this matrix to a complex matrix with imaginary part zero. */
371     LaGenMatComplex to_LaGenMatComplex() const;
372     /** Convert this matrix to a double (floating-point double precision) matrix. */
373     LaGenMatDouble to_LaGenMatDouble() const;
374     /** Convert this matrix to an int matrix. */
375     LaGenMatInt to_LaGenMatInt() const;
376     /** Convert this matrix to a long int matrix. */
377     LaGenMatLongInt to_LaGenMatLongInt() const;
378     //@}
379 
380 
381     /** @name Constructors for elementary matrices */
382     //@{
383     /** Returns a newly allocated all-zero matrix of dimension
384      * \c NxN, if \c M is not given, or \c NxM if \c M is given.
385      * (New in lapackpp-2.4.5) */
386     static matrix_type zeros (int N, int M = 0);
387     /** Returns a newly allocated all-one matrix of dimension \c
388      * NxN, if \c M is not given, or \c NxM if \c M is given.
389      * (New in lapackpp-2.4.5) */
390     static matrix_type ones (int N, int M = 0);
391     /** Returns a newly allocated identity matrix of dimension
392      * \c NxN, if \c M is not given, or a rectangular matrix \c
393      * NxM if \c M is given.  (New in lapackpp-2.4.5) */
394     static matrix_type eye (int N, int M = 0);
395     /** Returns a newly allocated matrix of dimension \c NxM
396      * with pseudo-random values. The values are uniformly
397      * distributed in the interval \c (0,1) or, if specified, \c
398      * (low,high).  (New in lapackpp-2.4.5)
399      *
400      * Note: Since this uses the system's \c rand() call, the
401      * randomness of the values might be questionable -- don't
402      * use this if you need really strong random numbers. */
403     static matrix_type rand (int N, int M,
404                              value_type low = 0, value_type high = 1);
405     /** Returns a newly allocated diagonal matrix of dimension
406      * \c NxN that has the vector \c vect of length \c N on the
407      * diagonal.  (New in lapackpp-2.4.5) */
408     static matrix_type from_diag (const matrix_type &vect);
409     /** Returns a newly allocated linarly spaced column vector
410      * with \c nr_points elements, between and including \c
411      * start and \c end. (New in lapackpp-2.4.5.) */
412     static matrix_type linspace (value_type start, value_type end,
413                                  int nr_points);
414     //@}
415 
416 };  //* End of LaGenMatFloat Class *//
417 
418 
419 namespace la
420 {
421 /** The matrix data type containing (single-precision) \c float
422     values. */
423 typedef LaGenMatFloat fmat;
424 } // namespace
425 
426 /** Print the matrix to the given output stream. If the matrix
427  * info flag is set, then this prints only the matrix info,
428  * see LaGenMatDouble::info(). Otherwise all matrix elements
429  * are printed.
430  *
431  * \see LaPreferences::setPrintFormat()
432  */
433 DLLIMPORT
434 std::ostream& operator<<(std::ostream&, const LaGenMatFloat&);
435 
436 
437 
438 //* Member Functions *//
439 
440 
441 
size(int d)442 inline int LaGenMatFloat::size(int d) const
443 {
444     return sz[d];
445 }
446 
inc(int d)447 inline int LaGenMatFloat::inc(int d) const
448 {
449     return ii[d].inc();
450 }
451 
gdim(int d)452 inline int LaGenMatFloat::gdim(int d) const
453 {
454     return dim[d];
455 }
456 
start(int d)457 inline int LaGenMatFloat::start(int d) const
458 {
459     return ii[d].start();
460 }
461 
end(int d)462 inline int LaGenMatFloat::end(int d) const
463 {
464     return ii[d].end();
465 }
466 
ref_count()467 inline int LaGenMatFloat::ref_count() const
468 {
469     return v.ref_count();
470 }
471 
472 
index(int d)473 inline LaIndex LaGenMatFloat::index(int d)  const
474 {
475     return ii[d];
476 }
477 
addr()478 inline float* LaGenMatFloat::addr() const
479 {
480     return  v.addr();
481 }
482 
debug()483 inline int LaGenMatFloat::debug() const
484 {
485     return debug_;
486 }
487 
debug(int d)488 inline int LaGenMatFloat::debug(int d)
489 {
490     return debug_ = d;
491 }
492 
operator()493 inline float& LaGenMatFloat::operator()(int i, int j)
494 {
495 
496 #ifdef LA_BOUNDS_CHECK
497     assert(i >= 0);
498     assert(i < size(0));
499     assert(j >= 0);
500     assert(j < size(1));
501 #endif
502     return v( dim[0] * (ii[1].start() + j * ii[1].inc()) +
503               ii[0].start() + i * ii[0].inc());
504 }
505 
operator()506 inline const float& LaGenMatFloat::operator()(int i, int j) const
507 {
508 
509 #ifdef LA_BOUNDS_CHECK
510     assert(i >= 0);
511     assert(i < size(0));
512     assert(j >= 0);
513     assert(j < size(1));
514 #endif
515 
516     return v( dim[0] * (ii[1].start() + j * ii[1].inc()) +
517               ii[0].start() + i * ii[0].inc());
518 }
519 
520 
521 
522 
shallow_assign()523 inline  LaGenMatFloat&  LaGenMatFloat::shallow_assign()
524 {
525     shallow_ = 1;
526     return *this;
527 }
528 
529 
530 
531 
532 
533 #endif
534 // _LA_GEN_MAT_H_
535