1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
//! Implements a type unifier for float like native types

use crate::{
    typing::AnyValue,
    error::{ Error, Result }
};
use std::{
    cmp::Ordering, convert::TryFrom,
    ops::{ Deref, DerefMut }
};


/// A type unifier for floats
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
#[repr(transparent)]
pub struct Float {
    /// The wrapped value
    inner: f64
}
impl From<f64> for Float {
    fn from(value: f64) -> Self {
        Self { inner: value }
    }
}
impl From<f32> for Float {
    fn from(value: f32) -> Self {
        Self { inner: value.into() }
    }
}
impl TryFrom<AnyValue> for Float {
    type Error = Error;
    fn try_from(value: AnyValue) -> Result<Self> {
        match value {
            AnyValue::Float(value) => Ok(value),
            value => Err(etype!("Cannot convert {:?} to float", value))
        }
    }
}
impl Deref for Float {
    type Target = f64;
    fn deref(&self) -> &Self::Target {
        &self.inner
    }
}
impl DerefMut for Float {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.inner
    }
}
impl AsRef<f64> for Float {
    fn as_ref(&self) -> &f64 {
        self
    }
}
impl AsMut<f64> for Float {
    fn as_mut(&mut self) -> &mut f64 {
        self
    }
}
impl Eq for Float {
    /* Nothing to see here */
}
impl Ord for Float {
    /// Implement total ordering using the unstable stdlib implementation (see also 72599)
    fn cmp(&self, other: &Self) -> Ordering {
        let mut left = self.to_bits() as i64;
        let mut right = other.to_bits() as i64;

        // In case of negatives, flip all the bits except the sign
        // to achieve a similar layout as two's complement integers
        //
        // Why does this work? IEEE 754 floats consist of three fields:
        // Sign bit, exponent and mantissa. The set of exponent and mantissa
        // fields as a whole have the property that their bitwise order is
        // equal to the numeric magnitude where the magnitude is defined.
        // The magnitude is not normally defined on NaN values, but
        // IEEE 754 totalOrder defines the NaN values also to follow the
        // bitwise order. This leads to order explained in the doc comment.
        // However, the representation of magnitude is the same for negative
        // and positive numbers – only the sign bit is different.
        // To easily compare the floats as signed integers, we need to
        // flip the exponent and mantissa bits in case of negative numbers.
        // We effectively convert the numbers to "two's complement" form.
        //
        // To do the flipping, we construct a mask and XOR against it.
        // We branchlessly calculate an "all-ones except for the sign bit"
        // mask from negative-signed values: right shifting sign-extends
        // the integer, so we "fill" the mask with sign bits, and then
        // convert to unsigned to push one more zero bit.
        // On positive values, the mask is all zeros, so it's a no-op.
        left ^= (((left >> 63) as u64) >> 1) as i64;
        right ^= (((right >> 63) as u64) >> 1) as i64;

        left.cmp(&right)
    }
}
impl From<Float> for f64 {
    fn from(value: Float) -> Self {
        value.inner
    }
}
impl From<Float> for AnyValue {
    fn from(value: Float) -> Self {
        AnyValue::Float(value)
    }
}