// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2006-2008, 2010 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// SPDX-License-Identifier: MPL-2.0

#ifndef EIGEN_DOT_H
#define EIGEN_DOT_H

// IWYU pragma: private
#include "./InternalHeaderCheck.h"

namespace Eigen {

namespace internal {

// Accumulate low-precision norms in float without changing the public result type.
template <typename RealScalar>
struct stable_norm_accumulator {
  using type = RealScalar;
};

template <>
struct stable_norm_accumulator<half> {
  using type = float;
};

template <>
struct stable_norm_accumulator<bfloat16> {
  using type = float;
};

template <typename RealScalar, typename Accumulator>
struct stable_normalization_normal_min {
  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Accumulator run() {
    return static_cast<Accumulator>((numext::numeric_limits<RealScalar>::min)());
  }
};

// The half and bfloat16 numeric_limits functions are not device functions.
template <typename Accumulator>
struct stable_normalization_normal_min<half, Accumulator> {
  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Accumulator run() { return Accumulator(1) / Accumulator(16384); }
};

template <typename Accumulator>
struct stable_normalization_normal_min<bfloat16, Accumulator> {
  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Accumulator run() {
    return static_cast<Accumulator>((numext::numeric_limits<float>::min)());
  }
};

template <typename RealScalar, typename Accumulator, bool = std::is_floating_point<Accumulator>::value>
struct stable_normalization_use_reciprocal {
  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE bool run(const Accumulator&) { return false; }
};

template <typename RealScalar, typename Accumulator>
struct stable_normalization_use_reciprocal<RealScalar, Accumulator, true> {
  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE bool run(const Accumulator& scale) {
    const Accumulator normal_min = stable_normalization_normal_min<RealScalar, Accumulator>::run();
    const Accumulator normal_max = Accumulator(1) / normal_min;
    return scale >= normal_min && scale <= normal_max;
  }
};

template <typename VectorType, typename Accumulator,
          bool = bool(traits<VectorType>::Flags & DirectAccessBit) &&
                 (int(inner_stride_at_compile_time<VectorType>::value) != 1)>
struct stable_normalization_dispatch {
  using Scalar = typename traits<VectorType>::Scalar;
  using RealScalar = typename NumTraits<Scalar>::Real;
  // Only complex_array_access scalars have a writable component view.
  using HasWritableRealView = bool_constant<!NumTraits<Scalar>::IsComplex || complex_array_access<Scalar>::value>;

  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Accumulator max_abs(const VectorType& vec) {
    return vec.realView().template cast<Accumulator>().cwiseAbs().template maxCoeff<PropagateNaN>();
  }

  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Accumulator scaled_squared_norm(const VectorType& vec,
                                                                               const Accumulator& factor) {
    return (vec.realView().template cast<Accumulator>() * factor).squaredNorm();
  }

  template <typename ResultType>
  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void assign_scaled(ResultType& result, const VectorType& vec,
                                                                  const Accumulator& factor) {
    assign_scaled_impl(result, vec, factor, HasWritableRealView());
  }

  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void scale_in_place(VectorType& vec, const Accumulator& factor) {
    scale_in_place_impl(vec, factor, HasWritableRealView());
  }

 private:
  template <typename ResultType>
  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void assign_scaled_impl(ResultType& result, const VectorType& vec,
                                                                       const Accumulator& factor, std::true_type) {
    result.realView() = (vec.realView().template cast<Accumulator>() * factor).template cast<RealScalar>();
  }

