M4 — pls4all source split plan

Source: Explore-agent analysis of cpp/src/core/model.cpp (4541 lines, 180 KB) + cpp/src/core/extra_pls.cpp (1647 lines, 80 KB).

Totals

File

Lines

Functions

Helpers (anon namespace)

model.cpp

4541

18

~1500 lines (L18–L1524)

extra_pls.cpp

1647

19

~290 lines (L18–L306)

Total

6188

37

~1790

Per-file function table

model.cpp

#

Function

Line

Length

Target

1

fit_pls_regression_nipals

1528

291

models/pls/nipals.cpp

2

fit_pls_canonical_nipals

1819

10

models/pls/canonical.cpp

3

fit_pls_canonical_svd

1829

10

models/pls/canonical.cpp

4

fit_pls_svd

1839

161

models/pls/plssvd.cpp

5

fit_opls_nipals

2000

350

models/opls/opls.cpp

6

fit_pls_regression_orthogonal_scores

2350

265

models/pls/oscores.cpp

7

fit_pls_regression_kernel

2615

280

models/pls/kernel.cpp

8

fit_pls_regression_svd

2895

166

models/pls/svd.cpp

9

fit_pls_regression_power

3061

166

models/pls/power.cpp

10

fit_pls_regression_randomized_svd

3227

170

models/pls/randomized_svd.cpp

11

fit_pcr_svd

3397

288

models/pcr/pcr.cpp

12

fit_pls_regression_simpls

3685

200

models/pls/simpls.cpp

13

predict_into

3885

36

models/core/dispatch.cpp

14

fit_di_pls

3921

242

models/classification/pls_da.cpp

15

fit_pls_sparse_simpls

4163

225

models/sparse/sparse_simpls.cpp

16

fit_model

4388

46

models/core/dispatch.cpp

17

transform_into

4434

36

models/core/dispatch.cpp

18

model_array

4470

72

models/core/dispatch.cpp

extra_pls.cpp

#

Function

Line

Length

Target

1

fit_sparse_pls_da

307

60

models/sparse/sparse_pls_da.cpp

2

fit_group_sparse_pls

367

78

models/sparse/group_sparse.cpp

3

fit_fused_sparse_pls

445

36

models/sparse/fused_sparse.cpp

4

fit_cppls

481

70

models/specialized/cppls.cpp

5

fit_weighted_pls

551

66

models/specialized/weighted.cpp

6

fit_robust_pls

617

61

models/specialized/robust_huber.cpp

7

fit_ridge_pls

678

59

models/specialized/ridge.cpp

8

fit_continuum_regression

737

63

models/specialized/continuum.cpp

9

fit_pls_glm

800

47

models/glm/pls_glm.cpp

10

fit_pls_qda

847

98

models/classification/pls_qda.cpp

11

fit_pls_cox

945

85

models/classification/pls_cox.cpp

12

fit_pds

1030

111

transfer/pds.cpp

13

fit_ds

1141

102

transfer/ds.cpp

14

fit_mir_pls

1243

90

models/local/mir_pls.cpp

15

fit_missing_aware_nipals

1333

65

models/specialized/missing_aware_nipals.cpp

16

approximate_press

1398

79

models/core/dispatch.cpp

17

fit_bagging_pls

1477

54

models/ensembles/bagging.cpp

18

fit_boosting_pls

1531

52

models/ensembles/boosting.cpp

19

fit_random_subspace_pls

1583

65

models/ensembles/random_subspace.cpp

High-risk cross-cutting helpers

The ~1790 lines of helpers (anonymous namespaces) MUST be extracted FIRST, into shared _common.cpp files, before any algorithm extraction:

Helper

Location

Used by

Extract to

simple_simpls

extra_pls.cpp:97

model.cpp fit_pls_sparse_simpls AND extra_pls sparse variants

models/pls/_common.cpp

center_scale_in_place

model.cpp:161

~15 model.cpp functions

models/core/_common.cpp

dominant_svd_pair, largest_symmetric_eigenvector

model.cpp helpers

SVD / Kernel / Canonical / OPLS

models/pls/_common.cpp

canonicalize_direction_sign, canonicalize_svd_pair_sign

model.cpp:274,691,772,919,953,1064,1086,1175,3801

SVD variants + OPLS chassis

models/pls/_common.cpp

soft_threshold

extra_pls.cpp:87

all 4 sparse variants

models/sparse/_common.cpp

copy_matrix, column_means, subtract_means, squared_norm

extra_pls.cpp helpers

sparse + specialized

models/sparse/_common.cpp

invert_square, dot, matrix_vector_product

model.cpp helpers

most algorithms

models/core/_common.cpp

validate_fit_request, copy_matrix_checked

model.cpp helpers

all fit_* functions

models/core/_common.cpp

Proposed extraction order (7 phases)

Phase

Scope

Commits

1

Helpers → _common.cpp (3 files)

3

2

Core PLS solvers (nipals, simpls, svd, plssvd, power, randomized_svd, kernel, canonical)

8

3

PCR + OPLS

2

4

Classification (pls_da, pls_qda, pls_cox)

3

5

Sparse (4 files)

4

6

Specialized (6) + ensembles (3) + transfer (2) + local + glm

12

7

Core dispatch + header consolidation

2

Total: ~34 commits if each extraction is its own commit (best for blame preservation). Per-commit gate: n4m_tests 265/265 still green and no function moves are functional changes.

Notes from the agent’s analysis

  • Lines 18–1524 of model.cpp form a tight ~1500-line anonymous-namespace helper block with a clear boundary; lines 18–306 of extra_pls.cpp form a ~290-line one. Both extract cleanly.

  • No explicit // === ALGORITHM === section dividers exist; functions appear in topological order by dependency.

  • The 18 model.cpp functions reach line 4541; the 19 extra_pls.cpp functions end at line 1647. Both files have no unaccounted top-level definitions.

  • Helpers do not cross between the two source files (each set is file-local). The simple_simpls cross-call from model.cpp → extra_pls.cpp via fit_pls_sparse_simpls is the ONE exception — extracting it first to models/pls/_common.cpp resolves it cleanly.