// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// 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/.

#ifndef EIGEN_SCALING_H
#define EIGEN_SCALING_H

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

namespace Eigen {

/** \geometry_module \ingroup Geometry_Module
 *
 * \class UniformScaling
 *
 * \brief Represents a generic uniform scaling transformation
 *
 * \tparam Scalar_ the scalar type, i.e., the type of the coefficients.
 *
 * This class represent a uniform scaling transformation. It is the return
 * type of Scaling(Scalar), and most of the time this is the only way it
 * is used. In particular, this class is not aimed to be used to store a scaling transformation,
 * but rather to make easier the constructions and updates of Transform objects.
 *
 * To represent an axis aligned scaling, use the DiagonalMatrix class.
 *
 * \sa Scaling(), class DiagonalMatrix, MatrixBase::asDiagonal(), class Translation, class Transform
 */

namespace internal {
// This helper helps nvcc+MSVC to properly parse this file.
// See bug 1412.
template <typename Scalar, int Dim, int Mode>
struct uniformscaling_times_affine_returntype {
  enum { NewMode = int(Mode) == int(Isometry) ? Affine : Mode };
  typedef Transform<Scalar, Dim, NewMode> type;
};
}  // namespace internal

template <typename Scalar_>
class UniformScaling {
 public:
  /** the scalar type of the coefficients */
  typedef Scalar_ Scalar;

 protected:
  Scalar m_factor;

 public:
  /** Default constructor without initialization. */
  UniformScaling() {}
  /** Constructs and initialize a uniform scaling transformation */
  explicit inline UniformScaling(const Scalar& s) : m_factor(s) {}

  inline const Scalar& factor() const { return m_factor; }
  inline Scalar& factor() { return m_factor; }

  /** Concatenates two uniform scaling */
  inline UniformScaling operator*(const UniformScaling& other) const {
    return UniformScaling(m_factor * other.factor());
  }

  /** Concatenates a uniform scaling and a translation */
  template <int Dim>
  inline Transform<Scalar, Dim, Affine> operator*(const Translation<Scalar, Dim>& t) const;

  /** Concatenates a uniform scaling and an affine transformation */
  template <int Dim, int Mode, int Options>
  inline typename internal::uniformscaling_times_affine_returntype<Scalar, Dim, Mode>::type operator*(
      const Transform<Scalar, Dim, Mode, Options>& t) const {
    typename internal::uniformscaling_times_affine_returntype<Scalar, Dim, Mode>::type res = t;
    res.prescale(factor());
    return res;
  }

  /** Concatenates a uniform scaling and a linear transformation matrix */
  // TODO returns an expression
  template <typename Derived>
  inline typename Eigen::internal::plain_matrix_type<Derived>::type operator*(const MatrixBase<Derived>& other) const {
    return other * m_factor;
  }

  template <typename Derived, int Dim>
  inline Matrix<Scalar, Dim, Dim> operator*(const RotationBase<Derived, Dim>& r) const {
    return r.toRotationMatrix() * m_factor;
  }

  /** \returns the inverse scaling */
  inline UniformScaling inverse() const { return UniformScaling(Scalar(1) / m_factor); }

  /** \returns \c *this with scalar type casted to \a NewScalarType
   *
   * Note that if \a NewScalarType is equal to the current scalar type of \c *this
   * then this function smartly returns a const reference to \c *this.
   */
  template <typename NewScalarType>
  inline UniformScaling<NewScalarType> cast() const {
    return UniformScaling<NewScalarType>(NewScalarType(m_factor));
  }

  /** Copy constructor with scalar type conversion */
  template <typename OtherScalarType>
  inline explicit UniformScaling(const UniformScaling<OtherScalarType>& other) {
    m_factor = Scalar(other.factor());
  }

  /** \returns \c true if \c *this is approximately equal to \a other, within the precision
   * determined by \a prec.
   *
   * \sa MatrixBase::isApprox() */
  bool isApprox(const UniformScaling& other,
                const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const {
    return internal::isApprox(m_factor, other.factor(), prec);
  }
};

/** \addtogroup Geometry_Module */
//@{

/** Concatenates a linear transformation matrix and a uniform scaling
 * \relates UniformScaling
 */
// NOTE this operator is defined in MatrixBase and not as a friend function
// of UniformScaling to fix an internal crash of Intel's ICC
template <typename Derived, typename Scalar>
EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(Derived, Scalar, product)
operator*(const MatrixBase<Derived>& matrix, const UniformScaling<Scalar>& s) {
  return matrix.derived() * s.factor();
}

/** Constructs a uniform scaling from scale factor \a s */
inline UniformScaling<float> Scaling(float s) { return UniformScaling<float>(s); }
/** Constructs a uniform scaling from scale factor \a s */
inline UniformScaling<double> Scaling(double s) { return UniformScaling<double>(s); }
/** Constructs a uniform scaling from scale factor \a s */
template <typename RealScalar>
inline UniformScaling<std::complex<RealScalar> > Scaling(const std::complex<RealScalar>& s) {
  return UniformScaling<std::complex<RealScalar> >(s);
}

/** Constructs a 2D axis aligned scaling */
template <typename Scalar>
inline DiagonalMatrix<Scalar, 2> Scaling(const Scalar& sx, const Scalar& sy) {
  return DiagonalMatrix<Scalar, 2>(sx, sy);
}
/** Constructs a 3D axis aligned scaling */
template <typename Scalar>
inline DiagonalMatrix<Scalar, 3> Scaling(const Scalar& sx, const Scalar& sy, const Scalar& sz) {
  return DiagonalMatrix<Scalar, 3>(sx, sy, sz);
}

/** Constructs an axis aligned scaling expression from vector expression \a coeffs
 * This is an alias for coeffs.asDiagonal()
 */
template <typename Derived>
inline const DiagonalWrapper<const Derived> Scaling(const MatrixBase<Derived>& coeffs) {
  return coeffs.asDiagonal();
}

/** Constructs an axis aligned scaling expression from vector \a coeffs when passed as an rvalue reference */
template <typename Derived>
inline typename DiagonalWrapper<const Derived>::PlainObject Scaling(MatrixBase<Derived>&& coeffs) {
  return typename DiagonalWrapper<const Derived>::PlainObject(std::move(coeffs.derived()));
}

/** \deprecated */
typedef DiagonalMatrix<float, 2> AlignedScaling2f;
/** \deprecated */
typedef DiagonalMatrix<double, 2> AlignedScaling2d;
/** \deprecated */
typedef DiagonalMatrix<float, 3> AlignedScaling3f;
/** \deprecated */
typedef DiagonalMatrix<double, 3> AlignedScaling3d;
//@}

template <typename Scalar>
template <int Dim>
inline Transform<Scalar, Dim, Affine> UniformScaling<Scalar>::operator*(const Translation<Scalar, Dim>& t) const {
  Transform<Scalar, Dim, Affine> res;
  res.matrix().setZero();
  res.linear().diagonal().fill(factor());
  res.translation() = factor() * t.vector();
  res(Dim, Dim) = Scalar(1);
  return res;
}

}  // end namespace Eigen

#endif  // EIGEN_SCALING_H
