pub use logicaffeine_base::numeric::cmp_i64_f64_exact as logos_cmp_i64_f64;
#[inline]
pub fn logos_i64_eq_f64(i: i64, f: f64) -> bool {
logos_cmp_i64_f64(i, f) == Some(core::cmp::Ordering::Equal)
}
#[inline]
pub fn logos_approx_eq(a: f64, b: f64) -> bool {
if a == b {
return true;
}
let diff = (a - b).abs();
diff <= f64::max(1e-9 * f64::max(a.abs(), b.abs()), 1e-12)
}
pub trait Truthy {
fn truthy(&self) -> bool;
}
impl Truthy for bool {
#[inline]
fn truthy(&self) -> bool {
*self
}
}
impl Truthy for i64 {
#[inline]
fn truthy(&self) -> bool {
*self != 0
}
}
impl Truthy for f64 {
#[inline]
fn truthy(&self) -> bool {
*self != 0.0
}
}
impl Truthy for char {
#[inline]
fn truthy(&self) -> bool {
true
}
}
impl Truthy for String {
#[inline]
fn truthy(&self) -> bool {
!self.is_empty()
}
}
impl Truthy for &str {
#[inline]
fn truthy(&self) -> bool {
!self.is_empty()
}
}
impl<T> Truthy for crate::types::LogosSeq<T> {
#[inline]
fn truthy(&self) -> bool {
!self.is_empty()
}
}
impl<K: Eq + core::hash::Hash, V> Truthy for crate::types::LogosMap<K, V> {
#[inline]
fn truthy(&self) -> bool {
!self.is_empty()
}
}
impl<T> Truthy for crate::types::FxIndexSet<T> {
#[inline]
fn truthy(&self) -> bool {
!self.is_empty()
}
}
impl<T: Truthy> Truthy for Option<T> {
#[inline]
fn truthy(&self) -> bool {
match self {
Some(v) => v.truthy(),
None => false,
}
}
}
impl Truthy for crate::types::LogosRational {
#[inline]
fn truthy(&self) -> bool {
!self.0.is_zero()
}
}
impl Truthy for crate::types::LogosDecimal {
#[inline]
fn truthy(&self) -> bool {
!self.0.is_zero()
}
}
impl Truthy for crate::types::LogosComplex {
#[inline]
fn truthy(&self) -> bool {
!self.0.is_zero()
}
}
#[inline]
pub fn logos_truthy<T: Truthy>(v: &T) -> bool {
v.truthy()
}
#[inline(always)]
pub fn logos_add_exact(a: impl Into<crate::types::LogosInt>, b: impl Into<crate::types::LogosInt>) -> crate::types::LogosInt {
a.into().add(&b.into())
}
#[inline(always)]
pub fn logos_sub_exact(a: impl Into<crate::types::LogosInt>, b: impl Into<crate::types::LogosInt>) -> crate::types::LogosInt {
a.into().sub(&b.into())
}
#[inline(always)]
pub fn logos_mul_exact(a: impl Into<crate::types::LogosInt>, b: impl Into<crate::types::LogosInt>) -> crate::types::LogosInt {
a.into().mul(&b.into())
}
#[inline(always)]
pub fn logos_div_exact(a: impl Into<crate::types::LogosInt>, b: impl Into<crate::types::LogosInt>) -> crate::types::LogosInt {
match a.into().div(&b.into()) {
Ok(v) => v,
Err(e) => panic!("{e}"),
}
}
#[inline(always)]
pub fn logos_floordiv_exact(a: impl Into<crate::types::LogosInt>, b: impl Into<crate::types::LogosInt>) -> crate::types::LogosInt {
match a.into().div_floor(&b.into()) {
Ok(v) => v,
Err(e) => panic!("{e}"),
}
}
#[inline(always)]
pub fn logos_add_i64(a: i64, b: i64) -> i64 {
match a.checked_add(b) {
Some(v) => v,
None => narrowed_overflow(logos_add_exact(a, b)),
}
}
#[inline(always)]
pub fn logos_sub_i64(a: i64, b: i64) -> i64 {
match a.checked_sub(b) {
Some(v) => v,
None => narrowed_overflow(logos_sub_exact(a, b)),
}
}
#[inline(always)]
pub fn logos_mul_i64(a: i64, b: i64) -> i64 {
match a.checked_mul(b) {
Some(v) => v,
None => narrowed_overflow(logos_mul_exact(a, b)),
}
}
#[inline(always)]
pub fn logos_div_i64(a: i64, b: i64) -> i64 {
match a.checked_div(b) {
Some(v) => v,
None => logos_div_exact(a, b).expect_i64("Int"),
}
}
#[inline(always)]
pub fn logos_rem_i64(a: i64, b: i64) -> i64 {
match a.checked_rem(b) {
Some(v) => v,
None => logos_rem_exact(a, b).expect_i64("Int"),
}
}
#[cold]
#[inline(never)]
fn narrowed_overflow(v: crate::types::LogosInt) -> ! {
panic!("Integer overflow: {v} does not fit a 64-bit Int")
}
#[inline(always)]
pub fn logos_narrow_i128(v: i128) -> i64 {
match i64::try_from(v) {
Ok(x) => x,
Err(_) => narrowed_overflow_i128(v),
}
}
#[cold]
#[inline(never)]
fn narrowed_overflow_i128(v: i128) -> ! {
panic!("Integer overflow: {v} does not fit a 64-bit Int")
}
#[inline(always)]
pub fn logos_div_i128(a: i128, b: i128) -> i128 {
if b == 0 {
panic!("Division by zero");
}
a / b
}
#[inline(always)]
pub fn logos_rem_i128(a: i128, b: i128) -> i128 {
if b == 0 {
panic!("Modulo by zero");
}
a % b
}
#[inline(always)]
pub fn logos_rem_exact(a: impl Into<crate::types::LogosInt>, b: impl Into<crate::types::LogosInt>) -> crate::types::LogosInt {
match a.into().rem(&b.into()) {
Ok(v) => v,
Err(e) => panic!("{e}"),
}
}
#[inline(always)]
pub fn logos_pow_exact(a: impl Into<crate::types::LogosInt>, b: impl Into<crate::types::LogosInt>) -> crate::types::LogosInt {
match a.into().pow(&b.into()) {
Ok(v) => v,
Err(e) => panic!("{e}"),
}
}
#[inline(always)]
pub fn logos_i64_key_of_f64(f: f64) -> Option<i64> {
if f.fract() == 0.0 && f >= i64::MIN as f64 && f <= i64::MAX as f64 {
Some(f as i64)
} else {
None
}
}