Herezh_dev/Resolin/Matrices_externes/MV++/mvmtp_GR.h
2023-05-03 17:23:49 +02:00

426 lines
13 KiB
C++
Executable file

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/* */
/* */
/* MV++ Numerical Matrix/Vector C++ Library */
/* MV++ Version 1.5 */
/* */
/* R. Pozo */
/* National Institute of Standards and Technology */
/* */
/* NOTICE */
/* */
/* Permission to use, copy, modify, and distribute this software and */
/* its documentation for any purpose and without fee is hereby granted */
/* provided that this permission notice appear in all copies and */
/* supporting documentation. */
/* */
/* Neither the Institution (National Institute of Standards and Technology) */
/* nor the author makes any representations about the suitability of this */
/* software for any purpose. This software is provided ``as is''without */
/* expressed or implied warranty. */
/* */
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
//
// mvmtp.h : basic templated numerical matrix class, storage
// by columns (Fortran oriented.)
//
//
//
// modif gérard RIO
// - déplacement de la surcharge d'écriture directement dans la classe (sinon pb
// avec code warrior)
// - modification de l'indice du type unsigned int au type int et vérification
// du nombre négatif
#ifndef _MV_MATRIX_H_
#define _MV_MATRIX_H_
#include "mvvtp_GR.h"
struct Matrix_
{
enum ref_type { ref = 1 };
};
#include <iostream> // for formatted printing of matrices
#ifdef MV_MATRIX_BOUNDS_CHECK
# include <assert.h>
#endif
template <class TYPE>
class MV_ColMat
{
private:
MV_Vector<TYPE> v_;
int dim0_; // perferred to using dim_[2]. some compilers
int dim1_; // refuse to initalize these in the constructor.
int lda_;
int ref_; // true if this is declared as a reference vector,
// i.e. it does not own the memory space, but
// rather it is a view to another vector or array.
public:
/*::::::::::::::::::::::::::*/
/* Constructors/Destructors */
/*::::::::::::::::::::::::::*/
MV_ColMat();
MV_ColMat( int, int);
// some compilers have difficulty with inlined 'for' statements.
MV_ColMat( int, int, const TYPE&);
// usual copy by value
// (can't use default parameter lda=m, because m is not a constant...)
//
MV_ColMat(TYPE*, int m, int n);
MV_ColMat(TYPE*, int m, int n, int lda);
// the "reference" versions
//
//
MV_ColMat(TYPE*, int m, int n, Matrix_::ref_type i);
MV_ColMat(TYPE*, int m, int n, int lda,
Matrix_::ref_type i);
MV_ColMat(const MV_ColMat<TYPE>&);
~MV_ColMat();
/*::::::::::::::::::::::::::::::::*/
/* Indices and access operations */
/*::::::::::::::::::::::::::::::::*/
inline TYPE& operator()( int, int);
inline const TYPE& operator()( int, int) const;
MV_ColMat<TYPE> operator()(const MV_VecIndex &I, const MV_VecIndex &J) ;
const MV_ColMat<TYPE> operator()(const MV_VecIndex &I, const MV_VecIndex &J) const;
int size(int i) const;
MV_ColMat<TYPE>& newsize( int, int);
int ref() const { return ref_;}
/*::::::::::::::*/
/* Assignment */
/*::::::::::::::*/
MV_ColMat<TYPE> & operator=(const MV_ColMat<TYPE>&);
MV_ColMat<TYPE> & operator=(const TYPE&);
friend ostream& operator<<(ostream &s, const MV_ColMat<TYPE> &V)
{
int M = V.size(0);
int N = V.size(1);
for (int i=0; i<M; i++)
{
for (int j=0; j<N; j++)
s << V(i,j) << " " ;
s << endl;
}
return s;
}
};
template<class TYPE>
int MV_ColMat<TYPE>::size(int i) const
{
if (i==0) return dim0_;
if (i==1) return dim1_;
else
{
cerr << "Called MV_ColMat::size(" << i << ") must be 0 or 1 " << endl;
Sortie(1);
}
// never should be here, but many compilers warn about not
// returning a value
return 0;
}
// NOTE: null construct have ref_ flag turned OFF, otherwise, we can
// never reset the size of matrix....
template <class TYPE>
MV_ColMat<TYPE>::MV_ColMat() : v_(), dim0_(0), dim1_(0) , lda_(0), ref_(0){}
template <class TYPE>
MV_ColMat<TYPE>::MV_ColMat( int m, int n) : v_(m*n),
dim0_(m), dim1_(n), lda_(m), ref_(0)
{
# ifdef MV_MATRIX_BOUNDS_CHECK
assert((n >= 0)&& (m>=0)); // modif GR
# endif
}
template <class TYPE>
MV_ColMat<TYPE>::MV_ColMat( int m, int n, const TYPE &s) : v_(m*n),
dim0_(m), dim1_(n), lda_(m), ref_(0)
{
operator=(s);
# ifdef MV_MATRIX_BOUNDS_CHECK
assert((n >= 0)&& (m>=0)); // modif GR
# endif
}
// operators and member functions
template <class TYPE>
inline TYPE& MV_ColMat<TYPE>::operator()( int i, int j)
{
#ifdef MV_MATRIX_BOUNDS_CHECK
assert(0<=i && i<size(0));
assert(0<=j && j<size(1));
#endif
return v_(j*lda_ + i); // could use indirect addressing
// instead...
}
template <class TYPE>
inline const TYPE& MV_ColMat<TYPE>::operator()
( int i, int j) const
{
#ifdef MV_MATRIX_BOUNDS_CHECK
assert(0<=i && i<size(0));
assert(0<=j && j<size(1));
#endif
return v_(j*lda_ + i);
}
template <class TYPE>
MV_ColMat<TYPE>& MV_ColMat<TYPE>::operator=(const TYPE & s)
{
int M = size(0);
int N = size(1);
if (lda_ == M) // if continuous, then just assign as a ?
v_ = s; // single long vector.
else
{
// this should run much faster than the just accessing each (i,j)
// element individually
//
MV_VecIndex I(0,M-1);
for (int j=0; j<N; j++)
{
v_(I) = s;
I += lda_;
}
}
return *this;
}
template <class TYPE>
MV_ColMat<TYPE>& MV_ColMat<TYPE>::newsize( int M, int N)
{
# ifdef MV_MATRIX_BOUNDS_CHECK
assert((N >= 0)&& (M>=0)); // modif GR
# endif
v_.newsize(M*N);
dim0_ = M;
dim1_ = N;
lda_ = M;
return *this;
}
template <class TYPE>
MV_ColMat<TYPE>& MV_ColMat<TYPE>::operator=(const MV_ColMat<TYPE> & m)
{
int lM = dim0_; // left hand arg (this)
int lN = dim1_;
int rM = m.dim0_; // right hand arg (m)
int rN = m.dim1_;
// if the left-hand side is a matrix reference, the we copy the
// elements of m *into* the region specfied by the reference.
// i.e. inject().
if (ref_)
{
// check conformance,
if (lM != rM || lN != rN)
{
cerr << "MV_ColMatRef::operator= non-conformant assignment.\n";
Sortie(1);
}
}
else
{
newsize(rM,rN);
}
// at this point the left hand and right hand sides are conformant
// this should run much faster than the just accessing each (i,j)
// element individually
// if both sides are contigous, then just copy as one vector
if ( lM == lda_ && rM == m.lda_)
{
MV_VecIndex I(0,rM*rN-1);
v_(I) = m.v_(I);
}
else
{
// slower way...
MV_VecIndex I(0,rM-1);
MV_VecIndex K(0,rM-1);
for (int j=0; j<rN; j++)
{
v_(I) = m.v_(K);
I += lda_;
K += m.lda_;
}
}
return *this;
}
template <class TYPE>
MV_ColMat<TYPE>::MV_ColMat(const MV_ColMat<TYPE> & m) :
v_(m.dim0_*m.dim1_), dim0_(m.dim0_),
dim1_(m.dim1_), ref_(0), lda_(m.dim0_)
{
int M = m.dim0_;
int N = m.dim1_;
// this should run much faster than the just accessing each (i,j)
// element individually
MV_VecIndex I(0,M-1);
MV_VecIndex K(0,M-1);
for (int j=0; j<N; j++)
{
v_(I) = m.v_(K);
I += lda_;
K += m.lda_;
}
}
template <class TYPE>
inline MV_ColMat<TYPE>::MV_ColMat(TYPE* d, int m, int n,
Matrix_::ref_type i ):
v_(d,m*n, MV_Vector_::ref), dim0_(m), dim1_(n), lda_(m), ref_(i)
{
# ifdef MV_MATRIX_BOUNDS_CHECK
assert((n >= 0)&& (m>=0)); // modif GR
# endif
}
template <class TYPE>
inline MV_ColMat<TYPE>::MV_ColMat(TYPE* d, int m, int n,
int lda, Matrix_::ref_type i) :
v_(d, lda*n, MV_Vector_::ref), dim0_(m), dim1_(n), lda_(lda),
ref_(i)
{
# ifdef MV_MATRIX_BOUNDS_CHECK
assert((n >= 0)&& (m>=0)&&(lda>=0)); // modif GR
# endif
}
template <class TYPE>
MV_ColMat<TYPE>::MV_ColMat(TYPE* d, int m, int n) :
v_(m*n), dim0_(m), dim1_(n), lda_(m), ref_(0)
{
# ifdef MV_MATRIX_BOUNDS_CHECK
assert((n >= 0)&& (m>=0)); // modif GR
# endif
int mn = m*n;
// d is contiguous, so just copy 1-d vector
for (int i=0; i< mn; i++)
v_[i] = d[i];
}
template <class TYPE>
MV_ColMat<TYPE>::MV_ColMat(TYPE* d, int m, int n,
int lda) :
v_(m*n), dim0_(m), dim1_(n), lda_(lda), ref_(0)
{
# ifdef MV_MATRIX_BOUNDS_CHECK
assert((n >= 0)&& (m>=0)&&(lda>=0)); // modif GR
# endif
for (int j=0; j< n; j++)
for (int i=0; i<m; i++)
operator()(i,j) = d[j*lda + i]; // could be made faster!!
}
template <class TYPE>
MV_ColMat<TYPE> MV_ColMat<TYPE>::operator()(const MV_VecIndex &I, const MV_VecIndex &J)
{
// check that index is not out of bounds
//
if (I.end() >= dim0_ || J.end() >= dim1_)
{
cerr << "Matrix index: (" << I.start() << ":" << I.end()
<< "," << J.start() << ":" << J.end()
<< ") not a subset of (0:" << dim0_ - 1 << ", 0:"
<< dim1_-1 << ") " << endl;
Sortie(1);
}
// this automatically returns a reference
//
return MV_ColMat<TYPE>(&v_[J.start()*lda_ + I.start()],
I.end() - I.start() + 1,
J.end() - J.start() + 1, lda_, Matrix_::ref);
}
template <class TYPE>
const MV_ColMat<TYPE> MV_ColMat<TYPE>::operator()(const MV_VecIndex &I,
const MV_VecIndex &J) const
{
cerr << "Const operator()(MV_VecIndex, MV_VecIndex) called " << endl;
// check that index is not out of bounds
//
if (I.end() >= dim0_ || J.end() >= dim1_)
{
cerr << "Matrix index: (" << I.start() << ":" << I.end()
<< "," << J.start() << ":" << J.end()
<< ") not a subset of (0:" << dim0_ - 1 << ", 0:"
<< dim1_-1 << ") " << endl;
Sortie(1);
}
// this automatically returns a reference. we need to
// "cast away" constness here, so the &v_[] arg will
// not cause a compiler error.
//
MV_ColMat<TYPE> *t = (MV_ColMat<TYPE>*) this;
return MV_ColMat<TYPE>(&(t->v_[J.start()*lda_ + I.start()]),
I.end() - I.start() + 1,
J.end() - J.start() + 1, lda_, Matrix_::ref);
}
template <class TYPE>
MV_ColMat<TYPE>::~MV_ColMat() {}
#endif
// _MV_MATRIX_H_