diff --git a/CHANGELOG.md b/CHANGELOG.md
index 108f86a7f2f6366990bdaceb7739e31d2a759c70..c0228d6f0fc14d27a3f0410001a72b0a623ddf11 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,7 +6,45 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
 
 
 ## [Unreleased]
-[Unreleased]: https://github.com/althonos/lightmotif/compare/v0.3.0...HEAD
+[Unreleased]: https://github.com/althonos/lightmotif/compare/v0.4.0...HEAD
+
+
+## [v0.4.0] - 2023-08-10
+[v0.4.0]: https://github.com/althonos/lightmotif/compare/v0.3.0...v0.4.0
+
+### Changed
+
+#### `lightmotif`
+- Improve `DenseMatrix::resize` performance when downsizing.
+- Explicitly panic when sequence is too long to be processed with `u32` indices in AVX2 and SSE2.
+- Reorganize `DenseMatrix` column alignment and index storage.
+- Improve `Score` performance by using pointers instead of slices in SIMD loops.
+- Rename `DenseMatrix::columns_effective` to `DenseMatrix::stride`.
+- Use streaming intrinsics to store data in AVX2 and SSE2 implementations.
+- Rename `BestPosition` trait to `Maximum`.
+
+#### `lightmotif-py`
+- Avoid error on missing symbols in `CountMatrix.__init__`
+
+### Added
+
+#### `lightmotif`
+- `Threshold` trait to find all position above a certain score in a `StripedScores` matrix.
+- `Encode` trait to encode an ASCII sequence into a `Vec<Symbol>`.
+- AVX2 implementation of `Score` using `gather` instead of `permute` for protein alphabets.
+- `From<Vec<_>>` and `Default` trait implementations to `EncodedSequence`.
+- `Alphabet` methods to operate on ASCII strings.
+- `StripedScores.is_empty` method to check if a `StripedScores` contains any score.
+
+#### `lightmotif-py`
+- `StripedScores.threshold` method wrapping the `Threshold` pipeline operation.
+- `StripedScores.max` and `StripedScores.argmax` methods to get the best score and best position.
+
+### Fixed
+
+#### `lightmotif`
+- `Score` causing an overflow when given a sequence shorter than the PSSM.
+- `Maximum` trait returns the smallest position on equal maxima.
 
 
 ## [v0.3.0] - 2023-06-25
diff --git a/lightmotif-bench/Cargo.toml b/lightmotif-bench/Cargo.toml
index 845428879cd81405049e5f87ca9d781cd5f28ca2..e720dd225afecede889ac5a40513c54d17830491 100644
--- a/lightmotif-bench/Cargo.toml
+++ b/lightmotif-bench/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "lightmotif-bench"
-version = "0.3.0"
+version = "0.4.0"
 edition = "2021"
 publish = false
 
diff --git a/lightmotif-py/Cargo.toml b/lightmotif-py/Cargo.toml
index a321471e0897d1b865c52ce177527aa96fb9f8c4..d3a53a15d7d3a8fd49db6a1e589253311f420110 100644
--- a/lightmotif-py/Cargo.toml
+++ b/lightmotif-py/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "lightmotif-py"
-version = "0.3.0"
+version = "0.4.0"
 authors = ["Martin Larralde <martin.larralde@embl.de>"]
 edition = "2021"
 license = "MIT"
@@ -17,7 +17,7 @@ path = "lightmotif/lib.rs"
 
 [dependencies.lightmotif]
 path = "../lightmotif"
-version = "0.3.0"
+version = "0.4.0"
 [dependencies]
 pyo3 = "0.18.3"
 generic-array = "0.14"
diff --git a/lightmotif-py/lightmotif/__init__.py b/lightmotif-py/lightmotif/__init__.py
index 118129151839077386d76cf5dffe5cc3990afceb..0ad04050c89189269b5991f7e7355079e63c4d6c 100644
--- a/lightmotif-py/lightmotif/__init__.py
+++ b/lightmotif-py/lightmotif/__init__.py
@@ -1,4 +1,4 @@
-__version__ = "0.3.0"
+__version__ = "0.4.0"
 
 from . import lib
 from .lib import (
diff --git a/lightmotif-tfmpvalue/Cargo.toml b/lightmotif-tfmpvalue/Cargo.toml
index 12170257292e7cf612c8e9a250dc4f6987d02d58..1286bf41fa987665225e216955605a7697000088 100644
--- a/lightmotif-tfmpvalue/Cargo.toml
+++ b/lightmotif-tfmpvalue/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "lightmotif-tfmpvalue"
-version = "0.3.0"
+version = "0.4.0"
 authors = ["Martin Larralde <martin.larralde@embl.de>"]
 edition = "2021"
 license = "GPL-3.0"
@@ -13,7 +13,7 @@ keywords = ["bioinformatics", "motif", "pssm", "pvalue"]
 
 [dependencies.lightmotif]
 path = "../lightmotif"
-version = "0.3.0"
+version = "0.4.0"
 [dependencies.fnv]
 version = "1.0"
 optional = true
diff --git a/lightmotif-transfac/Cargo.toml b/lightmotif-transfac/Cargo.toml
index d365b571a4f94aeb10e6bf21d6040ec882a127bc..affbe610788102a469269c8fd545e9153bef15e5 100644
--- a/lightmotif-transfac/Cargo.toml
+++ b/lightmotif-transfac/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "lightmotif-transfac"
-version = "0.3.0"
+version = "0.4.0"
 authors = ["Martin Larralde <martin.larralde@embl.de>"]
 edition = "2021"
 license = "MIT"
@@ -13,7 +13,7 @@ keywords = ["bioinformatics", "motif", "parser", "transfac"]
 
 [dependencies.lightmotif]
 path = "../lightmotif"
-version = "0.3.0"
+version = "0.4.0"
 [dependencies]
 nom = "7"
 memchr = "2"
diff --git a/lightmotif/Cargo.toml b/lightmotif/Cargo.toml
index 42004dd19fc8b14b4fd6fe9e30645438292c9cb9..332594d0890ced4e1cf6c112a4dba58589b402cb 100644
--- a/lightmotif/Cargo.toml
+++ b/lightmotif/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "lightmotif"
-version = "0.3.0"
+version = "0.4.0"
 authors = ["Martin Larralde <martin.larralde@embl.de>"]
 edition = "2021"
 license = "MIT"