#ifndef math_Transformation_H__
#define math_Transformation_H__
#include "Matrix.h"
#include "../Self.h"
#include <list>
#include <cstdlib>
namespace meow {
/*!
* @brief A base class for implementing kinds of transformations.
*
* We define that the input and output form of our transformations all be
* \b matrix . Some advance methods such as calculating jacobian matrix
* will require that the input form must be a vector.
* @author cat_leopard
*/
template<class Scalar>
class Transformation {
private:
struct Myself {
size_t inputRows_;
size_t inputCols_;
size_t outputRows_;
size_t outputCols_;
size_t psize_;
Myself(Myself const& b):
inputRows_(b.inputRows_), inputCols_(b.inputCols_),
outputRows_(b.outputRows_), outputCols_(b.outputCols_),
psize_(b.psize_) {
}
Myself(size_t ir, size_t ic, size_t or_, size_t oc, size_t ps):
inputRows_(ir), inputCols_(ic), outputRows_(or_), outputCols_(oc),
psize_(ps) {
}
~Myself() {
}
};
Self<Myself> const self;
protected:
/*!
* Construct and setup
* @param [in] inputRows number of rows of the input matrix.
* @param [in] inputCols number of columns of the input matrix.
* @param [in] outputRows number of rows of the output matrix.
* @param [in] outputCols number of columns of the output matrix.
* @param [in] psize number of parameters
*/
Transformation(size_t inputRows, size_t inputCols,
size_t outputRows, size_t outputCols,
size_t psize):
self(Myself(inputRows, inputCols, outputRows, outputCols, psize)) {
}
/*!
* Construct and copy setings from another transformation class.
* @param [in] b Specify where to copy the informations.
*/
Transformation(Transformation const& b):
self(b.self, Self<Myself>::COPY_FROM) {
}
/*!
* @brief Copy from the specified one
*
* @param [in] b The specified one
* @return \c *this
*/
Transformation& copyFrom(Transformation const& b) {
self().copyFrom(b.self);
return *this;
}
/*!
* @brief reference from the specified one
*
* @param [in] b The specified one
* @return \c *this
*/
Transformation& referenceFrom(Transformation const& b) {
self().referenceFrom(b.self);
return *this;
}
public:
/*!
* Destructor
*/
virtual ~Transformation() {
}
/*!
* @brief Return the number of rows of the input matrix.
*
* @return Number of rows.
*/
size_t inputRows() const {
return self->inputRows_;
}
/*!
* @brief Return the number of columns of the input matrix.
*
* @return Number of columns.
*/
size_t inputCols() const {
return self->inputCols_;
}
/*!
* @brief Return the number of rows of the output matrix.
*
* @return Number of rows.
*/
size_t outputRows() const {
return self->outputRows_;
}
/*!
* @brief Return the number of columns of the output matrix.
*
* @return Number of columns.
*/
size_t outputCols() const {
return self->outputCols_;
}
/*!
* @brief Return the number of parameters.
*
* @return Number of parameters.
*/
size_t parameterSize() const {
return self->psize_;
}
/*!
* @brief Get the \a i -th parameter.
*
* @param [in] i The index of the specified parameter.
* @note It's a pure virtual method.
*/
virtual Scalar parameter(size_t i) const = 0;
/*!
* @brief Setup the \a i -th parameter.
*
* @param [in] i The index of the specified parameter.
* @param [in] s The new value to the specified parameter.
* @note It's a pure virtual method.
*/
virtual Scalar parameter(size_t i, Scalar const& s) = 0;
/*!
* @brief Do transformate.
*
* @param [in] x The input matrix.
* @note It's a pure virtual method.
*/
virtual Matrix<Scalar> transformate(Matrix<Scalar> const& x) const = 0;
/*!
* @brief Calculate the jacobian matrix (derivate by the input matrix)
* of the transformation.
*
* Consider the case of a non-differentiable
* transformation might be implemented, we return an empty matrix
* now instead of making it be a pure virtual method.
* @param [in] x The input matrix.
* @return An empty matrix.
*/
virtual Matrix<Scalar> jacobian(Matrix<Scalar> const& x) const {
return Matrix<Scalar>();
}
/*!
* @brief Calculate the jacobian matrix (derivate by the \a i -th parameter)
* of the transformation.
*
* Consider the case of a non-differentiable transformation might be
* implemented, we return an empty matrix now instead of making it be
* a pure virtual method.
* @param [in] x The input matrix.
* @param [in] i The index of the specified parameter.
* @return An empty matrix.
*/
virtual Matrix<Scalar> jacobian(Matrix<Scalar> const& x, size_t i) const {
return Matrix<Scalar>();
}
/*!
* @brief Return whether this transformation is inversable or not
*
* @return \c false
*/
virtual bool inversable() const { return false; }
/*!
* @brief Do the inverse transformation
*
* @param [in] x The input matirx
* @return An empty matrix
*/
virtual Matrix<Scalar> transformateInv(Matrix<Scalar> const& x) const {
return Matrix<Scalar>();
}
/*!
* @brief Return the jacobian matrix of the inverse transformation
*
* @param [in] x The input matirx
* @return An empty matrix
*/
virtual Matrix<Scalar> jacobianInv(Matrix<Scalar> const& x) const {
return Matrix<Scalar>();
}
/*!
* @brief Return the jacobian matrix of the inverse transformation
*
* @param [in] x The input matirx
* @param [in] i The index of the specified parameter.
* @return An empty matrix
*/
virtual Matrix<Scalar> jacobianInv(Matrix<Scalar> const& x, size_t i) const {
return Matrix<Scalar>();
}
};
} // meow
#endif // math_Transformation_H__