inline
arma_warn_unused
typename
enable_if2
  <(is_arma_sparse_type<T1>::value) && (is_arma_sparse_type<T2>::value) && (is_same_type<typename T1::elem_type, typename T2::elem_type>::value),
   typename T1::elem_type
  >::result
dot
  (
  const SpBase<typename T1::elem_type, T1>& x,
  const SpBase<typename T2::elem_type, T2>& y
  )
  {
  arma_extra_debug_sigprint();

  const SpProxy<T1> pa(x.get_ref());
  const SpProxy<T2> pb(y.get_ref());

  arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_rows(), pb.get_n_cols(), "dot()");

  typedef typename T1::elem_type eT;

  if((&(x.get_ref()) == &(y.get_ref())) && (SpProxy<T1>::must_use_iterator == false))
    {
    // We can do it directly!
    return op_dot::direct_dot_arma(pa.get_n_nonzero(), pa.get_values(), pa.get_values());
    }
  else
    {
    // Iterate over both objects and see when they are the same
    eT result = eT(0);

    typename SpProxy<T1>::const_iterator_type a_it = pa.begin();
    typename SpProxy<T2>::const_iterator_type b_it = pb.begin();

    while((a_it.pos() < pa.get_n_nonzero()) && (b_it.pos() < pb.get_n_nonzero()))
      {
      if(a_it == b_it)
        {
        result += (*a_it) * (*b_it);

        ++a_it;
        ++b_it;
        }
      else if((a_it.col() < b_it.col()) || ((a_it.col() == b_it.col()) && (a_it.row() < b_it.row())))
        {
        // a_it is "behind"
        ++a_it;
        }
      else
        {
        // b_it is "behind"
        ++b_it;
        }
      }

    return result;
    }
  }
inline
arma_warn_unused
typename
enable_if2
  <(is_arma_type<T1>::value) && (is_arma_sparse_type<T2>::value) && (is_same_type<typename T1::elem_type, typename T2::elem_type>::value),
   typename T1::elem_type
  >::result
dot
  (
  const Base<typename T1::elem_type, T1>& x,
  const SpBase<typename T2::elem_type, T2>& y
  )
  {
  arma_extra_debug_sigprint();

  const Proxy<T1> pa(x.get_ref());
  const SpProxy<T2> pb(y.get_ref());

  arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_rows(), pb.get_n_cols(), "dot()");

  typedef typename T1::elem_type eT;

  eT result = eT(0);

  typename SpProxy<T2>::const_iterator_type it = pb.begin();

  // prefer_at_accessor won't save us operations
  while(it.pos() < pb.get_n_nonzero())
    {
    result += (*it) * pa.at(it.row(), it.col());
    ++it;
    }

  return result;
  }
inline
typename
enable_if2
  <
  (is_arma_type<T1>::value && is_arma_sparse_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::value),
  Mat<typename T1::elem_type>
  >::result
operator/
  (
  const   Base<typename T1::elem_type, T1>& x,
  const SpBase<typename T2::elem_type, T2>& y
  )
  {
  arma_extra_debug_sigprint();

  const   Proxy<T1> pa(x.get_ref());
  const SpProxy<T2> pb(y.get_ref());

  arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_rows(), pb.get_n_cols(), "element-wise division");

  Mat<typename T1::elem_type> result(pa.get_n_rows(), pa.get_n_cols());

  result.fill(Datum<typename T1::elem_type>::inf);

  // Now divide each element
  typename SpProxy<T2>::const_iterator_type it = pb.begin();

  while(it.pos() < pb.get_n_nonzero())
    {
    if(Proxy<T1>::prefer_at_accessor == false)
      {
      const uword index = (it.col() * result.n_rows) + it.row();
      result[index] = pa[index] / (*it);
      }
    else
      {
      result.at(it.row(), it.col()) = pa.at(it.row(), it.col()) / (*it);
      }

    ++it;
    }

  return result;
  }
Exemplo n.º 4
0
inline
void
spop_mean::apply_noalias_slow
  (
        SpMat<typename T1::elem_type>& out,
  const SpProxy<T1>&                   p,
  const uword                          dim
  )
  {
  arma_extra_debug_sigprint();

  typedef typename T1::elem_type eT;
  
  const uword p_n_rows = p.get_n_rows();
  const uword p_n_cols = p.get_n_cols();

  if(dim == 0)  // find the mean in each column
    {
    arma_extra_debug_print("spop_mean::apply_noalias(): dim = 0");
    
    out.set_size((p_n_rows > 0) ? 1 : 0, p_n_cols);
    
    if( (p_n_rows == 0) || (p.get_n_nonzero() == 0) )  { return; }
    
    for(uword col = 0; col < p_n_cols; ++col)
      {
      // Do we have to use an iterator or can we use memory directly?
      if(SpProxy<T1>::must_use_iterator)
        {
        typename SpProxy<T1>::const_iterator_type it  = p.begin_col(col);
        typename SpProxy<T1>::const_iterator_type end = p.begin_col(col + 1);
        
        const uword n_zero = p_n_rows - (end.pos() - it.pos());
        
        out.at(0,col) = spop_mean::iterator_mean(it, end, n_zero, eT(0));
        }
      else
        {
        out.at(0,col) = spop_mean::direct_mean
          (
          &p.get_values()[p.get_col_ptrs()[col]],
          p.get_col_ptrs()[col + 1] - p.get_col_ptrs()[col],
          p_n_rows
          );
        }
      }
    }
  else
  if(dim == 1)  // find the mean in each row
    {
    arma_extra_debug_print("spop_mean::apply_noalias(): dim = 1");
    
    out.set_size(p_n_rows, (p_n_cols > 0) ? 1 : 0);
    
    if( (p_n_cols == 0) || (p.get_n_nonzero() == 0) )  { return; }
    
    for(uword row = 0; row < p_n_rows; ++row)
      {
      // We must use an iterator regardless of how it is stored.
      typename SpProxy<T1>::const_row_iterator_type it  = p.begin_row(row);
      typename SpProxy<T1>::const_row_iterator_type end = p.end_row(row);
      
      const uword n_zero = p_n_cols - (end.pos() - it.pos());
      
      out.at(row,0) = spop_mean::iterator_mean(it, end, n_zero, eT(0));
      }
    }
  }
Exemplo n.º 5
0
inline
void
spop_var::apply_noalias
  (
        SpMat<typename T1::pod_type>& out_ref,
  const SpProxy<T1>&                  p,
  const uword                         norm_type,
  const uword                         dim
  )
  {
  arma_extra_debug_sigprint();

  typedef typename T1::elem_type  in_eT;
  //typedef typename T1::pod_type  out_eT;

  const uword p_n_rows = p.get_n_rows();
  const uword p_n_cols = p.get_n_cols();

  if(dim == 0)
    {
    arma_extra_debug_print("spop_var::apply(), dim = 0");

    arma_debug_check((p_n_rows == 0), "var(): given object has zero rows");

    out_ref.set_size(1, p_n_cols);

    for(uword col = 0; col < p_n_cols; ++col)
      {
      if(SpProxy<T1>::must_use_iterator == true)
        {
        // We must use an iterator; we can't access memory directly.
        typename SpProxy<T1>::const_iterator_type it  = p.begin_col(col);
        typename SpProxy<T1>::const_iterator_type end = p.begin_col(col + 1);
        
        const uword n_zero = p.get_n_rows() - (end.pos() - it.pos());
        
        // in_eT is used just to get the specialization right (complex / noncomplex)
        out_ref.at(col) = spop_var::iterator_var(it, end, n_zero, norm_type, in_eT(0));
        }
      else
        {
        // We can use direct memory access to calculate the variance.
        out_ref.at(col) = spop_var::direct_var
          (
          &p.get_values()[p.get_col_ptrs()[col]],
          p.get_col_ptrs()[col + 1] - p.get_col_ptrs()[col],
          p.get_n_rows(),
          norm_type
          );
        }
      }
    }
  else if(dim == 1)
    {
    arma_extra_debug_print("spop_var::apply_noalias(), dim = 1");
    
    arma_debug_check((p_n_cols == 0), "var(): given object has zero columns");
    
    out_ref.set_size(p_n_rows, 1);
    
    for(uword row = 0; row < p_n_rows; ++row)
      {
      // We have to use an iterator here regardless of whether or not we can
      // directly access memory.
      typename SpProxy<T1>::const_row_iterator_type it  = p.begin_row(row);
      typename SpProxy<T1>::const_row_iterator_type end = p.end_row(row);
      
      const uword n_zero = p.get_n_cols() - (end.pos() - it.pos());
      
      out_ref.at(row) = spop_var::iterator_var(it, end, n_zero, norm_type, in_eT(0));
      }
    }
  }
inline
typename
enable_if2
<
(is_arma_sparse_type<T1>::value && is_arma_sparse_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::value),
SpMat<typename T1::elem_type>
>::result
operator%
(
    const SpBase<typename T1::elem_type, T1>& x,
    const SpBase<typename T2::elem_type, T2>& y
)
{
    arma_extra_debug_sigprint();

    const SpProxy<T1> pa(x.get_ref());
    const SpProxy<T2> pb(y.get_ref());

    arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_rows(), pb.get_n_cols(), "element-wise multiplication");

    SpMat<typename T1::elem_type> result(pa.get_n_rows(), pa.get_n_cols());

    // Resize memory to correct size.
    result.mem_resize(n_unique(x, y, op_n_unique_mul()));

    // Now iterate across both matrices.
    typename SpProxy<T1>::const_iterator_type x_it = pa.begin();
    typename SpProxy<T2>::const_iterator_type y_it = pb.begin();

    uword cur_val = 0;
    while((x_it.pos() < pa.get_n_nonzero()) || (y_it.pos() < pb.get_n_nonzero()))
    {
        if(x_it == y_it)
        {
            const typename T1::elem_type val = (*x_it) * (*y_it);
            if (val != 0)
            {
                access::rw(result.values[cur_val]) = val;
                access::rw(result.row_indices[cur_val]) = x_it.row();
                ++access::rw(result.col_ptrs[x_it.col() + 1]);
                ++cur_val;
            }

            ++x_it;
            ++y_it;
        }
        else
        {
            if((x_it.col() < y_it.col()) || ((x_it.col() == y_it.col()) && (x_it.row() < y_it.row()))) // if y is closer to the end
            {
                ++x_it;
            }
            else
            {
                ++y_it;
            }
        }
    }

    // Fix column pointers to be cumulative.
    for(uword c = 1; c <= result.n_cols; ++c)
    {
        access::rw(result.col_ptrs[c]) += result.col_ptrs[c - 1];
    }

    return result;
}
inline
typename
enable_if2
<
(is_arma_type<T1>::value && is_arma_sparse_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::value),
SpMat<typename T1::elem_type>
>::result
operator%
(
    const   Base<typename T1::elem_type, T1>& x,
    const SpBase<typename T2::elem_type, T2>& y
)
{
    arma_extra_debug_sigprint();

    const   Proxy<T1> pa(x.get_ref());
    const SpProxy<T2> pb(y.get_ref());

    arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_rows(), pb.get_n_cols(), "element-wise multiplication");

    SpMat<typename T1::elem_type> result(pa.get_n_rows(), pa.get_n_cols());

    if(Proxy<T1>::prefer_at_accessor == false)
    {
        // use direct operator[] access
        // count new size
        uword new_n_nonzero = 0;
        typename SpProxy<T2>::const_iterator_type it = pb.begin();
        while(it.pos() < pb.get_n_nonzero())
        {
            if(((*it) * pa[(it.col() * pa.get_n_rows()) + it.row()]) != 0)
            {
                ++new_n_nonzero;
            }

            ++it;
        }

        // Resize memory accordingly.
        result.mem_resize(new_n_nonzero);

        uword cur_val = 0;
        typename SpProxy<T2>::const_iterator_type it2 = pb.begin();
        while(it2.pos() < pb.get_n_nonzero())
        {
            const typename T1::elem_type val = (*it2) * pa[(it2.col() * pa.get_n_rows()) + it2.row()];
            if(val != 0)
            {
                access::rw(result.values[cur_val]) = val;
                access::rw(result.row_indices[cur_val]) = it2.row();
                ++access::rw(result.col_ptrs[it2.col() + 1]);
                ++cur_val;
            }

            ++it2;
        }
    }
    else
    {
        // use at() access
        // count new size
        uword new_n_nonzero = 0;
        typename SpProxy<T2>::const_iterator_type it = pb.begin();
        while(it.pos() < pb.get_n_nonzero())
        {
            if(((*it) * pa.at(it.row(), it.col())) != 0)
            {
                ++new_n_nonzero;
            }

            ++it;
        }

        // Resize memory accordingly.
        result.mem_resize(new_n_nonzero);

        uword cur_val = 0;
        typename SpProxy<T2>::const_iterator_type it2 = pb.begin();
        while(it2.pos() < pb.get_n_nonzero())
        {
            const typename T1::elem_type val = (*it2) * pa.at(it2.row(), it2.col());
            if(val != 0)
            {
                access::rw(result.values[cur_val]) = val;
                access::rw(result.row_indices[cur_val]) = it2.row();
                ++access::rw(result.col_ptrs[it2.col() + 1]);
                ++cur_val;
            }

            ++it2;
        }
    }

    // Fix column pointers.
    for(uword c = 1; c <= result.n_cols; ++c)
    {
        access::rw(result.col_ptrs[c]) += result.col_ptrs[c - 1];
    }

    return result;
}
Exemplo n.º 8
0
inline
void
spop_var::apply_noalias
  (
        SpMat<typename T1::pod_type>& out,
  const SpProxy<T1>&                  p,
  const uword                         norm_type,
  const uword                         dim
  )
  {
  arma_extra_debug_sigprint();
  
  typedef typename T1::elem_type  in_eT;
  //typedef typename T1::pod_type  out_eT;
  
  const uword p_n_rows = p.get_n_rows();
  const uword p_n_cols = p.get_n_cols();
  
  // TODO: this is slow; rewrite based on the approach used by sparse mean()
  
  if(dim == 0)  // find variance in each column
    {
    arma_extra_debug_print("spop_var::apply_noalias(): dim = 0");
    
    out.set_size((p_n_rows > 0) ? 1 : 0, p_n_cols);
    
    if( (p_n_rows == 0) || (p.get_n_nonzero() == 0) )  { return; }
    
    for(uword col = 0; col < p_n_cols; ++col)
      {
      if(SpProxy<T1>::must_use_iterator)
        {
        // We must use an iterator; we can't access memory directly.
        typename SpProxy<T1>::const_iterator_type it  = p.begin_col(col);
        typename SpProxy<T1>::const_iterator_type end = p.begin_col(col + 1);
        
        const uword n_zero = p_n_rows - (end.pos() - it.pos());
        
        // in_eT is used just to get the specialization right (complex / noncomplex)
        out.at(0, col) = spop_var::iterator_var(it, end, n_zero, norm_type, in_eT(0));
        }
      else
        {
        // We can use direct memory access to calculate the variance.
        out.at(0, col) = spop_var::direct_var
          (
          &p.get_values()[p.get_col_ptrs()[col]],
          p.get_col_ptrs()[col + 1] - p.get_col_ptrs()[col],
          p_n_rows,
          norm_type
          );
        }
      }
    }
  else
  if(dim == 1)  // find variance in each row
    {
    arma_extra_debug_print("spop_var::apply_noalias(): dim = 1");
    
    out.set_size(p_n_rows, (p_n_cols > 0) ? 1 : 0);
    
    if( (p_n_cols == 0) || (p.get_n_nonzero() == 0) )  { return; }
    
    for(uword row = 0; row < p_n_rows; ++row)
      {
      // We have to use an iterator here regardless of whether or not we can
      // directly access memory.
      typename SpProxy<T1>::const_row_iterator_type it  = p.begin_row(row);
      typename SpProxy<T1>::const_row_iterator_type end = p.end_row(row);
      
      const uword n_zero = p_n_cols - (end.pos() - it.pos());
      
      out.at(row, 0) = spop_var::iterator_var(it, end, n_zero, norm_type, in_eT(0));
      }
    }
  }
