#ifndef __KOKKOSBATCHED_QR_FORM_Q_SERIAL_INTERNAL_HPP__
#define __KOKKOSBATCHED_QR_FORM_Q_SERIAL_INTERNAL_HPP__


/// \author Kyungjoo Kim (kyukim@sandia.gov)

#include "KokkosBatched_Util.hpp"
#include "KokkosBatched_Set_Internal.hpp"
#include "KokkosBatched_SetIdentity_Internal.hpp"
#include "KokkosBatched_ApplyQ_Serial_Internal.hpp"

namespace KokkosBatched {

  ///
  /// Serial Internal Impl
  /// ==================== 
  ///
  /// this impl follows the flame interface of householder transformation
  ///
  struct SerialQR_FormQ_Internal {
    template<typename ValueType>
    KOKKOS_INLINE_FUNCTION
    static int
    invoke(const int m, 
           const int k, 
           /* */ ValueType * A, const int as0, const int as1,
           /* */ ValueType * t, const int ts,
           /* */ ValueType * Q, const int qs0, const int qs1,
           /* */ ValueType * w,
           const bool is_Q_zero = false) {
      typedef ValueType value_type;
        
      /// Given a matrix A that includes QR factorization
      /// it forms a unitary matrix Q 
      ///   B = Q = (H0 H1 H2 H3 ... H(k-1)) I
      /// where
      ///   A is m x k (holding H0, H1 ... H(k-1)
      ///   t is k x 1 
      ///   B is m x m

      // set identity
      if (is_Q_zero)
        SerialSetInternal::invoke(m, value_type(1), Q, qs0+qs1);
      else
        SerialSetIdentityInternal::invoke(m, Q, qs0, qs1);

      return SerialApplyQ_LeftNoTransForwardInternal
        ::invoke(m, m, k,
                 A, as0, as1, 
                 t, ts,
                 Q, qs0, qs1,
                 w);
    }
  };

} // end namespace KokkosBatched


#endif
