/* -*- C++ -*-
* This file is part of ART
*
* Copyright (c) 2022 Alberto Griggio
*
* RawTherapee is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* RawTherapee is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see .
*/
#pragma once
#include
namespace rtengine {
template
class Vec3 {
public:
Vec3() { data_[0] = data_[1] = data_[2] = T(); }
Vec3(T a, T b, T c) { data_[0] = a; data_[1] = b; data_[2] = c; }
template
Vec3(T2 const a[3]) { data_[0] = a[0]; data_[1] = a[1]; data_[2] = a[2]; }
Vec3 &operator=(const Vec3 &a) = default;
template
Vec3 &operator=(T2 const a[3])
{
data_[0] = a[0]; data_[1] = a[1]; data_[2] = a[2];
return *this;
}
T operator[](int i) const { return data_[i]; }
T &operator[](int i) { return data_[i]; }
operator const T *() const { return data_; }
operator T *() { return data_; }
private:
T data_[3];
};
typedef Vec3 Vec3f;
template
class Mat33 {
public:
Mat33()
{
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
data_[i][j] = T();
}
}
}
Mat33(T a00, T a01, T a02,
T a10, T a11, T a12,
T a20, T a21, T a22)
{
data_[0][0] = a00; data_[0][1] = a01; data_[0][2] = a02;
data_[1][0] = a10; data_[1][1] = a11; data_[1][2] = a12;
data_[2][0] = a20; data_[2][1] = a21; data_[2][2] = a22;
}
template
Mat33(const T2 m[3][3])
{
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
data_[i][j] = m[i][j];
}
}
}
Mat33 &operator=(const Mat33 &m) = default;
template
Mat33 &operator=(const T2 m[3][3])
{
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
data_[i][j] = m[i][j];
}
}
return *this;
}
T const *operator[](int i) const { return data_[i]; }
T *operator[](int i) { return data_[i]; }
typedef const T(*Data)[3];
operator Data() const { return data_; }
private:
T data_[3][3];
};
typedef Mat33 Mat33f;
template
Mat33 identity()
{
return Mat33(1, 0, 0, 0, 1, 0, 0, 0, 1);
}
template
Mat33 diagonal(T a, T b, T c)
{
return Mat33(a, 0, 0, 0, b, 0, 0, 0, c);
}
template
Mat33 transpose(T const m[3][3])
{
return Mat33(m[0][0], m[1][0], m[2][0],
m[0][1], m[1][1], m[2][1],
m[0][2], m[1][2], m[2][2]);
}
template
Mat33 transpose(const Mat33 &m)
{
return transpose(static_cast::Data>(m));
}
template
bool inverse(T const m[3][3], Mat33 &out)
{
const T res00 = m[1][1] * m[2][2] - m[2][1] * m[1][2];
const T res10 = m[2][0] * m[1][2] - m[1][0] * m[2][2];
const T res20 = m[1][0] * m[2][1] - m[2][0] * m[1][1];
const T det = m[0][0] * res00 + m[0][1] * res10 + m[0][2] * res20;
if (std::abs(det) >= 1.0e-10) {
out[0][0] = res00 / det;
out[0][1] = (m[2][1] * m[0][2] - m[0][1] * m[2][2]) / det;
out[0][2] = (m[0][1] * m[1][2] - m[1][1] * m[0][2]) / det;
out[1][0] = res10 / det;
out[1][1] = (m[0][0] * m[2][2] - m[2][0] * m[0][2]) / det;
out[1][2] = (m[1][0] * m[0][2] - m[0][0] * m[1][2]) / det;
out[2][0] = res20 / det;
out[2][1] = (m[2][0] * m[0][1] - m[0][0] * m[2][1]) / det;
out[2][2] = (m[0][0] * m[1][1] - m[1][0] * m[0][1]) / det;
return true;
} else {
return false;
}
}
template
Mat33 inverse(const Mat33 &m)
{
Mat33 res;
inverse(static_cast::Data>(m), res);
return res;
}
template
Mat33 inverse(T const m[3][3])
{
Mat33 res;
inverse(m, res);
return res;
}
template
bool inverse(const Mat33 &m, Mat33 &out)
{
return inverse(static_cast::Data>(m), out);
}
template
Mat33 dot_product(T const a[3][3], T const b[3][3])
{
Mat33 res;
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
res[i][j] = 0;
for (int k = 0; k < 3; ++k) {
res[i][j] += a[i][k] * b[k][j];
}
}
}
return res;
}
template
Mat33 dot_product(const Mat33 &a, T const b[3][3])
{
return dot_product(static_cast::Data>(a), b);
}
template
Mat33 dot_product(T const a[3][3], const Mat33 &b)
{
return dot_product(a, static_cast::Data>(b));
}
template
Mat33 dot_product(const Mat33 &a, const Mat33 &b)
{
return dot_product(static_cast::Data>(a), static_cast::Data>(b));
}
template
Vec3 dot_product(T const a[3][3], T const b[3])
{
Vec3 res;
for (int i = 0; i < 3; ++i) {
res[i] = 0;
for (int k = 0; k < 3; ++k) {
res[i] += a[i][k] * b[k];
}
}
return res;
}
template
Vec3 dot_product(const Mat33 &a, T const b[3])
{
return dot_product(static_cast::Data>(a), b);
}
template
Vec3 dot_product(T const a[3][3], const Vec3 &b)
{
return dot_product(a, static_cast(b));
}
template
Vec3 dot_product(const Mat33 &a, const Vec3 &b)
{
return dot_product(static_cast::Data>(a), static_cast(b));
}
template
Mat33 operator*(const Mat33 &m, T v)
{
return Mat33(m[0][0] * v, m[0][1] * v, m[0][2] * v,
m[1][0] * v, m[1][1] * v, m[1][2] * v,
m[2][0] * v, m[2][1] * v, m[2][2] * v);
}
template
Vec3 operator*(const Vec3 &a, T v)
{
return Vec3(a[0] * v, a[1] * v, a[2] * v);
}
} // namespace rtengine