Skip to contents

libqe (development version)

libqe 0.2.5

Packaging only, in preparation for the first CRAN submission of the R package; the C++ headers and every binding behave as before.

  • R: the headers in inst/include/libqe/ are now a committed copy of include/libqe/ and the configure script is gone, so the package builds the same way from a git checkout, a devtools install and a source tarball. scripts/check-headers-in-sync.sh still fails CI when the two copies differ; run scripts/sync-headers.sh after editing a header and commit the result.
  • R: DESCRIPTION derives Author/Maintainer from Authors@R, and its Description is rewritten for CRAN users; the unused OpenMP flags are dropped from src/Makevars and src/Makevars.win; every exported function has a runnable \examples section; cran-comments.md added.

libqe 0.2.3

  • Julia: loading LibQE.jl no longer warns that fold_directed_network(::Vector{Float64}) is overwritten. The C++ library registered a one-argument method with the same signature as LibQE.jl’s fold_directed_network(v; diagonal = false); it is removed, and the Julia method calls the two-argument one. Results are unchanged.
  • Documentation: runnable examples in the WASM README, a Doxygen main page for the Conan package’s C++ API, and LibQE.jl’s README runs dev/local_jll.jl before the CMake build. libqe’s C++ headers and its R, Python and WASM code are unchanged.

libqe 0.2.2

  • Julia: LibQE.jl loads its C++ library from LibQE_jll, built by cranqe with BinaryBuilder for Linux (x86_64, aarch64) and Windows (x86_64), so Pkg.add("LibQE") needs no compiler there. LibQE.jl pins LibQE_jll to its own version (=0.2.2). Where LibQE_jll has no build (macOS for now), LibQE.jl loads a local CMake build from julia/lib/ as before. In a checkout, julia/dev/local_jll.jl develops a stand-in LibQE_jll that points at that local build (README: Development). No changes to the C++, R, Python or WASM code.

libqe 0.2.1

  • Adjacency helpers can include self-connections (the diagonal): connection_indices(), connection_names(), fold_directed_network() and network_to_vector() take diagonal (default FALSE), and new n_connections(n, diagonal) counts the columns (choose(n, 2), or n(n+1)/2). The layout is the column-major upper triangle with the diagonal – A & A, A & B, B & B, A & C, B & C, C & C – and folding keeps each self-connection once while pairs sum (A->B + B->A). Without diagonal, results are unchanged. In every binding: R and Python (diagonal=), WASM (an optional trailing argument), Julia (diagonal keyword).
  • WASM: the trajectory functions no longer throw “use of LAPACK must be enabled”. integrated_trajectory_distance and lagged_trajectory_distance (Gauss-Legendre rule: eig_sym) always threw, and fit_trajectory_poly threw for any fit above degree 1 (inv). They now use libqe’s LAPACK-free fallbacks (new qe::linalg::inv_sym); results match the LAPACK builds to about 1e-12. R, Python and Julia, which have LAPACK, run the same code as before.

libqe 0.2.0

Breaking: the ENA model code and all accumulation have moved out of libqe, finishing the split started in 0.1.9. libqe keeps the generic numerics (adjacency, normalization, statistics, linear-algebra fallbacks, lasso, door, trajectory, stability, validation).

  • The ENA model code — ena_svd, deflate, orthogonal_svd, complete_rotation, means_rotation, generalized_means_rotation, node_positions, directed_node_positions, directed_node_positions_combine_pairs, ena_correlation and ccd_window — is in rENA (C++ libena, Python qe-ena, @qe-libs/rena-wasm, ENA.jl, Conan libena).
  • All accumulation — connection_matrix, accumulate_stanza, rolling_window_sum, row_connections, accumulate_unit, accumulate_unit_with_rows, apply_tensor, apply_tensor_members, flat_index, finalize_row_connections and aggregate_row_connections — is in tma (C++ libtma, Python qe-tma, @qe-libs/tma-wasm, TMA.jl, Conan libtma).
  • Removed from every binding: the R exports above; Python’s qe.accumulation, qe.rotation and qe.ccd submodules, qe.modeling’s node-position functions and ena_correlation, and the NodePositions, UnitNetworks, TensorNetworks and RotationResult types; the same functions from libqe-wasm and LibQE.jl.
  • C++: include/libena/ and include/libtma/ are gone, and <libqe/libqe.hpp> no longer includes them. The Conan package ships include/libqe/ only (0.1.x packages also shipped stale copies of the other two trees). Include <libena/libena.hpp> or <libtma/libtma.hpp> from the rENA or tma packages instead.
  • Works with rENA >= 0.4.13, tma >= 0.3.6 and ona >= 0.1.3; earlier versions of those call the removed functions.

