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 "RationalMatrix.h"
11#include <iostream>
12#include <iomanip>
13#include "IntegerMath.h"
15#include <cfloat> // FLT_EPSILON
16
17namespace gbLAB
18{
19
20 /**********************************************************************/
21 template <int dim>
22 std::pair<typename RationalMatrix<dim>::MatrixDimI, typename RationalMatrix<dim>::IntScalarType> RationalMatrix<dim>::compute(const RationalMatrix<dim>::MatrixDimD &R)
23 {
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 {
32 for (int j = 0; j < dim; ++j)
33 {
34 BestRationalApproximation bra(R(i, j), maxDen);
35 nums(i, j) = bra.num;
36 dens(i, j) = bra.den;
37 sigma = IntegerMath<IntScalarType>::lcm(sigma, bra.den);
38 }
39 }
40
41 MatrixDimI im(MatrixDimI::Zero());
42 for (int i = 0; i < dim; ++i)
43 {
44 for (int j = 0; j < dim; ++j)
45 {
46 im(i, j) = nums(i, j) * (sigma / dens(i, j));
47 }
48 }
49
50 const double error = (im.template cast<double>() / sigma - R).norm() / (dim * dim);
51 if (error > FLT_EPSILON)
52 {
53 std::cout << "error=" << error << std::endl;
54 std::cout << "maxDen=" << maxDen << std::endl;
55 std::cout << "im=\n"
56 << std::setprecision(15) << std::scientific << im.template cast<double>() / sigma << std::endl;
57 std::cout << "= 1/" << sigma << "*\n"
58 << std::setprecision(15) << std::scientific << im << std::endl;
59 std::cout << "R=\n"
60 << std::setprecision(15) << std::scientific << R << std::endl;
61 throw std::runtime_error("Rational Matrix failed, check maxDen");
62 }
63
64 return std::make_pair(im, sigma);
65 }
66
67 template <int dim>
68 std::pair<typename RationalMatrix<dim>::MatrixDimI, typename RationalMatrix<dim>::IntScalarType>
70 {
71 if(Rd.any()==0)
72 throw std::runtime_error("Rational Matrix construction failed: denominator matrix has zeros");
73 MatrixDimI im(MatrixDimI::Zero());
74 MatrixDimI RnReduced(Rn);
75 MatrixDimI RdReduced(Rd);
76
77 // reduce the ratios
78 for (int i = 0; i < dim; ++i)
79 {
80 for (int j = 0; j < dim; ++j)
81 {
82 RnReduced(i,j) = Rn(i,j) / IntegerMath<IntScalarType>::gcd(Rn(i,j),Rd(i,j));
83 RdReduced(i,j) = Rd(i,j) / IntegerMath<IntScalarType>::gcd(Rn(i,j),Rd(i,j));
84 }
85 }
86 IntScalarType sigma= IntegerMath<IntScalarType>::lcm(RdReduced.cwiseAbs());
87 for (int i = 0; i < dim; ++i)
88 {
89 for (int j = 0; j < dim; ++j)
90 {
91 im(i, j) = RnReduced(i, j) * sigma / RdReduced(i, j);
92 }
93 }
95 std::cout << Rn << std::endl;
96 std::cout << Rd << std::endl;
97 std::cout << RnReduced << std::endl;
98 std::cout << RdReduced << std::endl;
99 std::cout << im << std::endl;
100 std::cout << sigma <<std::endl;
101 }
102 assert(IntegerMath<IntScalarType>::gcd(IntegerMath<IntScalarType>::gcd(im.cwiseAbs()), sigma) == 1);
103 return std::make_pair(im, sigma);
104 }
105 /**********************************************************************/
106 template <int dim>
108 /* init */ returnPair(compute(R)),
109 /* init */ integerMatrix(returnPair.first),
110 /* init */ mu(returnPair.second)
111 {
112 }
113
114 template <int dim>
116 /* init */ returnPair(reduce(Rn,Rd)),
117 /* init */ integerMatrix(returnPair.first),
118 /* init */ mu(returnPair.second)
119 {
120 }
121 catch(std::runtime_error& e)
122 {
123 std::cout << e.what() << std::endl;
124 throw(std::runtime_error("Rational Matrix construction failed. "));
125 }
126 template <int dim>
128 /* init */ returnPair(std::make_pair(Rn, Rd)),
129 /* init */ integerMatrix(returnPair.first),
130 /* init */ mu(returnPair.second)
131 {
132 }
133
134 template <int dim>
136 {
137 return integerMatrix.template cast<double>()/mu;
138 }
139
140
141
142 template class RationalMatrix<1>;
143 template class RationalMatrix<2>;
144 template class RationalMatrix<3>;
145 template class RationalMatrix<4>;
146 template class RationalMatrix<5>;
147
148} // end namespace
149#endif
Eigen::Matrix< double, dim, dim > MatrixDimD
MatrixDimD asMatrix() const
long long int IntScalarType
RationalMatrix(const MatrixDimD &R)
static std::pair< MatrixDimI, IntScalarType > reduce(const MatrixDimI &Rn, const MatrixDimI &Rd)
Eigen::Matrix< IntScalarType, dim, dim > MatrixDimI
static std::pair< MatrixDimI, IntScalarType > compute(const MatrixDimD &R)
static IntScalarType gcd(const IntScalarType &a, const IntScalarType &b)
Definition IntegerMath.h:33
static IntScalarType lcm(const IntScalarType &a, const IntScalarType &b)
Definition IntegerMath.h:80