#ifndef STAN_MATH_PRIM_MAT_FUN_MULTIPLY_LOWER_TRI_SELF_TRANSPOSE_HPP
#define STAN_MATH_PRIM_MAT_FUN_MULTIPLY_LOWER_TRI_SELF_TRANSPOSE_HPP

#include <stan/math/prim/mat/fun/typedefs.hpp>
#include <stan/math/prim/scal/fun/square.hpp>

namespace stan {
  namespace math {

    /**
     * Returns the result of multiplying the lower triangular
     * portion of the input matrix by its own transpose.
     * @param L Matrix to multiply.
     * @return The lower triangular values in L times their own
     * transpose.
     * @throw std::domain_error If the input matrix is not square.
     */
    inline matrix_d
    multiply_lower_tri_self_transpose(const matrix_d& L) {
      int K = L.rows();
      if (K == 0)
        return L;
      if (K == 1) {
        matrix_d result(1, 1);
        result(0) = square(L(0));  // first elt, so don't need double idx
        return result;
      }
      int J = L.cols();
      matrix_d LLt(K, K);
      matrix_d Lt = L.transpose();
      for (int m = 0; m < K; ++m) {
        int k = (J < m + 1) ? J : m + 1;
        LLt(m, m) = Lt.col(m).head(k).squaredNorm();
        for (int n = (m + 1); n < K; ++n)
          LLt(n, m) = LLt(m, n) = Lt.col(m).head(k).dot(Lt.col(n).head(k));
      }
      return LLt;
    }

  }
}
#endif
