From 8cc5df029091fcc444297fe4d83df0841faa2feb Mon Sep 17 00:00:00 2001 From: Gary Wolfman Date: Sun, 26 Jul 2026 20:37:51 -0400 Subject: [PATCH 1/2] refactor(build): restructure include/ to include/libstats/, drop the shim (#83) Moves all 79 headers include/ -> include/libstats/ (pure renames, zero content change) so the source tree mirrors the install tree, and deletes the include-shim machinery it existed to paper over: the configure-time symlink on macOS/Linux, and the flat copy + libstats_refresh_shim ALL-target + per-target ordering dependencies that dodged MSBuild copy/read races on Windows. The build tree now serves the installed package's dual include contract directly (LIBSTATS_BUILD_INCLUDE_DIRS: /include, /include/libstats, /generated); the generated libstats_version.h moves from the shim root to /generated/. Non-CMake touch-points updated: avx512-compilation.yml ad-hoc compiles, Doxyfile confirmed no-op (RECURSIVE), AGENTS/CONTRIBUTING ad-hoc compile templates gain -I./include/libstats, docs/tools/scripts path references. Verification (issue #83 gates): - Install byte-diff vs clean pre-change main: identical except the four binaries' LC_UUID/code-signature (DWARF embeds header paths under -g; nm -g symbol diff is empty). - compile_commands.json: 135/135 TUs show only the predicted hunk (-I/include_shim -> the three dirs above). - ctest -LE 'timing|benchmark': 49/49; consumer_example (find_package vs scratch install) and consumer_example_fetchcontent both build and run. Found in passing (pre-existing, not addressed here, recorded in PLAN.md): detect_threading_systems()'s cache guard skips find_package(Threads) on reconfigure, silently dropping Threads::Threads from the PUBLIC link and installed export of an already-configured build dir. Closes #83. Co-Authored-By: Claude Opus 5 --- .github/workflows/avx512-compilation.yml | 10 +- AGENTS.md | 24 ++-- CHANGELOG.md | 9 ++ CMakeLists.txt | 120 ++++++------------ CONTRIBUTING.md | 12 +- MIGRATION_GUIDE.md | 6 +- PLAN.md | 28 ++-- PROJECT_CONCEPT.md | 6 +- README.md | 2 +- docs/BUILD_SYSTEM_GUIDE.md | 33 ++--- docs/HEADER_ARCHITECTURE_GUIDE.md | 25 ++-- docs/HEADER_TOOLS_GUIDE.md | 17 ++- docs/PARALLEL_BATCH_PROCESSING_GUIDE.md | 2 +- docs/SIMD_OPTIMIZATION_REFERENCE.md | 2 +- examples/CMakeLists.txt | 2 +- examples/performance_dispatch_demo.cpp | 2 +- .../{ => libstats}/common/cpu_detection_fwd.h | 0 .../common/distribution_base_common.h | 0 .../common/distribution_common.h | 0 .../common/distribution_impl_common.h | 0 .../common/forward_declarations.h | 0 .../common/libstats_algorithm_common.h | 0 .../common/libstats_container_common.h | 0 .../common/libstats_string_common.h | 0 .../common/libstats_vector_common.h | 0 .../{ => libstats}/common/platform_common.h | 0 .../common/platform_constants_fwd.h | 0 .../common/simd_implementation_common.h | 0 .../{ => libstats}/common/simd_policy_fwd.h | 0 .../{ => libstats}/common/utility_common.h | 0 include/{ => libstats}/core/bessel.h | 0 include/{ => libstats}/core/constants.h | 0 include/{ => libstats}/core/debug_flags.h | 0 .../{ => libstats}/core/dispatch_thresholds.h | 0 include/{ => libstats}/core/dispatch_utils.h | 0 .../{ => libstats}/core/distribution_base.h | 0 .../{ => libstats}/core/distribution_cache.h | 0 .../core/distribution_concepts.h | 0 .../core/distribution_interface.h | 0 .../{ => libstats}/core/distribution_meta.h | 0 .../{ => libstats}/core/distribution_type.h | 0 .../core/distribution_validation.h | 0 include/{ => libstats}/core/error_handling.h | 0 .../{ => libstats}/core/essential_constants.h | 0 include/{ => libstats}/core/log_space_ops.h | 0 include/{ => libstats}/core/math_constants.h | 0 include/{ => libstats}/core/math_utils.h | 0 .../{ => libstats}/core/parallel_batch_fit.h | 0 .../core/performance_constants.h | 0 .../core/performance_dispatcher.h | 0 include/{ => libstats}/core/safety.h | 0 .../core/statistical_constants.h | 0 include/{ => libstats}/distributions/beta.h | 0 .../{ => libstats}/distributions/binomial.h | 0 include/{ => libstats}/distributions/cauchy.h | 0 .../distributions/chi_squared.h | 0 .../{ => libstats}/distributions/discrete.h | 0 .../distributions/exponential.h | 0 include/{ => libstats}/distributions/gamma.h | 0 .../{ => libstats}/distributions/gaussian.h | 0 .../{ => libstats}/distributions/geometric.h | 0 .../{ => libstats}/distributions/laplace.h | 0 .../{ => libstats}/distributions/lognormal.h | 0 .../distributions/negative_binomial.h | 0 include/{ => libstats}/distributions/pareto.h | 0 .../{ => libstats}/distributions/poisson.h | 0 .../{ => libstats}/distributions/rayleigh.h | 0 .../{ => libstats}/distributions/student_t.h | 0 .../{ => libstats}/distributions/uniform.h | 0 .../{ => libstats}/distributions/von_mises.h | 0 .../{ => libstats}/distributions/weibull.h | 0 include/{ => libstats}/libstats.h | 0 include/{ => libstats}/platform/benchmark.h | 0 .../{ => libstats}/platform/cpu_detection.h | 0 .../platform/cpu_vendor_constants.h | 0 .../platform/internal/cpu_tier.h | 0 .../platform/internal/type_traits.h | 0 .../platform/parallel_execution.h | 0 .../platform/platform_constants.h | 0 include/{ => libstats}/platform/simd.h | 0 include/{ => libstats}/platform/simd_policy.h | 0 include/{ => libstats}/platform/thread_pool.h | 0 .../platform/work_stealing_pool.h | 0 .../{ => libstats}/stats/analysis/analysis.h | 0 .../stats/analysis/binomial_analysis.h | 0 .../{ => libstats}/stats/analysis/bootstrap.h | 0 .../stats/analysis/cross_validation.h | 0 .../stats/analysis/discrete_analysis.h | 0 .../stats/analysis/exponential_analysis.h | 0 .../stats/analysis/gamma_analysis.h | 0 .../stats/analysis/gaussian_analysis.h | 0 .../stats/analysis/goodness_of_fit.h | 0 .../stats/analysis/information_criteria.h | 0 .../stats/analysis/poisson_analysis.h | 0 .../stats/analysis/statistical_utilities.h | 0 scripts/PROFILING_METHOD.md | 2 +- src/work_stealing_pool.cpp | 2 +- tests/CMakeLists.txt | 2 +- tools/CMakeLists.txt | 4 +- tools/header_analysis.py | 6 +- tools/header_optimization_analysis.py | 8 +- tools/math_cache_benchmark.py | 2 +- tools/static_analysis.py | 4 +- tools/threshold_validator.cpp | 2 +- 104 files changed, 149 insertions(+), 183 deletions(-) rename include/{ => libstats}/common/cpu_detection_fwd.h (100%) rename include/{ => libstats}/common/distribution_base_common.h (100%) rename include/{ => libstats}/common/distribution_common.h (100%) rename include/{ => libstats}/common/distribution_impl_common.h (100%) rename include/{ => libstats}/common/forward_declarations.h (100%) rename include/{ => libstats}/common/libstats_algorithm_common.h (100%) rename include/{ => libstats}/common/libstats_container_common.h (100%) rename include/{ => libstats}/common/libstats_string_common.h (100%) rename include/{ => libstats}/common/libstats_vector_common.h (100%) rename include/{ => libstats}/common/platform_common.h (100%) rename include/{ => libstats}/common/platform_constants_fwd.h (100%) rename include/{ => libstats}/common/simd_implementation_common.h (100%) rename include/{ => libstats}/common/simd_policy_fwd.h (100%) rename include/{ => libstats}/common/utility_common.h (100%) rename include/{ => libstats}/core/bessel.h (100%) rename include/{ => libstats}/core/constants.h (100%) rename include/{ => libstats}/core/debug_flags.h (100%) rename include/{ => libstats}/core/dispatch_thresholds.h (100%) rename include/{ => libstats}/core/dispatch_utils.h (100%) rename include/{ => libstats}/core/distribution_base.h (100%) rename include/{ => libstats}/core/distribution_cache.h (100%) rename include/{ => libstats}/core/distribution_concepts.h (100%) rename include/{ => libstats}/core/distribution_interface.h (100%) rename include/{ => libstats}/core/distribution_meta.h (100%) rename include/{ => libstats}/core/distribution_type.h (100%) rename include/{ => libstats}/core/distribution_validation.h (100%) rename include/{ => libstats}/core/error_handling.h (100%) rename include/{ => libstats}/core/essential_constants.h (100%) rename include/{ => libstats}/core/log_space_ops.h (100%) rename include/{ => libstats}/core/math_constants.h (100%) rename include/{ => libstats}/core/math_utils.h (100%) rename include/{ => libstats}/core/parallel_batch_fit.h (100%) rename include/{ => libstats}/core/performance_constants.h (100%) rename include/{ => libstats}/core/performance_dispatcher.h (100%) rename include/{ => libstats}/core/safety.h (100%) rename include/{ => libstats}/core/statistical_constants.h (100%) rename include/{ => libstats}/distributions/beta.h (100%) rename include/{ => libstats}/distributions/binomial.h (100%) rename include/{ => libstats}/distributions/cauchy.h (100%) rename include/{ => libstats}/distributions/chi_squared.h (100%) rename include/{ => libstats}/distributions/discrete.h (100%) rename include/{ => libstats}/distributions/exponential.h (100%) rename include/{ => libstats}/distributions/gamma.h (100%) rename include/{ => libstats}/distributions/gaussian.h (100%) rename include/{ => libstats}/distributions/geometric.h (100%) rename include/{ => libstats}/distributions/laplace.h (100%) rename include/{ => libstats}/distributions/lognormal.h (100%) rename include/{ => libstats}/distributions/negative_binomial.h (100%) rename include/{ => libstats}/distributions/pareto.h (100%) rename include/{ => libstats}/distributions/poisson.h (100%) rename include/{ => libstats}/distributions/rayleigh.h (100%) rename include/{ => libstats}/distributions/student_t.h (100%) rename include/{ => libstats}/distributions/uniform.h (100%) rename include/{ => libstats}/distributions/von_mises.h (100%) rename include/{ => libstats}/distributions/weibull.h (100%) rename include/{ => libstats}/libstats.h (100%) rename include/{ => libstats}/platform/benchmark.h (100%) rename include/{ => libstats}/platform/cpu_detection.h (100%) rename include/{ => libstats}/platform/cpu_vendor_constants.h (100%) rename include/{ => libstats}/platform/internal/cpu_tier.h (100%) rename include/{ => libstats}/platform/internal/type_traits.h (100%) rename include/{ => libstats}/platform/parallel_execution.h (100%) rename include/{ => libstats}/platform/platform_constants.h (100%) rename include/{ => libstats}/platform/simd.h (100%) rename include/{ => libstats}/platform/simd_policy.h (100%) rename include/{ => libstats}/platform/thread_pool.h (100%) rename include/{ => libstats}/platform/work_stealing_pool.h (100%) rename include/{ => libstats}/stats/analysis/analysis.h (100%) rename include/{ => libstats}/stats/analysis/binomial_analysis.h (100%) rename include/{ => libstats}/stats/analysis/bootstrap.h (100%) rename include/{ => libstats}/stats/analysis/cross_validation.h (100%) rename include/{ => libstats}/stats/analysis/discrete_analysis.h (100%) rename include/{ => libstats}/stats/analysis/exponential_analysis.h (100%) rename include/{ => libstats}/stats/analysis/gamma_analysis.h (100%) rename include/{ => libstats}/stats/analysis/gaussian_analysis.h (100%) rename include/{ => libstats}/stats/analysis/goodness_of_fit.h (100%) rename include/{ => libstats}/stats/analysis/information_criteria.h (100%) rename include/{ => libstats}/stats/analysis/poisson_analysis.h (100%) rename include/{ => libstats}/stats/analysis/statistical_utilities.h (100%) diff --git a/.github/workflows/avx512-compilation.yml b/.github/workflows/avx512-compilation.yml index 9e99a9f1..fd266a42 100644 --- a/.github/workflows/avx512-compilation.yml +++ b/.github/workflows/avx512-compilation.yml @@ -74,12 +74,12 @@ jobs: run: | echo "=== Compiling AVX-512 source files individually ===" - # Source files use #include "libstats/..." which resolves via the CMake-generated - # include shim at build/include_shim/ (created by the Configure step above). - # -I include alone cannot resolve the libstats/ prefix. + # Source files use #include "libstats/..." which resolves via -I include (the source tree + # now mirrors the install tree directly at include/libstats/ -- issue #83 removed the + # include-shim machinery this used to depend on). echo "Testing simd_avx512.cpp compilation..." ${{ matrix.compiler.cxx }} \ - -I build/include_shim \ + -I include \ -std=c++20 \ -DLIBSTATS_HAS_AVX512 \ -mavx512f -mavx512dq -mavx512bw -mavx512vl \ @@ -89,7 +89,7 @@ jobs: # Test compilation of dispatch logic with AVX-512 enabled echo "Testing simd_dispatch.cpp with AVX-512 enabled..." ${{ matrix.compiler.cxx }} \ - -I build/include_shim \ + -I include \ -std=c++20 \ -DLIBSTATS_HAS_AVX512 \ -mavx512f -mavx512dq -mavx512bw -mavx512vl \ diff --git a/AGENTS.md b/AGENTS.md index 3eeb4f7d..84e162c9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -42,7 +42,7 @@ $env:PROCESSOR_IDENTIFIER The active SIMD tier changes fundamentally between machines. SIMD code paths, performance thresholds, and test results are architecture-dependent. If the machine has changed since the last session: - Note the change explicitly. - Verify the build directory is current for this architecture (`cmake ..` may be needed). -- Dispatch thresholds in `include/core/dispatch_thresholds.h` are architecture-specific. +- Dispatch thresholds in `include/libstats/core/dispatch_thresholds.h` are architecture-specific. - Benchmark results are not comparable across architectures. | SIMD Tier | Example CPUs | Active simd_*.cpp files | @@ -190,13 +190,13 @@ macOS (Ventura 13+); alternate LLVM compiler setup is not required and not suppo ```bash # macOS — system AppleClang (recommended) clang++ -std=c++20 -stdlib=libc++ \ - -I./include \ + -I./include -I./include/libstats \ -L./build \ your_test.cpp -o test_output ./build/libstats.a # Linux — GCC 13+ or Clang 17+ g++ -std=c++20 -Wall -Wextra -O2 \ - -I./include \ + -I./include -I./include/libstats \ -L./build \ your_test.cpp -o test_output -lstats ``` @@ -218,7 +218,7 @@ int main() { Troubleshooting: - **Library not found**: Use static linking (`./build/libstats.a`) instead of `-lstats`. -- **Header not found**: Verify `-I./include` path is correct relative to the project root. +- **Header not found**: Verify `-I./include -I./include/libstats` paths are correct relative to the project root — the bare `#include "libstats.h"` template above resolves via `-I./include/libstats`, while any `#include "libstats/core/foo.h"`-style include resolves via `-I./include`. - **C++20 features not available**: Ensure compiler version meets minimum (AppleClang 15, GCC 13, Clang 17). ## Platform-Specific Notes @@ -355,7 +355,7 @@ Each implemented distribution provides: PDF/CDF/Quantiles, Statistical Moments, Header architecture: ``` -include/ +include/libstats/ # Mirrors the installed header layout ├── libstats.h # Complete library (single include) ├── core/ # Core mathematical and statistical components │ ├── constants/ # Mathematical, precision, statistical constants @@ -409,23 +409,23 @@ Object library architecture: the CMake system uses dependency-aware object libra ### Creating New Distributions -The registration checklist is authoritative in `include/core/distribution_meta.h`. Geometric (16), Laplace (17), and Cauchy (18) are the most recently implemented (2026-06-28); for any future distribution (N+1), follow all 6 steps below. +The registration checklist is authoritative in `include/libstats/core/distribution_meta.h`. Geometric (16), Laplace (17), and Cauchy (18) are the most recently implemented (2026-06-28); for any future distribution (N+1), follow all 6 steps below. **Steps for any future distribution (N+1):** -1. **Append** the new `DistributionType` enum value to `include/core/distribution_type.h` +1. **Append** the new `DistributionType` enum value to `include/libstats/core/distribution_type.h` (append-only; never reorder — values are used as array indices). -2. **Append** a `DistributionMeta` row to `kDistributionMeta[]` in `include/core/distribution_meta.h` +2. **Append** a `DistributionMeta` row to `kDistributionMeta[]` in `include/libstats/core/distribution_meta.h` (enum name, display name, `is_discrete`, `is_delegation_wrapper`). Bump the `static_assert(kDistributionTypeCount >= N, ...)` minimum to match the new count. 3. **Append** one `ThresholdRow` to each of the four `kXxx` tables in - `include/core/dispatch_thresholds.h` (use `{NEVER, NEVER, NEVER}` until profiled). + `include/libstats/core/dispatch_thresholds.h` (use `{NEVER, NEVER, NEVER}` until profiled). For delegation wrappers (e.g. Geometric→NegBinomial, Cauchy→StudentT), the delegate's thresholds apply — copy them or leave NEVER and profile after implementation. 4. **Implement** the distribution: - *Header* `include/distributions/dist.h` — use `exponential.h` as the reference: + *Header* `include/libstats/distributions/dist.h` — use `exponential.h` as the reference: - Inherit from `DistributionBase`. - Declare `static constexpr detail::DistributionType kDistributionType = detail::DistributionType::DIST_NAME;` and `static constexpr bool kIsDiscrete = false/true;` (must match the metadata row). @@ -461,7 +461,7 @@ The registration checklist is authoritative in `include/core/distribution_meta.h VectorizedMatchesScalar, VectorizedSpeedup (timing-labelled), MLEFit. 5. **Register** in four CMakeLists.txt locations (one top-level, three in - `tests/CMakeLists.txt`) and in `include/libstats.h`: + `tests/CMakeLists.txt`) and in `include/libstats/libstats.h`: *`CMakeLists.txt` (top-level) — `LIBSTATS_DISTRIBUTIONS_SOURCES`*, in the "Level 5: Distribution Implementations" block: @@ -481,7 +481,7 @@ The registration checklist is authoritative in `include/core/distribution_meta.h *`tests/CMakeLists.txt` — timing label* (if the enhanced test has speedup assertions): Add `test_dist_enhanced` to the `set_tests_properties(... PROPERTIES LABELS "timing")` call. - *`include/libstats.h`* — inside `#ifdef LIBSTATS_FULL_INTERFACE`: + *`include/libstats/libstats.h`* — inside `#ifdef LIBSTATS_FULL_INTERFACE`: - Add `#include "distributions/dist.h"` - Add `using DistName = DistNameDistribution;` in the `namespace stats { ... }` type-alias block. diff --git a/CHANGELOG.md b/CHANGELOG.md index 52a934e5..5d425d7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- **Include tree restructured to mirror the install tree (#83)**: all 79 + headers moved `include/` → `include/libstats/` (pure renames), deleting + the include-shim machinery — the configure-time symlink on macOS/Linux + and the flat copy + `libstats_refresh_shim` ALL-target + per-target + ordering dependencies that dodged MSBuild copy/read races on Windows. + The build tree now serves the same dual include contract as the installed + package (`#include "libstats/core/foo.h"` and bare `#include "libstats.h"`); + the generated `libstats_version.h` moves to `/generated/`. The + installed package is byte-identical; no consumer-facing change. - **Build-stack standardization (CMake)**: five CMake presets (`dev`, `release`, `debug`, `rel-with-debug`, `strict`) replace ad hoc configure invocations, and the CMake minimum rises to 3.25. Install paths now go through GNUInstallDirs, diff --git a/CMakeLists.txt b/CMakeLists.txt index bc7fa9ce..3049194f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -233,7 +233,7 @@ if(NOT LIBSTATS_PORTABLE) # NOTE: the global flag must follow the (possibly LIBSTATS_MAX_SIMD_TIER-capped) LIBSTATS_HAS_* # results from detect_simd_features(), not just "AVX512 or else AVX2". Applying /arch:AVX2 # globally regardless of a lower cap predefines the compiler's __AVX2__ macro for every TU - # (including src/simd_dispatch.cpp), which include/platform/simd.h's MSVC fallback then reads to + # (including src/simd_dispatch.cpp), which include/libstats/platform/simd.h's MSVC fallback then reads to # auto-#define LIBSTATS_HAS_AVX2 -- silently overriding an AVX or SSE2 cap and causing # getDispatchTable() to reference vector_*_avx2 symbols that were never compiled (simd_avx2.cpp # is excluded by the cap), producing LNK2019 unresolved externals. @@ -418,54 +418,20 @@ set(LIBSTATS_DISTRIBUTIONS_SOURCES # architecture flags and are platform-dependent # ============================================================================= -# INCLUDE PATH SHIM FOR INSTALLED HEADER PREFIX +# BUILD-TREE INCLUDE DIRECTORIES (dual contract, mirrors the install tree) # ============================================================================= -# Headers use #include "libstats/core/foo.h" so the include path is identical in the build tree and -# the install tree (where headers land in include/libstats/). -# -# Implementation strategy (platform-guarded): macOS/Linux — a single directory symlink: -# build/include_shim/libstats → /include Any edit to a header is immediately visible to the -# compiler; zero copy overhead per build. Re-running cmake is not required after header edits. -# -# Windows — a flat copy (symlinks require Developer Mode or elevated privileges and can trigger -# "untrusted mount point" errors): copy_directory at configure time, refreshed by an ALL custom -# target so mid-session header edits are picked up on the next cmake --build. -# -# Long-term: the canonical fix is to restructure include/ to include/libstats/ so the source tree -# mirrors the install tree and no shim is needed at all. Tracked as a post-v2.0 task. -set(LIBSTATS_INCLUDE_SHIM_DIR "${CMAKE_CURRENT_BINARY_DIR}/include_shim") -set(LIBSTATS_INCLUDE_SHIM_LINK "${LIBSTATS_INCLUDE_SHIM_DIR}/libstats") -file(MAKE_DIRECTORY "${LIBSTATS_INCLUDE_SHIM_DIR}") -file(REMOVE_RECURSE "${LIBSTATS_INCLUDE_SHIM_LINK}") -if(WIN32) - execute_process( - COMMAND "${CMAKE_COMMAND}" -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/include" - "${LIBSTATS_INCLUDE_SHIM_LINK}" RESULT_VARIABLE LIBSTATS_INCLUDE_SHIM_RESULT) - if(NOT LIBSTATS_INCLUDE_SHIM_RESULT EQUAL 0) - message(FATAL_ERROR "Failed to materialise include shim at ${LIBSTATS_INCLUDE_SHIM_LINK}") - endif() - # Re-copy on every build so mid-session header edits are picked up without requiring a cmake - # re-run. cmake -E copy_directory is timestamp-aware. - add_custom_target( - libstats_refresh_shim ALL - COMMAND "${CMAKE_COMMAND}" -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/include" - "${LIBSTATS_INCLUDE_SHIM_LINK}" - COMMENT "Refreshing include shim" - VERBATIM) -else() - execute_process( - COMMAND "${CMAKE_COMMAND}" -E create_symlink "${CMAKE_CURRENT_SOURCE_DIR}/include" - "${LIBSTATS_INCLUDE_SHIM_LINK}" RESULT_VARIABLE LIBSTATS_INCLUDE_SHIM_RESULT) - if(NOT LIBSTATS_INCLUDE_SHIM_RESULT EQUAL 0) - message( - FATAL_ERROR "Failed to create include shim symlink at ${LIBSTATS_INCLUDE_SHIM_LINK}") - endif() -endif() +# Headers use #include "libstats/core/foo.h" (resolved via /include) and libstats.h is also +# reachable bare via #include "libstats.h" (resolved via /include/libstats), matching the +# installed package's dual INSTALL_INTERFACE contract below. Since the source tree now mirrors the +# install tree directly (include/libstats/...), no shim/symlink/copy step is needed on any platform. +set(LIBSTATS_BUILD_INCLUDE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/include/libstats" + "${CMAKE_CURRENT_BINARY_DIR}/generated") # NEW-BS-1: Generate version header from CMake project() metadata so the runtime constants always # match the version in CMakeLists.txt. configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/libstats_version.h.in" - "${LIBSTATS_INCLUDE_SHIM_DIR}/libstats_version.h" @ONLY) + "${CMAKE_CURRENT_BINARY_DIR}/generated/libstats_version.h" @ONLY) # ============================================================================= # CREATE OBJECT LIBRARIES FOR PARALLEL COMPILATION @@ -474,68 +440,52 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/libstats_version.h.in" # add_dependencies() calls between the object libraries: they produce .o files that nothing consumes # until the final archive/link step, and header dependencies are tracked per-TU by the generator's # depfiles. Inter-tier add_dependencies (removed 2026-07-23) only serialized compilation into waves -# and reduced build parallelism. The one real ordering constraint is Windows' include-shim refresh -# (see the WIN32 block below). +# and reduced build parallelism. There is no longer any include-shim ordering constraint on Windows +# (removed with the include-shim machinery, see issue #83): headers are read directly from the +# source tree, so there is nothing to race with. # Foundation object library (Level 0-1) add_library(libstats_foundation_obj OBJECT ${LIBSTATS_FOUNDATION_SOURCES}) -target_include_directories(libstats_foundation_obj PRIVATE ${LIBSTATS_INCLUDE_SHIM_DIR}) +target_include_directories(libstats_foundation_obj PRIVATE ${LIBSTATS_BUILD_INCLUDE_DIRS}) libstats_apply_warnings(libstats_foundation_obj) # Phase 3B/B5 # SIMD definitions will be linked through interface target # Core utilities object library (Level 2) add_library(libstats_core_utilities_obj OBJECT ${LIBSTATS_CORE_UTILITIES_SOURCES}) -target_include_directories(libstats_core_utilities_obj PRIVATE ${LIBSTATS_INCLUDE_SHIM_DIR}) +target_include_directories(libstats_core_utilities_obj PRIVATE ${LIBSTATS_BUILD_INCLUDE_DIRS}) libstats_apply_warnings(libstats_core_utilities_obj) # Phase 3B/B5 # SIMD definitions will be linked through interface target # Platform capabilities object library (Level 2) add_library(libstats_platform_obj OBJECT ${LIBSTATS_PLATFORM_SOURCES}) -target_include_directories(libstats_platform_obj PRIVATE ${LIBSTATS_INCLUDE_SHIM_DIR}) +target_include_directories(libstats_platform_obj PRIVATE ${LIBSTATS_BUILD_INCLUDE_DIRS}) libstats_apply_warnings(libstats_platform_obj) # Phase 3B/B5 # SIMD definitions will be linked through interface target # Advanced infrastructure object library (Level 3) add_library(libstats_infrastructure_obj OBJECT ${LIBSTATS_INFRASTRUCTURE_SOURCES}) -target_include_directories(libstats_infrastructure_obj PRIVATE ${LIBSTATS_INCLUDE_SHIM_DIR}) +target_include_directories(libstats_infrastructure_obj PRIVATE ${LIBSTATS_BUILD_INCLUDE_DIRS}) libstats_apply_warnings(libstats_infrastructure_obj) # Phase 3B/B5 # SIMD definitions will be linked through interface target # Distribution framework object library (Level 4) add_library(libstats_framework_obj OBJECT ${LIBSTATS_FRAMEWORK_SOURCES}) -target_include_directories(libstats_framework_obj PRIVATE ${LIBSTATS_INCLUDE_SHIM_DIR}) +target_include_directories(libstats_framework_obj PRIVATE ${LIBSTATS_BUILD_INCLUDE_DIRS}) libstats_apply_warnings(libstats_framework_obj) # Phase 3B/B5 # SIMD definitions will be linked through interface target # Distribution implementations object library (Level 5) add_library(libstats_distributions_obj OBJECT ${LIBSTATS_DISTRIBUTIONS_SOURCES}) -target_include_directories(libstats_distributions_obj PRIVATE ${LIBSTATS_INCLUDE_SHIM_DIR}) +target_include_directories(libstats_distributions_obj PRIVATE ${LIBSTATS_BUILD_INCLUDE_DIRS}) libstats_apply_warnings(libstats_distributions_obj) # Phase 3B/B5 # SIMD definitions will be linked through interface target # SIMD object library (Platform-dependent, can compile in parallel) add_library(libstats_simd_obj OBJECT ${LIBSTATS_SIMD_SOURCES}) -target_include_directories(libstats_simd_obj PRIVATE ${LIBSTATS_INCLUDE_SHIM_DIR}) +target_include_directories(libstats_simd_obj PRIVATE ${LIBSTATS_BUILD_INCLUDE_DIRS}) libstats_apply_warnings(libstats_simd_obj) # Phase 3B/B5 # SIMD definitions will be linked through interface target -# Windows: ensure the shim copy finishes before any cl.exe job opens the copied headers. MSBuild -# runs ALL custom targets in parallel with compilation; without this ordering the copy_directory and -# compiler reads race on the same files, producing "Permission denied". -if(WIN32) - foreach( - _shim_dep - libstats_foundation_obj - libstats_core_utilities_obj - libstats_platform_obj - libstats_infrastructure_obj - libstats_framework_obj - libstats_distributions_obj - libstats_simd_obj) - add_dependencies(${_shim_dep} libstats_refresh_shim) - endforeach() -endif() - # ============================================================================= # COMBINED SOURCE LIST FOR FINAL LIBRARIES # ============================================================================= @@ -553,7 +503,9 @@ set(LIBSTATS_ALL_OBJECTS add_library(libstats_headers INTERFACE) target_include_directories( libstats_headers - INTERFACE $ + INTERFACE $ + $ + $ $ $) @@ -561,7 +513,9 @@ target_include_directories( add_library(libstats_static STATIC ${LIBSTATS_ALL_OBJECTS}) target_include_directories( libstats_static - PUBLIC $ + PUBLIC $ + $ + $ $ $) # Phase 3B/B5: has no compiled sources of its own (only $ from the object @@ -581,7 +535,9 @@ endif() add_library(libstats_shared SHARED ${LIBSTATS_ALL_OBJECTS}) target_include_directories( libstats_shared - PUBLIC $ + PUBLIC $ + $ + $ $ $) # Phase 3B/B5: see libstats_static above -- no compiled sources of its own, applied for structural @@ -731,20 +687,24 @@ install( INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) -# Install headers (exclude editor artifacts and macOS metadata) +# Install headers (exclude editor artifacts and macOS metadata). Note: no trailing slash on +# "include/libstats" -- DIRECTORY installs the libstats/ directory itself into DESTINATION, landing +# its contents at ${CMAKE_INSTALL_INCLUDEDIR}/libstats/... (same result as the old include/ -> +# .../libstats mapping, now that the source tree already mirrors the install tree). install( - DIRECTORY include/ - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/libstats + DIRECTORY include/libstats + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} PATTERN ".DS_Store" EXCLUDE PATTERN "*.bak" EXCLUDE PATTERN "*.bak2" EXCLUDE PATTERN ".gitkeep" EXCLUDE) # libstats.h #includes "libstats_version.h" (bare, unnamespaced), generated at configure time into -# the include shim (see NEW-BS-1 above) and reachable at build time via -# $. Without this, an installed find_package(libstats) -# consumer fails to compile: the generated header was never part of the installed tree. -install(FILES "${LIBSTATS_INCLUDE_SHIM_DIR}/libstats_version.h" +# ${CMAKE_CURRENT_BINARY_DIR}/generated (see NEW-BS-1 above) and reachable at build time via +# $. Without this, an installed +# find_package(libstats) consumer fails to compile: the generated header was never part of the +# installed tree. +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/generated/libstats_version.h" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/libstats) # Install CMake config files for find_package support diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 29e386a4..b98bad36 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -106,7 +106,7 @@ All contributions must include appropriate tests: ``` libstats/ -├── include/ # Public headers +├── include/libstats/ # Public headers (mirrors the installed layout) ├── src/ # Implementation files ├── tests/ # Unit and integration tests ├── examples/ # Usage examples @@ -117,20 +117,20 @@ libstats/ ### Adding New Distributions When contributing new probability distributions, follow the 5-step registration -checklist in `include/core/distribution_meta.h` (authoritative), then implement: +checklist in `include/libstats/core/distribution_meta.h` (authoritative), then implement: -1. **Append** the `DistributionType` enum value to `include/core/distribution_type.h` +1. **Append** the `DistributionType` enum value to `include/libstats/core/distribution_type.h` (append-only — values are used as array indices). -2. **Append** a `DistributionMeta` row to `kDistributionMeta[]` in `include/core/distribution_meta.h`. +2. **Append** a `DistributionMeta` row to `kDistributionMeta[]` in `include/libstats/core/distribution_meta.h`. 3. **Append** one `ThresholdRow` to each of the four `kXxx` tables in - `include/core/dispatch_thresholds.h` (use `{NEVER, NEVER, NEVER}` until profiled). + `include/libstats/core/dispatch_thresholds.h` (use `{NEVER, NEVER, NEVER}` until profiled). 4. **Implement** the distribution (see `exponential.h`/`.cpp` as the reference template): - Inherit from `DistributionBase`, implement all pure virtual methods. - Full statistical interface: PDF/LogPDF/CDF/quantile/sampling/MLE/`parallelBatchFit`. - Parameter validation and factory methods (`Result`/`VoidResult` API). - SIMD-optimized batch operations via the `VectorOps` pipeline in `*BatchUnsafeImpl`. - Tests: `*_basic.cpp` standalone + `*_enhanced.cpp` GTest with speedup assertions. -5. **Register** in `CMakeLists.txt` and `include/libstats.h`. +5. **Register** in `CMakeLists.txt` and `include/libstats/libstats.h`. ### SIMD Development diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index 9c7bd752..4d9d384e 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -224,7 +224,7 @@ VoidResult validateFoo(double x) { `validateBetaParameters`, `validateChiSquaredParameters`, `validateStudentTParameters` (and all other `validate*Parameters` functions) are no longer private static members of their distribution classes. They are now free functions returning -`VoidResult`, defined in `include/core/error_handling.h`, `namespace stats`. +`VoidResult`, defined in `include/libstats/core/error_handling.h`, `namespace stats`. ```cpp // v1.x @@ -246,7 +246,7 @@ function directly. v1.x used `DistributionTraits` template specializations (SFINAE) to constrain generic code to valid distribution types. v2.0.0 replaces this with -C++20 concepts in `stats::concepts` (`include/core/distribution_concepts.h`): +C++20 concepts in `stats::concepts` (`include/libstats/core/distribution_concepts.h`): | Concept | Requirement | |---|---| @@ -271,7 +271,7 @@ Two practical consequences for custom distributions: v1.x had two parallel enums for the same concept: a standalone `SIMDLevel` and `SIMDPolicy`'s own nested level enum. v2.0.0 makes `SIMDPolicy::Level` a -type alias for the canonical `SIMDLevel` (`include/platform/simd_policy.h`): +type alias for the canonical `SIMDLevel` (`include/libstats/platform/simd_policy.h`): ```cpp using Level = SIMDLevel; // was a separate nested enum in v1.x diff --git a/PLAN.md b/PLAN.md index 4b54334c..12146cd0 100644 --- a/PLAN.md +++ b/PLAN.md @@ -76,7 +76,8 @@ Renumbered top-down 2026-07-21 to make room for the shipped v2.1.0: former #1/#2/#3 titles each moved up one minor version. Milestone numbers and attached issues were unchanged; only titles moved. -- **v2.2.0 — Accuracy & Performance** (open, #1): 7 open / 0 closed. +- **v2.2.0 — Accuracy & Performance** (open, #1): 6 open / 1 closed + (#83 include restructure shipped 2026-07-26). - #46 — Benchmark: SIMD accuracy characterization vs mpmath. - #47 — bessel.h Tier 2 fallback limits VonMises accuracy to ~10⁻⁷ on macOS/AppleClang. @@ -92,8 +93,6 @@ and attached issues were unchanged; only titles moved. 5–10× slower than scipy. - #52 — Binomial CDF slower than scipy; PMF summation and scalar lgamma are the limiting factors. - - #83 — Restructure `include/` to `include/libstats/` and delete the - include shim. - **v2.3.0 — New Distributions (Foundation)** (open, #2): 4 open / 0 closed — #54 Logistic + Gumbel, #55 Bernoulli + Erlang, #56 F + InverseGamma, #57 HalfNormal + TruncatedNormal. @@ -130,10 +129,15 @@ and attached issues were unchanged; only titles moved. threshold, so for x in that one-double window the kernels return `exp(exp_max)` (~214 ULP low) where `std::exp` is still finite. This is a deliberate safety margin against a 1-ULP overshoot to inf; left as is. -- The include shim (`LIBSTATS_INCLUDE_SHIM_DIR`, CMakeLists.txt:436) still - costs a configure-time symlink on Unix and a flat copy plus a - `libstats_refresh_shim` ALL-target with per-target ordering dependencies - on Windows, to dodge MSBuild copy/read races. #83 deletes it. +- `detect_threading_systems()` (cmake/Threading.cmake:6) early-returns on + its cached completion flag, but imported targets are not cache-persistent + — so any reconfigure of an existing build dir skips + `find_package(Threads)`, and the `if(TARGET Threads::Threads)` guard + (CMakeLists.txt) silently drops `Threads::Threads` from the PUBLIC link + and the installed export. Found 2026-07-26 while verifying #83's + install-tree byte-diff (the stale-cache baseline was the side missing the + entry). Pre-existing, orthogonal to #83; needs an issue. On Linux this + can underlink installed-package consumers. ## Cross-Repo Dependencies [OPEN] pylibstats consumes this repo two ways — a `find_package` version floor and @@ -159,17 +163,17 @@ before starting either. scoped PRIVATE to the affected targets, fusion requested only in source, at ≤~8% measured cost. Authoring is machine-independent; **re-measuring the NEON ULP bounds needs the Mac Mini M1.** -2. **#83** — the include restructure. Specification and four verification - gates are written on the issue; the install-tree byte-diff is the primary - oracle. Atomic change, roughly half a day including one CI round. -3. **#48** — Cauchy closed-form arctan CDF. Smallest measurable win in the +2. **#48** — Cauchy closed-form arctan CDF. Smallest measurable win in the backlog (3–5× on Zen 4, and the gap widens with SIMD width). -4. Settle the corvus-adoption question above, then work the rest of v2.2.0 +3. Settle the corvus-adoption question above, then work the rest of v2.2.0 before starting v2.3.0/v2.4.0 or the v3.0.0 refactor. ## Resolved log One line per closed item; detail lives in `CHANGELOG.md`, `docs/`, and this file's git history. +- 2026-07-26 #83 include restructure: `include/` → `include/libstats/`, + shim machinery deleted; install tree byte-identical, 135/135 TUs show + only the predicted include-dir change, 49/49 tests + both consumers pass. - 2026-07-24 CI lint hardening: zizmor gated on medium+ severity, latent shellcheck findings cleared, `lint-workflows` job green. - 2026-07-21/23 Build-stack standardization Phases 0–4 (cross-repo effort in diff --git a/PROJECT_CONCEPT.md b/PROJECT_CONCEPT.md index f3cd8158..1d61998f 100644 --- a/PROJECT_CONCEPT.md +++ b/PROJECT_CONCEPT.md @@ -129,12 +129,12 @@ The library supports four execution strategies: - **PARALLEL** — multi-threaded execution for larger workloads - **WORK_STEALING** — dynamic load balancing for large or irregular workloads -Strategy selection uses empirically-derived per-architecture thresholds (from profiling bundles across four machines) stored as a constexpr lookup table in `include/core/dispatch_thresholds.h`. Power users can override strategy selection explicitly via `getXxxWithStrategy()` variants. +Strategy selection uses empirically-derived per-architecture thresholds (from profiling bundles across four machines) stored as a constexpr lookup table in `include/libstats/core/dispatch_thresholds.h`. Power users can override strategy selection explicitly via `getXxxWithStrategy()` variants. ## Repository Structure ### Core directories -- `include/` — public headers and internal header structure +- `include/libstats/` — public headers and internal header structure (mirrors the installed layout) - `src/` — implementation files - `tests/` — correctness, integration, and enhanced tests (all GTest-based) - `examples/` — usage-oriented demonstrations @@ -144,7 +144,7 @@ Strategy selection uses empirically-derived per-architecture thresholds (from pr - `data/profiles/dispatcher/` — profiling bundles for empirical threshold derivation ### User-facing entry points -- `include/libstats.h` — umbrella header +- `include/libstats/libstats.h` — umbrella header - `README.md` — project overview and onboarding - `AGENTS.md` — repository-specific development guidance for agents diff --git a/README.md b/README.md index cef96c81..ef687754 100644 --- a/README.md +++ b/README.md @@ -144,7 +144,7 @@ int main() { ``` libstats/ -├── include/ # Modular header architecture +├── include/libstats/ # Modular header architecture (mirrors the installed layout) │ ├── libstats.h # Complete library (single include) │ ├── core/ # Core mathematical and statistical components │ ├── distributions/ # Statistical distributions (Gaussian, Exponential, etc.) diff --git a/docs/BUILD_SYSTEM_GUIDE.md b/docs/BUILD_SYSTEM_GUIDE.md index 7dcebe37..2fb8bcba 100644 --- a/docs/BUILD_SYSTEM_GUIDE.md +++ b/docs/BUILD_SYSTEM_GUIDE.md @@ -81,19 +81,19 @@ Aliases: - `libstats::headers` - `libstats::simd` -## Include shim +## Include layout -The build tree exposes headers under: +The source tree mirrors the install tree directly: headers live under +`include/libstats/`, so `#include "libstats/core/foo.h"` resolves identically +in the build tree and after `cmake --install` — no shim, symlink, or copy +step is involved (issue #83 removed the previous include-shim machinery, +which cost a configure-time symlink on macOS/Linux and a flat copy plus an +ALL-target refresh on Windows). -```text -build/include_shim/libstats/ -``` - -This matches the install-tree path (`include/libstats/`) so `#include "libstats/core/foo.h"` works identically in both contexts. - -Implementation is platform-guarded: -- **macOS/Linux**: `build/include_shim/libstats` is a directory symlink to `include/`. Header edits are immediately visible to the compiler with no re-run of cmake required. -- **Windows**: a flat copy is used (symlinks require Developer Mode or elevated privileges). A `libstats_refresh_shim` build target re-copies the directory on every `cmake --build` so mid-session edits are picked up automatically. +The build tree carries the same dual include contract as the installed +package: `/include` (for `#include "libstats/core/foo.h"`), +`/include/libstats` (for the bare `#include "libstats.h"`), and +`/generated` (for the configure-time-generated `libstats_version.h`). ## SIMD detection @@ -170,16 +170,11 @@ Built tools live in `build/tools/`: ### Header not found -Use the build-tree shim include path: - -```bash --Ibuild/include_shim -``` - -or project source include path for direct ad hoc compilation: +For direct ad hoc compilation outside CMake, add both source include roots +(the dual bare/`libstats/`-prefixed contract, see AGENTS.md): ```bash --I./include +-I./include -I./include/libstats ``` ### SIMD source does not compile diff --git a/docs/HEADER_ARCHITECTURE_GUIDE.md b/docs/HEADER_ARCHITECTURE_GUIDE.md index 3205997e..4b3adbc5 100644 --- a/docs/HEADER_ARCHITECTURE_GUIDE.md +++ b/docs/HEADER_ARCHITECTURE_GUIDE.md @@ -21,13 +21,14 @@ Focused include: ```text include/ -├── libstats.h -├── common/ -├── core/ -├── distributions/ -├── platform/ -└── stats/ - └── analysis/ +└── libstats/ + ├── libstats.h + ├── common/ + ├── core/ + ├── distributions/ + ├── platform/ + └── stats/ + └── analysis/ ``` ## Core headers @@ -114,14 +115,12 @@ Removed v1.x APIs: ## Installed include path -Installed headers are expected under: +Installed headers land under: ```text include/libstats/ ``` -The build tree mirrors this via: - -```text -build/include_shim/libstats/ -``` +The source tree mirrors this layout directly (`/include/libstats/`), so +the build tree and the install tree resolve `#include "libstats/core/foo.h"` +identically with no shim, symlink, or copy step involved. diff --git a/docs/HEADER_TOOLS_GUIDE.md b/docs/HEADER_TOOLS_GUIDE.md index 2212fff3..68bcc7b8 100644 --- a/docs/HEADER_TOOLS_GUIDE.md +++ b/docs/HEADER_TOOLS_GUIDE.md @@ -42,7 +42,8 @@ When adding a public header: 2. Use `#pragma once`. 3. Include only what the header needs. 4. Use `libstats/...` include paths for installed-header compatibility. -5. Add tests that compile through the installed-style include shim. +5. Add tests that compile through the installed-style include path + (`include/libstats/...`, identical in the build tree and the install tree). 6. Update documentation if it changes public API. ## Analysis headers @@ -51,12 +52,10 @@ Generic analysis headers may be added to `stats/analysis/analysis.h`. Distribution-specific analysis headers must be included explicitly by users. Do not add them to the generic umbrella unless the design changes deliberately. -## Include shim +## Installed-style include paths -The build creates: - -```text -build/include_shim/libstats/ -``` - -Use this when testing installed-style include paths. +The source tree mirrors the install tree directly at `include/libstats/`, so +`#include "libstats/core/foo.h"` and the bare `#include "libstats.h"` both +resolve the same way in the build tree and after `cmake --install` — no +shim, symlink, or copy step is involved (issue #83 removed the previous +include-shim machinery). diff --git a/docs/PARALLEL_BATCH_PROCESSING_GUIDE.md b/docs/PARALLEL_BATCH_PROCESSING_GUIDE.md index 3621e611..3f1f0997 100644 --- a/docs/PARALLEL_BATCH_PROCESSING_GUIDE.md +++ b/docs/PARALLEL_BATCH_PROCESSING_GUIDE.md @@ -82,7 +82,7 @@ The default dispatcher considers: Thresholds live in: ```text -include/core/dispatch_thresholds.h +include/libstats/core/dispatch_thresholds.h ``` These thresholds are architecture-specific. Performance results from AVX2, NEON, and AVX-512 systems should not be compared directly. diff --git a/docs/SIMD_OPTIMIZATION_REFERENCE.md b/docs/SIMD_OPTIMIZATION_REFERENCE.md index 4b6b2762..ad54c4b8 100644 --- a/docs/SIMD_OPTIMIZATION_REFERENCE.md +++ b/docs/SIMD_OPTIMIZATION_REFERENCE.md @@ -123,7 +123,7 @@ The L2 boundary is architecture-specific and must not be assumed to hold on AVX2 ### Bessel function tier selection -`include/core/bessel.h` provides two tiers for `bessel_i0`, `bessel_i1`, and `log_bessel_i0`: +`include/libstats/core/bessel.h` provides two tiers for `bessel_i0`, `bessel_i1`, and `log_bessel_i0`: - **Tier 1** (MSVC/GCC/Clang with `LIBSTATS_HAS_CXX17_BESSEL`): delegates to `std::cyl_bessel_i` (C++17 §29.9.3). Achieves <1 ULP against scipy for κ=2. - **Tier 2** (AppleClang/macOS, `LIBSTATS_HAS_CXX17_BESSEL` not defined): A&S §9.8.1–9.8.4 polynomial approximation. Documented precision: <1.6×10⁻⁷. diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index a872b8c4..28c377c0 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -8,7 +8,7 @@ function(create_example EXAMPLE_NAME SOURCE_FILE) target_link_libraries(${EXAMPLE_NAME} PRIVATE libstats_static) # Add include directories - target_include_directories(${EXAMPLE_NAME} PRIVATE ${LIBSTATS_INCLUDE_SHIM_DIR} + target_include_directories(${EXAMPLE_NAME} PRIVATE ${LIBSTATS_BUILD_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/../src) # Phase 3B/B5: previously inherited the project's warning flags via directory-scope diff --git a/examples/performance_dispatch_demo.cpp b/examples/performance_dispatch_demo.cpp index e781d75b..e160503d 100644 --- a/examples/performance_dispatch_demo.cpp +++ b/examples/performance_dispatch_demo.cpp @@ -263,7 +263,7 @@ void demonstrate_performance_dispatcher() { std::cout << std::setw(15) << size << std::setw(22) << strategyToString(sg) << std::setw(22) << strategyToString(se) << std::setw(22) << strategyToString(sb) << "\n"; } - std::cout << "\nThresholds are in include/core/dispatch_thresholds.h and are tuned\n" + std::cout << "\nThresholds are in include/libstats/core/dispatch_thresholds.h and are tuned\n" << "per architecture using the strategy_profile tool.\n"; } diff --git a/include/common/cpu_detection_fwd.h b/include/libstats/common/cpu_detection_fwd.h similarity index 100% rename from include/common/cpu_detection_fwd.h rename to include/libstats/common/cpu_detection_fwd.h diff --git a/include/common/distribution_base_common.h b/include/libstats/common/distribution_base_common.h similarity index 100% rename from include/common/distribution_base_common.h rename to include/libstats/common/distribution_base_common.h diff --git a/include/common/distribution_common.h b/include/libstats/common/distribution_common.h similarity index 100% rename from include/common/distribution_common.h rename to include/libstats/common/distribution_common.h diff --git a/include/common/distribution_impl_common.h b/include/libstats/common/distribution_impl_common.h similarity index 100% rename from include/common/distribution_impl_common.h rename to include/libstats/common/distribution_impl_common.h diff --git a/include/common/forward_declarations.h b/include/libstats/common/forward_declarations.h similarity index 100% rename from include/common/forward_declarations.h rename to include/libstats/common/forward_declarations.h diff --git a/include/common/libstats_algorithm_common.h b/include/libstats/common/libstats_algorithm_common.h similarity index 100% rename from include/common/libstats_algorithm_common.h rename to include/libstats/common/libstats_algorithm_common.h diff --git a/include/common/libstats_container_common.h b/include/libstats/common/libstats_container_common.h similarity index 100% rename from include/common/libstats_container_common.h rename to include/libstats/common/libstats_container_common.h diff --git a/include/common/libstats_string_common.h b/include/libstats/common/libstats_string_common.h similarity index 100% rename from include/common/libstats_string_common.h rename to include/libstats/common/libstats_string_common.h diff --git a/include/common/libstats_vector_common.h b/include/libstats/common/libstats_vector_common.h similarity index 100% rename from include/common/libstats_vector_common.h rename to include/libstats/common/libstats_vector_common.h diff --git a/include/common/platform_common.h b/include/libstats/common/platform_common.h similarity index 100% rename from include/common/platform_common.h rename to include/libstats/common/platform_common.h diff --git a/include/common/platform_constants_fwd.h b/include/libstats/common/platform_constants_fwd.h similarity index 100% rename from include/common/platform_constants_fwd.h rename to include/libstats/common/platform_constants_fwd.h diff --git a/include/common/simd_implementation_common.h b/include/libstats/common/simd_implementation_common.h similarity index 100% rename from include/common/simd_implementation_common.h rename to include/libstats/common/simd_implementation_common.h diff --git a/include/common/simd_policy_fwd.h b/include/libstats/common/simd_policy_fwd.h similarity index 100% rename from include/common/simd_policy_fwd.h rename to include/libstats/common/simd_policy_fwd.h diff --git a/include/common/utility_common.h b/include/libstats/common/utility_common.h similarity index 100% rename from include/common/utility_common.h rename to include/libstats/common/utility_common.h diff --git a/include/core/bessel.h b/include/libstats/core/bessel.h similarity index 100% rename from include/core/bessel.h rename to include/libstats/core/bessel.h diff --git a/include/core/constants.h b/include/libstats/core/constants.h similarity index 100% rename from include/core/constants.h rename to include/libstats/core/constants.h diff --git a/include/core/debug_flags.h b/include/libstats/core/debug_flags.h similarity index 100% rename from include/core/debug_flags.h rename to include/libstats/core/debug_flags.h diff --git a/include/core/dispatch_thresholds.h b/include/libstats/core/dispatch_thresholds.h similarity index 100% rename from include/core/dispatch_thresholds.h rename to include/libstats/core/dispatch_thresholds.h diff --git a/include/core/dispatch_utils.h b/include/libstats/core/dispatch_utils.h similarity index 100% rename from include/core/dispatch_utils.h rename to include/libstats/core/dispatch_utils.h diff --git a/include/core/distribution_base.h b/include/libstats/core/distribution_base.h similarity index 100% rename from include/core/distribution_base.h rename to include/libstats/core/distribution_base.h diff --git a/include/core/distribution_cache.h b/include/libstats/core/distribution_cache.h similarity index 100% rename from include/core/distribution_cache.h rename to include/libstats/core/distribution_cache.h diff --git a/include/core/distribution_concepts.h b/include/libstats/core/distribution_concepts.h similarity index 100% rename from include/core/distribution_concepts.h rename to include/libstats/core/distribution_concepts.h diff --git a/include/core/distribution_interface.h b/include/libstats/core/distribution_interface.h similarity index 100% rename from include/core/distribution_interface.h rename to include/libstats/core/distribution_interface.h diff --git a/include/core/distribution_meta.h b/include/libstats/core/distribution_meta.h similarity index 100% rename from include/core/distribution_meta.h rename to include/libstats/core/distribution_meta.h diff --git a/include/core/distribution_type.h b/include/libstats/core/distribution_type.h similarity index 100% rename from include/core/distribution_type.h rename to include/libstats/core/distribution_type.h diff --git a/include/core/distribution_validation.h b/include/libstats/core/distribution_validation.h similarity index 100% rename from include/core/distribution_validation.h rename to include/libstats/core/distribution_validation.h diff --git a/include/core/error_handling.h b/include/libstats/core/error_handling.h similarity index 100% rename from include/core/error_handling.h rename to include/libstats/core/error_handling.h diff --git a/include/core/essential_constants.h b/include/libstats/core/essential_constants.h similarity index 100% rename from include/core/essential_constants.h rename to include/libstats/core/essential_constants.h diff --git a/include/core/log_space_ops.h b/include/libstats/core/log_space_ops.h similarity index 100% rename from include/core/log_space_ops.h rename to include/libstats/core/log_space_ops.h diff --git a/include/core/math_constants.h b/include/libstats/core/math_constants.h similarity index 100% rename from include/core/math_constants.h rename to include/libstats/core/math_constants.h diff --git a/include/core/math_utils.h b/include/libstats/core/math_utils.h similarity index 100% rename from include/core/math_utils.h rename to include/libstats/core/math_utils.h diff --git a/include/core/parallel_batch_fit.h b/include/libstats/core/parallel_batch_fit.h similarity index 100% rename from include/core/parallel_batch_fit.h rename to include/libstats/core/parallel_batch_fit.h diff --git a/include/core/performance_constants.h b/include/libstats/core/performance_constants.h similarity index 100% rename from include/core/performance_constants.h rename to include/libstats/core/performance_constants.h diff --git a/include/core/performance_dispatcher.h b/include/libstats/core/performance_dispatcher.h similarity index 100% rename from include/core/performance_dispatcher.h rename to include/libstats/core/performance_dispatcher.h diff --git a/include/core/safety.h b/include/libstats/core/safety.h similarity index 100% rename from include/core/safety.h rename to include/libstats/core/safety.h diff --git a/include/core/statistical_constants.h b/include/libstats/core/statistical_constants.h similarity index 100% rename from include/core/statistical_constants.h rename to include/libstats/core/statistical_constants.h diff --git a/include/distributions/beta.h b/include/libstats/distributions/beta.h similarity index 100% rename from include/distributions/beta.h rename to include/libstats/distributions/beta.h diff --git a/include/distributions/binomial.h b/include/libstats/distributions/binomial.h similarity index 100% rename from include/distributions/binomial.h rename to include/libstats/distributions/binomial.h diff --git a/include/distributions/cauchy.h b/include/libstats/distributions/cauchy.h similarity index 100% rename from include/distributions/cauchy.h rename to include/libstats/distributions/cauchy.h diff --git a/include/distributions/chi_squared.h b/include/libstats/distributions/chi_squared.h similarity index 100% rename from include/distributions/chi_squared.h rename to include/libstats/distributions/chi_squared.h diff --git a/include/distributions/discrete.h b/include/libstats/distributions/discrete.h similarity index 100% rename from include/distributions/discrete.h rename to include/libstats/distributions/discrete.h diff --git a/include/distributions/exponential.h b/include/libstats/distributions/exponential.h similarity index 100% rename from include/distributions/exponential.h rename to include/libstats/distributions/exponential.h diff --git a/include/distributions/gamma.h b/include/libstats/distributions/gamma.h similarity index 100% rename from include/distributions/gamma.h rename to include/libstats/distributions/gamma.h diff --git a/include/distributions/gaussian.h b/include/libstats/distributions/gaussian.h similarity index 100% rename from include/distributions/gaussian.h rename to include/libstats/distributions/gaussian.h diff --git a/include/distributions/geometric.h b/include/libstats/distributions/geometric.h similarity index 100% rename from include/distributions/geometric.h rename to include/libstats/distributions/geometric.h diff --git a/include/distributions/laplace.h b/include/libstats/distributions/laplace.h similarity index 100% rename from include/distributions/laplace.h rename to include/libstats/distributions/laplace.h diff --git a/include/distributions/lognormal.h b/include/libstats/distributions/lognormal.h similarity index 100% rename from include/distributions/lognormal.h rename to include/libstats/distributions/lognormal.h diff --git a/include/distributions/negative_binomial.h b/include/libstats/distributions/negative_binomial.h similarity index 100% rename from include/distributions/negative_binomial.h rename to include/libstats/distributions/negative_binomial.h diff --git a/include/distributions/pareto.h b/include/libstats/distributions/pareto.h similarity index 100% rename from include/distributions/pareto.h rename to include/libstats/distributions/pareto.h diff --git a/include/distributions/poisson.h b/include/libstats/distributions/poisson.h similarity index 100% rename from include/distributions/poisson.h rename to include/libstats/distributions/poisson.h diff --git a/include/distributions/rayleigh.h b/include/libstats/distributions/rayleigh.h similarity index 100% rename from include/distributions/rayleigh.h rename to include/libstats/distributions/rayleigh.h diff --git a/include/distributions/student_t.h b/include/libstats/distributions/student_t.h similarity index 100% rename from include/distributions/student_t.h rename to include/libstats/distributions/student_t.h diff --git a/include/distributions/uniform.h b/include/libstats/distributions/uniform.h similarity index 100% rename from include/distributions/uniform.h rename to include/libstats/distributions/uniform.h diff --git a/include/distributions/von_mises.h b/include/libstats/distributions/von_mises.h similarity index 100% rename from include/distributions/von_mises.h rename to include/libstats/distributions/von_mises.h diff --git a/include/distributions/weibull.h b/include/libstats/distributions/weibull.h similarity index 100% rename from include/distributions/weibull.h rename to include/libstats/distributions/weibull.h diff --git a/include/libstats.h b/include/libstats/libstats.h similarity index 100% rename from include/libstats.h rename to include/libstats/libstats.h diff --git a/include/platform/benchmark.h b/include/libstats/platform/benchmark.h similarity index 100% rename from include/platform/benchmark.h rename to include/libstats/platform/benchmark.h diff --git a/include/platform/cpu_detection.h b/include/libstats/platform/cpu_detection.h similarity index 100% rename from include/platform/cpu_detection.h rename to include/libstats/platform/cpu_detection.h diff --git a/include/platform/cpu_vendor_constants.h b/include/libstats/platform/cpu_vendor_constants.h similarity index 100% rename from include/platform/cpu_vendor_constants.h rename to include/libstats/platform/cpu_vendor_constants.h diff --git a/include/platform/internal/cpu_tier.h b/include/libstats/platform/internal/cpu_tier.h similarity index 100% rename from include/platform/internal/cpu_tier.h rename to include/libstats/platform/internal/cpu_tier.h diff --git a/include/platform/internal/type_traits.h b/include/libstats/platform/internal/type_traits.h similarity index 100% rename from include/platform/internal/type_traits.h rename to include/libstats/platform/internal/type_traits.h diff --git a/include/platform/parallel_execution.h b/include/libstats/platform/parallel_execution.h similarity index 100% rename from include/platform/parallel_execution.h rename to include/libstats/platform/parallel_execution.h diff --git a/include/platform/platform_constants.h b/include/libstats/platform/platform_constants.h similarity index 100% rename from include/platform/platform_constants.h rename to include/libstats/platform/platform_constants.h diff --git a/include/platform/simd.h b/include/libstats/platform/simd.h similarity index 100% rename from include/platform/simd.h rename to include/libstats/platform/simd.h diff --git a/include/platform/simd_policy.h b/include/libstats/platform/simd_policy.h similarity index 100% rename from include/platform/simd_policy.h rename to include/libstats/platform/simd_policy.h diff --git a/include/platform/thread_pool.h b/include/libstats/platform/thread_pool.h similarity index 100% rename from include/platform/thread_pool.h rename to include/libstats/platform/thread_pool.h diff --git a/include/platform/work_stealing_pool.h b/include/libstats/platform/work_stealing_pool.h similarity index 100% rename from include/platform/work_stealing_pool.h rename to include/libstats/platform/work_stealing_pool.h diff --git a/include/stats/analysis/analysis.h b/include/libstats/stats/analysis/analysis.h similarity index 100% rename from include/stats/analysis/analysis.h rename to include/libstats/stats/analysis/analysis.h diff --git a/include/stats/analysis/binomial_analysis.h b/include/libstats/stats/analysis/binomial_analysis.h similarity index 100% rename from include/stats/analysis/binomial_analysis.h rename to include/libstats/stats/analysis/binomial_analysis.h diff --git a/include/stats/analysis/bootstrap.h b/include/libstats/stats/analysis/bootstrap.h similarity index 100% rename from include/stats/analysis/bootstrap.h rename to include/libstats/stats/analysis/bootstrap.h diff --git a/include/stats/analysis/cross_validation.h b/include/libstats/stats/analysis/cross_validation.h similarity index 100% rename from include/stats/analysis/cross_validation.h rename to include/libstats/stats/analysis/cross_validation.h diff --git a/include/stats/analysis/discrete_analysis.h b/include/libstats/stats/analysis/discrete_analysis.h similarity index 100% rename from include/stats/analysis/discrete_analysis.h rename to include/libstats/stats/analysis/discrete_analysis.h diff --git a/include/stats/analysis/exponential_analysis.h b/include/libstats/stats/analysis/exponential_analysis.h similarity index 100% rename from include/stats/analysis/exponential_analysis.h rename to include/libstats/stats/analysis/exponential_analysis.h diff --git a/include/stats/analysis/gamma_analysis.h b/include/libstats/stats/analysis/gamma_analysis.h similarity index 100% rename from include/stats/analysis/gamma_analysis.h rename to include/libstats/stats/analysis/gamma_analysis.h diff --git a/include/stats/analysis/gaussian_analysis.h b/include/libstats/stats/analysis/gaussian_analysis.h similarity index 100% rename from include/stats/analysis/gaussian_analysis.h rename to include/libstats/stats/analysis/gaussian_analysis.h diff --git a/include/stats/analysis/goodness_of_fit.h b/include/libstats/stats/analysis/goodness_of_fit.h similarity index 100% rename from include/stats/analysis/goodness_of_fit.h rename to include/libstats/stats/analysis/goodness_of_fit.h diff --git a/include/stats/analysis/information_criteria.h b/include/libstats/stats/analysis/information_criteria.h similarity index 100% rename from include/stats/analysis/information_criteria.h rename to include/libstats/stats/analysis/information_criteria.h diff --git a/include/stats/analysis/poisson_analysis.h b/include/libstats/stats/analysis/poisson_analysis.h similarity index 100% rename from include/stats/analysis/poisson_analysis.h rename to include/libstats/stats/analysis/poisson_analysis.h diff --git a/include/stats/analysis/statistical_utilities.h b/include/libstats/stats/analysis/statistical_utilities.h similarity index 100% rename from include/stats/analysis/statistical_utilities.h rename to include/libstats/stats/analysis/statistical_utilities.h diff --git a/scripts/PROFILING_METHOD.md b/scripts/PROFILING_METHOD.md index 5c63f5ee..7d626188 100644 --- a/scripts/PROFILING_METHOD.md +++ b/scripts/PROFILING_METHOD.md @@ -1,7 +1,7 @@ # Dispatcher Threshold Profiling Method This document is the authoritative reference for how dispatch thresholds in -`include/core/dispatch_thresholds.h` are measured and derived. All agents +`include/libstats/core/dispatch_thresholds.h` are measured and derived. All agents that capture profiling runs or encode table values **must** follow this method exactly to ensure consistency across architectures and sessions. diff --git a/src/work_stealing_pool.cpp b/src/work_stealing_pool.cpp index bacf2517..8a1db2c9 100644 --- a/src/work_stealing_pool.cpp +++ b/src/work_stealing_pool.cpp @@ -37,7 +37,7 @@ namespace stats { using namespace stats::detail; using namespace stats::arch::simd; -// result_of_t is now defined canonically in include/platform/internal/type_traits.h +// result_of_t is now defined canonically in include/libstats/platform/internal/type_traits.h // and pulled in transitively via work_stealing_pool.h. // Thread-local storage for current worker ID diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 6e1dbd4e..a7c3a5e4 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -68,7 +68,7 @@ function(configure_common_test_settings TEST_NAME) # Add include directories target_include_directories( - ${TEST_NAME} PRIVATE ${LIBSTATS_INCLUDE_SHIM_DIR} ${CMAKE_SOURCE_DIR}/src + ${TEST_NAME} PRIVATE ${LIBSTATS_BUILD_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include) libstats_apply_warnings(${TEST_NAME}) # Phase 3B/B5 -- single insertion point for every test # target diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 3cbb4db0..22b9d87f 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -9,7 +9,7 @@ option( function(add_libstats_tool tool_name source_file) add_executable(${tool_name} ${source_file}) target_link_libraries(${tool_name} PRIVATE libstats_static) - target_include_directories(${tool_name} PRIVATE ${LIBSTATS_INCLUDE_SHIM_DIR} + target_include_directories(${tool_name} PRIVATE ${LIBSTATS_BUILD_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/src) libstats_apply_warnings(${tool_name}) # Phase 3B/B5 @@ -27,7 +27,7 @@ function(add_standalone_tool tool_name source_file) add_executable(${tool_name} ${source_file}) # No libstats linking - pure standard library tools Still needs include paths for tool_utils.h → # libstats headers - target_include_directories(${tool_name} PRIVATE ${LIBSTATS_INCLUDE_SHIM_DIR}) + target_include_directories(${tool_name} PRIVATE ${LIBSTATS_BUILD_INCLUDE_DIRS}) libstats_apply_warnings(${tool_name}) # Phase 3B/B5 set_target_properties(${tool_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY diff --git a/tools/header_analysis.py b/tools/header_analysis.py index bf99dd67..1120f7db 100755 --- a/tools/header_analysis.py +++ b/tools/header_analysis.py @@ -173,9 +173,9 @@ def get_transitive_deps(header: str, visited: Set[str] = None) -> Set[str]: # Analyze a few key headers key_headers = [ - 'include/distributions/gaussian.h', - 'include/core/distribution_base.h', - 'include/libstats.h' + 'include/libstats/distributions/gaussian.h', + 'include/libstats/core/distribution_base.h', + 'include/libstats/libstats.h' ] for header in key_headers: diff --git a/tools/header_optimization_analysis.py b/tools/header_optimization_analysis.py index 1f25ac70..ce6daa8a 100755 --- a/tools/header_optimization_analysis.py +++ b/tools/header_optimization_analysis.py @@ -227,11 +227,11 @@ def check_phase1_effectiveness(): # Determine correct paths if os.path.exists('include'): - forward_decl_path = 'include/common/forward_declarations.h' - libstats_path = 'include/libstats.h' + forward_decl_path = 'include/libstats/common/forward_declarations.h' + libstats_path = 'include/libstats/libstats.h' elif os.path.exists('../include'): - forward_decl_path = '../include/common/forward_declarations.h' - libstats_path = '../include/libstats.h' + forward_decl_path = '../include/libstats/common/forward_declarations.h' + libstats_path = '../include/libstats/libstats.h' else: print(" ❌ Cannot find include directory") return diff --git a/tools/math_cache_benchmark.py b/tools/math_cache_benchmark.py index ad4db276..4aa9ae40 100755 --- a/tools/math_cache_benchmark.py +++ b/tools/math_cache_benchmark.py @@ -197,7 +197,7 @@ def setup_paths(self): current_dir = Path.cwd() # Try to find project root by looking for key files - project_indicators = ['CMakeLists.txt', 'include/libstats.h', 'src/'] + project_indicators = ['CMakeLists.txt', 'include/libstats/libstats.h', 'src/'] # Check current directory first if all((current_dir / indicator).exists() for indicator in project_indicators): diff --git a/tools/static_analysis.py b/tools/static_analysis.py index 75182690..1eeef831 100755 --- a/tools/static_analysis.py +++ b/tools/static_analysis.py @@ -107,7 +107,7 @@ def validate_common_header_effectiveness(self) -> Dict[str, any]: results = {} for common_header in common_headers: - header_path = self.project_root / "include" / common_header + header_path = self.project_root / "include" / "libstats" / common_header if not header_path.exists(): results[common_header] = {'status': 'NOT_FOUND'} continue @@ -143,7 +143,7 @@ def generate_optimization_recommendations(self) -> List[str]: # Analyze all headers print("🎯 Generating optimization recommendations...") - distribution_headers = list(self.project_root.glob("include/distributions/*.h")) + distribution_headers = list(self.project_root.glob("include/libstats/distributions/*.h")) # Check distribution header consistency dist_includes = defaultdict(int) diff --git a/tools/threshold_validator.cpp b/tools/threshold_validator.cpp index 2d00f51a..0dde5897 100644 --- a/tools/threshold_validator.cpp +++ b/tools/threshold_validator.cpp @@ -346,6 +346,6 @@ int main(int argc, char* argv[]) { "ops)\n\n" << "Matching tolerance: compiled within 2x of measured is MATCH.\n" << "Input must be strategy_profile_results.csv (raw data), not crossovers.csv.\n" - << "Edit include/core/dispatch_thresholds.h to apply changes.\n"; + << "Edit include/libstats/core/dispatch_thresholds.h to apply changes.\n"; }); } From e07c0b7847b3f7d5e45d58387542faa6581b938a Mon Sep 17 00:00:00 2001 From: Gary Wolfman Date: Sun, 26 Jul 2026 20:41:20 -0400 Subject: [PATCH 2/2] docs(plan): point the Threading.cmake known gap at issue #90 Co-Authored-By: Claude Opus 5 --- PLAN.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/PLAN.md b/PLAN.md index 12146cd0..64bec1bb 100644 --- a/PLAN.md +++ b/PLAN.md @@ -136,8 +136,9 @@ and attached issues were unchanged; only titles moved. (CMakeLists.txt) silently drops `Threads::Threads` from the PUBLIC link and the installed export. Found 2026-07-26 while verifying #83's install-tree byte-diff (the stale-cache baseline was the side missing the - entry). Pre-existing, orthogonal to #83; needs an issue. On Linux this - can underlink installed-package consumers. + entry). Pre-existing, orthogonal to #83; filed as #90 (also covers the + identical TBB::tbb pattern). On Linux this can underlink + installed-package consumers. ## Cross-Repo Dependencies [OPEN] pylibstats consumes this repo two ways — a `find_package` version floor and