arma_hot
inline
void
spglue_minus::apply_noalias(SpMat<eT>& result, const SpProxy<T1>& pa, const SpProxy<T2>& pb)
  {
  arma_extra_debug_sigprint();
  
  arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_rows(), pb.get_n_cols(), "subtraction");

  result.set_size(pa.get_n_rows(), pa.get_n_cols());

  // Resize memory to correct size.
  result.mem_resize(n_unique(pa, pb, op_n_unique_sub()));

  // Now iterate across both matrices.
  typename SpProxy<T1>::const_iterator_type x_it = pa.begin();
  typename SpProxy<T2>::const_iterator_type y_it = pb.begin();

  uword cur_val = 0;
  while((x_it.pos() < pa.get_n_nonzero()) || (y_it.pos() < pb.get_n_nonzero()))
    {
    if(x_it == y_it)
      {
      const typename T1::elem_type val = (*x_it) - (*y_it);
      if (val != 0)
        {
        access::rw(result.values[cur_val]) = val;
        access::rw(result.row_indices[cur_val]) = x_it.row();
        ++access::rw(result.col_ptrs[x_it.col() + 1]);
        ++cur_val;
        }

      ++x_it;
      ++y_it;
      }
    else
      {
      if((x_it.col() < y_it.col()) || ((x_it.col() == y_it.col()) && (x_it.row() < y_it.row()))) // if y is closer to the end
        {
        access::rw(result.values[cur_val]) = (*x_it);
        access::rw(result.row_indices[cur_val]) = x_it.row();
        ++access::rw(result.col_ptrs[x_it.col() + 1]);
        ++cur_val;
        ++x_it;
        }
      else
        {
        access::rw(result.values[cur_val]) = -(*y_it);
        access::rw(result.row_indices[cur_val]) = y_it.row();
        ++access::rw(result.col_ptrs[y_it.col() + 1]);
        ++cur_val;
        ++y_it;
        }
      }
    }

  // Fix column pointers to be cumulative.
  for(uword c = 1; c <= result.n_cols; ++c)
    {
    access::rw(result.col_ptrs[c]) += result.col_ptrs[c - 1];
    }
  }
inline
typename
enable_if2
  <
  (is_arma_sparse_type<T1>::value && is_arma_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::value),
  SpMat<typename T1::elem_type>
  >::result
operator/
  (
  const SpBase<typename T1::elem_type, T1>& x,
  const   Base<typename T2::elem_type, T2>& y
  )
  {
  arma_extra_debug_sigprint();

  const SpProxy<T1> pa(x.get_ref());
  const   Proxy<T2> pb(y.get_ref());

  arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_rows(), pb.get_n_cols(), "element-wise division");

  SpMat<typename T1::elem_type> result(pa.get_n_rows(), pa.get_n_cols());

  // The compiler should be smart enough to optimize out the inner if/else statement entirely
  typename SpProxy<T1>::const_iterator_type it = pa.begin();
  uword new_n_nonzero;
  while(it.pos() < pa.get_n_nonzero())
    {
    if(Proxy<T2>::prefer_at_accessor == false)
      {
      const typename T1::elem_type val = (*it) / pb[(it.col() * pb.get_n_rows()) + it.row()];
      if(val != 0)
        {
        ++new_n_nonzero;
        }
      }
    else
      {
      const typename T1::elem_type val = (*it) / pb.at(it.row(), it.col());
      if(val != 0)
        {
        ++new_n_nonzero;
        }
      }

    ++it;
    }

  result.mem_resize(new_n_nonzero);

  typename SpProxy<T1>::const_iterator_type it2 = pa.begin();
  uword cur_pos = 0;
  while(it2.pos() < pa.get_n_nonzero())
    {
    if(Proxy<T2>::prefer_at_accessor == false)
      {
      const typename T1::elem_type val = (*it2) / pb[(it2.col() * pb.get_n_rows()) + it2.row()];
      if(val != 0)
        {
        access::rw(result.values[cur_pos]) = val;
        access::rw(result.row_indices[cur_pos]) = it2.row();
        ++access::rw(result.col_ptrs[it2.col() + 1]);
        ++cur_pos;
        }
      }
    else
      {
      const typename T1::elem_type val = (*it2) / pb.at(it2.row(), it2.col());
      if(val != 0)
        {
        access::rw(result.values[cur_pos]) = val;
        access::rw(result.row_indices[cur_pos]) = it2.row();
        ++access::rw(result.col_ptrs[it2.col() + 1]);
        ++cur_pos;
        }
      }

    ++it2;
    }

  // Fix column pointers
  for(uword col = 1; col <= result.n_cols; ++col)
    {
    access::rw(result.col_ptrs[col]) += result.col_ptrs[col - 1];
    }

  return result;
  }