Skip to content

LAPACKE test suite via the extended-API source generator #1349

Description

@ACSimon33

Summary

LAPACKE currently has no systematic test suite. Instead of copying the Fortran LAPACK test suite and hand-renaming symbols (the CBLAS-testing approach), reuse the extended-API source generator (CMAKE/Generate64BitSuffixedSource.cmake) to rewrite the existing TESTING/LIN and TESTING/EIG sources so that calls to LAPACKE-covered routines become calls to _TEST-suffixed symbols (e.g. DGELSDGELS_TEST). Those symbols are provided by a library of generated C wrappers that forward to LAPACKE_*_work, in both column-major and row-major flavors. The unmodified numerical verification and error-exit machinery of the Fortran suite then tests LAPACKE.

This is the same pattern already used to build the _64 test executables (xlintstd_64, xeigtstd_64, ...), so the generator is proven on exactly these sources.

Design

TESTING/LIN/*.f --(generator: SUFFIX=_TEST, allowlist, NO_STRING_REPLACEMENTS)--> renamed sources
                                                                                  (calls DGELS_TEST; DLATMS/ILAENV/harness stay native)
xlintstd_lapacke_{cm,rm} = renamed test objects (compiled once, OBJECT library)
                         + liblapacke_test_wrappers_{cm,rm} (generated C, one source compiled twice)
                         + lapacke + tmglib + lapack + blas

Each generated wrapper has the Fortran-mangled name (dgels_test_), the exact Fortran calling convention (hidden strlen args declared and ignored, reusing the lapack.h macros), and:

  • CM flavor: faithful passthrough to LAPACKE_dgels_work(LAPACK_COL_MAJOR, ...) — preserves workspace queries, minimal-workspace driver loops, and LWORK error exits.
  • RM flavor: allocates row-major shadow copies of matrix arguments, converts with LAPACKE's own LAPACKE_?{ge,tr,sy,po,gb,tb,tp,pp,...}_trans helpers, calls the _work function with LAPACK_ROW_MAJOR, converts back.
  • Info mapping: *info = ret < 0 ? ret + 1 : ret (undo the layout-argument shift); on any negative return, additionally call the interposed xerbla_ with the Fortran argument number (benign duplicate for Fortran-detected errors, the only notification for LAPACKE-detected ones).

Wrappers target the _work (middle-level) API, not the high-level API: high-level functions ignore caller WORK/LWORK, which breaks LWORK error-exit tests and workspace-stress loops. High-level/NaN-check coverage is a later opt-in flavor.

Row-major runs must disable error-exit tests (TSTERR = F input-file variants, generated at configure time): the xERR* routines encode column-major LD* semantics, and a transposing wrapper never forwards the caller's deliberately-bogus LDA. LAPACKE's RM-specific ld checks get a small dedicated C unit test instead.

Tasks

Phase 0 — Spike (validate all risky assumptions end to end)

  • Parameterize the generator: SUFFIX= (default _64) and SYMBOL_ALLOWLIST_FILE= options in Generate64BitSuffixedSource.cmake / ExtendedAPIHelpers.cmake, back-compat preserved
  • Hand-write ~10 double-precision wrappers (dgetrf/s, dpotrf, dgels, dgeqrf, dorgqr, dormqr, dlange)
  • Build xlintstd_lapacke_cm with a restricted allowlist; run dtest.in (GE/PO/QR paths) green, error-exit tests included

Phase 1 — Wrapper generator + full column-major LIN

  • Python generator: parse lapack.h (LAPACK_x_base) + lapacke.h (LAPACKE_x_work) prototypes; self-validating 1:1 argument zip; manual-override table for nonuniform interfaces; one generated file per routine, committed (LAPACKE precedent)
  • Handle: value-returning functions (?lange), no-INFO routines (?lacpy), callbacks (?gees/?gges SELECT), output char* args (EQUED)
  • Allowlist derivation at configure time (LAPACKE _work base names minus exclusions/local redefinitions)
  • LAPACKE_TESTING CMake option (requires LAPACKE=ON; CMake-only, like _64)
  • xlintstd_lapacke_cm green on full dtest.in; then s/c/z
  • Post-build nm audit: report allowlist symbols referenced but not renamed (missing EXTERNAL declarations)
  • Extend add_lapack_test + teach lapack_testing.py the new output names

Phase 2 — Row-major flavor

  • RM shape-lifting from lapacke_*_work.c RM branches; CM-fallback + gap report for unparseable routines
  • Generate TSTERR = F input-file variants at configure time
  • xlintst{s,d,c,z}_lapacke_rm runs; triage failures (expect genuine LAPACKE RM bugs — that is the payoff)
  • Dedicated C unit test for LAPACKE RM ld error checks

Phase 3 — Remaining suites

  • EIG (xeigtst*_lapacke_{cm,rm})
  • RFP (xlintstrf*), mixed precision (xlintstds/xlintstzc), DMD

Phase 4 — Future extensions

  • High-level-API wrapper flavor (NaN-check + auto-allocation coverage; LWORK error tests expected-failed; LAPACKE_set_nancheck control)
  • Combined _64 + LAPACKE variant (LAPACKE_64 already exists via API_SUFFIX; generator parameters compose)

I'll split this into many smaller PRs and extend the test suite bit by bit.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions