Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ jobs:
lua spec/test_stats.lua
lua spec/test_distributions.lua
lua spec/test_sampling.lua
lua spec/test_bivariate.lua
lua spec/test_shape.lua

- name: Run examples
run: |
Expand All @@ -67,5 +69,5 @@ jobs:
lua examples/poisson_arrivals.lua
lua examples/binomial_coin_flips.lua
lua examples/bootstrap_mean.lua
lua spec/test_bivariate.lua
lua examples/covariance_correlation.lua
lua examples/skewness_kurtosis.lua
5 changes: 4 additions & 1 deletion .github/workflows/publish-luarocks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:
rockspec:
description: "Rockspec file to validate or publish"
required: true
default: "rockspec/luasf-0.5.0-1.rockspec"
default: "rockspec/luasf-0.6.0-1.rockspec"
type: string
publish:
description: "Publish to LuaRocks after validation"
Expand Down Expand Up @@ -47,6 +47,9 @@ jobs:
- name: Test LuaRocks package entry point
run: lua -e 'local stats = require("luasf"); print(stats.sum({1,2,3}))'

- name: Test shape statistics entry point
run: lua -e 'local stats = require("luasf"); print(stats.skewness({1,2,3,4,5})); print(stats.kurtosis({1,2,3,4,5}))'

- name: Test LuaSF compatibility entry point
run: lua -e 'local stats = require("LuaSF"); print(stats.sumF({1,2,3}))'

Expand Down
50 changes: 42 additions & 8 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,48 @@ This project follows a lightweight changelog format inspired by [Keep a Changelo

## [Unreleased]

### Planned

* Continue improving examples and documentation.
* Explore a lightweight cross-reference with LuaHMF as a related pure-Lua math helper project.
* Evaluate future probability helpers such as `factorial`, `combinations`, and `permutations`.
* Evaluate optional formula-based simple regression summaries while keeping ML workflows outside the current scope.
* Add more distribution examples and simulation-oriented examples.

---

## [0.6.0] - 2026-06-07

### Added

* Added `central_moment(array, order)`.
* Added `skewness(array)`.
* Added `kurtosis(array)`.
* Added `excess_kurtosis(array)`.
* Added `src/luasf/shape.lua` for shape statistics helpers.
* Added `spec/test_shape.lua`.
* Added `examples/skewness_kurtosis.lua`.
* Added `rockspec/luasf-0.6.0-1.rockspec`.

### Changed

* Updated the public facade `src/luasf.lua` to expose shape statistics helpers.
* Updated CI to run shape statistics tests and the new shape statistics example.
* Updated LuaRocks publishing workflow default rockspec path for `v0.6.0`.
* Updated README, API documentation, changelog, and contribution notes for shape statistics.

### Notes

Shape statistics are implemented as moment-based descriptive statistics:

* `skewness(array)` returns the standardized third central moment.
* `kurtosis(array)` returns Pearson kurtosis.
* `excess_kurtosis(array)` returns `kurtosis(array) - 3`.

---

## [0.5.0] - 2026-06-07

### Added

* Added modular internal source layout under `src/luasf/`.
Expand All @@ -34,14 +76,6 @@ This project follows a lightweight changelog format inspired by [Keep a Changelo
* Updated documentation to describe the modular layout and bivariate statistics helpers.
* Updated CI expectations to include bivariate tests and the covariance/correlation example.

### Planned

* Add shape statistics helpers such as `skewness(array)` and `kurtosis(array)`.
* Explore future probability helpers such as `factorial(n)`, `combinations(n, r)`, and `permutations(n, r)`.
* Explore a lightweight cross-reference with LuaHMF as a related pure-Lua math helper project.
* Consider simple formula-based regression summaries later, without turning LuaSF into a machine learning framework.
* Add more distribution examples and simulation-oriented examples.

---

## [0.4.0] - 2026-06-04
Expand Down
43 changes: 41 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,44 @@ LuaSF is a small, pure-Lua statistics library. The project values simplicity, co
LuaSF aims to provide:

* Basic descriptive statistics
* Summary statistics helpers
* Shape statistics helpers such as skewness and kurtosis
* Bivariate statistics helpers such as covariance and correlation
* Pseudo-random variable generation
* Sampling utilities
* A small and readable Lua codebase
* Compatibility with the existing public API
* Useful examples for simulations, teaching, small scripts, and game/mod scripting

---

## Scope boundaries

LuaSF should remain lightweight and dependency-free.

Good fits for LuaSF:

* Descriptive statistics
* Shape statistics
* Bivariate statistics
* Probability helpers
* Random variable generation
* Sampling and simulation utilities
* Formula-based statistical summaries

Currently out of scope:

* Machine learning pipelines
* Optimization-based model training
* Non-linear regression fitting
* Deep learning
* Native dependencies
* Large framework-style APIs

Formula-based simple regression summaries may be considered in the future, but ML-style model training is intentionally outside the current scope.

---

## Compatibility first

Please avoid breaking the existing public API.
Expand Down Expand Up @@ -71,6 +102,7 @@ src/
distributions.lua
bivariate.lua
probability.lua
shape.lua
validation.lua
rng.lua
```
Expand All @@ -85,6 +117,7 @@ Recommended module ownership:
* `distributions.lua`: random variable generators
* `probability.lua`: future probability/combinatorics helpers
* `validation.lua`: reusable input validation helpers
* `shape.lua`: skewness and kurtosis helpers
* `rng.lua`: random generator and seed helpers
* `core.lua`: small reusable internal utilities

Expand All @@ -106,13 +139,20 @@ luarocks install --local luaunit
eval "$(luarocks path --local)"
```

If needed for local development, configure Lua to load the local `src/` module path:

```bash
export LUA_PATH="./src/?.lua;./?.lua;$LUA_PATH"
```

Run tests:

```bash
lua spec/test_stats.lua
lua spec/test_distributions.lua
lua spec/test_sampling.lua
lua spec/test_bivariate.lua
lua spec/test_shape.lua
```

Run examples:
Expand All @@ -127,6 +167,7 @@ lua examples/poisson_arrivals.lua
lua examples/binomial_coin_flips.lua
lua examples/bootstrap_mean.lua
lua examples/covariance_correlation.lua
lua examples/skewness_kurtosis.lua
```

---
Expand Down Expand Up @@ -233,8 +274,6 @@ Avoid:

Potential future additions include:

* `skewness(array)`
* `kurtosis(array)`
* `factorial(n)`
* `combinations(n, r)`
* `permutations(n, r)`
Expand Down
63 changes: 63 additions & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,69 @@ print(result.variance) -- 2.5
```


---

## Shape statistics

Shape statistics describe the asymmetry and tail behavior of a numeric array.

LuaSF implements moment-based shape helpers.

### `central_moment(array, order)`

Returns the central moment of a numeric array using denominator `n`.

The central moment of order `k` is computed as the average of `(x_i - mean)^k`.

```lua
local stats = require("luasf")

print(stats.central_moment({1, 2, 3, 4, 5}, 2)) -- 2
```

---

### `skewness(array)`

Returns the standardized third central moment.

Values near `0` indicate approximate symmetry. Positive values suggest right skew, while negative values suggest left skew.

```lua
local stats = require("luasf")

print(stats.skewness({1, 2, 3, 4, 5})) -- approximately 0
print(stats.skewness({1, 1, 2, 2, 10})) -- positive
```

---

### `kurtosis(array)`

Returns Pearson kurtosis.

```lua
local stats = require("luasf")

print(stats.kurtosis({1, 2, 3, 4, 5})) -- 1.7
```

---

### `excess_kurtosis(array)`

Returns Fisher-style excess kurtosis:

```text
kurtosis(array) - 3
```

```lua
local stats = require("luasf")

print(stats.excess_kurtosis({1, 2, 3, 4, 5})) -- -1.3
```

---

## Bivariate statistics
Expand Down
15 changes: 15 additions & 0 deletions examples/skewness_kurtosis.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
local stats = require("luasf")

local symmetric_values = {1, 2, 3, 4, 5}
local right_skewed_values = {1, 1, 2, 2, 10}

local function print_shape_summary(label, values)
print(label)
print("Skewness:", stats.skewness(values))
print("Kurtosis:", stats.kurtosis(values))
print("Excess kurtosis:", stats.excess_kurtosis(values))
print("")
end

print_shape_summary("Symmetric values", symmetric_values)
print_shape_summary("Right-skewed values", right_skewed_values)
41 changes: 41 additions & 0 deletions rockspec/luasf-0.6.0-1.rockspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package = "luasf"
version = "0.6.0-1"

source = {
url = "git://github.com/HubertRonald/LuaSF.git",
tag = "v0.6.0"
}

description = {
summary = "Lua Statistics Functions",
detailed = [[
LuaSF is a lightweight, pure-Lua library for descriptive statistics,
shape statistics, bivariate statistics, sampling utilities, simulation
examples, and random variable generation.
]],
homepage = "https://github.com/HubertRonald/LuaSF",
license = "MIT",
maintainer = "Hubert Ronald"
}

dependencies = {
"lua >= 5.1"
}

build = {
type = "builtin",
modules = {
luasf = "src/luasf.lua",
["luasf.core"] = "src/luasf/core.lua",
["luasf.validation"] = "src/luasf/validation.lua",
["luasf.rng"] = "src/luasf/rng.lua",
["luasf.descriptive"] = "src/luasf/descriptive.lua",
["luasf.shape"] = "src/luasf/shape.lua",
["luasf.sampling"] = "src/luasf/sampling.lua",
["luasf.distributions"] = "src/luasf/distributions.lua",
["luasf.bivariate"] = "src/luasf/bivariate.lua",
["luasf.probability"] = "src/luasf/probability.lua",
LuaSF = "LuaSF.lua",
LuaStat = "LuaStat.lua"
}
}
54 changes: 54 additions & 0 deletions spec/test_shape.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
local luaunit = require("luaunit")
local stats = require("luasf")

TestShape = {}

function TestShape:test_skewness_symmetric_data()
local values = {1, 2, 3, 4, 5}

luaunit.assertAlmostEquals(stats.skewness(values), 0, 0.000001)
end

function TestShape:test_skewness_positive_data()
local values = {1, 1, 2, 2, 10}

luaunit.assertTrue(stats.skewness(values) > 0)
end

function TestShape:test_skewness_negative_data()
local values = {1, 9, 10, 10, 10}

luaunit.assertTrue(stats.skewness(values) < 0)
end

function TestShape:test_kurtosis_for_simple_sequence()
local values = {1, 2, 3, 4, 5}

luaunit.assertAlmostEquals(stats.kurtosis(values), 1.7, 0.000001)
end

function TestShape:test_excess_kurtosis_for_simple_sequence()
local values = {1, 2, 3, 4, 5}

luaunit.assertAlmostEquals(stats.excess_kurtosis(values), -1.3, 0.000001)
end

function TestShape:test_central_moment_second_order()
local values = {1, 2, 3, 4, 5}

luaunit.assertAlmostEquals(stats.central_moment(values, 2), 2, 0.000001)
end

function TestShape:test_skewness_requires_non_constant_array()
luaunit.assertError(function()
stats.skewness({1, 1, 1})
end)
end

function TestShape:test_kurtosis_requires_non_constant_array()
luaunit.assertError(function()
stats.kurtosis({1, 1, 1})
end)
end

os.exit(luaunit.LuaUnit.run())
1 change: 1 addition & 0 deletions src/luasf.lua
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ local M = {}
merge(M, require(prefix .. "rng"))
merge(M, require(prefix .. "core"))
merge(M, require(prefix .. "descriptive"))
merge(M, require(prefix .. "shape"))
merge(M, require(prefix .. "sampling"))
merge(M, require(prefix .. "distributions"))
merge(M, require(prefix .. "bivariate"))
Expand Down
Loading
Loading