Skip to content

Commit

Permalink
Merge 66e3e19 into bcf9935
Browse files Browse the repository at this point in the history
  • Loading branch information
unageek committed Jun 23, 2021
2 parents bcf9935 + 66e3e19 commit a236510
Show file tree
Hide file tree
Showing 10 changed files with 97 additions and 131 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ The ❗ icon indicates a breaking change.

- Implemented the trait `Hash` for `Interval`, `Decoration` and `Overlap`.

### Removed

- ❗ Removed the method `IntervalError::value`.

### Changed

- ❗ Changed the return type of the functions `Interval::try_from_be_bytes`, `try_from_le_bytes` and `try_from_ne_bytes` to `Option<Interval>`.
- ❗ The same change have been made to the functions of `DecInterval`.
- ❗ Changed the struct `IntervalError` to be non-generic by the removal of the `value` method

## v0.9.9 - 2021-06-18

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion examples/cancellation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ fn prec(x: Interval) -> f64 {
-(x.rad() / x.mid().abs()).log10()
}

fn main() -> Result<(), IntervalError<Interval>> {
fn main() -> Result<(), IntervalError> {
let two = interval!("[2]")?;
let eleven = interval!("[11]")?;
let mut x = interval!("[0.2]")?;
Expand Down
4 changes: 2 additions & 2 deletions examples/exact.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// Formats and parses an exact interval literal.

use inari::{interval, Interval, IntervalError};
use inari::{interval, IntervalError};

fn main() -> Result<(), IntervalError<Interval>> {
fn main() -> Result<(), IntervalError> {
let x = interval!("[0.1]")?;
let s = format!("{:x}", x);
let y = interval!(&s, exact)?;
Expand Down
4 changes: 2 additions & 2 deletions examples/parse.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// Parses and displays interval literals.

use inari::{interval, Interval, IntervalError};
use inari::{interval, IntervalError};

fn main() -> Result<(), IntervalError<Interval>> {
fn main() -> Result<(), IntervalError> {
println!("{}", interval!("[ ]")?);
println!("{}", interval!("[ empty ]")?);
println!("{}", interval!("[ 1.0 ]")?);
Expand Down
4 changes: 2 additions & 2 deletions examples/quadratic.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// Solves the quadratic equation a x^2 + b x + c == 0.

use inari::{interval, Interval, IntervalError};
use inari::{interval, IntervalError};

fn main() -> Result<(), IntervalError<Interval>> {
fn main() -> Result<(), IntervalError> {
let a = interval!("[1]")?;
let b = interval!("[1e15]")?;
let c = interval!("[1e14]")?;
Expand Down
4 changes: 2 additions & 2 deletions src/_docs/conformance.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ c. Implementation-defined behavior

5. What mechanisms of exception handling are used in exception handlers provided by the implementation? What additional exception handling is provided by the implementation?

Some operations that may fail return [`Option<T>`] or [`Result<T>`], which can be handled with the Rust's standard library.
Some operations that may fail return [`Option<T>`] or [`Result<T>`], which can be handled with the Rust's standard error handling mechanism.

6. What is the tie-breaking method used in rounding of supported number formats F that are not IEEE 754 conforming?

Expand Down Expand Up @@ -257,7 +257,7 @@ c. Implementation-defined behavior

12. What is the result of Level 3 operations for invalid inputs?

inari prevents creation of invalid interval datums. For invalid inputs, bare interval constructors return an [`Err`] with the empty interval, and decorated interval constructors return an [`Err`] with a NaI. See also the answer to c.5.
inari prevents creation of invalid interval datums. For invalid inputs, bare interval constructors return an [`Err`] with either [`IntervalErrorKind::UndefinedOperation`] or [`IntervalErrorKind::PossiblyUndefinedOperation`]. See also the answers to b.3 and c.5.

13. What are the interchange representations of the fields of the standard Level 3 representation listed in 14.4?

Expand Down
59 changes: 24 additions & 35 deletions src/bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ macro_rules! impl_to_bytes {
macro_rules! impl_try_from_bytes {
($(#[$meta:meta])* $try_from_bytes:ident, $from_bytes:ident) => {
$(#[$meta])*
pub fn $try_from_bytes(bytes: [u8; 16]) -> Result<Self> {
pub fn $try_from_bytes(bytes: [u8; 16]) -> Option<Self> {
let a = f64::$from_bytes(<[u8; 8]>::try_from(&bytes[..8]).unwrap());
let b = f64::$from_bytes(<[u8; 8]>::try_from(&bytes[8..16]).unwrap());

Expand All @@ -26,14 +26,11 @@ macro_rules! impl_try_from_bytes {
&& (a != 0.0 || a.is_sign_negative())
&& (b != 0.0 || b.is_sign_positive())
{
Ok(Self::with_infsup_raw(a, b))
Some(Self::with_infsup_raw(a, b))
} else if a == f64::INFINITY && b == f64::NEG_INFINITY {
Ok(Self::EMPTY)
Some(Self::EMPTY)
} else {
Err(IntervalError {
kind: IntervalErrorKind::UndefinedOperation,
value: Self::EMPTY,
})
None
}
}
};
Expand Down Expand Up @@ -84,7 +81,7 @@ macro_rules! impl_to_bytes {

macro_rules! impl_try_from_bytes {
($try_from_bytes:ident, $from_bytes:ident) => {
pub fn $try_from_bytes(bytes: [u8; 17]) -> Result<Self> {
pub fn $try_from_bytes(bytes: [u8; 17]) -> Option<Self> {
use Decoration::*;
let a = f64::$from_bytes(<[u8; 8]>::try_from(&bytes[..8]).unwrap());
let b = f64::$from_bytes(<[u8; 8]>::try_from(&bytes[8..16]).unwrap());
Expand All @@ -94,12 +91,7 @@ macro_rules! impl_try_from_bytes {
8 => Def,
12 => Dac,
16 => Com,
_ => {
return Err(IntervalError {
kind: IntervalErrorKind::UndefinedOperation,
value: Self::NAI,
})
}
_ => return None,
};

if a <= b
Expand All @@ -109,16 +101,13 @@ macro_rules! impl_try_from_bytes {
&& (b != 0.0 || b.is_sign_positive())
&& (dec != Com || a != f64::NEG_INFINITY && b != f64::INFINITY)
{
Ok(Self::new_unchecked(Interval::with_infsup_raw(a, b), dec))
Some(Self::new_unchecked(Interval::with_infsup_raw(a, b), dec))
} else if a == f64::INFINITY && b == f64::NEG_INFINITY && dec == Trv {
Ok(Self::EMPTY)
Some(Self::EMPTY)
} else if a.is_nan() && b.is_nan() && dec == Ill {
Ok(Self::NAI)
Some(Self::NAI)
} else {
Err(IntervalError {
kind: IntervalErrorKind::UndefinedOperation,
value: Self::NAI,
})
None
}
}
};
Expand Down Expand Up @@ -170,11 +159,11 @@ mod tests {
bytes
}

assert!(I::try_from_ne_bytes(make_bytes(3.0, -2.0)).is_err());
assert!(I::try_from_ne_bytes(make_bytes(f64::INFINITY, f64::INFINITY)).is_err());
assert!(I::try_from_ne_bytes(make_bytes(f64::NEG_INFINITY, f64::NEG_INFINITY)).is_err());
assert!(I::try_from_ne_bytes(make_bytes(0.0, 0.0)).is_err());
assert!(I::try_from_ne_bytes(make_bytes(-0.0, -0.0)).is_err());
assert!(I::try_from_ne_bytes(make_bytes(3.0, -2.0)).is_none());
assert!(I::try_from_ne_bytes(make_bytes(f64::INFINITY, f64::INFINITY)).is_none());
assert!(I::try_from_ne_bytes(make_bytes(f64::NEG_INFINITY, f64::NEG_INFINITY)).is_none());
assert!(I::try_from_ne_bytes(make_bytes(0.0, 0.0)).is_none());
assert!(I::try_from_ne_bytes(make_bytes(-0.0, -0.0)).is_none());
}

#[test]
Expand Down Expand Up @@ -217,18 +206,18 @@ mod tests {
bytes
}

assert!(DI::try_from_ne_bytes(make_bytes(3.0, -2.0, Trv)).is_err());
assert!(DI::try_from_ne_bytes(make_bytes(f64::INFINITY, f64::INFINITY, Trv)).is_err());
assert!(DI::try_from_ne_bytes(make_bytes(3.0, -2.0, Trv)).is_none());
assert!(DI::try_from_ne_bytes(make_bytes(f64::INFINITY, f64::INFINITY, Trv)).is_none());
assert!(
DI::try_from_ne_bytes(make_bytes(f64::NEG_INFINITY, f64::NEG_INFINITY, Trv)).is_err()
DI::try_from_ne_bytes(make_bytes(f64::NEG_INFINITY, f64::NEG_INFINITY, Trv)).is_none()
);
assert!(DI::try_from_ne_bytes(make_bytes(0.0, 0.0, Trv)).is_err());
assert!(DI::try_from_ne_bytes(make_bytes(-0.0, -0.0, Trv)).is_err());
assert!(DI::try_from_ne_bytes(make_bytes(0.0, 0.0, Trv)).is_none());
assert!(DI::try_from_ne_bytes(make_bytes(-0.0, -0.0, Trv)).is_none());

assert!(DI::try_from_ne_bytes(make_bytes(-2.0, f64::NAN, Ill)).is_err());
assert!(DI::try_from_ne_bytes(make_bytes(f64::NAN, 3.0, Ill)).is_err());
assert!(DI::try_from_ne_bytes(make_bytes(-2.0, f64::NAN, Ill)).is_none());
assert!(DI::try_from_ne_bytes(make_bytes(f64::NAN, 3.0, Ill)).is_none());

assert!(DI::try_from_ne_bytes(make_bytes(f64::NEG_INFINITY, 3.0, Com)).is_err());
assert!(DI::try_from_ne_bytes(make_bytes(-2.0, f64::INFINITY, Com)).is_err());
assert!(DI::try_from_ne_bytes(make_bytes(f64::NEG_INFINITY, 3.0, Com)).is_none());
assert!(DI::try_from_ne_bytes(make_bytes(-2.0, f64::INFINITY, Com)).is_none());
}
}
24 changes: 7 additions & 17 deletions src/interval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,18 @@ pub enum IntervalErrorKind {
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct IntervalError<T: fmt::Debug> {
pub struct IntervalError {
pub(crate) kind: IntervalErrorKind,
pub(crate) value: T,
}

impl<T: fmt::Debug> IntervalError<T> {
impl IntervalError {
/// Returns the type of the error.
pub fn kind(&self) -> IntervalErrorKind {
self.kind
}

/// Returns a reasonable fallback value for the error.
pub fn value(self) -> T {
self.value
}
}

impl<T: fmt::Debug> fmt::Display for IntervalError<T> {
impl fmt::Display for IntervalError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.kind {
IntervalErrorKind::PossiblyUndefinedOperation => {
Expand All @@ -43,10 +37,10 @@ impl<T: fmt::Debug> fmt::Display for IntervalError<T> {
}
}

impl<T: fmt::Debug> Error for IntervalError<T> {}
impl Error for IntervalError {}

/// An alias for [`Result<T, E>`](`result::Result`) with [`E = IntervalError`](`IntervalError`).
pub type Result<T> = result::Result<T, IntervalError<T>>;
pub type Result<T> = result::Result<T, IntervalError>;

/// An interval with [`f64`] bounds.
///
Expand Down Expand Up @@ -110,15 +104,14 @@ impl Hash for Interval {
}

impl TryFrom<(f64, f64)> for Interval {
type Error = IntervalError<Self>;
type Error = IntervalError;

fn try_from((a, b): (f64, f64)) -> Result<Self> {
if a <= b && a != f64::INFINITY && b != f64::NEG_INFINITY {
Ok(Self::with_infsup_raw(a, b))
} else {
Err(Self::Error {
kind: IntervalErrorKind::UndefinedOperation,
value: Self::EMPTY,
})
}
}
Expand Down Expand Up @@ -221,14 +214,13 @@ impl PartialEq for DecInterval {
}

impl TryFrom<(f64, f64)> for DecInterval {
type Error = IntervalError<Self>;
type Error = IntervalError;

fn try_from(x: (f64, f64)) -> Result<Self> {
match Interval::try_from(x) {
Ok(x) => Ok(Self::new(x)),
_ => Err(Self::Error {
kind: IntervalErrorKind::UndefinedOperation,
value: Self::NAI,
}),
}
}
Expand Down Expand Up @@ -262,7 +254,6 @@ macro_rules! interval {
/// an [`Err`] with [`IntervalErrorKind::UndefinedOperation`] is returned.
/// If it cannot determine whether the construction is valid or not,
/// [`IntervalErrorKind::PossiblyUndefinedOperation`] is returned.
/// In both cases, the error contains the empty interval as a reasonable fallback value.
///
/// - `interval!(a, b)`
///
Expand Down Expand Up @@ -330,7 +321,6 @@ macro_rules! dec_interval {
/// an [`Err`] with [`IntervalErrorKind::UndefinedOperation`] is returned.
/// If it cannot determine whether the construction is valid or not,
/// [`IntervalErrorKind::PossiblyUndefinedOperation`] is returned.
/// In both cases, the error contains a NaI as a reasonable fallback value.
///
/// - `dec_interval!(a, b)`
///
Expand Down
Loading

0 comments on commit a236510

Please sign in to comment.