* --- 2026-09-02 :: qcluster v3.0.0 ---

  Validation moves from bootstrap to held-out validation: each candidate is
  fitted on a training block drawn without replacement and scored on the
  complementary block. Student-t mixtures join the Gaussian ones, method sets
  can be screened, printed and summarised, and the plots of a fit read the
  quadratic score directly. The API changes; no compatibility alias is kept.

  changelog

  - new `qcluster()`, `qcluster_rank()` and `qcluster_select()`: held-out
    validation, re-ranking and full-data refit of clustering solutions. The
    score summary reports `mean`, `sterr`, `lower`, `upper`, `complexity`
    (apparent minus held-out score), `crank` and `na_prop`; the ranking rules
    are `"mean"`, `"lpb"` and `"se"`, the last admitting the methods within
    `delta` dispersions of the best and flagging them as `selected`
  - new `tmix()`: constrained ML estimation and clustering of Student-t
    mixtures (ECM algorithm in C), with fixed or estimated degrees of freedom.
    Scatter and covariance are both returned; the covariance is `NA` for
    `df <= 2`. `mset_tmix()` puts it in a method set
  - new `mset_screen()`: two-step preselection of a method set before an
    intensive run
  - new `apply_method()`: fit one method of a set on a data set
  - new `print()` and `summary()` methods for method sets; every `mset_*()`
    constructor gains `method_name` for custom codenames
  - fits are of class `c("gmix", "qcfit")` and `c("tmix", "qcfit")`, with
    `print`, `plot` and `predict` methods; `predict()` and `plot()` on a
    `tmix` fit use the Student-t rule
  - `plot_clustering()`: the `"boundary"` layer shades the decision regions
    of the quadratic score; the `"contour"` layer draws, for each cluster,
    the level set of its component score at the median over the cluster's
    points, labelled with the level
  - `plot.qcluster()` gains `nmax` (methods displayed) and `magnify` (bars
    emphasised)
  - parallel runs are reproducible under `set.seed()` for any `ncores`, also
    for methods with internal randomness
  - fixes: univariate data (`P = 1`) errored in fitting, scoring and plotting
    since 2.0.0; `gmix(save_params = FALSE)` errored; a fit with
    `save_cluster = FALSE` carried an empty `cluster` component; a single
    method or a single cluster could not be plotted; unchecked allocations and
    type fixes in the C code

  deprecation log

  - removed: `bqs()`, `bqs_rank()`, `bqs_select()` and class `"bqs"` (see
    `qcluster*()`); class `"mbcfit"` and the `$type` component of a fit;
    the `type` and `df` arguments of `plot_clustering()`; `which` of
    `summary.qcmethod()` (now `id`/`method_name`); `label` of `mset_user()`
    (now `method_name`); `top` of `plot.bqs()` (see `magnify` and `nmax`)
  - renamed arguments: `iter.max`, `init.nstart`, `init.iter.max`, `init.tol`
    become `iter_max`, `init_nstart`, `init_iter_max`, `init_tol` in `gmix()`,
    `tmix()`, `mset_gmix()`, `mset_tmix()`; `df.fixed`, `df.range`,
    `df.warmup` become `df_fixed`, `df_range`, `df_warmup`. From `bqs()` to
    `qcluster()`: `methodset` -> `method_set`, `oob` -> `sprop` (training
    fraction), `alpha` -> `prob`, `boot_na_share` -> `max_na_prop`,
    `savescores` -> `save_scores` (default `TRUE`), `saveparams` dropped;
    `rankby` values `"lq"` and `"1se"` become `"lpb"` and `"se"`, `"ci"` is
    removed
  - renamed columns of the score summary: `lower_qnt`/`upper_qnt` ->
    `lower`/`upper`, `n_obs`/`n_missing` -> `na_prop`; `best_*` is now
    `list(id, method_name, crank)`

* --- 2026-06-03 :: qcluster v2.0.1 ---
  - Strengthened tests to avoid dependencies on BLAS implementation
  - added defensive C-level validation and `size_t` allocation sizes in the
  ECM routine

* --- 2026-04-12 :: qcluster v2.0.0 ---

  major update of the package internals, documentation and test suite

  user-visible changes

  - improved numerical stability in Gaussian-mixture fitting and scoring:
    log-scale normalization is now used in the most fragile steps of ECM
    initialization and scoring; several low-level numerical issues and one
    undefined-behaviour warning in the C code were fixed
  - strengthened input validation throughout the public API:
    `gmix()`, `qscore()`, `clust2params()`, `bqs()` and related methods now
    reject malformed data and parameters earlier and with clearer messages
  - `gmix()` now validates all supported initialization modes more strictly,
    including custom functions, matrices/data frames of weights, vectors of
    labels, and unsupported character initializers
  - `predict.mbcfit()` now fails early when mixture parameters are not
    Gaussian-ready; plotting methods distinguish more clearly between plots
    that only need clustering assignments and plots that require valid
    Gaussian parameters
  - `qscore()` now returns `NA` for the score component that was not requested,
    while preserving `NaN` for requested scores that cannot be computed
  - `bqs_rank()` and `bqs_select()` were revised:
    reranking now clears stale `best_*` solutions, ranks remain `NA` when the
    chosen ranking criterion is not available, and `bqs_select()` always
    refits selected solutions on the full data
  - `bqs_select()` now reports full-data refit failures as structured
    `bqs_select_error` objects instead of bare strings
  - `plot.bqs()` was fixed for `rankby = "1se"` and now validates requested
    score components against the score summaries actually stored in the object
  - `bqs()` now validates `B`, `ncores`, and empty method sets more carefully;
    BLAS/OpenMP threading inside PSOCK workers is serialized by default to
    avoid oversubscription

  infrastructure and maintenance

  - migrated package documentation to roxygen2 and regenerated `NAMESPACE`
    and the manual pages accordingly
  - added a package-level help page and updated help files to reflect the
    current API and behaviour of the package
  - expanded the test suite substantially with `testthat`, including
    regression tests for clustering output, scoring, plotting, validation,
    ranking/selection logic, and parallel-thread handling
  - updated package metadata, URLs and author information

* --- 2024-12-23 :: qcluster v1.2.1 ---

  updated citation information

* --- 2024-12-06 :: qcluster v1.2 ---

  first version of the package was finally uploaded on CRAN