  template <typename ResultType>
  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void assign_scaled_impl(ResultType& result, const VectorType& vec,
                                                                       const Accumulator& factor, std::false_type) {
    result = vec * static_cast<RealScalar>(factor);
  }

  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void scale_in_place_impl(VectorType& vec, const Accumulator& factor,
                                                                        std::true_type) {
    vec.realView() = (vec.realView().template cast<Accumulator>() * factor).template cast<RealScalar>();
  }

  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void scale_in_place_impl(VectorType& vec, const Accumulator& factor,
                                                                        std::false_type) {
    vec = vec * static_cast<RealScalar>(factor);
  }
};

// Runtime-contiguous expressions can still use packet traversal.
template <typename VectorType, typename Accumulator>
struct stable_normalization_dispatch<VectorType, Accumulator, true> {
  using Scalar = typename traits<VectorType>::Scalar;
  using RealScalar = typename NumTraits<Scalar>::Real;
  // A dynamic map avoids over-unrolling fixed-size normalization paths.
  using PlainVector = Matrix<Scalar, Dynamic, 1>;
  using ConstContiguousMap = Map<const PlainVector, evaluator<VectorType>::Alignment>;
  using ContiguousMap = Map<PlainVector, evaluator<VectorType>::Alignment>;

  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE bool is_contiguous(const VectorType& vec) {
    return vec.innerStride() == 1 && (vec.outerSize() == 1 || vec.outerStride() == vec.innerSize());
  }

  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Accumulator max_abs(const VectorType& vec) {
    if (is_contiguous(vec)) {
      const ConstContiguousMap contiguous(vec.data(), vec.size());
      return stable_normalization_dispatch<ConstContiguousMap, Accumulator, false>::max_abs(contiguous);
    }
    return stable_normalization_dispatch<VectorType, Accumulator, false>::max_abs(vec);
  }

  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Accumulator scaled_squared_norm(const VectorType& vec,
                                                                               const Accumulator& factor) {
    if (is_contiguous(vec)) {
      const ConstContiguousMap contiguous(vec.data(), vec.size());
      return stable_normalization_dispatch<ConstContiguousMap, Accumulator, false>::scaled_squared_norm(contiguous,
                                                                                                        factor);
    }
    return stable_normalization_dispatch<VectorType, Accumulator, false>::scaled_squared_norm(vec, factor);
  }

