Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 11 additions & 44 deletions src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ macro_rules! mk_impl {
use std::prelude::v1::*;
use std::{$f, usize};

use {Ieee754, Iter};
use {Ieee754};

// test both `next`, and any potential internal-iteration
// optimisations that the iterators support (which will
Expand All @@ -202,7 +202,6 @@ macro_rules! mk_impl {
fn count_fold<I: Iterator>(it: I) -> usize {
it.fold(0, |i, _| i + 1)
}
#[cfg(nightly)]
fn count_try_fold<I: Iterator>(mut it: I) -> usize {
const AT_A_TIME: usize = 5;
(0..10).map(|_| {
Expand All @@ -217,28 +216,10 @@ macro_rules! mk_impl {
}).unwrap_or_else(|x| x.0)
}).take_while(|x| *x > 0).sum()
}
#[cfg(not(nightly))]
fn count_try_fold<I: Iterator>(it: I) -> usize {
count_fold(it)
}
fn count_try_fold_result(mut it: Iter<$f>) -> usize {
fn count_try_rfold<I: Iterator + DoubleEndedIterator>(mut it: I) -> usize {
const AT_A_TIME: usize = 5;
(0..10).map(|_| {
it.try_fold_result(0, |i, _| {
let count = i + 1;
if count < AT_A_TIME {
Ok(count)
} else {
// make the error value different to the ok one
Err((count,))
}
}).unwrap_or_else(|x| x.0)
}).take_while(|x| *x > 0).sum()
}
fn count_try_rfold_result(mut it: Iter<$f>) -> usize {
const AT_A_TIME: usize = 5;
(0..10).map(|_| {
it.try_rfold_result(0, |i, _| {
it.try_rfold(0, |i, _| {
let count = i + 1;
if count < AT_A_TIME {
Ok(count)
Expand Down Expand Up @@ -271,7 +252,6 @@ macro_rules! mk_impl {
fn collect_fold<I: Iterator>(it: I) -> Vec<I::Item> {
it.fold(vec![], |mut v, x| { v.push(x); v })
}
#[cfg(nightly)]
fn collect_try_fold<I: Iterator>(mut it: I) -> Vec<I::Item> {
const AT_A_TIME: usize = 5;
(0..10).map(|_| {
Expand All @@ -281,23 +261,10 @@ macro_rules! mk_impl {
}).unwrap_or_else(|x| x)
}).take_while(|x| x.len() > 0).flat_map(|x| x).collect()
}
#[cfg(not(nightly))]
fn collect_try_fold<I: Iterator>(it: I) -> Vec<I::Item> {
collect_fold(it)
}
fn collect_try_fold_result(mut it: Iter<$f>) -> Vec<$f> {
const AT_A_TIME: usize = 5;
(0..10).map(|_| {
it.try_fold_result(vec![], |mut v, x| {
v.push(x);
if v.len() < AT_A_TIME { Ok(v) } else { Err(v) }
}).unwrap_or_else(|x| x)
}).take_while(|x| x.len() > 0).flat_map(|x| x).collect()
}
fn collect_try_rfold_result(mut it: Iter<$f>) -> Vec<$f> {
fn collect_try_rfold<I: Iterator + DoubleEndedIterator>(mut it: I) -> Vec<I::Item> {
const AT_A_TIME: usize = 5;
(0..10).map(|_| {
it.try_rfold_result(vec![], |mut v, x| {
it.try_rfold(vec![], |mut v, x| {
v.push(x);
if v.len() < AT_A_TIME { Ok(v) } else { Err(v) }
}).unwrap_or_else(|x| x)
Expand All @@ -319,31 +286,31 @@ macro_rules! mk_impl {
fn upto() {
let one = (0.0 as $f).upto(0.0);
assert_eq!(collect(one.clone()), &[0.0]);
assert_eq!(collect_try_fold_result(one), &[0.0]);
assert_eq!(collect_try_fold(one), &[0.0]);

let ten = $f::recompose(false, 1, 1).upto($f::recompose(false, 1, 10));
assert_eq!(count(ten.clone()), 10);
assert_eq!(count_try_fold_result(ten), 10);
assert_eq!(count_try_fold(ten), 10);

let twenty_one = $f::recompose(true, -$f::exponent_bias(), 10)
.upto($f::recompose(false, -$f::exponent_bias(), 10));
assert_eq!(count(twenty_one.clone()), 21);
assert_eq!(count_try_fold_result(twenty_one), 21);
assert_eq!(count_try_fold(twenty_one), 21);
}
#[test]
fn upto_rev() {
let one = (0.0 as $f).upto(0.0);
assert_eq!(collect(one.clone().rev()), &[0.0]);
assert_eq!(collect_try_rfold_result(one), &[0.0]);
assert_eq!(collect_try_rfold(one), &[0.0]);

let ten = $f::recompose(false, 1, 1).upto($f::recompose(false, 1, 10));
assert_eq!(count(ten.clone().rev()), 10);
assert_eq!(count_try_rfold_result(ten), 10);
assert_eq!(count_try_rfold(ten), 10);

let twenty_one = $f::recompose(true, -$f::exponent_bias(), 10)
.upto($f::recompose(false, -$f::exponent_bias(), 10));
assert_eq!(count(twenty_one.clone().rev()), 21);
assert_eq!(count_try_rfold_result(twenty_one), 21);
assert_eq!(count_try_rfold(twenty_one), 21);
}

#[test]
Expand Down
143 changes: 72 additions & 71 deletions src/iter/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use core::ops::ControlFlow;
use core::usize;
use core::fmt;
#[cfg(nightly)]
use core::ops::Try;
use {Bits, Ieee754};

Expand Down Expand Up @@ -52,34 +52,12 @@ fn u64_to_size_hint(x: u64) -> (usize, Option<usize>) {
}
}

#[cfg(nightly)]
fn result_to_try<R: Try>(r: Result<R::Ok, R::Error>) -> R {
match r {
Ok(ok) => R::from_ok(ok),
Err(error) => R::from_error(error)
}
}

impl<T: Ieee754> Iter<T> {
fn len(&self) -> u64 {
self.neg.len() + self.pos.len()
}

fn done(&self) -> bool { self.neg.done() && self.pos.done() }

/// A non-nightly only version of `Iterator::try_fold`.
pub fn try_fold_result<B, F, E>(&mut self, init: B, mut f: F) -> Result<B, E>
where F: FnMut(B, T) -> Result<B, E> {
let next = self.neg.try_fold_result(init, &mut f)?;
self.pos.try_fold_result(next, f)
}

/// A non-nightly only version of `Iterator::try_fold`.
pub fn try_rfold_result<B, F, E>(&mut self, init: B, mut f: F) -> Result<B, E>
where F: FnMut(B, T) -> Result<B, E> {
let next = self.pos.try_rfold_result(init, &mut f)?;
self.neg.try_fold_result(next, f)
}
}

impl<T: Ieee754> Iterator for Iter<T> {
Expand All @@ -100,18 +78,24 @@ impl<T: Ieee754> Iterator for Iter<T> {
self.pos.fold(next, f)
}

#[cfg(nightly)]
fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
where F: FnMut(B, Self::Item) -> R,
R: Try<Ok = B> {
result_to_try(self.try_fold_result(init, |b, x| f(b, x).into_result()))
where F: FnMut(B, T) -> R, R: Try<Output = B> {
let next = self.neg.try_fold(init, &mut f)?;
self.pos.try_fold(next, f)
}

}

impl<T: Ieee754> DoubleEndedIterator for Iter<T> {
fn next_back(&mut self) -> Option<T> {
self.pos.next_back().or_else(|| self.neg.next_back())
}

fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
where F: FnMut(B, T) -> R, R: Try<Output = B> {
let next = self.pos.try_rfold(init, &mut f)?;
self.neg.try_rfold(next, f)
}
}

// equal if they would iterate the same elements, even if the precise
Expand Down Expand Up @@ -197,36 +181,6 @@ impl<T: Ieee754, S: Sign> SingleSignIter<T, S> {
self.from == self.to
}

fn try_fold_result<B, F, E>(&mut self, mut value: B, mut f: F) -> Result<B, E>
where F: FnMut(B, T) -> Result<B, E> {
let SingleSignIter { mut from, to, .. } = *self;
while from != to {
let this = T::from_bits(from);
from = S::to_pos_inf(from);
value = f(value, this).map_err(|e| {
// save the new state before leaving, since we might iterate again
self.from = from;
e
})?;
}
self.from = from;
Ok(value)
}

fn try_rfold_result<B, F, E>(&mut self, mut value: B, mut f: F) -> Result<B, E>
where F: FnMut(B, T) -> Result<B, E> {
let SingleSignIter { from, mut to, .. } = *self;
while from != to {
to = S::to_neg_inf(to);
let this = T::from_bits(to);
value = f(value, this).map_err(|e| {
self.to = to;
e
})?;
}
self.to = to;
Ok(value)
}
}

impl<T: Ieee754, S: Sign> Iterator for SingleSignIter<T, S> {
Expand All @@ -246,24 +200,42 @@ impl<T: Ieee754, S: Sign> Iterator for SingleSignIter<T, S> {
u64_to_size_hint(self.len())
}

fn try_fold<B, F, R>(&mut self, mut value: B, mut f: F) -> R
where F: FnMut(B, T) -> R,
R: Try<Output = B> {
let SingleSignIter { mut from, to, .. } = *self;
while from != to {
let this = T::from_bits(from);
from = S::to_pos_inf(from);
let cf = f(value, this).branch();
match cf {
ControlFlow::Continue(a) => value = a,
ControlFlow::Break(r) => {
// save the new state before leaving, since we might iterate again
self.from = from;
return R::from_residual(r)
}
}
}
self.from = from;
R::from_output(value)
}

fn fold<B, F>(mut self, init: B, mut f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{
enum Void {}

match self.try_fold_result(init, |b, x| Ok::<_, Void>(f(b, x))) {
Ok(result) => result,
Err(_) => unreachable!()
let cf = self.try_fold(init, |b, x| -> ControlFlow<Void, B> {
Try::from_output(f(b, x))
});
match cf {
ControlFlow::Continue(accum) => accum,
ControlFlow::Break(_) => unreachable!()
}
}

#[cfg(nightly)]
fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
where F: FnMut(B, Self::Item) -> R,
R: Try<Ok = B> {
result_to_try(self.try_fold_result(init, |b, x| f(b, x).into_result()))
}
}

impl<T: Ieee754, S: Sign> DoubleEndedIterator for SingleSignIter<T, S> {
Expand All @@ -276,10 +248,39 @@ impl<T: Ieee754, S: Sign> DoubleEndedIterator for SingleSignIter<T, S> {
}
}

#[cfg(nightly)]
fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
where F: FnMut(B, Self::Item) -> R,
R: Try<Ok = B> {
result_to_try(self.try_fold_result(init, |b, x| f(b, x).into_result()))
fn try_rfold<B, F, R>(&mut self, mut value: B, mut f: F) -> R
where F: FnMut(B, T) -> R,
R: Try<Output = B> {
let SingleSignIter { from, mut to, .. } = *self;
while from != to {
to = S::to_neg_inf(to);
let this = T::from_bits(to);
let cf = f(value, this).branch();
match cf {
ControlFlow::Continue(a) => value = a,
ControlFlow::Break(r) => {
// save the new state before leaving, since we might iterate again
self.to = to;
return R::from_residual(r)
}
}
}
self.to = to;
R::from_output(value)
}

fn rfold<B, F>(mut self, init: B, mut f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{
enum Void {}

let cf = self.try_rfold(init, |b, x| -> ControlFlow<Void, B> {
Try::from_output(f(b, x))
});
match cf {
ControlFlow::Continue(accum) => accum,
ControlFlow::Break(_) => unreachable!()
}
}
}
3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@
//! ```

#![no_std]
#![cfg_attr(nightly, feature(try_trait))]
//#![cfg_attr(nightly, feature(try_trait_v2))]
#![feature(try_trait_v2)]
#[cfg(test)] #[macro_use] extern crate std;

mod iter;
Expand Down