embedded-complex-f32 0.1.0

Nombres complexes f32 no_std pour systèmes embarqués sans dépendance C, sans unsafe
Documentation
  • Coverage
  • 100%
    22 out of 22 items documented9 out of 16 items with examples
  • Size
  • Source code size: 25.04 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 1.77 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 1m 24s Average build duration of successful builds.
  • all releases: 1m 24s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • jorgeandrecastro/embedded-complex-f32
    0 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • jorgeandrecastro

embedded-complex-f32

Nombres complexes f32 pour systèmes embarqués no_std.

Zéro dépendance C · Sans unsafe · Racine carrée via embedded-f32-sqrt

Crates.io Docs.rs License: GPL-2.0-or-later


Fonctionnalités

  • Arithmétique complète : +, -, *, / (opérateurs Rust natifs)
  • Opérations scalaires f32 : z + 1.0, z * 2.0, etc.
  • Module (norme), carré de la norme, conjugué
  • Puissance entière (powi) par exponentiation rapide
  • Racine carrée complexe (csqrt)
  • Inverse (inv), division vérifiée (checked_div)
  • Gestion robuste de NaN / Infinity (IEEE 754)
  • Display et Debug via core::fmt
  • Conversions From<f32>, From<(f32, f32)>, Into<(f32, f32)>

Hors périmètre

arg(), to_polar(), from_polar(), exp(), ln() requièrent des fonctions trigonométriques précises. Utilisez libm ou micromath selon votre target et construisez par-dessus ce type.


Installation

[dependencies]
embedded-complex-f32 = "0.1.0"

Démarrage rapide

use embedded_complex_f32::Complex;

let a = Complex::new(3.0, 4.0);   // 3 + 4i
let b = Complex::new(1.0, -1.0);  // 1 - i

// Arithmétique de base
let sum  = a + b;   // 4 + 3i
let diff = a - b;   // 2 + 5i
let prod = a * b;   // 7 + i
let quot = a / b;   // NaN + NaN·i si |b| == 0 préférer checked_div

// Module et conjugué
assert!((a.norm() - 5.0).abs() < 1e-4);  // |3 + 4i| = 5
assert_eq!(a.conj(), Complex::new(3.0, -4.0));

// Division sûre
match a.checked_div(b) {
    Ok(r)  => { /* utiliser r */ }
    Err(e) => { /* ComplexError::DivisionByZero */ }
}

Référence API

Constantes

Complex::ZERO   // 0 + 0i
Complex::ONE    // 1 + 0i
Complex::I      // 0 + 1i

Constructeurs et accesseurs

Complex::new(re: f32, im: f32) -> Complex

z.re() -> f32    // partie réelle
z.im() -> f32    // partie imaginaire

z.is_nan()      -> bool
z.is_infinite() -> bool
z.is_finite()   -> bool

Arithmétique

// Complex op Complex
z1 + z2    z1 - z2    z1 * z2    z1 / z2
z1 += z2   z1 -= z2   z1 *= z2   z1 /= z2

// Complex op f32
z + 1.0    z - 1.0    z * 2.0    z / 2.0

// Négation
-z

Opérations algébriques

// Conjugué : re - im·i
z.conj() -> Complex

// Norme : √(re² + im²)
z.norm() -> f32

// Carré de la norme : re² + im²  (évite la racine carrée)
z.norm_sq() -> f32

// Division vérifiée
z.checked_div(rhs: Complex) -> Result<Complex, ComplexError>

// Inverse : 1 / self
z.inv() -> Result<Complex, ComplexError>

// Racine carrée complexe
z.csqrt() -> Result<Complex, ComplexError>
//   Complex::new( 9.0, 0.0).csqrt() -> Ok(3.0 + 0.0i)
//   Complex::new(-1.0, 0.0).csqrt() -> Ok(0.0 + 1.0i)

// Puissance entière (n négatif autorisé)
z.powi(n: i32) -> Result<Complex, ComplexError>
//   Complex::I.powi(4)              -> Ok(1.0 + 0.0i)
//   Complex::new(2.0, 0.0).powi(-1) -> Ok(0.5 + 0.0i)

Conversions

Complex::from(3.0f32)             // 3.0 + 0.0i
Complex::from((1.0f32, -2.0f32))  // 1.0 - 2.0i

let (re, im): (f32, f32) = z.into();

Gestion d'erreurs

use embedded_complex_f32::ComplexError;

match z.checked_div(w) {
    Ok(result)                        => { /* ... */ }
    Err(ComplexError::DivisionByZero) => { /* |w| == 0 */ }
    Err(ComplexError::NegativeInput)  => { /* entrée invalide pour √ */ }
    Err(ComplexError::Undefined)      => { /* NaN propagé */ }
}

Exemples

Filtre IIR (pôle complexe)

use embedded_complex_f32::Complex;

// Pôle fourni sous forme cartésienne par l'appelant
let pole = Complex::new(0.8, 0.3);

// Un pas : y[n] = x[n] + pole * y[n-1]
fn iir_step(x: f32, y_prev: Complex, pole: Complex) -> Complex {
    Complex::from(x) + pole * y_prev
}

Puissance entière

use embedded_complex_f32::Complex;

// (1 + i)^8 = 16
let z = Complex::new(1.0, 1.0);
let r = z.powi(8).unwrap();
assert!((r.re() - 16.0).abs() < 1e-3);
assert!(r.im().abs() < 1e-3);

Racine carrée

use embedded_complex_f32::Complex;

// Vérification : s² == z
let z = Complex::new(3.0, 4.0);
let s = z.csqrt().unwrap();
let back = s * s;
assert!((back.re() - 3.0).abs() < 1e-4);
assert!((back.im() - 4.0).abs() < 1e-4);

Précision numérique

Toutes les opérations reposent sur l'arithmétique IEEE 754 f32 native aucune approximation trigonométrique n'est introduite par cette crate.

Opération Précision
+, -, *, / arrondi IEEE 754 f32
norm, norm_sq arrondi IEEE 754 f32
csqrt < 1e-4 (via embedded-f32-sqrt)
powi accumulation d'arrondi f32

no_std

#![no_std] :utilise uniquement core. Compatible avec tout target Rust embarqué : ARM Cortex-M, RISC-V, AVR, etc. Aucun feature flag requis.


Testée sur la Waveshare 2350B

let z = Complex::new(-1.0, 0.0);

Donne bien z=−1+0i , ∣z∣=(−1)2+02​=1 , z^2=(−1)^2=1 et sqrt = 0 + 1i

⚠️ Petit détail subtil (mais important)

Il existe 2 solutions :i et −i , La fonction csqrt choisit une convention (basée sur le signe de im) → c’est très bien

Licence

Copyright (C) 2026 Jorge Andre Castro

Ce programme est un logiciel libre : vous pouvez le redistribuer et/ou le modifier selon les termes de la GNU General Public License telle que publiée par la Free Software Foundation, soit la version 2 de la licence, soit (à votre gré) n'importe quelle version ultérieure.

Ce programme est distribué dans l'espoir qu'il sera utile, mais sans aucune garantie ; sans même la garantie implicite de commercialisation ou d'adéquation à un usage particulier.

SPDX-License-Identifier: GPL-2.0-or-later https://www.gnu.org/licenses/