Skip to main content

cinrs_rt/
lib.rs

1//! The runtime the code [`cinrs`](https://docs.rs/cinrs) generates links
2//! against.
3//!
4//! There is exactly one thing in it — C's complex arithmetic — and it is here
5//! for two reasons.
6//!
7//! * **A type the ecosystem already has.** `double _Complex` needs a Rust type
8//!   with the same layout, and inventing one would make every `c99!` block's
9//!   complex values incompatible with every other crate's. [`Complex`] is
10//!   [`num_complex::Complex`], which is `#[repr(C)]`, `Copy`, and the type the
11//!   numeric half of crates.io already speaks; `Complex<f64>` is two `f64`s in
12//!   declaration order, so it *is* C's `double _Complex` as far as the ABI is
13//!   concerned.
14//! * **Semantics that would otherwise be copied into every expansion.** C's
15//!   multiplication and division of two complex values are not the naive
16//!   formulas: C99 Annex G.5.1 requires an infinite result to be recovered
17//!   where the naive one would be NaN + iNaN, which is a couple of dozen lines
18//!   apiece. A procedural macro that wrote them out per unit — or worse, per
19//!   expression — would bloat every expansion; [`complex`] holds one copy.
20//!
21//! Nothing else belongs here. Everything else `cinrs` generates is `core`-only
22//! (with `alloc` or `std` for a variable length array, `alloca` and
23//! `_Thread_local`), and this crate is `#![no_std]` so that `_Complex` does not
24//! change that.
25//!
26//! # Versioning
27//!
28//! This crate is versioned *with* `cinrs` and is not a stable interface of its
29//! own: the generated code names `::cinrs::rt`, the re-export the `cinrs`
30//! crate provides under its `complex` feature, and the two always come from
31//! the same release. Use [`Complex`] from here — or from `num-complex`
32//! directly, which is the same type — to hand a complex value to a `c99!`
33//! function or to read one back.
34//!
35//! ```
36//! use cinrs_rt::Complex;
37//! use cinrs_rt::complex::mul_f64;
38//!
39//! let z = Complex::new(1.0f64, 2.0);
40//! let w = Complex::new(3.0f64, -4.0);
41//! assert_eq!(mul_f64(z, w), Complex::new(11.0, 2.0));
42//! ```
43
44#![no_std]
45#![warn(missing_docs)]
46
47pub mod complex;
48
49/// The complex number type the generated code uses.
50///
51/// A re-export of [`num_complex::Complex`], which is `#[repr(C)]` with the
52/// real part first: `Complex<f32>` is C's `float _Complex` and `Complex<f64>`
53/// is its `double _Complex` (and its `long double _Complex`, which `cinrs`
54/// maps onto `double` exactly as it maps `long double`).
55pub use num_complex::Complex;