257 lines
6.8 KiB
C++

// Copyright 2018 Slightech Co., Ltd. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#ifndef SRC_MYNTEYE_API_CAMERA_MODELS_models_MATRIX_SOLVER_H_
#define SRC_MYNTEYE_API_CAMERA_MODELS_models_MATRIX_SOLVER_H_
#include <cmath>
#include <complex>
#include "mynteye/mynteye.h"
MYNTEYE_BEGIN_NAMESPACE
static bool Matrix_EigenValue(double *k1, int n,
int loop_number, double error1, double *ret);
static void Matrix_Hessenberg(double *a1, int n, double *ret);
namespace models {
class EigenSolver {
public:
explicit EigenSolver(SMatrix<double> s) {
double *A = new double[s.rows()*2];
double *B = new double[s.size()];
for (int i = 0; i < s.size(); i++)
B[i] = s(i);
memset(A, 0, sizeof(s.rows()*2));
Matrix_EigenValue(B, s.rows(), 1000, 1e-10, A);
Matrix<double> tt(A, s.rows(), 2);
t = tt;
SMatrix<double> s2(A, s.rows());
delete []A;
delete []B;
}
Matrix<double> eigenvalues(void) {
return t;
}
private:
Matrix<double> t;
};
} // namespace models
static void Matrix_Hessenberg(double *a1, int n, double *ret) {
int MaxNumber;
double temp, *A;
A = new double[n*n];
memset(A, 0, sizeof(double)*n*n);
for (int i = 0; i < n; i++) {
int k = i * n;
for (int j = 0; j < n; j++) {
A[k + j] = a1[k + j];
}
}
for (int k = 1; k < n-1; k++) {
int i = k-1;
MaxNumber = k;
temp = fabs(A[k*n+i]);
for (int j = k+1; j < n; j++) {
if (fabs(A[j * n + i]) > temp) {
temp = fabs(A[j * n + i]);
MaxNumber = j;
}
}
ret[0] = A[MaxNumber * n + i];
if (ret[0] != 0) {
if (MaxNumber != k) {
for (int j = k-1; j < n; j++) {
temp = A[i * n + j];
A[i * n + j] = A[k * n + j];
A[k * n + j] = temp;
}
for (int j = 0; j < n; j++) {
temp = A[j * n + i];
A[j * n + i] = A[j * n + k];
A[j * n + k] = temp;
}
}
for (int i = k + 1; i < n; i++) {
temp = A[i * n + k - 1] / ret[0];
A[i * n + k - 1] = 0;
for (int j = k; j < n; j++) {
A[i * n + j] -= temp * A[k * n + j];
}
for (int j = 0; j < n; j++) {
A[j * n + k] += temp * A[j * n + i];
}
}
}
}
for (int i = 0; i < n; i++) {
int k = i * n;
for (int j = 0; j < n; j++) {
ret[k + j] = A[k + j];
}
}
delete []A;
}
static bool Matrix_EigenValue(double *k1, int n,
int loop_number, double error1, double *ret) {
int i, j, k, t, m, Loop1;
double b, c, d, g, xy, p, q, r, x, s, e, f, z, y, temp, *A;
A = new double[n * n];
memset(A, 0, sizeof(double) * n * n);
Matrix_Hessenberg(k1, n, A);
m = n;
Loop1 = loop_number;
while (m != 0) {
t = m - 1;
while (t > 0) {
temp = fabs(A[(t - 1) * n + t - 1]);
temp += fabs(A[t * n + t]);
temp = temp * error1;
if (fabs(A[t * n + t - 1]) > temp) {
t--;
} else {
break;
}
}
if (t == m-1) {
ret[(m - 1) * 2] = A[(m - 1) * n + m - 1];
ret[(m - 1) * 2 + 1] = 0;
m -= 1;
Loop1 = loop_number;
} else if (t == m - 2) {
b = -A[(m - 1) * n + m - 1] - A[(m - 2) * n + m - 2];
c = A[(m - 1) * n + m - 1] * A[(m - 2) * n + m - 2]
- A[(m - 1) * n + m - 2] * A[(m - 2) * n + m - 1];
d = b * b - 4 * c;
y = sqrt(fabs(d));
if (d > 0) {
xy = 1;
if (b < 0) {
xy = -1;
}
ret[(m - 1) * 2] = -(b + xy * y) / 2;
ret[(m - 1) * 2 + 1] = 0;
ret[(m - 2) * 2] = c / ret[(m - 1) * 2];
ret[(m - 2) * 2 + 1] = 0;
} else {
ret[(m - 1) * 2] = -b / 2;
ret[(m - 2) * 2] = -b / 2;
ret[(m - 1) * 2 + 1] = y / 2;
ret[(m - 2) * 2 + 1] = -y / 2;
}
m -= 2;
Loop1 = loop_number;
} else {
if (Loop1 < 1) {
delete []A;
return false;
}
Loop1--;
j = t + 2;
while (j < m) {
A[j * n + j - 2] = 0;
j++;
}
j = t + 3;
while (j < m) {
A[j * n + j - 3] = 0;
j++;
}
k = t;
while (k < m - 1) {
if (k != t) {
p = A[k * n + k - 1];
q = A[(k + 1) * n + k - 1];
if (k != m - 2) {
r = A[(k + 2) * n + k - 1];
} else {
r = 0;
}
} else {
b = A[(m - 1) * n + m - 1];
c = A[(m - 2) * n + m - 2];
x = b + c;
y = b * c - A[(m - 2) * n + m - 1] * A[(m - 1) * n + m - 2];
p = A[t * n + t] * (A[t * n + t] - x) +
A[t * n + t + 1] * A[(t + 1) * n + t] + y;
q = A[(t + 1) * n + t] * (A[t * n + t] + A[(t + 1) * n + t + 1] - x);
r = A[(t + 1) * n + t] * A[(t + 2) * n + t + 1];
}
if (p != 0 || q != 0 || r != 0) {
if (p < 0) {
xy = -1;
} else {
xy = 1;
}
s = xy * sqrt(p * p + q * q + r * r);
if (k != t) {
A[k * n + k - 1]= -s;
}
e = -q / s;
f = -r / s;
x = -p / s;
y = -x - f * r / (p + s);
g = e * r / (p + s);
z = -x - e * q / (p + s);
for (j = k; j < m; j++) {
b = A[k * n + j];
c = A[(k + 1) * n + j];
p = x * b + e * c;
q = e * b + y * c;
r = f * b + g * c;
if (k != m - 2) {
b = A[(k + 2) * n + j];
p += f * b;
q += g * b;
r += z * b;
A[(k + 2) * n + j] = r;
}
A[(k + 1) * n + j] = q;
A[k * n + j] = p;
}
j = k + 3;
if (j > m - 2) {
j = m - 1;
}
for (i = t; i < j + 1; i++) {
b = A[i * n + k];
c = A[i * n + k + 1];
p = x * b + e * c;
q = e * b + y * c;
r = f * b + g * c;
if (k != m - 2) {
b = A[i * n + k + 2];
p += f * b;
q += g * b;
r += z * b;
A[i * n + k + 2] = r;
}
A[i * n + k + 1] = q;
A[i * n + k] = p;
}
}
k++;
}
}
}
delete []A;
return true;
}
MYNTEYE_END_NAMESPACE
#endif // SRC_MYNTEYE_API_CAMERA_MODELS_models_MATRIX_SOLVER_H_