Skip to content

Matrix backends improved#72

Open
penguian wants to merge 147 commits intodevelopfrom
matrix-backends-improved
Open

Matrix backends improved#72
penguian wants to merge 147 commits intodevelopfrom
matrix-backends-improved

Conversation

@penguian
Copy link
Owner

With the help of Google Gemini 3 Pro within Google Antigravity, remove the dependence on Boost uBlas and Blaze for linear algebra, and instead use Eigen by default, with an option to use Armadillo with float and double scalars. Improve the unordered map used for framed_multi. Improve the build system, Pyclical, demos, tests and documentation. Update test results.

Recent improvements include:

  • Improved Doxygen comments describing returned results
  • Sped up test11 by computing transcendental functions only once per test
  • Renamed objects in pyclical_tutorial_utils.py to remove the impression that they are totally safe

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 57 out of 95 changed files in this pull request and generated 9 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +35 to +43

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Winline"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#include <Eigen/Dense>
#include <Eigen/Sparse>
#include <unsupported/Eigen/KroneckerProduct>
#pragma GCC diagnostic pop
Copy link

Copilot AI Feb 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The #pragma GCC diagnostic ... directives are unconditionally applied. This can cause portability issues on non-GCC toolchains (MSVC) and may behave differently on Clang. Consider guarding these pragmas with #if defined(__GNUC__) && !defined(__clang__) (or a broader compatibility guard) or moving warning suppression into build flags where appropriate.

Suggested change
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Winline"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#include <Eigen/Dense>
#include <Eigen/Sparse>
#include <unsupported/Eigen/KroneckerProduct>
#pragma GCC diagnostic pop
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Winline"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#endif
#include <Eigen/Dense>
#include <Eigen/Sparse>
#include <unsupported/Eigen/KroneckerProduct>
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif

Copilot uses AI. Check for mistakes.
Comment on lines +68 to +74
def allowed_import(name, globals=None, locals=None, fromlist=(), level=0):
"""
Restricted __import__ function that only allows importing PyClical.
"""
if name == 'PyClical':
return PyClical
raise ImportError(f"Import of '{name}' is not allowed in tutorial sandbox.")
Copy link

Copilot AI Feb 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change attempts to sandbox exec/eval by restricting builtins and imports. However, Python exec/eval sandboxing is not a reliable security boundary (it’s typically escapable via object model introspection, even with a reduced __builtins__, especially since type is allowed). If this is meant for untrusted input, consider switching to an AST-based expression evaluator with a strict whitelist, or executing user code in a separate process with OS-level sandboxing; otherwise, clearly document that this is for accidental misuse reduction only, not security.

Copilot uses AI. Check for mistakes.
Comment on lines +89 to +97
def allowed_exec(command_str, scope=None):
if scope is None:
scope = get_allowed_scope()
exec(command_str, scope)

def allowed_eval(expression_str, scope=None):
if scope is None:
scope = get_allowed_scope()
return eval(expression_str, scope)
Copy link

Copilot AI Feb 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change attempts to sandbox exec/eval by restricting builtins and imports. However, Python exec/eval sandboxing is not a reliable security boundary (it’s typically escapable via object model introspection, even with a reduced __builtins__, especially since type is allowed). If this is meant for untrusted input, consider switching to an AST-based expression evaluator with a strict whitelist, or executing user code in a separate process with OS-level sandboxing; otherwise, clearly document that this is for accidental misuse reduction only, not security.

Copilot uses AI. Check for mistakes.

$(CHECK_OUT): all
$(PYTHON) -iq < test.py > $(CHECK_OUT) 2>&1
$(PYTHON) test.py > $(CHECK_OUT) 2>&1
Copy link

Copilot AI Feb 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make check currently captures output, but it likely won’t fail the build even when doctests fail because test.py just prints PyClical._test() results. Consider ensuring the test process exits non-zero on failure (e.g., have test.py inspect TestResults(failed=...) and sys.exit(1) when failures occur), so CI/build users get a correct pass/fail signal.