  template <typename ResultType>
  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void assign_scaled(ResultType& result, const VectorType& vec,
                                                                  const Accumulator& factor) {
    if (is_contiguous(vec)) {
      const ConstContiguousMap contiguous(vec.data(), vec.size());
      Map<PlainVector> output(result.data(), result.size());
      stable_normalization_dispatch<ConstContiguousMap, Accumulator, false>::assign_scaled(output, contiguous, factor);
      return;
    }
    stable_normalization_dispatch<VectorType, Accumulator, false>::assign_scaled(result, vec, factor);
  }

  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void scale_in_place(VectorType& vec, const Accumulator& factor) {
    if (is_contiguous(vec)) {
      ContiguousMap contiguous(vec.data(), vec.size());
      stable_normalization_dispatch<ContiguousMap, Accumulator, false>::scale_in_place(contiguous, factor);
      return;
    }
    stable_normalization_dispatch<VectorType, Accumulator, false>::scale_in_place(vec, factor);
  }
};

// Prevent fast-math from merging normal scale factors into a subnormal factor.
template <typename VectorType, typename Accumulator>
EIGEN_DEVICE_FUNC EIGEN_DONT_INLINE void stable_normalization_scale_in_place(VectorType& vec,
                                                                             const Accumulator& factor) {
  stable_normalization_dispatch<VectorType, Accumulator>::scale_in_place(vec, factor);
}

template <typename VectorType, typename Divisor>
EIGEN_DEVICE_FUNC EIGEN_DONT_INLINE void stable_normalization_divide_in_place(VectorType& vec, const Divisor& divisor) {
  vec /= divisor;
}

// squaredNorm() reduces realView().cwiseAbs2(), a cwise expression with no direct access, so when
// the underlying expression has an inner stride that is not statically 1 (a dynamic-inner-stride
// Map/Ref, a row of a 1xN matrix, ...) the reduction falls back to a scalar traversal even though
// the data is frequently contiguous at runtime. This trait flags the cases where a runtime
// contiguity check is worthwhile; it mirrors the reduction fast path in Redux.h (redux_dispatch).
// bool is excluded: its squared norm is any(), handled by a dedicated specialization below.
template <typename Xpr>
struct squared_norm_runtime_unit_stride {
  using Scalar = typename traits<Xpr>::Scalar;
  static constexpr bool value =
      bool(traits<Xpr>::Flags & DirectAccessBit) && bool(packet_traits<Scalar>::Vectorizable) &&
      !bool(internal::is_same<Scalar, bool>::value) && (int(inner_stride_at_compile_time<Xpr>::value) != 1);
};

template <typename Derived, typename Scalar = typename traits<Derived>::Scalar, typename Enable = void>
struct squared_norm_impl {
  using Real = typename NumTraits<Scalar>::Real;
  static EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Real run(const Derived& a) {
    return a.realView().cwiseAbs2().sum();
  }
};

template <typename Derived>
struct squared_norm_impl<Derived, bool, void> {
  static EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE bool run(const Derived& a) { return a.any(); }
};

// Runtime contiguity fast path: when the data is contiguous at runtime (inner stride 1, and a
// single inner panel or no gap between inner panels), reduce the underlying buffer as a contiguous
// vector, recovering vectorization of the abs2 reduction.
template <typename Derived, typename Scalar>
struct squared_norm_impl<Derived, Scalar, std::enable_if_t<squared_norm_runtime_unit_stride<Derived>::value>> {
  using Real = typename NumTraits<Scalar>::Real;
  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Real run(const Derived& a) {
    if (a.innerStride() == 1 && (a.outerSize() == 1 || a.outerStride() == a.innerSize())) {
      using PlainVector = Matrix<Scalar, Dynamic, 1>;
      Map<const PlainVector, evaluator<Derived>::Alignment> contiguous(a.data(), a.size());
      return contiguous.realView().cwiseAbs2().sum();
    }
    return a.realView().cwiseAbs2().sum();
  }
};

}  // end namespace internal

/** \fn MatrixBase::dot
 * \returns the dot product of *this with other.
 *
 * \only_for_vectors
 *
 * \note If the scalar type is complex numbers, then this function returns the hermitian
 * (sesquilinear) dot product, conjugate-linear in the first variable and linear in the
 * second variable.
 *
 * \sa squaredNorm(), norm()
 */
template <typename Derived>
template <typename OtherDerived>
EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE
    typename ScalarBinaryOpTraits<typename internal::traits<Derived>::Scalar,
                                  typename internal::traits<OtherDerived>::Scalar>::ReturnType
    MatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const {
  return internal::dot_impl<Derived, OtherDerived>::run(derived(), other.derived());
}

//---------- implementation of L2 norm and related functions ----------

/** \returns, for vectors, the squared \em l2 norm of \c *this, and for matrices the squared Frobenius norm.
 * In both cases, it consists in the sum of the square of all the matrix entries.
 * For vectors, this is also equal to the dot product of \c *this with itself.
 *
 * \sa dot(), norm(), lpNorm()
 */
template <typename Derived>
EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
MatrixBase<Derived>::squaredNorm() const {
  return internal::squared_norm_impl<Derived>::run(derived());
}

/** \returns, for vectors, the \em l2 norm of \c *this, and for matrices the Frobenius norm.
 * In both cases, it consists in the square root of the sum of the square of all the matrix entries.
 * For vectors, this is also equal to the square root of the dot product of \c *this with itself.
 *
 * \sa lpNorm(), dot(), squaredNorm()
 */
template <typename Derived>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
MatrixBase<Derived>::norm() const {
  return numext::sqrt(squaredNorm());
}

/** \returns an expression of the quotient of \c *this by its own norm.
 *
 * \warning If the input vector is too small (i.e., this->norm()==0),
 *          then this function returns a copy of the input.
 *
 * \only_for_vectors
 *
 * \sa norm(), normalize()
 */
template <typename Derived>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::PlainObject MatrixBase<Derived>::normalized()
    const {
  using Nested_ = typename internal::nested_eval<Derived, 2>::type;
  Nested_ n(derived());
  RealScalar z = n.squaredNorm();
  // NOTE: after extensive benchmarking, this conditional does not impact performance, at least on recent x86 CPU
  if (z > RealScalar(0))
    return n / numext::sqrt(z);
  else
    return n;
}

/** Normalizes the vector, i.e. divides it by its own norm.
 *
 * \only_for_vectors
 *
 * \warning If the input vector is too small (i.e., this->norm()==0), then \c *this is left unchanged.
 *
 * \sa norm(), normalized()
 */
template <typename Derived>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void MatrixBase<Derived>::normalize() {
  RealScalar z = squaredNorm();
  // NOTE: after extensive benchmarking, this conditional does not impact performance, at least on recent x86 CPU
  if (z > RealScalar(0)) derived() /= numext::sqrt(z);
}

/** \returns an expression of the quotient of \c *this by its own norm while avoiding underflow and overflow.
 *
 * \only_for_vectors
 *
 * This method is analogue to the normalized() method, but it reduces the risk of
 * underflow and overflow when computing the norm.
 *
 * \warning If the input vector is too small (i.e., this->norm()==0),
 *          then this function returns a copy of the input.
 *
 * \sa stableNorm(), stableNormalize(), normalized()
 */
template <typename Derived>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::PlainObject
MatrixBase<Derived>::stableNormalized() const {
  using Nested_ = typename internal::nested_eval<Derived, 3>::type;
  using NestedClean = internal::remove_all_t<Nested_>;
  using Accumulator = typename internal::stable_norm_accumulator<RealScalar>::type;
  using Dispatch = internal::stable_normalization_dispatch<NestedClean, Accumulator>;
  Nested_ vec(derived());
  if (EIGEN_PREDICT_FALSE(vec.size() == 0)) return vec;

  // Component-wise scaling stays finite when a finite complex value has an
  // overflowing magnitude, and avoids a hypot per coefficient.
  const Accumulator w = Dispatch::max_abs(vec);
  const Accumulator highest = static_cast<Accumulator>(NumTraits<RealScalar>::highest());
  if (EIGEN_PREDICT_FALSE(!(w > Accumulator(0)) || !(w <= highest))) return vec;

  if (EIGEN_PREDICT_TRUE((internal::stable_normalization_use_reciprocal<RealScalar, Accumulator>::run(w)))) {
    // Here w and its reciprocal are normal, so multiplication is safe.
    const Accumulator inv_w = Accumulator(1) / w;
    const Accumulator z = Dispatch::scaled_squared_norm(vec, inv_w);
    if (z > Accumulator(0)) {
      const Accumulator sqrt_z = numext::sqrt(z);
      const Accumulator factor = inv_w / sqrt_z;
      PlainObject normalized(rows(), cols());
      const Accumulator accumulator_normal_min =
          internal::stable_normalization_normal_min<Accumulator, Accumulator>::run();
      if (EIGEN_PREDICT_TRUE(factor >= accumulator_normal_min)) {
        Dispatch::assign_scaled(normalized, vec, factor);
      } else {
        // inv_w and sqrt_z are normal even though their quotient is not.
        Dispatch::assign_scaled(normalized, vec, inv_w);
        internal::stable_normalization_divide_in_place(normalized, static_cast<RealScalar>(sqrt_z));
      }
      return normalized;
    }
    return vec;
  }

  // Two normal divisors avoid an exceptional reciprocal and fast-math
  // reassociation into multiplication by 1 / w.
  const Accumulator sqrt_w = numext::sqrt(w);
  const RealScalar scale1 = static_cast<RealScalar>(sqrt_w);
  const RealScalar scale2 = static_cast<RealScalar>(w / sqrt_w);
  PlainObject normalized = vec;
  internal::stable_normalization_divide_in_place(normalized, scale1);
  internal::stable_normalization_divide_in_place(normalized, scale2);
  const Accumulator z = normalized.realView().template cast<Accumulator>().squaredNorm();
  if (z > Accumulator(0)) {
    internal::stable_normalization_scale_in_place(normalized, Accumulator(1) / numext::sqrt(z));
  }
  return normalized;
}

/** Normalizes the vector while avoid underflow and overflow
 *
 * \only_for_vectors
 *
 * This method is analogue to the normalize() method, but it reduces the risk of
 * underflow and overflow when computing the norm.
 *
 * \warning If the input vector is too small (i.e., this->norm()==0), then \c *this is left unchanged.
 *
 * \sa stableNorm(), stableNormalized(), normalize()
 */
template <typename Derived>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void MatrixBase<Derived>::stableNormalize() {
  using Accumulator = typename internal::stable_norm_accumulator<RealScalar>::type;
  using Dispatch = internal::stable_normalization_dispatch<Derived, Accumulator>;
  if (EIGEN_PREDICT_FALSE(size() == 0)) return;

  const Accumulator w = Dispatch::max_abs(derived());
  const Accumulator highest = static_cast<Accumulator>(NumTraits<RealScalar>::highest());
  if (EIGEN_PREDICT_FALSE(!(w > Accumulator(0)) || !(w <= highest))) return;

  if (EIGEN_PREDICT_TRUE((internal::stable_normalization_use_reciprocal<RealScalar, Accumulator>::run(w)))) {
    const Accumulator inv_w = Accumulator(1) / w;
    const Accumulator z = Dispatch::scaled_squared_norm(derived(), inv_w);
    if (z > Accumulator(0)) {
      const Accumulator sqrt_z = numext::sqrt(z);
      const Accumulator factor = inv_w / sqrt_z;
      const Accumulator accumulator_normal_min =
          internal::stable_normalization_normal_min<Accumulator, Accumulator>::run();
      if (EIGEN_PREDICT_TRUE(factor >= accumulator_normal_min)) {
        Dispatch::scale_in_place(derived(), factor);
      } else {
        internal::stable_normalization_scale_in_place(derived(), inv_w);
        internal::stable_normalization_divide_in_place(derived(), static_cast<RealScalar>(sqrt_z));
      }
    }
    return;
  }

  const Accumulator sqrt_w = numext::sqrt(w);
  const RealScalar scale1 = static_cast<RealScalar>(sqrt_w);
  const RealScalar scale2 = static_cast<RealScalar>(w / sqrt_w);
  internal::stable_normalization_divide_in_place(derived(), scale1);
  internal::stable_normalization_divide_in_place(derived(), scale2);
  const Accumulator z = derived().realView().template cast<Accumulator>().squaredNorm();
  if (z > Accumulator(0)) {
    internal::stable_normalization_scale_in_place(derived(), Accumulator(1) / numext::sqrt(z));
  }
}

//---------- implementation of other norms ----------

namespace internal {

template <typename Derived, int p>
struct lpNorm_selector {
  using RealScalar = typename NumTraits<typename traits<Derived>::Scalar>::Real;
  EIGEN_DEVICE_FUNC static inline RealScalar run(const MatrixBase<Derived>& m) {
    EIGEN_USING_STD(pow)
    return pow(m.cwiseAbs().array().pow(p).sum(), RealScalar(1) / p);
  }
};

template <typename Derived>
struct lpNorm_selector<Derived, 1> {
  EIGEN_DEVICE_FUNC static inline typename NumTraits<typename traits<Derived>::Scalar>::Real run(
      const MatrixBase<Derived>& m) {
    return m.cwiseAbs().sum();
  }
};

template <typename Derived>
struct lpNorm_selector<Derived, 2> {
  EIGEN_DEVICE_FUNC static inline typename NumTraits<typename traits<Derived>::Scalar>::Real run(
      const MatrixBase<Derived>& m) {
    return m.norm();
  }
};

template <typename Derived>
struct lpNorm_selector<Derived, Infinity> {
  using RealScalar = typename NumTraits<typename traits<Derived>::Scalar>::Real;
  EIGEN_DEVICE_FUNC static inline RealScalar run(const MatrixBase<Derived>& m) {
    if (Derived::SizeAtCompileTime == 0 || (Derived::SizeAtCompileTime == Dynamic && m.size() == 0))
      return RealScalar(0);
    return m.cwiseAbs().maxCoeff();
  }
};

}  // end namespace internal

/** \returns the \b coefficient-wise \f$ \ell^p \f$ norm of \c *this, that is, returns the p-th root of the sum of the
 * p-th powers of the absolute values of the coefficients of \c *this. If \a p is the special value \a Eigen::Infinity,
 * this function returns the \f$ \ell^\infty \f$ norm, that is the maximum of the absolute values of the coefficients of
 * \c *this.
 *
 * In all cases, if \c *this is empty, then the value 0 is returned.
 *
 * \note For matrices, this function does not compute the <a
 * href="https://en.wikipedia.org/wiki/Operator_norm">operator-norm</a>. That is, if \c *this is a matrix, then its
 * coefficients are interpreted as a 1D vector. Nonetheless, you can easily compute the 1-norm and \f$\infty\f$-norm
 * matrix operator norms using \link TutorialReductionsVisitorsBroadcastingReductionsNorm partial reductions \endlink.
 *
 * \sa norm()
 */
template <typename Derived>
template <int p>
#ifndef EIGEN_PARSED_BY_DOXYGEN
EIGEN_DEVICE_FUNC inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
#else
EIGEN_DEVICE_FUNC MatrixBase<Derived>::RealScalar
#endif
MatrixBase<Derived>::lpNorm() const {
  return internal::lpNorm_selector<Derived, p>::run(*this);
}

//---------- implementation of isOrthogonal / isUnitary ----------

/** \returns true if *this is approximately orthogonal to \a other,
 *          within the precision given by \a prec.
 *
 * Example: \include MatrixBase_isOrthogonal.cpp
 * Output: \verbinclude MatrixBase_isOrthogonal.out
 */
template <typename Derived>
template <typename OtherDerived>
bool MatrixBase<Derived>::isOrthogonal(const MatrixBase<OtherDerived>& other, const RealScalar& prec) const {
  typename internal::nested_eval<Derived, 2>::type nested(derived());
  typename internal::nested_eval<OtherDerived, 2>::type otherNested(other.derived());
  return numext::abs2(nested.dot(otherNested)) <= prec * prec * nested.squaredNorm() * otherNested.squaredNorm();
}

/** \returns true if *this is approximately an unitary matrix,
 *          within the precision given by \a prec. In the case where the \a Scalar
 *          type is real numbers, a unitary matrix is an orthogonal matrix, whence the name.
 *
 * \note This can be used to check whether a family of vectors forms an orthonormal basis.
 *       Indeed, \c m.isUnitary() returns true if and only if the columns (equivalently, the rows) of m form an
 *       orthonormal basis.
 *
 * Example: \include MatrixBase_isUnitary.cpp
 * Output: \verbinclude MatrixBase_isUnitary.out
 */
template <typename Derived>
bool MatrixBase<Derived>::isUnitary(const RealScalar& prec) const {
  typename internal::nested_eval<Derived, 1>::type self(derived());
  for (Index i = 0; i < cols(); ++i) {
    if (!internal::isApprox(self.col(i).squaredNorm(), static_cast<RealScalar>(1), prec)) return false;
    for (Index j = 0; j < i; ++j)
      if (!internal::isMuchSmallerThan(self.col(i).dot(self.col(j)), static_cast<Scalar>(1), prec)) return false;
  }
  return true;
}

}  // end namespace Eigen

#endif  // EIGEN_DOT_H
