oILAB
Loading...
Searching...
No Matches
RationalMatrix.cpp
Go to the documentation of this file.
1/* This file is part of gbLAB.
2 *
3 * gbLAB is distributed without any warranty under the MIT License.
4 */
5
6
7#ifndef gbLAB_RationalMatrix_cpp_
8#define gbLAB_RationalMatrix_cpp_
9
10#include "../../include/Math/RationalMatrix.h"
11#include "../../include/Math/BestRationalApproximation.h"
12#include "../../include/Math/IntegerMath.h"
13#include <cfloat> // FLT_EPSILON
14#include <iomanip>
15#include <iostream>
16
17namespace oILAB {
18
19/**********************************************************************/
20template <int dim>
21std::pair<typename RationalMatrix<dim>::MatrixDimI,
24
25 // Find the BestRationalApproximation of each entry
26 MatrixDimI nums(MatrixDimI::Zero());
27 MatrixDimI dens(MatrixDimI::Ones());
28
29 IntScalarType sigma = 1;
30 for (int i = 0; i < dim; ++i) {
31 for (int j = 0; j < dim; ++j) {
32 BestRationalApproximation bra(R(i, j), maxDen);
33 nums(i, j) = bra.num;
34 dens(i, j) = bra.den;
35 sigma = IntegerMath<IntScalarType>::lcm(sigma, bra.den);
36 }
37 }
38
39 MatrixDimI im(MatrixDimI::Zero());
40 for (int i = 0; i < dim; ++i) {
41 for (int j = 0; j < dim; ++j) {
42 im(i, j) = nums(i, j) * (sigma / dens(i, j));
43 }
44 }
45
46 const double error =
47 (im.template cast<double>() / sigma - R).norm() / (dim * dim);
48 if (error > FLT_EPSILON) {
49 std::cout << "error=" << error << std::endl;
50 std::cout << "maxDen=" << maxDen << std::endl;
51 std::cout << "im=\n"
52 << std::setprecision(15) << std::scientific
53 << im.template cast<double>() / sigma << std::endl;
54 std::cout << "= 1/" << sigma << "*\n"
55 << std::setprecision(15) << std::scientific << im << std::endl;
56 std::cout << "R=\n"
57 << std::setprecision(15) << std::scientific << R << std::endl;
58 throw std::runtime_error("Rational Matrix failed, check maxDen");
59 }
60
61 return std::make_pair(im, sigma);
62 }
63
64 template <int dim>
65 std::pair<typename RationalMatrix<dim>::MatrixDimI, typename RationalMatrix<dim>::IntScalarType>
67 {
68 if(Rd.any()==0)
69 throw std::runtime_error("Rational Matrix construction failed: denominator matrix has zeros");
70 MatrixDimI im(MatrixDimI::Zero());
71 MatrixDimI RnReduced(Rn);
72 MatrixDimI RdReduced(Rd);
73
74 // reduce the ratios
75 for (int i = 0; i < dim; ++i)
76 {
77 for (int j = 0; j < dim; ++j)
78 {
79 RnReduced(i,j) = Rn(i,j) / IntegerMath<IntScalarType>::gcd(Rn(i,j),Rd(i,j));
80 RdReduced(i,j) = Rd(i,j) / IntegerMath<IntScalarType>::gcd(Rn(i,j),Rd(i,j));
81 }
82 }
83 IntScalarType sigma= IntegerMath<IntScalarType>::lcm(RdReduced.cwiseAbs());
84 for (int i = 0; i < dim; ++i)
85 {
86 for (int j = 0; j < dim; ++j)
87 {
88 im(i, j) = RnReduced(i, j) * sigma / RdReduced(i, j);
89 }
90 }
92 std::cout << Rn << std::endl;
93 std::cout << Rd << std::endl;
94 std::cout << RnReduced << std::endl;
95 std::cout << RdReduced << std::endl;
96 std::cout << im << std::endl;
97 std::cout << sigma <<std::endl;
98 }
99 assert(IntegerMath<IntScalarType>::gcd(IntegerMath<IntScalarType>::gcd(im.cwiseAbs()), sigma) == 1);
100 return std::make_pair(im, sigma);
101 }
102 /**********************************************************************/
103 template <int dim>
105 /* init */ returnPair(compute(R)),
106 /* init */ integerMatrix(returnPair.first),
107 /* init */ mu(returnPair.second)
108 {
109 }
110
111 template <int dim>
113 /* init */ returnPair(reduce(Rn,Rd)),
114 /* init */ integerMatrix(returnPair.first),
115 /* init */ mu(returnPair.second)
116 {
117 }
118 catch(std::runtime_error& e)
119 {
120 std::cout << e.what() << std::endl;
121 throw(std::runtime_error("Rational Matrix construction failed. "));
122 }
123 template <int dim>
125 /* init */ returnPair(std::make_pair(Rn, Rd)),
126 /* init */ integerMatrix(returnPair.first),
127 /* init */ mu(returnPair.second)
128 {
129 }
130
131 template <int dim>
133 {
134 return integerMatrix.template cast<double>()/mu;
135 }
136
137
138
139 template class RationalMatrix<1>;
140 template class RationalMatrix<2>;
141 template class RationalMatrix<3>;
142 template class RationalMatrix<4>;
143 template class RationalMatrix<5>;
144
145 } // namespace oILAB
146#endif
static std::pair< MatrixDimI, IntScalarType > compute(const MatrixDimD &R)
Eigen::Matrix< IntScalarType, dim, dim > MatrixDimI
static std::pair< MatrixDimI, IntScalarType > reduce(const MatrixDimI &Rn, const MatrixDimI &Rd)
RationalMatrix(const MatrixDimD &R)
Eigen::Matrix< double, dim, dim > MatrixDimD
MatrixDimD asMatrix() const
long long int IntScalarType
static IntScalarType lcm(const IntScalarType &a, const IntScalarType &b)
Definition IntegerMath.h:65
static IntScalarType gcd(const IntScalarType &a, const IntScalarType &b)
Definition IntegerMath.h:26