libqe 0.1.9

  • Bounds checking at the language boundaries. The WASM bindings copied rows × cols values without checking the array length, so a size larger than the data returned leftover heap memory in the results (e.g. 4,096 values from one input); they now raise an error. flat_index() rejects out-of-range indices, and apply_tensor_unit() validates the tensor length against dims, unit rows, receiver dimensions, and times/context_lookup coverage before indexing (R, Python and WASM).
  • C++ headers reorganised ahead of splitting libqe into three layers: libqe (generic numerics), libena (ENA model code, moving to rENA) and libtma (all accumulation, moving to tma). Rotation, generalized rotation, node positions / ena_correlation and CCD are now under include/libena/; accumulation is under include/libtma/; modeling.hpp is split into libqe/stats.hpp and libena/positions.hpp. <libqe/libqe.hpp> still includes everything, so code that includes it is unaffected; code that includes an individual header needs the new path (e.g. <libqe/rotation.hpp> → <libena/rotation.hpp>). The R package and the Conan package ship all three header trees. No functions changed.
  • New libqe/validate.hpp (require_finite, require_dims) and libqe/bind/{nanobind,emscripten,cxxwrap}.hpp (array conversion), shared by the Python, WASM and Julia bindings instead of each carrying its own copy.
  • Julia: the binding now links cxxwrap_julia_stl, fixing a macOS link failure (jlcxx::stl::StlWrappers::instance() undefined).

libqe 0.1.8

  • Python: the qe-lib sdist is self-contained. It used to omit the libqe headers (CMake read them from ../include, outside the sdist), so every source install failed — Windows, Python 3.14, macOS before 26. scripts/sync-headers.sh now also copies them into python/include/.
  • Python: Windows wheels are built by the GitHub windows-builds.yml workflow from the published sdist (dispatched by cranqe’s nightly), and the build uses a fixed build/{wheel_tag} directory instead of a temp dir whose cleanup failed on Windows (WinError 32).

libqe 0.1.7

  • Python: the package is now published as qe-lib and imported as qe (was pylibqe; extension module _pylibqe → _qe). Already-published pylibqe wheels stay installable from qe-libs.org. The C++ API is unchanged.
  • Python: Linux wheels link exactly one BLAS/LAPACK (OpenBLAS) and use Armadillo header-only. They used to link the distro’s libarmadillo wrapper plus every BLAS CMake found — three OpenBLAS builds, ATLAS, reference BLAS/LAPACK, SuperLU and ARPACK — all of which auditwheel bundled, making each manylinux wheel ~43 MB (the qe-libs.org site passed GitLab Pages’ 1 GB limit). A manylinux_2_28 wheel is now ~5 MB (aarch64: 23.1 → 5.2 MB) with identical results. macOS (Accelerate) and Windows (vcpkg) builds are unchanged.

libqe 0.1.6

  • Fixed complete_rotation — and so generalized_means_rotation (GMR, rENA’s ena.rotate.by.generalized) — returning a non-orthonormal rotation on rank-deficient data, e.g. a model with a masked (all-zero) connection column or fewer units than connections. The trailing SVD axes then came from the deflated data’s null space, which contains the named axes, so one could nearly duplicate GMR1 (|cos| 0.99 on a masked RS.data model): the SVD axes after the named ones were skewed and the variance shares wrong (GMR1 23.7% instead of 29.9%). Null-space axes are now orthogonalised against the named axes and each other. Full-rank results are unchanged (bit-identical on RS.data), as is the rENA pattern for non-orthogonal named axes.
  • R: corrected the OpenMP flags in Makevars / Makevars.win to SHLIB_OPENMP_CXXFLAGS for both compiling and linking (was the C/Fortran variables), as R requires for a C++ package; fixes linking on Windows.
  • Package metadata (R URL/BugReports, Python project URLs, npm repository) now points at https://github.com/epistemic-analytics/libqe.

libqe 0.1.5

  • Added weight models to aggregate_row_connections (= rENA’s weight.by): "binary", "product", "sqrt" and "log1p" (alias "log"). The weight is applied per response row — after the fold (unordered) or per directed cell (ordered) — and before rows are summed into the unit network, the same stage legacy rENA applies weight.by. "binary" on ordered networks keeps the raw directed counts, as before.
  • Added finalize_row_connections, the per-row step (fold + weight) without the sum, so callers can expose line-level connection counts.
  • The weight argument accepts either a weight-model name or the previous boolean binary flag (TRUE = "binary", FALSE = "product"); existing callers are unaffected. The C++ bool binary overload is retained with identical results.
  • Both functions are now exported from the R package (previously WASM and Python only). WASM and Python bindings updated; the Python keyword is now weight.

libqe 0.1.4

  • Added aggregate_row_connections, the fold + per-row-binarize + sum aggregation of apply_tensor_unit’s per-response-row counts into a unit vector — the step tma performs in R (as.unordered + colSums.ena.matrix(binary)), now shared in the C++ kernel. WASM and Python bindings added. apply_tensor_unit itself is unchanged, so the R tma pipeline (which already does this aggregation in R) is unaffected; no R wrapper is exported for the new function. Note: the JS (rena-wasm) and Python (pytma) consumers previously mis-aggregated the tensor path by reading the raw connection_counts — both now call aggregate_row_connections.

libqe 0.1.3

  • Added the cross-covariance decay (CCD) window-size kernel (ccd_window) shared across the R, WASM, and Python surfaces; ports rENA’s ena.ccd numeric core to C++.

libqe 0.1.2

Released: 2026-09-03

  • Added door temporal pooling kernels for lookback and EMA smoothing, including ETM-compatible missing-value handling.
  • Added trajectory kernels for R-compatible polynomial fitting, curve evaluation, derivatives, integrated distances, lagged distances, signed turn-lag analysis, and distance-distance correlation.
  • Added R bindings for the new door and trajectory surfaces.
  • Made orthogonal polynomial fitting portable to no-LAPACK WASM builds.
  • Added parity and regression coverage for door and trajectory behavior.