#![warn(missing_docs)]
pub mod core;
pub mod filters;
pub mod textures;
#[cfg(feature = "float-as-double")]
pub mod float {
pub use std::f64::*;
pub type Float = f64;
}
#[cfg(not(feature = "float-as-double"))]
pub mod float {
pub use std::f32::*;
pub type Float = f32;
}
pub use float::Float;
#[derive(Copy, Clone)]
pub struct Degree(pub(crate) Float);
impl From<Float> for Degree {
fn from(f: Float) -> Degree {
Degree(f)
}
}
#[derive(Clone, Debug)]
pub struct Options {
pub num_threads: u32,
pub quick_render: bool,
pub quiet: bool,
pub verbose: bool,
pub image_file: String,
}
impl Default for Options {
fn default() -> Options {
Options {
num_threads: 1,
quick_render: false,
quiet: false,
verbose: true,
image_file: "".to_owned(),
}
}
}
pub fn gamma_correct(value: Float) -> Float {
if value <= 0.0031308 {
12.92 * value
} else {
1.055 * value.powf(1. / 2.4) - 0.055
}
}
pub fn clamp<T>(val: T, low: T, high: T) -> T
where
T: PartialOrd,
{
if val < low {
low
} else if val > high {
high
} else {
val
}
}
pub fn lerp(t: Float, v1: Float, v2: Float) -> Float {
(1. - t) * v1 + t * v2
}
pub fn assert_almost_equal_options(l: Option<(Float, Float)>, r: Option<(Float, Float)>) {
if l.is_none() && r.is_none() {
return;
}
assert!(l.is_some());
assert!(r.is_some());
let l = l.unwrap();
let r = r.unwrap();
assert_almost_equal(l.0, r.0);
assert_almost_equal(l.1, r.1);
}
fn assert_almost_equal(f1: Float, f2: Float) {
let diff = (f1 - f2).abs();
assert!(diff < float::EPSILON, "{} != {}, diff of {}", f1, f2, diff);
}
pub fn quadratic(a: Float, b: Float, c: Float) -> Option<(Float, Float)> {
let a = a as f64;
let b = b as f64;
let c = c as f64;
let discrim = b * b - 4. * a * c;
if discrim < 0. {
return None;
}
let root_discrim = discrim.sqrt();
let q = if b < 0. {
-0.5 * (b - root_discrim)
} else {
-0.5 * (b + root_discrim)
};
let t0 = (q / a) as Float;
let t1 = (c / q) as Float;
if t0 > t1 {
Some((t1, t0))
} else {
Some((t0, t1))
}
}