linear_srgb/default.rs
1//! Recommended API for sRGB ↔ linear conversion.
2//!
3//! This module provides the optimal implementation for each use case:
4//!
5//! - **Single values**: Scalar functions (SIMD overhead not worthwhile)
6//! - **Slices**: SIMD-accelerated with runtime CPU dispatch
7//! - **x8 batches**: SIMD with dispatch (`_dispatch`) or inlineable (`_inline`)
8//!
9//! # Quick Start
10//!
11//! ```rust
12//! use linear_srgb::default::{srgb_to_linear, linear_to_srgb};
13//!
14//! // Single value conversion
15//! let linear = srgb_to_linear(0.5);
16//! let srgb = linear_to_srgb(linear);
17//! ```
18//!
19//! # Batch Processing
20//!
21//! ```rust
22//! use linear_srgb::default::{srgb_to_linear_slice, linear_to_srgb_slice};
23//!
24//! let mut values = vec![0.5f32; 10000];
25//! srgb_to_linear_slice(&mut values); // SIMD-accelerated
26//! linear_to_srgb_slice(&mut values);
27//! ```
28//!
29//! # x8 SIMD Functions
30//!
31//! For manual SIMD control, use the x8 functions:
32//!
33//! - `*_x8` - Default with CPU dispatch (standalone use)
34//! - `inline` module - `#[inline(always)]` variants for use inside your own `#[magetypes]` code
35//!
36//! ```rust
37//! use linear_srgb::default::{linear_to_srgb_x8, linear_to_srgb_u8_x8};
38//! use wide::f32x8;
39//!
40//! let linear = f32x8::splat(0.214);
41//! let srgb = linear_to_srgb_x8(linear); // CPU dispatch
42//! let srgb_u8 = linear_to_srgb_u8_x8(linear);
43//! ```
44//!
45//! For use inside `#[magetypes]` functions (no dispatch overhead):
46//! ```rust,ignore
47//! use linear_srgb::default::inline::*;
48//! ```
49
50// ============================================================================
51// Single-value functions (scalar - best for individual values)
52// ============================================================================
53
54pub use crate::scalar::{
55 // Custom gamma (pure power function)
56 gamma_to_linear,
57 gamma_to_linear_f64,
58 linear_to_gamma,
59 linear_to_gamma_f64,
60 // f32 sRGB (exact powf)
61 linear_to_srgb,
62 linear_to_srgb_extended,
63 // f64 sRGB (high precision)
64 linear_to_srgb_f64,
65 // f32 sRGB (fast polynomial, no powf)
66 linear_to_srgb_fast,
67 linear_to_srgb_u8,
68 // u16 sRGB (LUT-based)
69 linear_to_srgb_u16,
70 srgb_to_linear,
71 srgb_to_linear_extended,
72 srgb_to_linear_f64,
73 // f32 sRGB (fast polynomial, no powf)
74 srgb_to_linear_fast,
75 srgb_u16_to_linear,
76};
77
78// u8 → f32 uses LUT (20x faster than scalar powf)
79pub use crate::simd::srgb_u8_to_linear;
80
81// ============================================================================
82// Slice functions (SIMD with dispatch - best for batches)
83// ============================================================================
84
85pub use crate::simd::{
86 // Custom gamma slices
87 gamma_to_linear_slice,
88 // f32x8 slices (for pre-aligned SIMD data)
89 gamma_to_linear_x8_slice,
90 linear_to_gamma_slice,
91 linear_to_gamma_x8_slice,
92 // f32 slices (in-place)
93 linear_to_srgb_slice,
94 // u8 ↔ f32 slices
95 linear_to_srgb_u8_slice,
96 // u16 slices
97 linear_to_srgb_u16_slice,
98 linear_to_srgb_x8_slice,
99 srgb_to_linear_slice,
100 srgb_to_linear_x8_slice,
101 srgb_u8_to_linear_slice,
102 srgb_u16_to_linear_slice,
103};
104
105// ============================================================================
106// x8 SIMD functions with CPU dispatch (default)
107// ============================================================================
108
109pub use crate::simd::{
110 // Custom gamma x8 with dispatch
111 gamma_to_linear_x8_dispatch as gamma_to_linear_x8,
112 linear_to_gamma_x8_dispatch as linear_to_gamma_x8,
113 // sRGB x8 with dispatch
114 linear_to_srgb_u8_x8_dispatch as linear_to_srgb_u8_x8,
115 linear_to_srgb_x8_dispatch as linear_to_srgb_x8,
116 srgb_to_linear_x8_dispatch as srgb_to_linear_x8,
117 // u8 x8 (LUT-based, no dispatch needed)
118 srgb_u8_to_linear_x8,
119};
120
121// ============================================================================
122// LUT converter (zero-cost const tables)
123// ============================================================================
124
125pub use crate::lut::SrgbConverter;
126
127pub mod inline {
128 //! Dispatch-free inline variants for use inside `#[magetypes]` functions.
129 //!
130 //! When building your own SIMD-accelerated functions with `archmage`,
131 //! use these `_inline` variants to avoid nested dispatch overhead.
132 //! These functions are `#[inline(always)]` and contain no dispatch overhead.
133 //!
134 //! # Example
135 //!
136 //! ```rust,ignore
137 //! use linear_srgb::default::inline::*;
138 //! use archmage::magetypes;
139 //! use wide::f32x8;
140 //!
141 //! #[magetypes(v3)] // Your function handles dispatch
142 //! fn process_pixels(_token: Token, data: &mut [f32]) {
143 //! for chunk in data.chunks_exact_mut(8) {
144 //! let v = f32x8::from([
145 //! chunk[0], chunk[1], chunk[2], chunk[3],
146 //! chunk[4], chunk[5], chunk[6], chunk[7],
147 //! ]);
148 //! // Use inline variants - no dispatch, just raw SIMD
149 //! let linear = srgb_to_linear_x8(v);
150 //! let processed = linear * f32x8::splat(1.5);
151 //! let result = linear_to_srgb_x8(processed);
152 //! let arr: [f32; 8] = result.into();
153 //! chunk.copy_from_slice(&arr);
154 //! }
155 //! }
156 //! ```
157
158 // Re-export inline x8 functions with clean names (no _inline suffix)
159 pub use crate::simd::{
160 gamma_to_linear_x8_inline as gamma_to_linear_x8,
161 linear_to_gamma_x8_inline as linear_to_gamma_x8,
162 linear_to_srgb_u8_x8_inline as linear_to_srgb_u8_x8,
163 linear_to_srgb_x8_inline as linear_to_srgb_x8,
164 srgb_to_linear_x8_inline as srgb_to_linear_x8,
165 };
166
167 // Re-export inline x8 slice functions with clean names (no _inline suffix)
168 pub use crate::simd::{
169 gamma_to_linear_x8_slice_inline as gamma_to_linear_x8_slice,
170 linear_to_gamma_x8_slice_inline as linear_to_gamma_x8_slice,
171 linear_to_srgb_x8_slice_inline as linear_to_srgb_x8_slice,
172 srgb_to_linear_x8_slice_inline as srgb_to_linear_x8_slice,
173 };
174}