#![doc = include_str!("../README")]
#![no_std]
#![deny(missing_docs)]
extern crate libc;
#[path = "../binding/binding.rs"]
#[allow(non_snake_case)]
#[allow(non_upper_case_globals)]
#[allow(non_camel_case_types)]
#[allow(dead_code)]
#[allow(clippy::useless_transmute)]
#[allow(missing_docs)]
mod binding;
use binding::_bindgen_ty_1 as cfexcpt;
use binding::_bindgen_ty_2 as cfround;
use core::ffi::c_int;
use core::num::NonZeroI32;
#[allow(missing_docs)]
pub mod raw {
pub use crate::binding::*;
}
type Result<T> = core::result::Result<T, NonZeroI32>;
#[inline(always)]
fn result(result: core::ffi::c_int) -> Result<()> {
NonZeroI32::new(result).map(Err).unwrap_or(Ok(()))
}
macro_rules! flag_ty {
(
$(#[$($attr:meta)*])*
struct $ident:ident ($ty:ty);
$(
const $c_ident:ident = $c_expr:expr;
)*
) => {
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
$(#[$($attr)*])*
pub struct $ident($ty);
impl $ident {
$(
#[allow(missing_docs)]
pub const $c_ident: Self = Self($c_expr);
)*
#[allow(missing_docs)]
#[inline(always)]
pub fn none() -> Self {
Self(0)
}
#[inline(always)]
pub fn has(self, other: Self) -> bool {
self.0 & other.0 != 0
}
#[inline(always)]
pub fn or(self, other: Self) -> Self {
Self(self.0 | other.0)
}
#[inline(always)]
pub fn not(self, other: Self) -> Self {
Self(self.0 & !other.0)
}
#[inline(always)]
pub fn as_raw(self) -> $ty {
self.0
}
}
impl core::ops::BitOr for $ident {
type Output = Self;
#[inline(always)]
fn bitor(self, rhs: Self) -> Self::Output {
self.or(rhs)
}
}
impl core::ops::BitOrAssign for $ident {
#[inline(always)]
fn bitor_assign(&mut self, rhs: Self) {
*self = self.or(rhs);
}
}
};
}
flag_ty! (
struct FExcept(cfexcpt::Type);
const INVALID = cfexcpt::FE_INVALID;
const DENORM = cfexcpt::__FE_DENORM;
const DIV_BY_ZERO = cfexcpt::FE_DIVBYZERO;
const OVERFLOW = cfexcpt::FE_OVERFLOW;
const UNDERFLOW = cfexcpt::FE_UNDERFLOW;
const INEXACT = cfexcpt::FE_INEXACT;
const FE_ALL = binding::FE_ALL_EXCEPT;
);
flag_ty!(
struct FRound(cfround::Type);
const NEAREST = cfround::FE_TONEAREST;
const DOWNWARD = cfround::FE_DOWNWARD;
const UPWARD = cfround::FE_UPWARD;
const TOWARD_ZERO = cfround::FE_TOWARDZERO;
);
impl FExcept {
#[inline(always)]
pub fn clear(self) -> Result<()> {
result(unsafe { binding::feclearexcept(self.as_raw() as c_int) })
}
#[inline(always)]
pub fn getflag(self) -> Result<Self> {
let mut excepts = binding::fexcept_t::default();
result(unsafe { binding::fegetexceptflag(&mut excepts as *mut _, self.as_raw() as c_int) })
.map(|_| Self(excepts as cfexcpt::Type))
}
#[inline(always)]
pub fn setflag(self) -> Result<()> {
let excepts = self.as_raw() as binding::fexcept_t;
result(unsafe { binding::fesetexceptflag(&excepts as *const _, self.as_raw() as c_int) })
}
#[inline(always)]
pub fn raise(self) -> Result<()> {
result(unsafe { binding::feraiseexcept(self.as_raw() as c_int) })
}
#[inline(always)]
pub fn test(self) -> Self {
Self(unsafe { binding::fetestexcept(self.as_raw() as c_int) } as cfexcpt::Type)
}
}
impl FRound {
#[inline(always)]
pub fn getround() -> Self {
Self(unsafe { binding::fegetround() as cfround::Type })
}
#[inline(always)]
pub fn setround(self) -> Result<()> {
result(unsafe { binding::fesetround(self.as_raw() as c_int) })
}
}
#[inline(always)]
pub fn set_rounding_mode(flags: FRound) -> Result<()> {
flags.setround()
}
#[inline(always)]
pub fn get_rounding_mode() -> FRound {
FRound::getround()
}
#[derive(Clone, Debug)]
pub struct FEnv(binding::fenv_t);
impl FEnv {
#[allow(missing_docs)]
pub fn new() -> Result<Self> {
let mut this: Self = unsafe { core::mem::zeroed() };
this.get().map(|_| this)
}
#[inline(always)]
pub fn hold(&mut self) -> Result<()> {
result(unsafe { binding::feholdexcept(&mut self.0 as *mut _) })
}
#[inline(always)]
pub fn set(&self) -> Result<()> {
result(unsafe { binding::fesetenv(&self.0 as *const _) })
}
#[inline(always)]
pub fn get(&mut self) -> Result<()> {
result(unsafe { binding::fegetenv(&mut self.0 as *mut _) })
}
#[inline(always)]
pub fn update(&self) -> Result<()> {
result(unsafe { binding::feupdateenv(&self.0 as *const _) })
}
#[allow(missing_docs)]
#[inline(always)]
pub fn inner(&self) -> &binding::fenv_t {
&self.0
}
#[allow(missing_docs)]
#[inline(always)]
pub fn inner_mut(&mut self) -> &mut binding::fenv_t {
&mut self.0
}
}
impl core::ops::Deref for FEnv {
type Target = binding::fenv_t;
fn deref(&self) -> &Self::Target {
self.inner()
}
}
impl core::ops::DerefMut for FEnv {
fn deref_mut(&mut self) -> &mut Self::Target {
self.inner_mut()
}
}