linear_algebra_system.hpp 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. #ifndef __LINEAR_ALGEBRA_SYSTEM_SOLE_CRAMERS_METHOD_HPP__
  2. #define __LINEAR_ALGEBRA_SYSTEM_SOLE_CRAMERS_METHOD_HPP__
  3. #include <cstdint>
  4. #include <cstddef>
  5. #include <array>
  6. #include <tuple>
  7. namespace math::linear_algebra_system
  8. {
  9. typedef long double ld;
  10. template<typename MatrixType, size_t Rows, size_t Columns,
  11. std::enable_if_t<
  12. std::is_integral<MatrixType>::value,
  13. int64_t
  14. > = 0
  15. > using matrix = std::array<std::array<MatrixType, Rows>, Columns>;
  16. template<typename MatrixType,
  17. std::enable_if_t<
  18. std::is_integral<MatrixType>::value,
  19. int64_t
  20. > = 0
  21. > using matrix_3x3 = matrix<MatrixType, 3, 3>;
  22. namespace cramers_method
  23. {
  24. enum class DeltaType : uint8_t
  25. {
  26. X, Y, Z
  27. };
  28. template<typename MatrixType,
  29. std::enable_if_t<
  30. std::is_integral<MatrixType>::value,
  31. int64_t
  32. > = 0
  33. > constexpr auto
  34. compute_delta(const matrix_3x3<MatrixType> matrix)
  35. {
  36. if (!(matrix.size() >= 3 && matrix[0].size() >= 3)) {
  37. throw std::runtime_error("Matrix must be 3x3!");
  38. }
  39. return (
  40. ((matrix[0][0] * matrix[1][1] * matrix[2][2]) +
  41. (matrix[0][2] * matrix[2][1] * matrix[1][0]) +
  42. (matrix[0][1] * matrix[1][2] * matrix[2][0]))
  43. -
  44. ((matrix[0][2] * matrix[1][1] * matrix[2][0]) +
  45. (matrix[0][1] * matrix[1][0] * matrix[2][2]) +
  46. (matrix[0][0] * matrix[1][2] * matrix[2][1]))
  47. );
  48. }
  49. template<typename MatrixType,
  50. std::enable_if_t<
  51. std::is_integral<MatrixType>::value,
  52. int64_t
  53. > = 0
  54. > constexpr auto
  55. compute_delta(matrix_3x3<MatrixType> matrix, const DeltaType delta_type,
  56. const std::tuple<MatrixType, MatrixType, MatrixType>& b_values)
  57. {
  58. if (!(matrix.size() >= 3 && matrix[0].size() >= 3)) {
  59. throw std::runtime_error("Matrix must be 3x3!");
  60. }
  61. switch (delta_type) {
  62. case DeltaType::X: std::tie(matrix[0][0], matrix[1][0], matrix[2][0]) = b_values; break;
  63. case DeltaType::Y: std::tie(matrix[0][1], matrix[1][1], matrix[2][1]) = b_values; break;
  64. case DeltaType::Z: std::tie(matrix[0][2], matrix[1][2], matrix[2][2]) = b_values; break;
  65. }
  66. return compute_delta(matrix);
  67. }
  68. template<typename MatrixType,
  69. std::enable_if_t<
  70. std::is_integral<MatrixType>::value,
  71. int64_t
  72. > = 0
  73. > inline constexpr auto
  74. compute_all(const matrix_3x3<MatrixType> matrix, const std::tuple<MatrixType, MatrixType, MatrixType>& b_values)
  75. {
  76. const auto delta {compute_delta(matrix)};
  77. return std::make_tuple(compute_delta(matrix, DeltaType::X, b_values) / static_cast<ld>(delta),
  78. compute_delta(matrix, DeltaType::Y, b_values) / static_cast<ld>(delta),
  79. compute_delta(matrix, DeltaType::Z, b_values) / static_cast<ld>(delta));
  80. }
  81. } // namespace cramers_method
  82. } // namespace math::linear_algebra_system
  83. #endif // __LINEAR_ALGEBRA_SYSTEM_SOLE_CRAMERS_METHOD_HPP__