1 // Copyright (C) 2007-2015 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : Anthony Geay
21 #include "MEDCouplingMatrix.hxx"
23 #include "InterpKernelMatrixTools.hxx"
25 using namespace ParaMEDMEM;
27 DenseMatrix *DenseMatrix::New(int nbRows, int nbCols)
29 return new DenseMatrix(nbRows,nbCols);
32 DenseMatrix *DenseMatrix::New(DataArrayDouble *array, int nbRows, int nbCols)
34 return new DenseMatrix(array,nbRows,nbCols);
37 DenseMatrix *DenseMatrix::deepCpy() const
39 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(getData()->deepCpy());
40 MEDCouplingAutoRefCountObjectPtr<DenseMatrix> ret(DenseMatrix::New(arr,getNumberOfRows(),getNumberOfCols()));
44 DenseMatrix *DenseMatrix::shallowCpy() const
46 MEDCouplingAutoRefCountObjectPtr<DenseMatrix> ret(DenseMatrix::New(const_cast<DataArrayDouble *>(getData()),getNumberOfRows(),getNumberOfCols()));
50 std::size_t DenseMatrix::getHeapMemorySizeWithoutChildren() const
52 return sizeof(DenseMatrix);
55 std::vector<const BigMemoryObject *> DenseMatrix::getDirectChildrenWithNull() const
57 std::vector<const BigMemoryObject *> ret;
58 ret.push_back((const DataArrayDouble *)_data);
62 void DenseMatrix::updateTime() const
64 const DataArrayDouble *pt(_data);
70 * This method scratch \a this to use a new input. The shape of \a this can be modified freely without any constraints.
72 * \param [in] array - The array containing data that is expected to be taken as new data.
73 * \param [in] nbRows - The new number of rows (>0 or -1). If -1, the current number of rows will be taken.
74 * \param [in] nbCols - The new number of columns (>0 or -1). If -1, the current number of cols will be taken.
78 void DenseMatrix::reBuild(DataArrayDouble *array, int nbRows, int nbCols)
80 int nbr(getNumberOfRowsExt(nbRows)),nbc(getNumberOfColsExt(nbCols));
81 CheckArraySizes(array,nbr,nbc);
82 DataArrayDouble *data(_data);
85 _data=array; _data->incrRef();
101 * This method does \b not change the content of the data in \a this. It only changes the shape (with a same number of elements in the matrix).
102 * If the number of elements needs to be changed call reBuild method instead.
104 * \param [in] nbRows - The new number of rows (>0)
105 * \param [in] nbCols - The new number of columns (>0)
106 * \throw if the \c nbRows*nbCols is not equal to \c this->getNbOfElems()
109 void DenseMatrix::reShape(int nbRows, int nbCols)
111 if(nbRows<0 || nbCols<0)
112 throw INTERP_KERNEL::Exception("DenseMatrix::reShape : number of rows and number of cols must be > 0 both !");
113 if(nbRows*nbCols!=getNbOfElems())
114 throw INTERP_KERNEL::Exception("DenseMatrix::reShape : This method is designed to change only the shape ! Number of elements must remain the same !");
127 void DenseMatrix::transpose()
129 const MemArray<double>& mem(getData()->accessToMemArray());
130 double *pt(mem.toNoInterlace(getNumberOfCols()));
131 std::copy(pt,pt+getNbOfElems(),getData()->getPointer());//declareAsNew done here automatically by getPointer
133 std::swap(_nb_rows,_nb_cols);
137 bool DenseMatrix::isEqual(const DenseMatrix& other, double eps) const
140 return isEqualIfNotWhy(other,eps,tmp);
143 bool DenseMatrix::isEqualIfNotWhy(const DenseMatrix& other, double eps, std::string& reason) const
145 if(_nb_rows!=other._nb_rows)
147 std::ostringstream oss; oss << "Number of rows differs (" << _nb_rows << "!=" << other._nb_rows << ") !";
151 if(_nb_cols!=other._nb_cols)
153 std::ostringstream oss; oss << "Number of cols differs (" << _nb_cols << "!=" << other._nb_cols << ") !";
158 if(!_data->isEqualIfNotWhy(*other._data,eps,tmp1))
160 reason+="Data differs : "+tmp1;
166 DataArrayDouble *DenseMatrix::matVecMult(const DataArrayDouble *vec) const
168 return MatVecMult(this,vec);
171 DataArrayDouble *DenseMatrix::MatVecMult(const DenseMatrix *mat, const DataArrayDouble *vec)
174 throw INTERP_KERNEL::Exception("DenseMatrix::MatVecMult : input matrix or vec is NULL !");
175 vec->checkAllocated();
176 if(vec->getNumberOfComponents()!=1)
177 throw INTERP_KERNEL::Exception("DenseMatrix::MatVecMult : input vector must have only one component !");
178 if(vec->getNumberOfTuples()!=mat->getNumberOfCols())
179 throw INTERP_KERNEL::Exception("DenseMatrix::MatVecMult : Number of columns of this must be equal to number of tuples of vec !");
180 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(mat->getNumberOfRows(),1);
181 INTERP_KERNEL::matrixProduct(mat->getData()->begin(),mat->getNumberOfRows(),mat->getNumberOfCols(),vec->begin(),vec->getNumberOfTuples(),1,ret->getPointer());
185 DenseMatrix *DenseMatrix::Add(const DenseMatrix *a1, const DenseMatrix *a2)
188 throw INTERP_KERNEL::Exception("DenseMatrix::Add : input matrices must be not NULL !");
189 CheckSameSize(a1,a2);
190 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> data(DataArrayDouble::Add(a1->getData(),a2->getData()));
191 MEDCouplingAutoRefCountObjectPtr<DenseMatrix> ret(DenseMatrix::New(data,a1->getNumberOfRows(),a1->getNumberOfCols()));
195 void DenseMatrix::addEqual(const DenseMatrix *other)
198 throw INTERP_KERNEL::Exception("DenseMatrix::addEqual : other must be not NULL !");
199 CheckSameSize(this,other);
200 getData()->addEqual(other->getData());
203 DenseMatrix *DenseMatrix::Substract(const DenseMatrix *a1, const DenseMatrix *a2)
206 throw INTERP_KERNEL::Exception("DenseMatrix::Substract : input matrices must be not NULL !");
207 CheckSameSize(a1,a2);
208 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> data(DataArrayDouble::Substract(a1->getData(),a2->getData()));
209 MEDCouplingAutoRefCountObjectPtr<DenseMatrix> ret(DenseMatrix::New(data,a1->getNumberOfRows(),a1->getNumberOfCols()));
213 void DenseMatrix::substractEqual(const DenseMatrix *other)
216 throw INTERP_KERNEL::Exception("DenseMatrix::substractEqual : other must be not NULL !");
217 CheckSameSize(this,other);
218 getData()->substractEqual(other->getData());
221 DenseMatrix *DenseMatrix::Multiply(const DenseMatrix *a1, const DenseMatrix *a2)
224 throw INTERP_KERNEL::Exception("DenseMatrix::Multiply : input matrices must be not NULL !");
225 CheckCompatibleSizeForMul(a1,a2);
226 int nbr(a1->getNumberOfRows()),nbc(a2->getNumberOfCols());
227 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> data(DataArrayDouble::New()); data->alloc(nbr*nbc,1);
228 MEDCouplingAutoRefCountObjectPtr<DenseMatrix> ret(DenseMatrix::New(data,a1->getNumberOfRows(),a2->getNumberOfCols()));
229 INTERP_KERNEL::matrixProduct(a1->getData()->begin(),a1->getNumberOfRows(),a1->getNumberOfCols(),a2->getData()->begin(),a2->getNumberOfRows(),a2->getNumberOfCols(),data->getPointer());
233 DenseMatrix *DenseMatrix::Multiply(const DenseMatrix *a1, const DataArrayDouble *a2)
235 if(!a1 || !a2 || !a2->isAllocated())
236 throw INTERP_KERNEL::Exception("DenseMatrix::Multiply #2 : input matrices must be not NULL and a2 allocated !");
237 if(a2->getNumberOfComponents()!=1)
238 throw INTERP_KERNEL::Exception("DenseMatrix::Multiply #2 : The 2nd member must have exactly one component !");
239 MEDCouplingAutoRefCountObjectPtr<DenseMatrix> a2Bis(DenseMatrix::New(const_cast<DataArrayDouble *>(a2),a2->getNumberOfTuples(),1));
240 return DenseMatrix::Multiply(a1,a2Bis);
243 DenseMatrix::~DenseMatrix()
247 DenseMatrix::DenseMatrix(int nbRows, int nbCols):_nb_rows(nbRows),_nb_cols(nbCols),_data(DataArrayDouble::New())
249 if(_nb_rows<0 || _nb_cols<0)
250 throw INTERP_KERNEL::Exception("constructor of DenseMatrix : number of rows and number of cols must be > 0 both !");
251 int nbOfTuples(_nb_rows*_nb_cols);
252 _data->alloc(nbOfTuples,1);
255 DenseMatrix::DenseMatrix(DataArrayDouble *array, int nbRows, int nbCols):_nb_rows(nbRows),_nb_cols(nbCols)
257 CheckArraySizes(array,_nb_rows,_nb_cols);
258 _data=array; _data->incrRef();
261 int DenseMatrix::getNumberOfRowsExt(int nbRows) const
264 throw INTERP_KERNEL::Exception("DenseMatrix::getNumberOfRowsExt : invalid input must be >= -1 !");
271 int DenseMatrix::getNumberOfColsExt(int nbCols) const
274 throw INTERP_KERNEL::Exception("DenseMatrix::getNumberOfColsExt : invalid input must be >= -1 !");
281 void DenseMatrix::checkValidData() const
284 throw INTERP_KERNEL::Exception("DenseMatrix::checkValidData : data is NULL !");
285 if(!getData()->isAllocated())
286 throw INTERP_KERNEL::Exception("DenseMatrix::checkValidData : data is not allocated !");
287 if(getData()->getNumberOfComponents()!=1)
288 throw INTERP_KERNEL::Exception("DenseMatrix::checkValidData : data has not 1 component !");
291 void DenseMatrix::CheckArraySizes(DataArrayDouble *array, int nbRows, int nbCols)
293 if(nbRows<0 || nbCols<0)
294 throw INTERP_KERNEL::Exception("constructor #2 of DenseMatrix : number of rows and number of cols must be > 0 both !");
295 if(!array || !array->isAllocated())
296 throw INTERP_KERNEL::Exception("constructor #2 of DenseMatrix : input array is empty or not allocated !");
297 if(array->getNumberOfComponents()!=1)
298 throw INTERP_KERNEL::Exception("constructor #2 of DenseMatrix : input array must have exactly one component !");
299 std::size_t nbr((std::size_t)nbRows),nbc((std::size_t)nbCols);
300 if(nbr*nbc!=array->getNbOfElems())
301 throw INTERP_KERNEL::Exception("constructor #2 of DenseMatrix : the number of elems in input array is not equal to the product of nbRows and nbCols !");
304 void DenseMatrix::CheckSameSize(const DenseMatrix *a1, const DenseMatrix *a2)
307 throw INTERP_KERNEL::Exception("DenseMatrix::CheckSameSize : a1 or a2 is NULL !");
308 a1->checkValidData(); a2->checkValidData();
309 if(a1->getNumberOfRows()!=a2->getNumberOfRows())
310 throw INTERP_KERNEL::Exception("DenseMatrix::CheckSameSize : number of rows mismatches !");
311 if(a1->getNumberOfCols()!=a2->getNumberOfCols())
312 throw INTERP_KERNEL::Exception("DenseMatrix::CheckSameSize : number of columns mismatches !");
316 void DenseMatrix::CheckCompatibleSizeForMul(const DenseMatrix *a1, const DenseMatrix *a2)
319 throw INTERP_KERNEL::Exception("DenseMatrix::CheckCompatibleSizeForMul : a1 or a2 is NULL !");
320 a1->checkValidData(); a2->checkValidData();
321 if(a1->getNumberOfCols()!=a2->getNumberOfRows())
322 throw INTERP_KERNEL::Exception("DenseMatrix::CheckCompatibleSizeForMul : number of cols of a1 must be equal to number of rows of a2 !");