embedded-sqrt
Racine carrée en virgule fixe Q15 pour systèmes embarqués
no_std, zéro dépendance, testée sur pico 2040 sans fpu.
Update version 0.2.1 testée sur la pico 2040 qui n'a pas de fpu
La version 0.2.1 est identique à la version 0.2.0 , elle introduit un exemple clé en main pour la pico 2040 qui n'a pas de FPU , rétrouvez l'exemple dans la section exemples .
Update Version 0.2.0
La version introduit #![forbid(unsafe_code)] pour le safe on veut pas de code unsafe.
Fonctionnalités
#![no_std]— fonctionne sans bibliothèque standard- Arithmétique entière pure : pas de flottants, pas de
libm - Compatible Raspberry Pi Pico (RP2040) et Pico 2 (RP2350)
- Algorithme Newton-Raphson : convergence quadratique en 6 itérations
- Précision : erreur < 150 ULP sur toute la plage Q15
Format Q15
En Q15, un entier i32 représente un nombre réel dans [0.0, 1.0[ :
valeur_réelle = valeur_i32 / 32768.0
Valeur i32 |
Valeur réelle |
|---|---|
0 |
0.0 |
8192 |
0.25 |
16384 |
0.5 |
23170 |
≈ 0.707 (1/√2) |
32767 |
≈ 1.0 |
Installation
Dans votre Cargo.toml :
[]
= "0.2.2"
Utilisation
use sqrt;
// sqrt(0.25) = 0.5 → 8192 en Q15 → 16384 en Q15
let res = sqrt;
assert!;
// sqrt(≈1.0) = ≈1.0
let res = sqrt;
assert!;
// Entrée négative ou nulle → 0
assert_eq!;
assert_eq!;
Exemple Pico 2040 sans FPU
use Write;
use cortex_m_rt as _;
use Spawner;
use ;
use ;
use ;
// Mathématiques et formatage
use String;
use sqrt;
// Drivers et partage de bus
use LcdI2c;
use NoopRawMutex;
use Mutex;
use I2cDevice;
use bind_interrupts;
use I2C0;
// Configuration des interruptions pour l'I2C0
bind_interrupts!;
// TASK : SYSTEM_TASK
// Cette tâche s'occupe de calculer et d'afficher les racines carrées
async
// MAIN : POINT D'ENTRÉE
async
Le Cargo.toml indispensable sans lui pas de programme ni affichage
[dependencies]
embassy-rp = { version = "0.6.0", features = ["rt", "rp2040", "time-driver", "critical-section-impl"] }
embassy-executor = { version = "0.6.3", features = ["arch-cortex-m", "executor-thread", "task-arena-size-32768"] }
embassy-time = { version = "0.4.0", features = ["generic-queue-8"] }
embassy-sync = { version = "0.6.1" }
embassy-embedded-hal = { version = "0.3.0" }
embedded-hal = "1.0.0"
embedded-hal-async = "1.0.0"
embedded-hal-bus = { version = "0.2.0", features = ["async"] }
portable-atomic = { version = "1.5" }
cortex-m = "0.7.7"
cortex-m-rt = "0.7.3"
panic-halt = "0.2.0"
heapless = "0.8.0"
hd44780-i2c-nostd = "0.3.0"
embedded-sqrt = "0.2.0"
static_cell = "2.1.1"
[profile.release]
opt-level = "s"
lto = true
codegen-units = 1
panic = "abort"
strip = true
Algorithme
Newton-Raphson en virgule fixe
La racine carrée est calculée par la méthode de Newton-Raphson :
x_{n+1} = (x_n + a / x_n) / 2
Étapes
-
Normalisation l'entrée
aest ramenée dans[0.5, 2.0[en Q15 par décalages :sqrt(a · 4^n) = 2^n · sqrt(a) -
Estimation initiale — deux constantes couvrent les deux moitiés de la plage :
[0.5, 1.0[→x0 = 0.84(≈ 27525 en Q15)[1.0, 2.0[→x0 = 1.19(≈ 39000 en Q15)
-
6 itérations la convergence est quadratique (les bits corrects doublent à chaque étape). 6 itérations suffisent pour dépasser 15 bits de précision.
-
Dénormalisation le décalage appliqué à l'entrée est annulé sur le résultat.
Pourquoi pas CORDIC ?
Le CORDIC hyperbolique pour la racine carrée avec l'initialisation
x₀ = a + 0.25, y₀ = a - 0.25 n'a pas un gain constant sur la plage Q15 :
le facteur K_hyp varie selon la valeur d'entrée, ce qui rend la correction impossible
avec une simple constante. Newton-Raphson est plus simple, plus précis, et garanti convergent.
Compatibilité
| Cible | Statut |
|---|---|
thumbv6m-none-eabi (RP2040, Cortex-M0+) |
✅ |
thumbv8m.main-none-eabihf (RP2350, Cortex-M33) |
✅ |
thumbv7em-none-eabihf (STM32, Cortex-M4F) |
✅ |
tout target no_std |
✅ |
La division i64 est générée en software par le compilateur sur les cibles
sans division hardware 64 bits (ex. RP2040). Le coût est d'environ 200–300 cycles
par appel sur Cortex-M0+.
Configuration recommandée
.cargo/config.toml pour Pico (RP2040) :
[]
= "thumbv6m-none-eabi"
Pour Pico 2 (RP2350) :
[]
= "thumbv8m.main-none-eabihf"
Cargo.toml :
[]
= 3
= true
= 1
Licence
Ce programme est un logiciel libre : vous pouvez le redistribuer et/ou le modifier selon les termes de la Licence Publique Générale GNU telle que publiée par la Free Software Foundation, soit la version 2 de la licence, soit (à votre choix) n'importe quelle version ultérieure.
Ce programme est distribué dans l'espoir qu'il sera utile, mais sans aucune garantie.
Voir le fichier LICENSE ou gnu.org/licenses pour les détails.
Copyright (C) 2026 Jorge Andre Castro — Licence GNU GPL v2 ou ultérieure.