matrix.hpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:24k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: matrix.hpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/04/16 15:28:41  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [CATCHUP_003] Dev-tree R1.6
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. #ifndef UTIL_MATH___MATRIX__HPP
  10. #define UTIL_MATH___MATRIX__HPP
  11. /*  $Id: matrix.hpp,v 1000.1 2004/04/16 15:28:41 gouriano Exp $
  12.  * ===========================================================================
  13.  *
  14.  *                            PUBLIC DOMAIN NOTICE
  15.  *               National Center for Biotechnology Information
  16.  *
  17.  *  This software/database is a "United States Government Work" under the
  18.  *  terms of the United States Copyright Act.  It was written as part of
  19.  *  the author's official duties as a United States Government employee and
  20.  *  thus cannot be copyrighted.  This software/database is freely available
  21.  *  to the public for use. The National Library of Medicine and the U.S.
  22.  *  Government have not placed any restriction on its use or reproduction.
  23.  *
  24.  *  Although all reasonable efforts have been taken to ensure the accuracy
  25.  *  and reliability of the software and data, the NLM and the U.S.
  26.  *  Government do not and cannot warrant the performance or results that
  27.  *  may be obtained by using this software or data. The NLM and the U.S.
  28.  *  Government disclaim all warranties, express or implied, including
  29.  *  warranties of performance, merchantability or fitness for any particular
  30.  *  purpose.
  31.  *
  32.  *  Please cite the author in any work or product based on this material.
  33.  *
  34.  * ===========================================================================
  35.  *
  36.  * Authors:  Mike DiCuccio
  37.  *
  38.  * File Description:
  39.  *
  40.  */
  41. #include <corelib/ncbistr.hpp>
  42. #include <util/math/promote.hpp>
  43. #include <vector>
  44. BEGIN_NCBI_SCOPE
  45. template <class T> class CNcbiMatrix;
  46. template <class T>
  47. class CNcbiMatrix
  48. {
  49. public:
  50.     typedef vector<T>                      TData;
  51.     typedef typename TData::iterator       iterator;
  52.     typedef typename TData::const_iterator const_iterator;
  53.     CNcbiMatrix();
  54.     CNcbiMatrix(size_t r, size_t c, T val = T(0));
  55.     // make this matrix an identity matrix of a given size
  56.     void Identity(size_t size);
  57.     // make this matrix an identity matrix
  58.     void Identity();
  59.     // make this matrix a diagonal matrix of a given size, with a given value
  60.     // on the diagonal
  61.     void Diagonal(size_t size, T val);
  62.     // make this matrix a diagonal matrix, with a given value on the diagonal
  63.     void Diagonal(T val);
  64.     // transpose this matrix
  65.     void Transpose();
  66.     // resize this matrix, filling the empty cells with a known value
  67.     void Resize(size_t i, size_t j, T val = T(0));
  68.     // swap two rows in the matrix
  69.     void SwapRows(size_t i, size_t j);
  70.     // get the number of rows in this matrix
  71.     size_t GetRows() const;
  72.     // get the number of columns in this matrix
  73.     size_t GetCols() const;
  74.     // retrieve the data associated with this matrix
  75.     TData&         GetData();
  76.     const TData&   GetData() const;
  77.     // iterators
  78.     iterator begin();
  79.     iterator end();
  80.     const_iterator begin() const;
  81.     const_iterator end() const;
  82.     // set all values in the matrix to a known value
  83.     void Set(T val);
  84.     // swap two matrices efficiently
  85.     void Swap(CNcbiMatrix<T>& M);
  86.     // operator[] for raw data indexing
  87.     const T&    operator[] (size_t i) const;
  88.     T&          operator[] (size_t i);
  89.     // operator() for row/column indexing
  90.     const T&    operator() (size_t i, size_t j) const;
  91.     T&          operator() (size_t i, size_t j);
  92. protected:
  93.     // the data strip we use
  94.     TData  m_Data;
  95.     // size of this matrix
  96.     size_t m_Rows;
  97.     size_t m_Cols;
  98. };
  99. ///
  100. /// global operators
  101. ///
  102. ///
  103. /// stream input.
  104. ///
  105. /// One line per row, with entries readable by successive calls
  106. /// to operator>>.  For doubles, this just means they're separated
  107. /// by whitespace.
  108. template <class T>
  109. inline CNcbiIstream&
  110. operator>> (CNcbiIstream& is, CNcbiMatrix<T>& M);
  111. ///
  112. /// stream output.
  113. ///
  114. /// One line per row, with entries separated by a single space
  115. template <class T>
  116. inline CNcbiOstream&
  117. operator<< (CNcbiOstream& os, const CNcbiMatrix<T>& M);
  118. ///
  119. /// global addition: matrix + matrix
  120. ///
  121. template <class T, class U>
  122. inline CNcbiMatrix< NCBI_PROMOTE(T,U) >
  123. operator+ (const CNcbiMatrix<T>&, const CNcbiMatrix<U>&);
  124. ///
  125. /// global subtraction: matrix - matrix
  126. ///
  127. template <class T, class U>
  128. inline CNcbiMatrix< NCBI_PROMOTE(T,U) >
  129. operator- (const CNcbiMatrix<T>&, const CNcbiMatrix<U>&);
  130. ///
  131. /// global multiplication: matrix * scalar
  132. /// this is a hack, as MSVC doesn't support partial template specialization
  133. /// we provide implementations for a number of popular types
  134. ///
  135. template <class T>
  136. inline CNcbiMatrix< NCBI_PROMOTE(T, size_t) >
  137. operator* (const CNcbiMatrix<T>&, size_t);
  138. template <class U>
  139. inline CNcbiMatrix< NCBI_PROMOTE(size_t, U) >
  140. operator* (size_t, const CNcbiMatrix<U>&);
  141. template <class T>
  142. inline CNcbiMatrix< NCBI_PROMOTE(T, float) >
  143. operator* (const CNcbiMatrix<T>&, float);
  144. template <class U>
  145. inline CNcbiMatrix< NCBI_PROMOTE(float, U) >
  146. operator* (float, const CNcbiMatrix<U>&);
  147. template <class T>
  148. inline CNcbiMatrix< NCBI_PROMOTE(T, double) >
  149. operator* (const CNcbiMatrix<T>&, double);
  150. template <class U>
  151. inline CNcbiMatrix< NCBI_PROMOTE(double, U) >
  152. operator* (double, const CNcbiMatrix<U>&);
  153. ///
  154. /// global multiplication: matrix * matrix
  155. ///
  156. template <class T, class U>
  157. inline CNcbiMatrix< NCBI_PROMOTE(T,U) >
  158. operator* (const CNcbiMatrix<T>&, const CNcbiMatrix<U>&);
  159. ///
  160. /// global multiplication: matrix * vector
  161. ///
  162. template <class T, class U>
  163. inline vector< NCBI_PROMOTE(T,U) >
  164. operator* (const CNcbiMatrix<T>&, const vector<U>&);
  165. ///
  166. /// global multiplication: vector * matrix
  167. ///
  168. template <class T, class U>
  169. inline vector< NCBI_PROMOTE(T,U) >
  170. operator* (const vector<T>&, const CNcbiMatrix<U>&);
  171. ///
  172. /// global addition: matrix += matrix
  173. ///
  174. template <class T, class U>
  175. inline CNcbiMatrix<T>&
  176. operator+= (CNcbiMatrix<T>&, const CNcbiMatrix<U>&);
  177. ///
  178. /// global subtraction: matrix -= matrix
  179. ///
  180. template <class T, class U>
  181. inline CNcbiMatrix<T>&
  182. operator-= (CNcbiMatrix<T>&, const CNcbiMatrix<U>&);
  183. ///
  184. /// global multiplication: matrix *= matrix
  185. ///
  186. template <class T, class U>
  187. inline CNcbiMatrix<T>&
  188. operator*= (CNcbiMatrix<T>&, const CNcbiMatrix<U>&);
  189. ///
  190. /// global multiplication: matrix *= vector
  191. ///
  192. template <class T, class U>
  193. inline vector<T>&
  194. operator*= (CNcbiMatrix<T>&, const vector<U>&);
  195. ///
  196. /// global multiplication: matrix *= scalar
  197. ///
  198. template <class T>
  199. inline CNcbiMatrix<T>&
  200. operator*= (CNcbiMatrix<T>&, T);
  201. ///
  202. /// global division: matrix /= matrix
  203. ///
  204. template <class T>
  205. inline CNcbiMatrix<T>&
  206. operator/= (CNcbiMatrix<T>&, T);
  207. ///
  208. /// global comparison: matrix == matrix
  209. ///
  210. template <class T, class U>
  211. inline bool
  212. operator== (const CNcbiMatrix<T>&, const CNcbiMatrix<U>&);
  213. ///
  214. /// global comparison: matrix != matrix
  215. ///
  216. template <class T, class U>
  217. inline bool
  218. operator!= (const CNcbiMatrix<T>&, const CNcbiMatrix<U>&);
  219. /////////////////////////////////////////////////////////////////////////////
  220. //
  221. // Inline Methods
  222. //
  223. ///
  224. /// default ctor
  225. template <class T>
  226. inline CNcbiMatrix<T>::CNcbiMatrix()
  227.     : m_Rows(0),
  228.       m_Cols(0)
  229. {
  230. }
  231. template <class T>
  232. inline CNcbiMatrix<T>::CNcbiMatrix(size_t r, size_t c, T val)
  233.     : m_Rows(r),
  234.       m_Cols(c)
  235. {
  236.     m_Data.resize(r*c, val);
  237. }
  238. template <class T>
  239. inline size_t CNcbiMatrix<T>::GetRows() const
  240. {
  241.     return m_Rows;
  242. }
  243. template <class T>
  244. inline size_t CNcbiMatrix<T>::GetCols() const
  245. {
  246.     return m_Cols;
  247. }
  248. template <class T>
  249. inline typename CNcbiMatrix<T>::TData& CNcbiMatrix<T>::GetData()
  250. {
  251.     return m_Data;
  252. }
  253. template <class T>
  254. inline const typename CNcbiMatrix<T>::TData& CNcbiMatrix<T>::GetData() const
  255. {
  256.     return m_Data;
  257. }
  258. template <class T>
  259. inline typename CNcbiMatrix<T>::iterator CNcbiMatrix<T>::begin()
  260. {
  261.     return m_Data.begin();
  262. }
  263. template <class T>
  264. inline typename CNcbiMatrix<T>::iterator CNcbiMatrix<T>::end()
  265. {
  266.     return m_Data.end();
  267. }
  268. template <class T>
  269. inline typename CNcbiMatrix<T>::const_iterator CNcbiMatrix<T>::begin() const
  270. {
  271.     return m_Data.begin();
  272. }
  273. template <class T>
  274. inline typename CNcbiMatrix<T>::const_iterator CNcbiMatrix<T>::end() const
  275. {
  276.     return m_Data.end();
  277. }
  278. template <class T>
  279. inline const T&
  280. CNcbiMatrix<T>::operator[] (size_t i) const
  281. {
  282.     _ASSERT(i >= 0  &&  i < m_Data.size());
  283.     return m_Data[i];
  284. }
  285. template <class T>
  286. inline T& CNcbiMatrix<T>::operator[] (size_t i)
  287. {
  288.     _ASSERT(i >= 0  &&  i < m_Data.size());
  289.     return m_Data[i];
  290. }
  291. template <class T>
  292. inline const T& CNcbiMatrix<T>::operator() (size_t i, size_t j) const
  293. {
  294.     _ASSERT(i >= 0  &&  i < m_Rows);
  295.     _ASSERT(j >= 0  &&  j < m_Cols);
  296.     return m_Data[i * m_Cols + j];
  297. template <class T>
  298. inline T& CNcbiMatrix<T>::operator() (size_t i, size_t j)
  299. {
  300.     _ASSERT(i >= 0  &&  i < m_Rows);
  301.     _ASSERT(j >= 0  &&  j < m_Cols);
  302.     return m_Data[i * m_Cols + j];
  303. }
  304. template <class T>
  305. inline void CNcbiMatrix<T>::Resize(size_t new_rows, size_t new_cols, T val)
  306. {
  307.     if (new_cols == m_Cols && new_rows >= m_Rows) {
  308.         // common special case that can easily be handled efficiently
  309.         m_Data.resize(new_rows * new_cols, val);
  310.     } else {
  311.         /// hack: we just make a new strip and copy things correctly
  312.         /// there is a faster way to do this
  313.         TData new_data(new_rows * new_cols, val);
  314.         size_t i = min(new_rows, m_Rows);
  315.         size_t j = min(new_cols, m_Cols);
  316.         
  317.         for (size_t r = 0;  r < i;  ++r) {
  318.             for (size_t c = 0;  c < j;  ++c) {
  319.                 new_data[r * new_cols + c] = m_Data[r * m_Cols + c];
  320.             }
  321.         }
  322.         new_data.swap(m_Data);
  323.     }
  324.     m_Rows = new_rows;
  325.     m_Cols = new_cols;
  326. }
  327. template <class T>
  328. inline void CNcbiMatrix<T>::Set(T val)
  329. {
  330.     m_Data.clear();
  331.     m_Data.resize(m_Rows * m_Cols, val);
  332. }
  333. template <class T>
  334. inline void CNcbiMatrix<T>::Identity()
  335. {
  336.     _ASSERT(m_Rows == m_Cols);
  337.     Set(T(0));
  338.     for (size_t i = 0;  i < m_Rows;  ++i) {
  339.         m_Data[i * m_Cols + i] = T(1);
  340.     }
  341. }
  342. template <class T>
  343. inline void CNcbiMatrix<T>::Identity(size_t size)
  344. {
  345.     Resize(size, size);
  346.     Set(T(0));
  347.     for (size_t i = 0;  i < m_Rows;  ++i) {
  348.         m_Data[i * m_Cols + i] = T(1);
  349.     }
  350. }
  351. template <class T>
  352. inline void CNcbiMatrix<T>::Diagonal(T val)
  353. {
  354.     _ASSERT(m_Rows == GetCols());
  355.     Set(T(0));
  356.     for (size_t i = 0;  i < m_Rows;  ++i) {
  357.         m_Data[i * m_Cols + i] = val;
  358.     }
  359. }
  360. template <class T>
  361. inline void CNcbiMatrix<T>::Diagonal(size_t size, T val)
  362. {
  363.     Resize(size, size);
  364.     Set(T(0));
  365.     for (size_t i = 0;  i < m_Rows;  ++i) {
  366.         m_Data[i * m_Cols + i] = val;
  367.     }
  368. }
  369. template <class T>
  370. inline void CNcbiMatrix<T>::Transpose()
  371. {
  372.     TData new_data(m_Cols * m_Rows);
  373.     for (size_t i = 0;  i < m_Rows;  ++i) {
  374.         for (size_t j = 0;  j < m_Cols;  ++j) {
  375.             new_data[j * m_Cols + i] = m_Data[i * m_Cols + j];
  376.         }
  377.     }
  378.     m_Data.swap(new_data);
  379.     swap(m_Rows, m_Cols);
  380. }
  381. template <class T>
  382. inline void CNcbiMatrix<T>::SwapRows(size_t i, size_t j)
  383. {
  384.     size_t i_offs = i * m_Cols;
  385.     size_t j_offs = j * m_Cols;
  386.     for (size_t c = 0;  c < m_Cols;  ++c) {
  387.         swap(m_Data[i_offs + c], m_Data[j_offs + c] );
  388.     }
  389. }
  390. template <class T>
  391. inline void CNcbiMatrix<T>::Swap(CNcbiMatrix<T>& M)
  392. {
  393.     m_Data.swap(M.m_Data);
  394.     swap(m_Cols, M.m_Cols);
  395.     swap(m_Rows, M.m_Rows);
  396. }
  397. ///
  398. /// global operators
  399. ///
  400. ///
  401. /// addition
  402. ///
  403. template <class T, class U>
  404. inline CNcbiMatrix< NCBI_PROMOTE(T,U) >
  405. operator+ (const CNcbiMatrix<T>& m0, const CNcbiMatrix<U>& m1)
  406. {
  407.     _ASSERT(m0.GetRows() == m1.GetRows());
  408.     _ASSERT(m0.GetCols() == m1.GetCols());
  409.     CNcbiMatrix<NCBI_PROMOTE(T,U)> res(m0.GetRows(), m0.GetCols());
  410.     typename CNcbiMatrix<NCBI_PROMOTE(T,U)>::iterator res_iter = res.begin();
  411.     typename CNcbiMatrix<NCBI_PROMOTE(T,U)>::iterator res_end  = res.end();
  412.     typename CNcbiMatrix<T>::const_iterator           m0_iter  = m0.begin();
  413.     typename CNcbiMatrix<U>::const_iterator           m1_iter  = m1.begin();
  414.     for ( ;  res_iter != res_end;  ++res_iter, ++m0_iter, ++m1_iter) {
  415.         *res_iter = *m0_iter + *m1_iter;
  416.     }
  417.     return res;
  418. }
  419. template <class T, class U>
  420. inline CNcbiMatrix<T>&
  421. operator+= (CNcbiMatrix<T>& m0, const CNcbiMatrix<U>& m1)
  422. {
  423.     _ASSERT(m0.GetRows() == m1.GetRows());
  424.     _ASSERT(m0.GetCols() == m1.GetCols());
  425.     typename CNcbiMatrix<T>::iterator           m0_iter  = m0.begin();
  426.     typename CNcbiMatrix<T>::iterator           m0_end   = m0.end();
  427.     typename CNcbiMatrix<U>::const_iterator     m1_iter  = m1.begin();
  428.     size_t mod = (m0.GetRows() * m0.GetCols()) % 4;
  429.     for ( ;  mod;  --mod, ++m0_iter, ++m1_iter) {
  430.         *m0_iter += *m1_iter;
  431.     }
  432.     for ( ;  m0_iter != m0_end;  ) {
  433.         *m0_iter++ += *m1_iter++;
  434.         *m0_iter++ += *m1_iter++;
  435.         *m0_iter++ += *m1_iter++;
  436.         *m0_iter++ += *m1_iter++;
  437.     }
  438.     return m0;
  439. }
  440. ///
  441. /// subtraction
  442. ///
  443. template <class T, class U>
  444. inline CNcbiMatrix< NCBI_PROMOTE(T,U) >
  445. operator- (const CNcbiMatrix<T>& m0, const CNcbiMatrix<U>& m1)
  446. {
  447.     _ASSERT(m0.GetRows() == m1.GetRows());
  448.     _ASSERT(m0.GetCols() == m1.GetCols());
  449.     CNcbiMatrix< NCBI_PROMOTE(T,U) > res(m0.GetRows(), m0.GetCols());
  450.     typename CNcbiMatrix<NCBI_PROMOTE(T,U)>::iterator res_iter = res.begin();
  451.     typename CNcbiMatrix<NCBI_PROMOTE(T,U)>::iterator res_end  = res.end();
  452.     typename CNcbiMatrix<T>::const_iterator           m0_iter  = m0.begin();
  453.     typename CNcbiMatrix<U>::const_iterator           m1_iter  = m1.begin();
  454.     for ( ;  res_iter != res_end;  ++res_iter, ++m0_iter, ++m1_iter) {
  455.         *res_iter = *m0_iter - *m1_iter;
  456.     }
  457.     return res;
  458. }
  459. template <class T, class U>
  460. inline CNcbiMatrix<T>&
  461. operator-= (CNcbiMatrix<T>& m0, const CNcbiMatrix<U>& m1)
  462. {
  463.     _ASSERT(m0.GetRows() == m1.GetRows());
  464.     _ASSERT(m0.GetCols() == m1.GetCols());
  465.     typename CNcbiMatrix<T>::iterator           m0_iter  = m0.begin();
  466.     typename CNcbiMatrix<T>::iterator           m0_end   = m0.end();
  467.     typename CNcbiMatrix<U>::const_iterator     m1_iter  = m1.begin();
  468.     for ( ;  m0_iter != m0_end;  ++m0_iter, ++m1_iter) {
  469.         *m0_iter -= *m1_iter;
  470.     }
  471.     return m0;
  472. }
  473. ///
  474. /// multiplication
  475. ///
  476. template <class T>
  477. inline CNcbiMatrix< NCBI_PROMOTE(T, size_t) >
  478. operator* (const CNcbiMatrix<T>& m0, size_t val)
  479. {
  480.     CNcbiMatrix< NCBI_PROMOTE(T, size_t) > res(m0.GetRows(), m0.GetCols());
  481.     typename CNcbiMatrix<T>::iterator       res_iter = res.begin();
  482.     typename CNcbiMatrix<T>::iterator       res_end  = res.end();
  483.     typename CNcbiMatrix<T>::const_iterator m0_iter  = m0.begin();
  484.     for ( ;  res_iter != res_end;  ++res_iter, ++m0_iter) {
  485.         *res_iter = *m0_iter * val;
  486.     }
  487.     return res;
  488. }
  489. template <class U>
  490. inline CNcbiMatrix< NCBI_PROMOTE(size_t, U) >
  491. operator* (size_t val, const CNcbiMatrix<U>& m0)
  492. {
  493.     CNcbiMatrix< NCBI_PROMOTE(U, size_t) > res(m0.GetRows(), m0.GetCols());
  494.     typename CNcbiMatrix<U>::iterator       res_iter = res.begin();
  495.     typename CNcbiMatrix<U>::iterator       res_end  = res.end();
  496.     typename CNcbiMatrix<U>::const_iterator m0_iter  = m0.begin();
  497.     for ( ;  res_iter != res_end;  ++res_iter, ++m0_iter) {
  498.         *res_iter = *m0_iter * val;
  499.     }
  500.     return res;
  501. }
  502. template <class T>
  503. inline CNcbiMatrix< NCBI_PROMOTE(T, float) >
  504. operator* (const CNcbiMatrix<T>& m0, float val)
  505. {
  506.     CNcbiMatrix< NCBI_PROMOTE(T, float) > res(m0.GetRows(), m0.GetCols());
  507.     typename CNcbiMatrix<T>::iterator       res_iter = res.begin();
  508.     typename CNcbiMatrix<T>::iterator       res_end  = res.end();
  509.     typename CNcbiMatrix<T>::const_iterator m0_iter  = m0.begin();
  510.     for ( ;  res_iter != res_end;  ++res_iter, ++m0_iter) {
  511.         *res_iter = *m0_iter * val;
  512.     }
  513.     return res;
  514. }
  515. template <class U>
  516. inline CNcbiMatrix< NCBI_PROMOTE(float, U) >
  517. operator* (float val, const CNcbiMatrix<U>& m0)
  518. {
  519.     CNcbiMatrix< NCBI_PROMOTE(U, float) > res(m0.GetRows(), m0.GetCols());
  520.     typename CNcbiMatrix<U>::iterator       res_iter = res.begin();
  521.     typename CNcbiMatrix<U>::iterator       res_end  = res.end();
  522.     typename CNcbiMatrix<U>::const_iterator m0_iter  = m0.begin();
  523.     for ( ;  res_iter != res_end;  ++res_iter, ++m0_iter) {
  524.         *res_iter = *m0_iter * val;
  525.     }
  526.     return res;
  527. }
  528. template <class T>
  529. inline CNcbiMatrix< NCBI_PROMOTE(T, double) >
  530. operator* (const CNcbiMatrix<T>& m0, double val)
  531. {
  532.     CNcbiMatrix< NCBI_PROMOTE(T, double) > res(m0.GetRows(), m0.GetCols());
  533.     typename CNcbiMatrix<T>::iterator       res_iter = res.begin();
  534.     typename CNcbiMatrix<T>::iterator       res_end  = res.end();
  535.     typename CNcbiMatrix<T>::const_iterator m0_iter  = m0.begin();
  536.     for ( ;  res_iter != res_end;  ++res_iter, ++m0_iter) {
  537.         *res_iter = *m0_iter * val;
  538.     }
  539.     return res;
  540. }
  541. template <class U>
  542. inline CNcbiMatrix< NCBI_PROMOTE(double, U) >
  543. operator* (double val, const CNcbiMatrix<U>& m0)
  544. {
  545.     CNcbiMatrix< NCBI_PROMOTE(U, double) > res(m0.GetRows(), m0.GetCols());
  546.     typename CNcbiMatrix<U>::iterator       res_iter = res.begin();
  547.     typename CNcbiMatrix<U>::iterator       res_end  = res.end();
  548.     typename CNcbiMatrix<U>::const_iterator m0_iter  = m0.begin();
  549.     for ( ;  res_iter != res_end;  ++res_iter, ++m0_iter) {
  550.         *res_iter = *m0_iter * val;
  551.     }
  552.     return res;
  553. }
  554. template <class T>
  555. inline CNcbiMatrix<T>&
  556. operator*= (CNcbiMatrix<T>& m0, T val)
  557. {
  558.     typename CNcbiMatrix<T>::iterator m0_iter  = m0.begin();
  559.     typename CNcbiMatrix<T>::iterator m0_end  = m0.end();
  560.     for ( ;  m0_iter != m0_end;  ++m0_iter) {
  561.         *m0_iter *= val;
  562.     }
  563.     return m0;
  564. }
  565. template <class T>
  566. inline CNcbiMatrix<T>&
  567. operator/= (CNcbiMatrix<T>& m0, T val)
  568. {
  569.     val = T(1/val);
  570.     typename CNcbiMatrix<T>::iterator m0_iter  = m0.begin();
  571.     typename CNcbiMatrix<T>::iterator m0_end  = m0.end();
  572.     for ( ;  m0_iter != m0_end;  ++m0_iter) {
  573.         *m0_iter *= val;
  574.     }
  575.     return m0;
  576. }
  577. template <class T, class U>
  578. inline vector< NCBI_PROMOTE(T,U) >
  579. operator* (const CNcbiMatrix<T>& m, const vector<U>& v)
  580. {
  581.     _ASSERT(m.GetCols() == v.size());
  582.     typedef NCBI_PROMOTE(T,U) TPromote;
  583.     vector< TPromote > res(m.GetRows(), TPromote(0));
  584.     for (size_t r = 0;  r < m.GetRows();  ++r) {
  585.         for (size_t i = 0;  i < m.GetCols();  ++i) {
  586.             res[r] += m(r,i) * v[i];
  587.         }
  588.     }
  589.     return res;
  590. }
  591. template <class T, class U>
  592. inline vector< NCBI_PROMOTE(T,U) >
  593. operator* (const vector<T>& v, const CNcbiMatrix<U>& m)
  594. {
  595.     _ASSERT(m.GetRows() == v.size());
  596.     typedef NCBI_PROMOTE(T,U) TPromote;
  597.     vector<TPromote> res(m.GetCols(), TPromote(0));
  598.     for (size_t c = 0;  c < m.GetCols();  ++c) {
  599.         for (size_t i = 0;  i < m.GetRows();  ++i) {
  600.             res[c] += m(i,c) * v[i];
  601.         }
  602.     }
  603.     return res;
  604. }
  605. template <class T, class U>
  606. inline CNcbiMatrix< NCBI_PROMOTE(T,U) >
  607. operator* (const CNcbiMatrix<T>& m0, const CNcbiMatrix<U>& m1)
  608. {
  609.     _ASSERT(m0.GetCols() == m1.GetRows());
  610.     typedef NCBI_PROMOTE(T,U) TPromote;
  611.     CNcbiMatrix< TPromote > res(m0.GetRows(), m1.GetCols(), TPromote(0));
  612. #if 1
  613.     for (size_t r = 0; r < m0.GetRows();  ++r) {
  614.         for (size_t c = 0;  c < m1.GetCols();  ++c) {
  615.             for (size_t i = 0;  i < m0.GetCols();  ++i) {
  616.                 res(r,c) += m0(r,i) * m1(i,c);
  617.             }
  618.         }
  619.     }
  620. #endif
  621. #if 0
  622.     const vector<T>& lhs = m0.GetData();
  623.     const vector<U>& rhs = m1.GetData();
  624.     size_t col_mod = m0.GetCols() % 4;
  625.     for (size_t r = 0;  r < m0.GetRows();  ++r) {
  626.         size_t r_offs = r * m0.GetCols();
  627.         for (size_t c = 0;  c < m1.GetCols();  ++c) {
  628.             size_t i=0;
  629.             T t0 = 0;
  630.             T t1 = 0;
  631.             T t2 = 0;
  632.             T t3 = 0;
  633.             switch(col_mod) {
  634.             default:
  635.             case 0:
  636.                 break;
  637.             case 3:
  638.                 t0 += m0.GetData()[r_offs + 2] * m1(2,c);
  639.                 ++i;
  640.             case 2:
  641.                 t0 += m0.GetData()[r_offs + 1] * m1(1,c);
  642.                 ++i;
  643.             case 1:
  644.                 t0 += m0.GetData()[r_offs + 0] * m1(0,c);
  645.                 ++i;
  646.                 break;
  647.             }
  648.             for (;  i < m0.GetCols();  i += 2) {
  649.                 t0 += lhs[r_offs + i + 0] * m1(i + 0, c);
  650.                 t1 += lhs[r_offs + i + 1] * m1(i + 1, c);
  651.                 //t2 += lhs[r_offs + i + 2] * m1(i + 2, c);
  652.                 //t3 += lhs[r_offs + i + 3] * m1(i + 3, c);
  653.             }
  654.             res(r,c) = t0 + t1 + t2 + t3;
  655.         }
  656.     }
  657. #endif
  658.     return res;
  659. }
  660. template <class T, class U>
  661. inline CNcbiMatrix<T>&
  662. operator*= (CNcbiMatrix<T>& m0, const CNcbiMatrix<U>& m1)
  663. {
  664.     _ASSERT(m0.GetCols() == m1.GetRows());
  665.     m0 = m0 * m1;
  666.     return m0;
  667. }
  668. ///
  669. /// comparators
  670. ///
  671. template <class T, class U>
  672. inline bool
  673. operator== (const CNcbiMatrix<T>& m0, const CNcbiMatrix<U>& m1)
  674. {
  675.     if (m0.GetRows() != m1.GetRows()) {
  676.         return false;
  677.     }
  678.     if (m0.GetCols() != m1.GetCols()) {
  679.         return false;
  680.     }
  681.     for (size_t i = 0;  i < m0.GetData().size();  ++i) {
  682.         if (m0[i] != m1[i]) {
  683.             return false;
  684.         }
  685.     }
  686.     return true;
  687. }
  688. template <class T, class U>
  689. inline bool
  690. operator!= (const CNcbiMatrix<T>& m0, const CNcbiMatrix<U>& m1)
  691. {
  692.     return !(m0 == m1);
  693. }
  694. ///
  695. /// stream output
  696. template <class T>
  697. inline CNcbiOstream& operator<<(CNcbiOstream& os, const CNcbiMatrix<T>& M)
  698. {
  699.     for (size_t i = 0;  i < M.GetRows();  ++i) {
  700.         for (size_t j = 0;  j < M.GetCols();  ++j) {
  701.             if (j > 0) {
  702.                 os << " ";
  703.             }
  704.             os << M(i, j);
  705.         }
  706.         os << NcbiEndl;
  707.     }
  708.     return os;
  709. }
  710. ///
  711. /// stream input
  712. template <class T>
  713. inline CNcbiIstream& operator>>(CNcbiIstream& is, CNcbiMatrix<T>& M)
  714. {
  715.     CNcbiMatrix<T> A;
  716.     string line;
  717.     vector<T> row;
  718.     T entry;
  719.     int linenum = 0;
  720.     while(getline(is, line)) {
  721.         linenum++;
  722.         if (line.empty() || line[0] == '#') {
  723.             continue;
  724.         }
  725.         CNcbiIstrstream iss(line.c_str(), line.size());
  726.         row.clear();
  727.         while(1) {
  728.             iss >> entry;
  729.             if (!iss) {
  730.                 break;
  731.             }
  732.             row.push_back(entry);
  733.         }
  734.         if (A.GetCols() == 0) {
  735.             A.Resize(A.GetCols(), row.size());
  736.         }
  737.         if (row.size() != A.GetCols()) {
  738.             NCBI_THROW(CException, eUnknown,
  739.                        "error at line " +
  740.                        NStr::IntToString(linenum) + ": expected " +
  741.                        NStr::IntToString(A.GetCols()) + " columns; got" +
  742.                        NStr::IntToString(row.size()));
  743.         }
  744.         A.Resize(A.GetRows() + 1, A.GetCols());
  745.         for (int i = 0;  i < A.GetCols();  ++i) {
  746.             A(A.GetRows() - 1, i) = row[i];
  747.         }
  748.     }
  749.     M.Swap(A);
  750.     return is;
  751. }
  752. END_NCBI_SCOPE
  753. /*
  754.  * ===========================================================================
  755.  * $Log: matrix.hpp,v $
  756.  * Revision 1000.1  2004/04/16 15:28:41  gouriano
  757.  * PRODUCTION: UPGRADED [CATCHUP_003] Dev-tree R1.6
  758.  *
  759.  * Revision 1.6  2004/03/11 17:31:42  jcherry
  760.  * Sped up adding of rows (greatly speeds reading from streams)
  761.  *
  762.  * Revision 1.5  2004/03/10 14:13:29  dicuccio
  763.  * Corrected include - use ncbistr instead of ncbistre
  764.  *
  765.  * Revision 1.4  2004/02/10 21:17:54  jcherry
  766.  * Made operator>> work for a matrix of any contained type that defines
  767.  * operator>> (not just doubles)
  768.  *
  769.  * Revision 1.3  2004/02/10 14:29:51  jcherry
  770.  * Removed wayward use of protected data in operator>>
  771.  *
  772.  * Revision 1.2  2004/02/10 14:00:40  dicuccio
  773.  * Added comments.  Fixed spacing issues.  Changed extraction operator to be
  774.  * non-friend function
  775.  *
  776.  * Revision 1.1  2004/02/09 17:34:11  dicuccio
  777.  * Moved from gui/math
  778.  *
  779.  * Revision 1.4  2004/02/02 15:55:49  jcherry
  780.  * Added Swap() method and stream reader
  781.  *
  782.  * Revision 1.3  2004/01/29 22:38:03  jcherry
  783.  * Fixed typo
  784.  *
  785.  * Revision 1.2  2004/01/29 21:30:17  jcherry
  786.  * Added stream output operator
  787.  *
  788.  * Revision 1.1  2004/01/23 13:54:15  dicuccio
  789.  * Initial revision
  790.  *
  791.  * ===========================================================================
  792.  */
  793. #endif  // UTIL_MATH___MATRIX__HPP