/*
* This is free and unencumbered software released into the public domain.
*
* Anyone is free to copy, modify, publish, use, compile, sell, or
* distribute this software, either in source code form or as a compiled
* binary, for any purpose, commercial or non-commercial, and by any
* means.
*
* In jurisdictions that recognize copyright laws, the author or authors
* of this software dedicate any and all copyright interest in the
* software to the public domain. We make this dedication for the benefit
* of the public at large and to the detriment of our heirs and
* successors. We intend this dedication to be an overt act of
* relinquishment in perpetuity of all present and future rights to this
* software under copyright law.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* For more information, please refer to
*/
#ifndef SVD_H
#define SVD_H
#ifndef NO_OSTREAM
#include
#endif
namespace svd
{
class SMat3
{
public:
double m00, m01, m02, m11, m12, m22;
public:
SMat3();
SMat3(const double m00, const double m01, const double m02,
const double m11, const double m12, const double m22);
void clear() ;
void setSymmetric(const double m00, const double m01, const double m02,
const double m11,
const double m12, const double m22) ;
void setSymmetric(const SMat3 &rhs) ;
private:
SMat3(const SMat3 &rhs);
SMat3 &operator=(const SMat3 &rhs);
};
class Mat3
{
public:
double m00, m01, m02, m10, m11, m12, m20, m21, m22;
public:
Mat3();
Mat3(const double m00, const double m01, const double m02,
const double m10, const double m11, const double m12,
const double m20, const double m21, const double m22);
void clear() ;
void set(const double m00, const double m01, const double m02,
const double m10, const double m11, const double m12,
const double m20, const double m21, const double m22) ;
void set(const Mat3 &rhs) ;
void setSymmetric(const double a00, const double a01, const double a02,
const double a11, const double a12, const double a22) ;
void setSymmetric(const SMat3 &rhs);
private:
Mat3(const Mat3 &rhs);
Mat3 &operator=(const Mat3 &rhs);
};
class Vec3
{
public:
double x, y, z;
public:
Vec3();
Vec3(const double x, const double y, const double z);
void clear();
void set(const double x, const double y, const double z);
void set(const Vec3 &rhs);
private:
Vec3(const Vec3 &rhs);
Vec3 &operator=(const Vec3 &rhs);
};
#ifndef NO_OSTREAM
std::ostream &operator<<(std::ostream &os, const Mat3 &m) ;
std::ostream &operator<<(std::ostream &os, const SMat3 &m) ;
std::ostream &operator<<(std::ostream &os, const Vec3 &v) ;
#endif
class MatUtils
{
public:
static double fnorm(const Mat3 &a) ;
static double fnorm(const SMat3 &a) ;
static double off(const Mat3 &a) ;
static double off(const SMat3 &a) ;
public:
static void mmul(Mat3 &out, const Mat3 &a, const Mat3 &b) ;
static void mmul_ata(SMat3 &out, const Mat3 &a) ;
static void transpose(Mat3 &out, const Mat3 &a);
static void vmul(Vec3 &out, const Mat3 &a, const Vec3 &v) ;
static void vmul_symmetric(Vec3 &out, const SMat3 &a, const Vec3 &v) ;
};
class VecUtils
{
public:
static void addScaled(Vec3 &v, const double s, const Vec3 &rhs) ;
static double dot(const Vec3 &a, const Vec3 &b) ;
static void normalize(Vec3 &v) ;
static void scale(Vec3 &v, const double s) ;
static void sub(Vec3 &c, const Vec3 &a, const Vec3 &b) ;
};
class Givens
{
public:
static void rot01_post(Mat3 &m, const double c, const double s);
static void rot02_post(Mat3 &m, const double c, const double s);
static void rot12_post(Mat3 &m, const double c, const double s);
};
class Schur2
{
public:
static void rot01(SMat3 &out, double &c, double &s) ;
static void rot02(SMat3 &out, double &c, double &s) ;
static void rot12(SMat3 &out, double &c, double &s) ;
};
class Svd
{
public:
static void getSymmetricSvd(const SMat3 &a, SMat3 &vtav, Mat3 &v,
const double tol, const int max_sweeps);
static void pseudoinverse(Mat3 &out, const SMat3 &d, const Mat3 &v,
const double tol);
static double solveSymmetric(const SMat3 &A, const Vec3 &b, Vec3 &x,
const double svd_tol, const int svd_sweeps, const double pinv_tol);
};
class LeastSquares
{
public:
static double solveLeastSquares(const Mat3 &a, const Vec3 &b, Vec3 &x,
const double svd_tol, const int svd_sweeps, const double pinv_tol) ;
};
};
#endif