// 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/.
// SPDX-License-Identifier: 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 represents 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: return an expression instead of a dense matrix.
  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
