From 1c1ed3b5f378c7edb65a775cb9e6c8806101a01e Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Sun, 11 Oct 2020 01:05:54 +0100 Subject: [PATCH] zcoord range in Rust Signed-off-by: Ian Jackson --- templates/bigfloat.ts | 33 ------------------ zcoord/zcoord.rs | 78 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 73 insertions(+), 38 deletions(-) diff --git a/templates/bigfloat.ts b/templates/bigfloat.ts index 66e733a1..aebfc9f9 100644 --- a/templates/bigfloat.ts +++ b/templates/bigfloat.ts @@ -68,44 +68,11 @@ namespace Bigfloats { } } - function limb_val_lookup(v: Unpacked, i: Limb): number { - if (i >= v.limbs.length) return 0; - return v.limbs[i]; } export function iter_upto(ap: Packed, bp: Packed, count: number): () => Packed { // result can be called count times to produce values > av, < bv - let av = unpack(ap); - let bv = unpack(bp); - for (let i = 0; - ; - i++) { - if (i >= av.limbs.length && i >= bv.limbs.length) { - // Oh actually these numbers are equal! - return function(){ return pack(av); } - } - let la = limb_val_lookup(av,i); - let lb = limb_val_lookup(bv,i); - if (la == lb) continue; - - let avail = limb_mask(lb - la); - let current = clone(av); - let step : number; // actual floating point! - if (avail > count+1) { - step = avail / (count+1); - } else { - current.limbs.push(0); - i++; - step = LIMB_MODULUS / (count+1); - } - step = Math.floor(step); - return function() { - current.limbs[i] += step; - return pack(current); - } - } - } } /* diff --git a/zcoord/zcoord.rs b/zcoord/zcoord.rs index ad88c882..5c8f1b3b 100644 --- a/zcoord/zcoord.rs +++ b/zcoord/zcoord.rs @@ -97,9 +97,17 @@ const LIMB_MASK : LimbVal = Wrapping(RAW_LIMB_MODULUS-1); pub struct ZCoord(innards::Innards); #[derive(Error,Clone,Copy,Debug)] -#[error("error parsing zcoord (z value)")] +#[error("error parsing Z coordinate")] pub struct ParseError; +#[derive(Error,Clone,Copy,Debug)] +#[error("Z coordinate range has end before start, cannot iterate")] +pub struct RangeBackwards; + +#[derive(Error,Debug,Copy,Clone,Serialize,Deserialize)] +#[error("Z coordinate overflow")] +pub struct Overflow; + //---------- Mutabel ---------- #[derive(Clone,Debug)] @@ -121,10 +129,6 @@ impl ZCoord { } } -#[derive(Error,Debug,Copy,Clone,Serialize,Deserialize)] -#[error("Z coordinate overflow")] -pub struct Overflow; - impl From for Overflow { fn from(_: TryFromIntError) -> Overflow { Overflow } } @@ -198,6 +202,70 @@ impl Mutable { pub fn repack(&self) -> ZCoord { self.try_into()? } } +pub type RangeIterator = std::iter::Take; + +pub struct RangeIteratorCore { + current: Mutable, + i: usize, + step: LimbVal, +} + +impl Mutable { + fn limb_val_lookup(&self, i: usize) -> LimbVal { + *self.limbs.get(i).unwrap_or(&ZERO) + } + + #[throws(RangeBackwards)] + fn range_core(a: &Mutable, b: &Mutable, count: u32) -> RangeIteratorCore { + let count = count as RawLimbVal; + let mut i = 0; + let current = a.clone(); + loop { + if i >= a.limbs.len() && i >= b.limbs.len() { + // Oh actually these numbers are equal! + break RangeIteratorCore { current, i: 0, step: ZERO }; + } + let la = a.limb_val_lookup(i); + let lb = b.limb_val_lookup(i); + if la == lb { continue } + if la > lb { throw!(RangeBackwards) } + + let mut current = current; + let wantgaps = count+1; + let avail = lb.0 - la.0; + let (step, init); + if avail > wantgaps { + step = avail / wantgaps; + init = la; + } else { + i += 1; + step = (RAW_LIMB_MODULUS-1) / wantgaps; + init = ZERO; + } + current.limbs.resize(i+1, ZERO); + current.limbs[i] = init; + break RangeIteratorCore { current, i, step: Wrapping(step) }; + } + } + + #[throws(RangeBackwards)] + pub fn range(&self, other: &Mutable, count: u32) -> RangeIterator { + Mutable::range_core(self, other, count)?.take(count as usize) + } +} + +impl Iterator for RangeIteratorCore { + type Item = ZCoord; + #[throws(as Option)] + fn next(&mut self) -> ZCoord { + self.current.limbs[self.i] += self.step; + self.current.repack().unwrap() + } +} +impl ExactSizeIterator for RangeIteratorCore { + fn len(&self) -> usize { return usize::MAX } +} + //---------- main features of a Zcoord ---------- impl ZCoord { -- 2.30.2