7 const std::shared_ptr<SymbolicExpr>& A,
17 "matrix input cannot be null",
24 "input must be a matrix",
27 if (require_square && matrix->rows() != matrix->cols()) {
30 "matrix must be square",
37 const std::shared_ptr<SymbolicExpr>& expr,
38 const std::string&
name,
45 name +
" output is not a matrix",
53 for (
const auto& operand :
add.operands()) {
55 if (!
value)
return std::nullopt;
63 for (
const auto& operand :
mul.operands()) {
65 if (!
value)
return std::nullopt;
66 product = product * *
value;
73 if (!
node)
return std::nullopt;
74 if (
auto number = std::dynamic_pointer_cast<const NumberNode>(
node)) {
77 if (
auto add = std::dynamic_pointer_cast<const AddNode>(
node)) {
78 return exact_rational_sum(*
add);
80 if (
auto mul = std::dynamic_pointer_cast<const MultiplyNode>(
node)) {
81 return exact_rational_product(*
mul);
83 if (
auto fn = std::dynamic_pointer_cast<const FunctionNode>(
node)) {
86 if (!
value)
return std::nullopt;
98 (
context).limits().max_ast_nodes,
"transform");
111 return simplify_exact_rational_expr(
node,
context);
115 if (
value.get_denominator() == BigInt(1)) {
125 if (!matrix)
return std::nullopt;
126 std::vector<std::vector<Rational>> values(
127 matrix->rows(), std::vector<Rational>(matrix->cols(), Rational(0)));
128 for (
size_t row = 0; row < matrix->rows(); ++row) {
129 for (
size_t col = 0; col < matrix->cols(); ++col) {
130 const auto&
node = matrix->get(row, col);
135 if (!
value)
return std::nullopt;
136 values[row][col] = *
value;
142 std::vector<std::vector<std::shared_ptr<SymbolicExpr>>> grid(
143 n, std::vector<std::shared_ptr<SymbolicExpr>>(n, SymbolicExpr::number(0)));
144 for (
size_t i = 0; i < n; ++i) {
145 grid[i][i] = SymbolicExpr::number(1);
147 return SymbolicExpr::matrix(grid);
153 if (!values)
return std::nullopt;
154 const size_t rows = values->size();
155 const size_t cols = rows == 0 ? 0 : (*values)[0].size();
156 const size_t diag_count = std::min(rows, cols);
157 std::vector<Rational> diagonal(diag_count, Rational(0));
158 for (
size_t row = 0; row < rows; ++row) {
159 for (
size_t col = 0; col < cols; ++col) {
160 const bool is_diag = row == col && row < diag_count;
161 if (!is_diag && (*values)[row][col] != Rational(0)) {
165 diagonal[row] = (*values)[row][col];
175 if (!values)
return std::nullopt;
176 const size_t rows = values->size();
177 const size_t cols = rows == 0 ? 0 : (*values)[0].size();
178 if (rows != cols)
return std::nullopt;
179 std::vector<Rational> diagonal(rows, Rational(0));
180 for (
size_t row = 0; row < rows; ++row) {
181 for (
size_t col = 0; col < cols; ++col) {
183 diagonal[row] = (*values)[row][col];
184 }
else if ((*values)[row][col] != Rational(0)) {
195 const std::vector<Rational>& diagonal) {
196 std::vector<std::vector<std::shared_ptr<SymbolicExpr>>> grid(
197 rows, std::vector<std::shared_ptr<SymbolicExpr>>(cols, SymbolicExpr::number(0)));
198 for (
size_t i = 0; i < diagonal.size(); ++i) {
201 return SymbolicExpr::matrix(grid);
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(T value)
std::optional< Rational > exact_rational_product(const MultiplyNode &mul)
std::optional< Rational > simplify_exact_rational_expr(const std::shared_ptr< const SymbolicNode > &node, ComputationContext &context)
std::optional< Rational > exact_rational_sum(const AddNode &add)
std::shared_ptr< SymbolicExpr > identity_matrix_expr(std::size_t n)
std::shared_ptr< SymbolicExpr > exact_number_expr(const Rational &value)
std::optional< Rational > exact_rational_expr(const std::shared_ptr< const SymbolicNode > &node)
std::optional< std::vector< Rational > > exact_diagonal_entries(const std::shared_ptr< const MatrixNode > &matrix, ComputationContext &context)
std::shared_ptr< SymbolicExpr > rectangular_diagonal_expr(std::size_t rows, std::size_t cols, const std::vector< Rational > &diagonal)
Result< std::shared_ptr< const MatrixNode > > validate_decomposition_matrix(const std::shared_ptr< SymbolicExpr > &A, bool require_square, ComputationContext &context, const std::string &operation)
std::optional< std::vector< Rational > > exact_rectangular_diagonal_entries(const std::shared_ptr< const MatrixNode > &matrix, ComputationContext &context)
Result< void > validate_decomposition_output(const std::shared_ptr< SymbolicExpr > &expr, const std::string &name, const std::string &operation)
std::optional< std::vector< std::vector< Rational > > > exact_rational_matrix(const std::shared_ptr< const MatrixNode > &matrix, ComputationContext &context)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
std::shared_ptr< const Node > make_node(Args &&... args)
ComputationContext const std::string & operation
std::optional< Rational > exact_rational_value(const NumberNode &number)
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
std::size_t std::size_t ComputationContext & context
ExprResult mul(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
ExprResult add(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
const std::string const ExprPtr & value
__attribute__((visibility("default"))) Result< EqvProfile > eqv_profile_from_name(const std const std::string & name