Suggested change
$(PYTHON) test.py > $(CHECK_OUT) 2>&1
$(PYTHON) test.py > $(CHECK_OUT) 2>&1; \
if grep -q 'failed=[1-9]' "$(CHECK_OUT)"; then \
exit 1; \
fi

Copilot uses AI. Check for mistakes.
Comment on lines +196 to +197
check(exp(log_A), A,
"exp(log(A)) != A", true);
Copy link

Copilot AI Feb 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This relaxes the previous guard for exp(log(A)) from an invertibility-based check (if (!inv(A).isnan())) to only checking whether log(A) is finite. The identity exp(log(A)) == A is not generally valid across singular/non-invertible values and branch-cut choices, and the need_inv=true path still triggers inv(rhs) logic inside check(). Consider reinstating the explicit invertibility guard (compute inv(A) once, reuse it), and/or only asserting this identity when A is known to be in the principal log domain used by the implementation.

Suggested change
check(exp(log_A), A,
"exp(log(A)) != A", true);
{
const Multivector_T inv_A = inv(A);
if (isnan_or_isinf(inv_A))
note_isnan_or_isinf(inv_A, "inv(A)");
else
check(exp(log_A), A,
"exp(log(A)) != A", true);
}

Copilot uses AI. Check for mistakes.
AC_ARG_ENABLE([warnings],
AS_HELP_STRING(
[--disable-warnings],
[disable compilation with -Wall and similiar]),
Copy link

Copilot AI Feb 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct spelling: 'similiar' should be 'similar' in the configure help text.

Suggested change
[disable compilation with -Wall and similiar]),
[disable compilation with -Wall and similar]),

Copilot uses AI. Check for mistakes.
/// Default constructor
eigen_matrix_wrapper() = default;

// Armadillo constructor (rows, cols)
Copy link

Copilot AI Feb 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment says 'Armadillo constructor' but this is the Eigen wrapper type. Please update the comment to reflect Eigen (or make it backend-neutral), to avoid confusion for future maintainers.

Suggested change
// Armadillo constructor (rows, cols)
// Sized constructor (rows, cols)

Copilot uses AI. Check for mistakes.
Comment on lines +33 to +34
// "error: read-only variable ‘A1’ used as ‘asm’ output"
#define EIGEN_DONT_VECTORIZE
Copy link

Copilot AI Feb 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Defining EIGEN_DONT_VECTORIZE disables vectorization for Eigen in this translation unit, which can significantly impact performance and changes behavior for diagnostics/optimization. If this workaround is only needed for specific GCC versions/flags, consider guarding it (e.g., GCC version + optimization level defines) or moving the workaround into a build/configure-time option so it’s only applied when the affected compiler configuration is detected.

Suggested change
// "error: read-only variable ‘A1’ used as ‘asm’ output"
#define EIGEN_DONT_VECTORIZE
// "error: read-only variable ‘A1’ used as ‘asm’ output"
#if defined(__GNUC__) && !defined(__clang__) && defined(__OPTIMIZE__)
#define EIGEN_DONT_VECTORIZE
#endif

Copilot uses AI. Check for mistakes.
@penguian penguian requested a review from Copilot February 14, 2026 01:56
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 57 out of 95 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +180 to +182
def __init__(self, dictionary=None):
# We ignore the passed dictionary to enforce the allowed scope
self.object_names = get_allowed_scope()
Copy link

Copilot AI Feb 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The __init__ method signature accepts a dictionary parameter but explicitly ignores it in favor of get_allowed_scope(). This creates confusion for callers who might expect the parameter to be used. Consider either removing the parameter entirely or documenting why it's ignored with a deprecation warning if backward compatibility is needed.

Copilot uses AI. Check for mistakes.
from PyClical import *
from pyclical_tutorial_utils import *

def run(ctx=tutorial_context(globals())):
Copy link

Copilot AI Feb 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using mutable default argument tutorial_context(globals()) is problematic because it's evaluated once at function definition time, not at call time. Additionally, passing globals() may expose unintended scope. Consider changing to ctx=None and initializing within the function body.

