spop_strans_meat.hpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. // Copyright 2008-2016 Conrad Sanderson (http://conradsanderson.id.au)
  2. // Copyright 2008-2016 National ICT Australia (NICTA)
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // ------------------------------------------------------------------------
  15. //! \addtogroup spop_strans
  16. //! @{
  17. template<typename eT>
  18. inline
  19. void
  20. spop_strans::apply_noalias(SpMat<eT>& B, const SpMat<eT>& A)
  21. {
  22. arma_extra_debug_sigprint();
  23. B.reserve(A.n_cols, A.n_rows, A.n_nonzero); // deliberately swapped
  24. if(A.n_nonzero == 0) { return; }
  25. // This follows the TRANSP algorithm described in
  26. // 'Sparse Matrix Multiplication Package (SMMP)'
  27. // (R.E. Bank and C.C. Douglas, 2001)
  28. const uword m = A.n_rows;
  29. const uword n = A.n_cols;
  30. const eT* a = A.values;
  31. eT* b = access::rwp(B.values);
  32. const uword* ia = A.col_ptrs;
  33. const uword* ja = A.row_indices;
  34. uword* ib = access::rwp(B.col_ptrs);
  35. uword* jb = access::rwp(B.row_indices);
  36. // // ib is already zeroed, as B is freshly constructed
  37. //
  38. // for(uword i=0; i < (m+1); ++i)
  39. // {
  40. // ib[i] = 0;
  41. // }
  42. for(uword i=0; i < n; ++i)
  43. {
  44. for(uword j = ia[i]; j < ia[i+1]; ++j)
  45. {
  46. ib[ ja[j] + 1 ]++;
  47. }
  48. }
  49. for(uword i=0; i < m; ++i)
  50. {
  51. ib[i+1] += ib[i];
  52. }
  53. for(uword i=0; i < n; ++i)
  54. {
  55. for(uword j = ia[i]; j < ia[i+1]; ++j)
  56. {
  57. const uword jj = ja[j];
  58. const uword ib_jj = ib[jj];
  59. jb[ib_jj] = i;
  60. b[ib_jj] = a[j];
  61. ib[jj]++;
  62. }
  63. }
  64. for(uword i = m-1; i >= 1; --i)
  65. {
  66. ib[i] = ib[i-1];
  67. }
  68. ib[0] = 0;
  69. }
  70. template<typename T1>
  71. inline
  72. void
  73. spop_strans::apply(SpMat<typename T1::elem_type>& out, const SpOp<T1,spop_strans>& in)
  74. {
  75. arma_extra_debug_sigprint();
  76. typedef typename T1::elem_type eT;
  77. const unwrap_spmat<T1> U(in.m);
  78. if(U.is_alias(out))
  79. {
  80. SpMat<eT> tmp;
  81. spop_strans::apply_noalias(tmp, U.M);
  82. out.steal_mem(tmp);
  83. }
  84. else
  85. {
  86. spop_strans::apply_noalias(out, U.M);
  87. }
  88. }
  89. //! for transpose of non-complex matrices, redirected from spop_htrans::apply()
  90. template<typename T1>
  91. inline
  92. void
  93. spop_strans::apply(SpMat<typename T1::elem_type>& out, const SpOp<T1,spop_htrans>& in)
  94. {
  95. arma_extra_debug_sigprint();
  96. typedef typename T1::elem_type eT;
  97. const unwrap_spmat<T1> U(in.m);
  98. if(U.is_alias(out))
  99. {
  100. SpMat<eT> tmp;
  101. spop_strans::apply_noalias(tmp, U.M);
  102. out.steal_mem(tmp);
  103. }
  104. else
  105. {
  106. spop_strans::apply_noalias(out, U.M);
  107. }
  108. }
  109. //! @}