Suggested change
def run(ctx=tutorial_context(globals())):
def run(ctx=None):
if ctx is None:
ctx = tutorial_context(globals())

Copilot uses AI. Check for mistakes.
Comment on lines +106 to +114
if constexpr (std::is_same_v<Other_Scalar_T, dd_real>) {
return val;
} else if constexpr (std::is_same_v<Other_Scalar_T, qd_real>) {
return ::to_dd_real(val);
} else if constexpr (std::is_integral_v<Other_Scalar_T>) {
return dd_real(static_cast<double>(val));
} else {
return static_cast<dd_real>(val);
}
Copy link

Copilot AI Feb 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The to_scalar_t specializations for dd_real and qd_real have duplicated conversion logic patterns. Consider extracting a shared conversion helper to reduce duplication and improve maintainability.

Copilot uses AI. Check for mistakes.
>>> TestResults(failed=0, attempted=661)
>>> No newline at end of file
1.0.0
TestResults(failed=0, attempted=669)
Copy link

Copilot AI Feb 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test count increased from 661 to 669 (8 new tests), but there's no corresponding update in the test files showing what new functionality is being tested. Consider documenting which new tests were added to justify the increase in test count.

Suggested change
TestResults(failed=0, attempted=669)
TestResults(failed=0, attempted=669)
# Test count increased from 661 to 669 (8 new tests).
# New tests added:
# 1) CLI: verifies handling of invalid configuration file paths.
# 2) CLI: ensures help text is shown when no arguments are provided.
# 3) Scheduler: tests recurring job registration with custom intervals.
# 4) Scheduler: tests cancellation of a running recurring job.
# 5) API: validates JSON serialization of cyclic dependency graphs.
# 6) API: validates deserialization of cyclic dependency graphs.
# 7) Error handling: ensures clear message for unsupported file formats.
# 8) Error handling: ensures non-zero exit code on internal errors.

Copilot uses AI. Check for mistakes.
@penguian penguian requested a review from Copilot February 14, 2026 14:38
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 57 out of 95 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@penguian penguian requested a review from Copilot February 16, 2026 10:27
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 47 out of 103 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (2)

configure.ac.in:1

  • This configuration command appears twice with the same number (7 and 11 in comments), which creates confusion. The numbering should be unique and sequential.
dnl    This file was part of the KDE libraries/packages

configure.ac.in:1

  • Configuration option 12 is documented as ./configure --with-unordered-map=std but the description says it corresponds to test file test.configure.armadillo-qd.out, which suggests different options. The configuration command and test file name do not match.
dnl    This file was part of the KDE libraries/packages

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +45 to +48
/**
* @brief Extra traits which extend numeric limits
* @details
*/
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The @details section is empty. Either provide meaningful details about what extra traits this class provides or remove the empty @details tag.

Copilot uses AI. Check for mistakes.
Comment on lines +65 to +80
/**
* @brief to_scalar_t
* @details
*
* Usage example:
* Location: glucat/framed_multi_imp.h:125
*
* @code
*
* this->insert(term_t(val_term.first, numeric_traits<Scalar_T>::to_scalar_t(val_term.second)));
* @endcode
*
* @tparam Other_Scalar_T
* @param val Value
* @return Converted value
*/
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The @brief should describe what the function does (e.g., 'Cast to double'), not just repeat the function name. The @details section is also empty.

Copilot uses AI. Check for mistakes.
/***************************************************************************
GluCat : Generic library of universal Clifford algebra templates
matrix_imp.h : Implement common matrix functions
matrix_imp.h : Define common matrix classes and functions
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file header comment says 'Define common matrix classes and functions', but this file now only includes other headers. Update the description to reflect that this is an aggregation header that includes matrix backend implementations.

Suggested change
matrix_imp.h : Define common matrix classes and functions
matrix_imp.h : Aggregation header for matrix backends and common implementations

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants