src/iterate.rs

changeset 90
b3c35d16affe
parent 87
72968cf30033
equal deleted inserted replaced
25:d14c877e14b7 90:b3c35d16affe
17 max_iter : 100, 17 max_iter : 100,
18 verbose_iter : Verbose::Every(10), 18 verbose_iter : Verbose::Every(10),
19 .. Default::default() 19 .. Default::default()
20 }; 20 };
21 let mut x = 1 as float; 21 let mut x = 1 as float;
22 # let mut iter_clone = iter.clone();
22 iter.iterate(|state|{ 23 iter.iterate(|state|{
23 // This is our computational step 24 // This is our computational step
24 x = x + x.sqrt(); 25 x = x + x.sqrt();
25 state.if_verbose(||{ 26 state.if_verbose(||{
26 // return current value when requested 27 // return current value when requested
27 return x 28 return x
28 }) 29 })
29 }) 30 });
31 // or alternatively (avoiding problems with moves)
32 # iter = iter_clone;
33 for state in iter.iter() {
34 // This is our computational step
35 x = x + x.sqrt();
36 state.if_verbose(||{
37 // return current value when requested
38 return x
39 })
40 }
30 ``` 41 ```
31 There is no colon after `state.if_verbose`, because we need to return its value. If you do something after the step, you need to store the result in a variable and return it from the main computational step afterwards. 42 There is no colon after `state.if_verbose`, because we need to return its value. If you do something after the step, you need to store the result in a variable and return it from the main computational step afterwards.
32 43
33 This will print out 44 This will print out
34 ```output 45 ```output
50 use serde::{Serialize, Deserialize}; 61 use serde::{Serialize, Deserialize};
51 use cpu_time::ProcessTime; 62 use cpu_time::ProcessTime;
52 use std::marker::PhantomData; 63 use std::marker::PhantomData;
53 use std::time::Duration; 64 use std::time::Duration;
54 use std::error::Error; 65 use std::error::Error;
66 use std::cell::RefCell;
67 use std::rc::Rc;
55 use crate::types::*; 68 use crate::types::*;
56 use crate::logger::*; 69 use crate::logger::*;
57 70
58 /// Create the displayed presentation for log items. 71 /// Create the displayed presentation for log items.
59 pub trait LogRepr : Debug { 72 pub trait LogRepr : Debug {
112 125
113 /// State of an [`AlgIterator`]. 126 /// State of an [`AlgIterator`].
114 /// 127 ///
115 /// This is the parameter obtained by the closure passed to [`AlgIterator::iterate`] or 128 /// This is the parameter obtained by the closure passed to [`AlgIterator::iterate`] or
116 /// [`AlgIteratorFactory::iterate`]. 129 /// [`AlgIteratorFactory::iterate`].
117 pub trait AlgIteratorState { 130 pub trait AlgIteratorState : Sized {
118 /// Call `call_objective` if this is a verbose iteration. 131 /// Call `call_objective` if this is a verbose iteration.
119 /// 132 ///
120 /// Verbosity depends on the [`AlgIterator`] that produced this state. 133 /// Verbosity depends on the [`AlgIterator`] that produced this state.
121 /// 134 ///
122 /// The closure `calc_objective` should return an arbitrary value of type `V`, to be inserted 135 /// The closure `calc_objective` should return an arbitrary value of type `V`, to be inserted
123 /// into the log, or whatever is deemed by the [`AlgIterator`]. For usage instructions see the 136 /// into the log, or whatever is deemed by the [`AlgIterator`]. For usage instructions see the
124 /// [module documentation][self]. 137 /// [module documentation][self].
125 fn if_verbose<V, E : Error>(&self, calc_objective : impl FnMut() -> V) -> Step<V, E>; 138 fn if_verbose<V, E : Error>(self, calc_objective : impl FnOnce() -> V) -> Step<V, Self, E>;
126 139
127 /// Returns the current iteration count. 140 /// Returns the current iteration count.
128 fn iteration(&self) -> usize; 141 fn iteration(&self) -> usize;
142
143 /// Indicates whether the iterator is quiet
144 fn is_quiet(&self) -> bool;
129 } 145 }
130 146
131 /// Result of a step of an [`AlgIterator`] 147 /// Result of a step of an [`AlgIterator`]
132 #[derive(Debug, Serialize)] 148 #[derive(Debug, Serialize)]
133 pub enum Step<V, Fail : Error = std::convert::Infallible> { 149 pub enum Step<V, S, Fail : Error = std::convert::Infallible> {
134 /// Iteration should be terminated 150 /// Iteration should be terminated
135 Terminated, 151 Terminated,
136 /// Iteration should be terminated due to failure 152 /// Iteration should be terminated due to failure
137 Failure(Fail), 153 Failure(Fail),
138 /// No result this iteration (due to verbosity settings) 154 /// No result this iteration (due to verbosity settings)
139 Quiet, 155 Quiet,
140 /// Result of this iteration (due to verbosity settings) 156 /// Result of this iteration (due to verbosity settings)
141 Result(V), 157 Result(V, S),
142 } 158 }
143 159
144 impl<V, E : Error> Step<V, E> { 160 impl<V, S, E : Error> Step<V, S, E> {
145 /// Maps the value contained within the `Step`, if any, by the closure `f`. 161 /// Maps the value contained within the `Step`, if any, by the closure `f`.
146 pub fn map<U>(self, mut f : impl FnMut(V) -> U) -> Step<U, E> { 162 pub fn map<U>(self, mut f : impl FnMut(V) -> U) -> Step<U, S, E> {
147 match self { 163 match self {
148 Step::Result(v) => Step::Result(f(v)), 164 Step::Result(v, s) => Step::Result(f(v), s),
149 Step::Failure(e) => Step::Failure(e), 165 Step::Failure(e) => Step::Failure(e),
150 Step::Quiet => Step::Quiet, 166 Step::Quiet => Step::Quiet,
151 Step::Terminated => Step::Terminated, 167 Step::Terminated => Step::Terminated,
152 } 168 }
169 }
170 }
171
172 impl<V, S, E : Error> Default for Step<V, S, E> {
173 fn default() -> Self {
174 Step::Quiet
153 } 175 }
154 } 176 }
155 177
156 /// An iterator for algorithms, produced by [`AlgIteratorFactory::prepare`]. 178 /// An iterator for algorithms, produced by [`AlgIteratorFactory::prepare`].
157 /// 179 ///
158 /// Typically not accessed directly, but transparently produced by an [`AlgIteratorFactory`]. 180 /// Typically not accessed directly, but transparently produced by an [`AlgIteratorFactory`].
159 /// Every [`AlgIteratorFactory`] has to implement a corresponding `AlgIterator`. 181 /// Every [`AlgIteratorFactory`] has to implement a corresponding `AlgIterator`.
160 pub trait AlgIterator : Sized { 182 pub trait AlgIterator : Sized {
161 /// The state type 183 /// The state type
162 type State : AlgIteratorState; 184 type State : AlgIteratorState;
163 /// The output type for [`Self::step`]. 185 /// The output type for [`Self::poststep`] and [`Self::step`].
164 type Output; 186 type Output;
165 /// The error type for [`Self::step`] and [`Self::iterate`]. 187 /// The input type for [`Self::poststep`].
166 type Err : Error; 188 type Input;
167 189
168 /// Advance the iterator. 190 /// Advance the iterator, performing `step_fn` with the state
169 fn step(&mut self) -> Step<Self::Output, Self::Err>; 191 fn step<F, E>(&mut self, step_fn : &mut F) -> Step<Self::Output, Self::State, E>
192 where F : FnMut(Self::State) -> Step<Self::Input, Self::State, E>,
193 E : Error {
194 self.prestep().map_or(Step::Terminated,
195 |state| self.poststep(step_fn(state)))
196 }
197
198 /// Initial stage of advancing the iterator, before the actual step
199 fn prestep(&mut self) -> Option<Self::State>;
200
201 /// Handle step result
202 fn poststep<E>(&mut self, result : Step<Self::Input, Self::State, E>)
203 -> Step<Self::Output, Self::State, E>
204 where E : Error;
170 205
171 /// Return current iteration count. 206 /// Return current iteration count.
172 fn iteration(&self) -> usize { 207 fn iteration(&self) -> usize {
173 self.state().iteration() 208 self.state().iteration()
174 } 209 }
175 210
176 /// Return current state. 211 /// Return current state.
177 fn state(&self) -> Self::State; 212 fn state(&self) -> Self::State;
178 213
179 /// Iterate the `AlgIterator` until termination. 214 /// Iterate the `AlgIterator` until termination, erforming `step_fn` on each step.
180 /// 215 ///
181 /// Returns either `()` or an error if the step closure terminated in [`Step::FailureĀ“]. 216 /// Returns either `()` or an error if the step closure terminated in [`Step::FailureĀ“].
182 #[inline] 217 #[inline]
183 fn iterate(&mut self) -> Result<(), Self::Err> { 218 fn iterate<F, E>(&mut self, mut step_fn : F) -> Result<(), E>
219 where F : FnMut(Self::State) -> Step<Self::Input, Self::State, E>,
220 E : Error {
184 loop { 221 loop {
185 match self.step() { 222 match self.step(&mut step_fn) {
186 Step::Terminated => return Ok(()), 223 Step::Terminated => return Ok(()),
187 Step::Failure(e) => return Err(e), 224 Step::Failure(e) => return Err(e),
188 _ => {}, 225 _ => {},
189 } 226 }
190 } 227 }
191 } 228 }
192
193 /// Converts the `AlgIterator` into a plain [`Iterator`].
194 ///
195 /// [`Step::Quiet`] results are discarded, and [`Step::Failure`] results **panic**.
196 fn downcast(self) -> AlgIteratorI<Self> {
197 AlgIteratorI(self)
198 }
199 }
200
201 /// Conversion of an `AlgIterator` into a plain [`Iterator`].
202 ///
203 /// The conversion discards [`Step::Quiet`] and **panics** on [`Step::Failure`].
204 pub struct AlgIteratorI<A>(A);
205
206 impl<A> Iterator for AlgIteratorI<A>
207 where A : AlgIterator {
208 type Item = A::Output;
209
210 fn next(&mut self) -> Option<A::Output> {
211 loop {
212 match self.0.step() {
213 Step::Result(v) => return Some(v),
214 Step::Failure(e) => panic!("{e:?}"),
215 Step::Terminated => return None,
216 Step::Quiet => continue,
217 }
218 }
219 }
220 } 229 }
221 230
222 /// A factory for producing an [`AlgIterator`]. 231 /// A factory for producing an [`AlgIterator`].
223 /// 232 ///
224 /// For usage instructions see the [module documentation][self]. 233 /// For usage instructions see the [module documentation][self].
225 pub trait AlgIteratorFactory<V> : Sized { 234 pub trait AlgIteratorFactory<V> : Sized {
226 type Iter<F, E> : AlgIterator<State = Self::State, Output = Self::Output, Err = E> 235 type Iter : AlgIterator<State = Self::State, Input = V, Output = Self::Output>;
227 where F : FnMut(&Self::State) -> Step<V, E>, 236
228 E : Error;
229 /// The state type of the corresponding [`AlgIterator`]. 237 /// The state type of the corresponding [`AlgIterator`].
230 /// A reference to this is passed to the closures passed to methods such as [`Self::iterate`]. 238 /// A reference to this is passed to the closures passed to methods such as [`Self::iterate`].
231 type State : AlgIteratorState; 239 type State : AlgIteratorState;
232 /// The output type of the corresponding [`AlgIterator`]. 240 /// The output type of the corresponding [`AlgIterator`].
233 /// This is the output of the closures passed to methods such as [`Self::iterate`] after 241 /// This is the output of the closures passed to methods such as [`Self::iterate`] after
234 /// mappings performed by each [`AlgIterator`] implementation. 242 /// mappings performed by each [`AlgIterator`] implementation.
235 type Output; 243 type Output;
236 244
237 /// Prepare an [`AlgIterator`], consuming the factory. 245 /// Prepare an [`AlgIterator`], consuming the factory.
238 /// 246 fn prepare(self) -> Self::Iter;
239 /// The function `step_fn` should accept a `state` ([`AlgIteratorState`] parameter, and return
240 /// a [`Step`].
241 fn prepare<F, E>(self, step_fn : F) -> Self::Iter<F, E>
242 where F : FnMut(&Self::State) -> Step<V, E>,
243 E : Error;
244 247
245 /// Iterate the the closure `step`. 248 /// Iterate the the closure `step`.
246 /// 249 ///
247 /// The closure should accept a `state` parameter (satisfying the trait [`AlgIteratorState`]). 250 /// The closure should accept a `state` parameter (satisfying the trait [`AlgIteratorState`]).
248 /// It should return the output of 251 /// It should return the output of
250 /// completion for other reason, or [`Step::Failure`] for termination for failure. 253 /// completion for other reason, or [`Step::Failure`] for termination for failure.
251 /// 254 ///
252 /// This method is equivalent to [`Self::prepare`] followed by [`AlgIterator::iterate`]. 255 /// This method is equivalent to [`Self::prepare`] followed by [`AlgIterator::iterate`].
253 #[inline] 256 #[inline]
254 fn iterate_fallible<F, E>(self, step : F) -> Result<(), E> 257 fn iterate_fallible<F, E>(self, step : F) -> Result<(), E>
255 where F : FnMut(&Self::State) -> Step<V, E>, 258 where F : FnMut(Self::State) -> Step<V, Self::State, E>,
256 E : Error { 259 E : Error {
257 self.prepare(step).iterate() 260 self.prepare().iterate(step)
258 } 261 }
259 262
260 /// Iterate the the closure `step`. 263 /// Iterate the closure `step`.
261 /// 264 ///
262 /// The closure should accept a `state` parameter (satisfying the trait [`AlgIteratorState`]), 265 /// The closure should accept a `state` parameter (satisfying the trait [`AlgIteratorState`]),
263 /// It should return the output of 266 /// It should return the output of
264 /// `state.`[`if_verbose`][AlgIteratorState::if_verbose]. 267 /// `state.`[`if_verbose`][AlgIteratorState::if_verbose].
265 /// 268 ///
267 /// 270 ///
268 /// This method is equivalent to [`Self::prepare`] followed by [`AlgIterator::iterate`] 271 /// This method is equivalent to [`Self::prepare`] followed by [`AlgIterator::iterate`]
269 /// with the error type `E=`[`std::convert::Infallible`]. 272 /// with the error type `E=`[`std::convert::Infallible`].
270 #[inline] 273 #[inline]
271 fn iterate<F>(self, step : F) 274 fn iterate<F>(self, step : F)
272 where F : FnMut(&Self::State) -> Step<V> { 275 where F : FnMut(Self::State) -> Step<V, Self::State> {
273 self.iterate_fallible(step).unwrap_or_default() 276 self.iterate_fallible(step).unwrap_or_default()
274 } 277 }
275 278
276 /// Iterate the closure `step` with data produced by `datasource`. 279 /// Iterate the closure `step` with data produced by `datasource`.
277 /// 280 ///
283 /// If the `datasource` runs out of data, the iterator is considered having terminated 286 /// If the `datasource` runs out of data, the iterator is considered having terminated
284 /// successsfully. 287 /// successsfully.
285 /// 288 ///
286 /// For usage instructions see the [module documentation][self]. 289 /// For usage instructions see the [module documentation][self].
287 #[inline] 290 #[inline]
288 fn iterate_data_fallible<F, D, I, E>(self, mut datasource : I, mut step : F) -> Result<(), E> 291 fn iterate_data_fallible<F, D, I, E>(self, mut datasource : I, mut step : F)
289 where F : FnMut(&Self::State, D) -> Step<V, E>, 292 -> Result<(), E>
293 where F : FnMut(Self::State, D) -> Step<V, Self::State, E>,
290 I : Iterator<Item = D>, 294 I : Iterator<Item = D>,
291 E : Error { 295 E : Error {
292 self.prepare(move |state| { 296 self.prepare().iterate(move |state| {
293 datasource.next().map_or(Step::Terminated, |d| step(state, d)) 297 datasource.next().map_or(Step::Terminated, |d| step(state, d))
294 }).iterate() 298 })
295 } 299 }
296 300
297 /// Iterate the closure `step` with data produced by `datasource`. 301 /// Iterate the closure `step` with data produced by `datasource`.
298 /// 302 ///
299 /// The closure should accept a `state` parameter (satisfying the trait [`AlgIteratorState`]), 303 /// The closure should accept a `state` parameter (satisfying the trait [`AlgIteratorState`]),
304 /// successsfully. 308 /// successsfully.
305 /// 309 ///
306 /// For usage instructions see the [module documentation][self]. 310 /// For usage instructions see the [module documentation][self].
307 #[inline] 311 #[inline]
308 fn iterate_data<F, D, I>(self, datasource : I, step : F) 312 fn iterate_data<F, D, I>(self, datasource : I, step : F)
309 where F : FnMut(&Self::State, D) -> Step<V>, 313 where F : FnMut(Self::State, D) -> Step<V, Self::State>,
310 I : Iterator<Item = D> { 314 I : Iterator<Item = D> {
311 self.iterate_data_fallible(datasource, step).unwrap_or_default() 315 self.iterate_data_fallible(datasource, step).unwrap_or_default()
312 } 316 }
313 317
314 // fn make_iterate<'own>(self) 318 // fn make_iterate<'own>(self)
393 StallIteratorFactory { base_options : self, stall : stall } 397 StallIteratorFactory { base_options : self, stall : stall }
394 } 398 }
395 399
396 /// Is the iterator quiet, i.e., on-verbose? 400 /// Is the iterator quiet, i.e., on-verbose?
397 fn is_quiet(&self) -> bool { false } 401 fn is_quiet(&self) -> bool { false }
402
403 /// Returns an an [`std::iter::Iterator`] that can be used in a `for`-loop.
404 fn iter(self) -> AlgIteratorIterator<Self::Iter> {
405 AlgIteratorIterator {
406 algi : Rc::new(RefCell::new(self.prepare())),
407 }
408 }
409
410 /// Returns an an [`std::iter::Iterator`] that can be used in a `for`-loop,
411 /// also inputting an initial iteration status calculated by `f` if needed.
412 fn iter_init(self, f : impl FnOnce() -> <Self::Iter as AlgIterator>::Input)
413 -> AlgIteratorIterator<Self::Iter> {
414 let mut i = self.prepare();
415 let st = i.state();
416 let step : Step<<Self::Iter as AlgIterator>::Input, Self::State> = st.if_verbose(f);
417 i.poststep(step);
418 AlgIteratorIterator {
419 algi : Rc::new(RefCell::new(i)),
420 }
421 }
398 } 422 }
399 423
400 /// Options for [`BasicAlgIteratorFactory`]. 424 /// Options for [`BasicAlgIteratorFactory`].
401 /// 425 ///
402 /// Use as: 426 /// Use as:
425 /// $b$ is indicated logarithmic base. So, with $b=10$, 449 /// $b$ is indicated logarithmic base. So, with $b=10$,
426 /// * every iteration for first 10 iterations, 450 /// * every iteration for first 10 iterations,
427 /// * every 10 iterations from there on until 100 iterations, 451 /// * every 10 iterations from there on until 100 iterations,
428 /// * every 100 iteartinos frmo there on until 1000 iterations, etc. 452 /// * every 100 iteartinos frmo there on until 1000 iterations, etc.
429 Logarithmic(usize), 453 Logarithmic(usize),
454 /// Same as `Logarithmic`, but $\log_b(n)$ is replaced by $min\{c, \log_b(n)\}$ where $c$
455 /// is the given `cap`. For example, with `base=10` and `cap=2`, the first ten iterations
456 /// will be output, then every tenth iteration, and after 100 iterations, every 100th iteration,
457 /// without further logarithmic progression.
458 LogarithmicCap{ base : usize, cap : u32 },
430 } 459 }
431 460
432 impl Verbose { 461 impl Verbose {
433 /// Indicates whether given iteration number is verbose 462 /// Indicates whether given iteration number is verbose
434 pub fn is_verbose(&self, iter : usize) -> bool { 463 pub fn is_verbose(&self, iter : usize) -> bool {
441 }, 470 },
442 &Verbose::Logarithmic(base) => { 471 &Verbose::Logarithmic(base) => {
443 let every = base.pow((iter as float).log(base as float).floor() as u32); 472 let every = base.pow((iter as float).log(base as float).floor() as u32);
444 iter % every == 0 473 iter % every == 0
445 } 474 }
475 &Verbose::LogarithmicCap{base, cap} => {
476 let every = base.pow(((iter as float).log(base as float).floor() as u32).min(cap));
477 iter % every == 0
478 }
446 } 479 }
447 } 480 }
448 } 481 }
449 482
450 impl Default for AlgIteratorOptions { 483 impl Default for AlgIteratorOptions {
465 /// Whether the iteration is verbose, i.e., results should be displayed. 498 /// Whether the iteration is verbose, i.e., results should be displayed.
466 /// Requires `calc` to be `true`. 499 /// Requires `calc` to be `true`.
467 verbose : bool, 500 verbose : bool,
468 /// Whether results should be calculated. 501 /// Whether results should be calculated.
469 calc : bool, 502 calc : bool,
503 /// Indicates whether the iteration is quiet
504 quiet : bool,
470 } 505 }
471 506
472 /// [`AlgIteratorFactory`] for [`BasicAlgIterator`] 507 /// [`AlgIteratorFactory`] for [`BasicAlgIterator`]
473 #[derive(Clone,Debug)] 508 #[derive(Clone,Debug)]
474 pub struct BasicAlgIteratorFactory<V> { 509 pub struct BasicAlgIteratorFactory<V> {
476 _phantoms : PhantomData<V>, 511 _phantoms : PhantomData<V>,
477 } 512 }
478 513
479 /// The simplest [`AlgIterator`], created by [`BasicAlgIteratorFactory`] 514 /// The simplest [`AlgIterator`], created by [`BasicAlgIteratorFactory`]
480 #[derive(Clone,Debug)] 515 #[derive(Clone,Debug)]
481 pub struct BasicAlgIterator<F, V, E : Error> { 516 pub struct BasicAlgIterator<V> {
482 options : AlgIteratorOptions, 517 options : AlgIteratorOptions,
483 iter : usize, 518 iter : usize,
484 step_fn : F, 519 _phantoms : PhantomData<V>,
485 _phantoms : PhantomData<(V, E)>,
486 } 520 }
487 521
488 impl AlgIteratorOptions { 522 impl AlgIteratorOptions {
489 /// [`AlgIteratorOptions`] is directly a factory for [`BasicAlgIterator`], 523 /// [`AlgIteratorOptions`] is directly a factory for [`BasicAlgIterator`],
490 /// however, due to type inference issues, it may become convenient to instantiate 524 /// however, due to type inference issues, it may become convenient to instantiate
498 } 532 }
499 533
500 impl<V> AlgIteratorFactory<V> for AlgIteratorOptions 534 impl<V> AlgIteratorFactory<V> for AlgIteratorOptions
501 where V : LogRepr { 535 where V : LogRepr {
502 type State = BasicState; 536 type State = BasicState;
503 type Iter<F, E> = BasicAlgIterator<F, V, E> 537 type Iter = BasicAlgIterator<V>;
504 where F : FnMut(&Self::State) -> Step<V, E>,
505 E : Error;
506 type Output = V; 538 type Output = V;
507 539
508 fn prepare<F, E>(self, step_fn : F) -> Self::Iter<F, E> 540 fn prepare(self) -> Self::Iter {
509 where F : FnMut(&Self::State) -> Step<V, E>,
510 E : Error {
511 BasicAlgIterator{ 541 BasicAlgIterator{
512 options : self, 542 options : self,
513 iter : 0, 543 iter : 0,
514 step_fn,
515 _phantoms : PhantomData, 544 _phantoms : PhantomData,
516 } 545 }
517 } 546 }
518 547
519 #[inline] 548 #[inline]
523 } 552 }
524 553
525 impl<V> AlgIteratorFactory<V> for BasicAlgIteratorFactory<V> 554 impl<V> AlgIteratorFactory<V> for BasicAlgIteratorFactory<V>
526 where V : LogRepr { 555 where V : LogRepr {
527 type State = BasicState; 556 type State = BasicState;
528 type Iter<F, E> = BasicAlgIterator<F, V, E> 557 type Iter = BasicAlgIterator<V>;
529 where F : FnMut(&Self::State) -> Step<V, E>,
530 E : Error;
531 type Output = V; 558 type Output = V;
532 559
533 fn prepare<F, E>(self, step_fn : F) -> Self::Iter<F, E> 560 fn prepare(self) -> Self::Iter {
534 where F : FnMut(&Self::State) -> Step<V, E>,
535 E : Error {
536 BasicAlgIterator { 561 BasicAlgIterator {
537 options : self.options, 562 options : self.options,
538 iter : 0, 563 iter : 0,
539 step_fn,
540 _phantoms : PhantomData 564 _phantoms : PhantomData
541 } 565 }
542 } 566 }
543 567
544 #[inline] 568 #[inline]
545 fn is_quiet(&self) -> bool { 569 fn is_quiet(&self) -> bool {
546 self.options.quiet 570 self.options.quiet
547 } 571 }
548 } 572 }
549 573
550 impl<F, V, E> AlgIterator for BasicAlgIterator<F, V, E> 574 impl<V> AlgIterator for BasicAlgIterator<V>
551 where V : LogRepr, 575 where V : LogRepr {
552 E : Error,
553 F : FnMut(&BasicState) -> Step<V, E> {
554 type State = BasicState; 576 type State = BasicState;
555 type Output = V; 577 type Output = V;
556 type Err = E; 578 type Input = V;
557 579
558 #[inline] 580 #[inline]
559 fn step(&mut self) -> Step<V, E> { 581 fn prestep(&mut self) -> Option<Self::State> {
560 if self.iter >= self.options.max_iter { 582 if self.iter >= self.options.max_iter {
561 Step::Terminated 583 None
562 } else { 584 } else {
563 self.iter += 1; 585 self.iter += 1;
564 let state = self.state(); 586 Some(self.state())
565 let res = (self.step_fn)(&state); 587 }
566 if let Step::Result(ref val) = res { 588 }
567 if state.verbose && !self.options.quiet { 589
568 println!("{}{}/{} {}{}", "".dimmed(), 590 fn poststep<E : Error>(&mut self, res : Step<V, Self::State, E>) -> Step<V, Self::State, E> {
569 state.iter, 591 if let Step::Result(ref val, ref state) = res {
570 self.options.max_iter, 592 if state.verbose && !self.options.quiet {
571 val.logrepr(), 593 println!("{}{}/{} {}{}", "".dimmed(),
572 "".clear()); 594 state.iter,
573 } 595 self.options.max_iter,
596 val.logrepr(),
597 "".clear());
574 } 598 }
575 res 599 }
576 } 600 res
577 } 601 }
578 602
579 #[inline] 603 #[inline]
580 fn iteration(&self) -> usize { 604 fn iteration(&self) -> usize {
581 self.iter 605 self.iter
583 607
584 #[inline] 608 #[inline]
585 fn state(&self) -> BasicState { 609 fn state(&self) -> BasicState {
586 let iter = self.iter; 610 let iter = self.iter;
587 let verbose = self.options.verbose_iter.is_verbose(iter); 611 let verbose = self.options.verbose_iter.is_verbose(iter);
588 BasicState{ 612 BasicState {
589 iter : iter, 613 iter : iter,
590 verbose : verbose, 614 verbose : verbose,
591 calc : verbose, 615 calc : verbose,
616 quiet : self.options.quiet
592 } 617 }
593 } 618 }
594 } 619 }
595 620
596 impl AlgIteratorState for BasicState { 621 impl AlgIteratorState for BasicState {
597 #[inline] 622 #[inline]
598 fn if_verbose<V, E : Error>(&self, mut calc_objective : impl FnMut() -> V) -> Step<V, E> { 623 fn if_verbose<V, E : Error>(self, calc_objective : impl FnOnce() -> V) -> Step<V, Self, E> {
599 if self.calc { 624 if self.calc {
600 Step::Result(calc_objective()) 625 Step::Result(calc_objective(), self)
601 } else { 626 } else {
602 Step::Quiet 627 Step::Quiet
603 } 628 }
604 } 629 }
605 630
606 #[inline] 631 #[inline]
607 fn iteration(&self) -> usize { 632 fn iteration(&self) -> usize {
608 return self.iter; 633 self.iter
634 }
635
636 #[inline]
637 fn is_quiet(&self) -> bool {
638 self.quiet
609 } 639 }
610 } 640 }
611 641
612 // 642 //
613 // Stall detecting iteration function. 643 // Stall detecting iteration function.
634 664
635 impl<V, U, BaseFactory> AlgIteratorFactory<V> 665 impl<V, U, BaseFactory> AlgIteratorFactory<V>
636 for StallIteratorFactory<U, BaseFactory> 666 for StallIteratorFactory<U, BaseFactory>
637 where BaseFactory : AlgIteratorFactory<V, Output=U>, 667 where BaseFactory : AlgIteratorFactory<V, Output=U>,
638 U : SignedNum + PartialOrd { 668 U : SignedNum + PartialOrd {
639 type Iter<F, E> = StallIterator<U, BaseFactory::Iter<F, E>> 669 type Iter = StallIterator<U, BaseFactory::Iter>;
640 where F : FnMut(&Self::State) -> Step<V, E>,
641 E : Error;
642 type State = BaseFactory::State; 670 type State = BaseFactory::State;
643 type Output = BaseFactory::Output; 671 type Output = BaseFactory::Output;
644 672
645 fn prepare<F, E>(self, step_fn : F) -> Self::Iter<F, E> 673 fn prepare(self) -> Self::Iter {
646 where F : FnMut(&Self::State) -> Step<V, E>,
647 E : Error {
648 StallIterator { 674 StallIterator {
649 base_iterator : self.base_options.prepare(step_fn), 675 base_iterator : self.base_options.prepare(),
650 stall : self.stall, 676 stall : self.stall,
651 previous_value : None, 677 previous_value : None,
652 } 678 }
653 } 679 }
654 680
660 impl<U, BaseIterator> AlgIterator 686 impl<U, BaseIterator> AlgIterator
661 for StallIterator<U, BaseIterator> 687 for StallIterator<U, BaseIterator>
662 where BaseIterator : AlgIterator<Output=U>, 688 where BaseIterator : AlgIterator<Output=U>,
663 U : SignedNum + PartialOrd { 689 U : SignedNum + PartialOrd {
664 type State = BaseIterator::State; 690 type State = BaseIterator::State;
665 type Output = BaseIterator::Output; 691 type Output = U;
666 type Err = BaseIterator::Err; 692 type Input = BaseIterator::Input;
667 693
668 #[inline] 694 #[inline]
669 fn step(&mut self) -> Step<U, Self::Err> { 695 fn prestep(&mut self) -> Option<Self::State> {
670 match self.base_iterator.step() { 696 self.base_iterator.prestep()
671 Step::Result(nv) => { 697 }
698
699 #[inline]
700 fn poststep<E>(&mut self, res : Step<Self::Input, Self::State, E>) -> Step<U, Self::State, E>
701 where E : Error {
702 match self.base_iterator.poststep(res) {
703 Step::Result(nv, state) => {
672 let previous_v = self.previous_value; 704 let previous_v = self.previous_value;
673 self.previous_value = Some(nv); 705 self.previous_value = Some(nv);
674 match previous_v { 706 match previous_v {
675 Some(pv) if (nv - pv).abs() <= self.stall * pv.abs() => Step::Terminated, 707 Some(pv) if (nv - pv).abs() <= self.stall * pv.abs() => Step::Terminated,
676 _ => Step::Result(nv), 708 _ => Step::Result(nv, state),
677 } 709 }
678 }, 710 },
679 val => val, 711 val => val,
680 } 712 }
681 } 713 }
709 741
710 impl<V, U, BaseFactory> AlgIteratorFactory<V> 742 impl<V, U, BaseFactory> AlgIteratorFactory<V>
711 for ValueIteratorFactory<U, BaseFactory> 743 for ValueIteratorFactory<U, BaseFactory>
712 where BaseFactory : AlgIteratorFactory<V, Output=U>, 744 where BaseFactory : AlgIteratorFactory<V, Output=U>,
713 U : SignedNum + PartialOrd { 745 U : SignedNum + PartialOrd {
714 type Iter<F, E> = ValueIterator<U, BaseFactory::Iter<F, E>> 746 type Iter = ValueIterator<U, BaseFactory::Iter>;
715 where F : FnMut(&Self::State) -> Step<V, E>,
716 E : Error;
717 type State = BaseFactory::State; 747 type State = BaseFactory::State;
718 type Output = BaseFactory::Output; 748 type Output = BaseFactory::Output;
719 749
720 fn prepare<F, E>(self, step_fn : F) -> Self::Iter<F, E> 750 fn prepare(self) -> Self::Iter {
721 where F : FnMut(&Self::State) -> Step<V, E>,
722 E : Error {
723 ValueIterator { 751 ValueIterator {
724 base_iterator : self.base_options.prepare(step_fn), 752 base_iterator : self.base_options.prepare(),
725 target : self.target 753 target : self.target
726 } 754 }
727 } 755 }
728 756
729 fn is_quiet(&self) -> bool { 757 fn is_quiet(&self) -> bool {
734 impl<U, BaseIterator> AlgIterator 762 impl<U, BaseIterator> AlgIterator
735 for ValueIterator<U, BaseIterator> 763 for ValueIterator<U, BaseIterator>
736 where BaseIterator : AlgIterator<Output=U>, 764 where BaseIterator : AlgIterator<Output=U>,
737 U : SignedNum + PartialOrd { 765 U : SignedNum + PartialOrd {
738 type State = BaseIterator::State; 766 type State = BaseIterator::State;
739 type Output = BaseIterator::Output; 767 type Output = U;
740 type Err = BaseIterator::Err; 768 type Input = BaseIterator::Input;
741 769
742 #[inline] 770 #[inline]
743 fn step(&mut self) -> Step<U, Self::Err> { 771 fn prestep(&mut self) -> Option<Self::State> {
744 match self.base_iterator.step() { 772 self.base_iterator.prestep()
745 Step::Result(v) => { 773 }
774
775 #[inline]
776 fn poststep<E>(&mut self, res : Step<Self::Input, Self::State, E>) -> Step<U, Self::State, E> where E : Error{
777 match self.base_iterator.poststep(res) {
778 Step::Result(v, state) => {
746 if v <= self.target { 779 if v <= self.target {
747 Step::Terminated 780 Step::Terminated
748 } else { 781 } else {
749 Step::Result(v) 782 Step::Result(v, state)
750 } 783 }
751 }, 784 },
752 val => val, 785 val => val,
753 } 786 }
754 } 787 }
790 impl<'log, V, BaseFactory> AlgIteratorFactory<V> 823 impl<'log, V, BaseFactory> AlgIteratorFactory<V>
791 for LoggingIteratorFactory<'log, BaseFactory::Output, BaseFactory> 824 for LoggingIteratorFactory<'log, BaseFactory::Output, BaseFactory>
792 where BaseFactory : AlgIteratorFactory<V>, 825 where BaseFactory : AlgIteratorFactory<V>,
793 BaseFactory::Output : 'log { 826 BaseFactory::Output : 'log {
794 type State = BaseFactory::State; 827 type State = BaseFactory::State;
795 type Iter<F, E> = LoggingIterator<'log, BaseFactory::Output, BaseFactory::Iter<F, E>> 828 type Iter = LoggingIterator<'log, BaseFactory::Output, BaseFactory::Iter>;
796 where F : FnMut(&Self::State) -> Step<V, E>,
797 E : Error;
798 type Output = (); 829 type Output = ();
799 830
800 fn prepare<F, E>(self, step_fn : F) -> Self::Iter<F, E> 831 fn prepare(self) -> Self::Iter {
801 where F : FnMut(&Self::State) -> Step<V, E>,
802 E : Error {
803 LoggingIterator { 832 LoggingIterator {
804 base_iterator : self.base_options.prepare(step_fn), 833 base_iterator : self.base_options.prepare(),
805 logger : self.logger, 834 logger : self.logger,
806 } 835 }
807 } 836 }
808 837
809 #[inline] 838 #[inline]
816 for LoggingIterator<'log, BaseIterator::Output, BaseIterator> 845 for LoggingIterator<'log, BaseIterator::Output, BaseIterator>
817 where BaseIterator : AlgIterator, 846 where BaseIterator : AlgIterator,
818 BaseIterator::Output : 'log { 847 BaseIterator::Output : 'log {
819 type State = BaseIterator::State; 848 type State = BaseIterator::State;
820 type Output = (); 849 type Output = ();
821 type Err = BaseIterator::Err; 850 type Input = BaseIterator::Input;
822 851
823 #[inline] 852 #[inline]
824 fn step(&mut self) -> Step<Self::Output, Self::Err> { 853 fn prestep(&mut self) -> Option<Self::State> {
825 match self.base_iterator.step() { 854 self.base_iterator.prestep()
826 Step::Result(v) => { 855 }
856
857 #[inline]
858 fn poststep<E>(&mut self, res : Step<Self::Input, Self::State, E>) -> Step<(), Self::State, E> where E : Error {
859 match self.base_iterator.poststep(res) {
860 Step::Result(v, _) => {
827 self.logger.log(v); 861 self.logger.log(v);
828 Step::Quiet 862 Step::Quiet
829 }, 863 },
830 Step::Quiet => Step::Quiet, 864 Step::Quiet => Step::Quiet,
831 Step::Terminated => Step::Terminated, 865 Step::Terminated => Step::Terminated,
843 self.base_iterator.state() 877 self.base_iterator.state()
844 } 878 }
845 } 879 }
846 880
847 /// This [`AlgIteratorFactory`] allows output mapping. 881 /// This [`AlgIteratorFactory`] allows output mapping.
848 /// 882 ///
849 /// Typically produced with [`AlgIteratorFactory::mapped`]. 883 /// Typically produced with [`AlgIteratorFactory::mapped`].
850 #[derive(Debug)] 884 #[derive(Debug)]
851 pub struct MappingIteratorFactory<G, BaseFactory> { 885 pub struct MappingIteratorFactory<G, BaseFactory> {
852 /// Base [`AlgIteratorFactory`] on which to build 886 /// Base [`AlgIteratorFactory`] on which to build
853 base_options : BaseFactory, 887 base_options : BaseFactory,
866 impl<V, U, G, BaseFactory> AlgIteratorFactory<V> 900 impl<V, U, G, BaseFactory> AlgIteratorFactory<V>
867 for MappingIteratorFactory<G, BaseFactory> 901 for MappingIteratorFactory<G, BaseFactory>
868 where BaseFactory : AlgIteratorFactory<V>, 902 where BaseFactory : AlgIteratorFactory<V>,
869 G : Fn(usize, BaseFactory::Output) -> U { 903 G : Fn(usize, BaseFactory::Output) -> U {
870 type State = BaseFactory::State; 904 type State = BaseFactory::State;
871 type Iter<F, E> = MappingIterator<G, BaseFactory::Iter<F, E>> 905 type Iter = MappingIterator<G, BaseFactory::Iter>;
872 where F : FnMut(&Self::State) -> Step<V, E>,
873 E : Error;
874 type Output = U; 906 type Output = U;
875 907
876 fn prepare<F, E>(self, step_fn : F) -> Self::Iter<F, E> 908 fn prepare(self) -> Self::Iter {
877 where F : FnMut(&Self::State) -> Step<V, E>,
878 E : Error {
879 MappingIterator { 909 MappingIterator {
880 base_iterator : self.base_options.prepare(step_fn), 910 base_iterator : self.base_options.prepare(),
881 map : self.map 911 map : self.map
882 } 912 }
883 } 913 }
884 914
885 #[inline] 915 #[inline]
892 for MappingIterator<G, BaseIterator> 922 for MappingIterator<G, BaseIterator>
893 where BaseIterator : AlgIterator, 923 where BaseIterator : AlgIterator,
894 G : Fn(usize, BaseIterator::Output) -> U { 924 G : Fn(usize, BaseIterator::Output) -> U {
895 type State = BaseIterator::State; 925 type State = BaseIterator::State;
896 type Output = U; 926 type Output = U;
897 type Err = BaseIterator::Err; 927 type Input = BaseIterator::Input;
898 928
899 #[inline] 929 #[inline]
900 fn step(&mut self) -> Step<Self::Output, Self::Err> { 930 fn prestep(&mut self) -> Option<Self::State> {
901 match self.base_iterator.step() { 931 self.base_iterator.prestep()
902 Step::Result(v) => Step::Result((self.map)(self.iteration(), v)), 932 }
933
934 #[inline]
935 fn poststep<E>(&mut self, res : Step<Self::Input, Self::State, E>) -> Step<Self::Output, Self::State, E> where E : Error {
936 match self.base_iterator.poststep(res) {
937 Step::Result(v, state) => Step::Result((self.map)(self.iteration(), v), state),
903 Step::Quiet => Step::Quiet, 938 Step::Quiet => Step::Quiet,
904 Step::Terminated => Step::Terminated, 939 Step::Terminated => Step::Terminated,
905 Step::Failure(e) => Step::Failure(e), 940 Step::Failure(e) => Step::Failure(e),
906 } 941 }
907 } 942 }
933 } 968 }
934 969
935 /// Data `U` with production time attached 970 /// Data `U` with production time attached
936 #[derive(Copy, Clone, Debug, Serialize)] 971 #[derive(Copy, Clone, Debug, Serialize)]
937 pub struct Timed<U> { 972 pub struct Timed<U> {
973 /// CPU time taken
938 pub cpu_time : Duration, 974 pub cpu_time : Duration,
975 /// Iteration number
976 pub iter : usize,
977 /// User data
939 //#[serde(flatten)] 978 //#[serde(flatten)]
940 pub data : U 979 pub data : U
941 } 980 }
942 981
943 impl<T> LogRepr for Timed<T> where T : LogRepr { 982 impl<T> LogRepr for Timed<T> where T : LogRepr {
949 988
950 impl<V, BaseFactory> AlgIteratorFactory<V> 989 impl<V, BaseFactory> AlgIteratorFactory<V>
951 for TimingIteratorFactory<BaseFactory> 990 for TimingIteratorFactory<BaseFactory>
952 where BaseFactory : AlgIteratorFactory<V> { 991 where BaseFactory : AlgIteratorFactory<V> {
953 type State = BaseFactory::State; 992 type State = BaseFactory::State;
954 type Iter<F, E> = TimingIterator<BaseFactory::Iter<F, E>> 993 type Iter = TimingIterator<BaseFactory::Iter>;
955 where F : FnMut(&Self::State) -> Step<V, E>,
956 E : Error;
957 type Output = Timed<BaseFactory::Output>; 994 type Output = Timed<BaseFactory::Output>;
958 995
959 fn prepare<F, E>(self, step_fn : F) -> Self::Iter<F, E> 996 fn prepare(self) -> Self::Iter {
960 where F : FnMut(&Self::State) -> Step<V, E>,
961 E : Error {
962 TimingIterator { 997 TimingIterator {
963 base_iterator : self.0.prepare(step_fn), 998 base_iterator : self.0.prepare(),
964 start_time : ProcessTime::now() 999 start_time : ProcessTime::now()
965 } 1000 }
966 } 1001 }
967 1002
968 #[inline] 1003 #[inline]
974 impl<BaseIterator> AlgIterator 1009 impl<BaseIterator> AlgIterator
975 for TimingIterator<BaseIterator> 1010 for TimingIterator<BaseIterator>
976 where BaseIterator : AlgIterator { 1011 where BaseIterator : AlgIterator {
977 type State = BaseIterator::State; 1012 type State = BaseIterator::State;
978 type Output = Timed<BaseIterator::Output>; 1013 type Output = Timed<BaseIterator::Output>;
979 type Err = BaseIterator::Err; 1014 type Input = BaseIterator::Input;
980 1015
981 #[inline] 1016 #[inline]
982 fn step(&mut self) -> Step<Self::Output, Self::Err> { 1017 fn prestep(&mut self) -> Option<Self::State> {
983 match self.base_iterator.step() { 1018 self.base_iterator.prestep()
984 Step::Result(data) => { 1019 }
1020
1021 #[inline]
1022 fn poststep<E>(&mut self, res : Step<Self::Input, Self::State, E>) -> Step<Self::Output, Self::State, E> where E : Error {
1023 match self.base_iterator.poststep(res) {
1024 Step::Result(data, state) => {
985 Step::Result(Timed{ 1025 Step::Result(Timed{
986 cpu_time : self.start_time.elapsed(), 1026 cpu_time : self.start_time.elapsed(),
1027 iter : self.iteration(),
987 data 1028 data
988 }) 1029 }, state)
989 }, 1030 },
990 Step::Quiet => Step::Quiet, 1031 Step::Quiet => Step::Quiet,
991 Step::Terminated => Step::Terminated, 1032 Step::Terminated => Step::Terminated,
992 Step::Failure(e) => Step::Failure(e), 1033 Step::Failure(e) => Step::Failure(e),
993 } 1034 }
999 } 1040 }
1000 1041
1001 #[inline] 1042 #[inline]
1002 fn state(&self) -> Self::State { 1043 fn state(&self) -> Self::State {
1003 self.base_iterator.state() 1044 self.base_iterator.state()
1045 }
1046 }
1047
1048 //
1049 // New for-loop interface
1050 //
1051
1052 pub struct AlgIteratorIterator<I : AlgIterator> {
1053 algi : Rc<RefCell<I>>,
1054 }
1055
1056 pub struct AlgIteratorIteration<I : AlgIterator> {
1057 state : I::State,
1058 algi : Rc<RefCell<I>>,
1059 }
1060
1061 impl<I : AlgIterator> std::iter::Iterator for AlgIteratorIterator<I> {
1062 type Item = AlgIteratorIteration<I>;
1063
1064 fn next(&mut self) -> Option<Self::Item> {
1065 let algi = self.algi.clone();
1066 RefCell::borrow_mut(&self.algi).prestep().map(|state| AlgIteratorIteration {
1067 state,
1068 algi,
1069 })
1070 }
1071 }
1072
1073 /// Types of errors that may occur
1074 #[derive(Debug,PartialEq,Eq)]
1075 pub enum IterationError {
1076 /// [`AlgIteratorIteration::if_verbose_check`] is not called in iteration order.
1077 ReportingOrderingError
1078 }
1079
1080 impl<I : AlgIterator> AlgIteratorIteration<I> {
1081 /// Call `call_objective` if this is a verbose iteration.
1082 ///
1083 /// Verbosity depends on the [`AlgIterator`] that produced this state.
1084 ///
1085 /// The closure `calc_objective` should return an arbitrary value of type `V`, to be inserted
1086 /// into the log, or whatever is deemed by the [`AlgIterator`]. For usage instructions see the
1087 /// [module documentation][self].
1088 ///
1089 /// This function may panic if result reporting is not ordered correctly (an unlikely mistake
1090 /// if using this facility correctly). For a version that propagates errors, see
1091 /// [`Self::if_verbose_check`].
1092 pub fn if_verbose(self, calc_objective : impl FnOnce() -> I::Input) {
1093 self.if_verbose_check(calc_objective).unwrap()
1094 }
1095
1096 /// Version of [`Self::if_verbose`] that propagates errors instead of panicking.
1097 pub fn if_verbose_check(self, calc_objective : impl FnOnce() -> I::Input)
1098 -> Result<(), IterationError> {
1099 let mut algi = match RefCell::try_borrow_mut(&self.algi) {
1100 Err(_) => return Err(IterationError::ReportingOrderingError),
1101 Ok(algi) => algi
1102 };
1103 if self.state.iteration() != algi.iteration() {
1104 Err(IterationError::ReportingOrderingError)
1105 } else {
1106 let res : Step<I::Input, I::State, std::convert::Infallible>
1107 = self.state.if_verbose(calc_objective);
1108 algi.poststep(res);
1109 Ok(())
1110 }
1111 }
1112
1113 /// Returns the current iteration count.
1114 pub fn iteration(&self) -> usize {
1115 self.state.iteration()
1116 }
1117
1118 /// Indicates whether the iterator is quiet
1119 pub fn is_quiet(&self) -> bool {
1120 self.state.is_quiet()
1004 } 1121 }
1005 } 1122 }
1006 1123
1007 // 1124 //
1008 // Tests 1125 // Tests
1048 .skip(2) 1165 .skip(2)
1049 .step_by(3) 1166 .step_by(3)
1050 .collect::<Vec<int>>()) 1167 .collect::<Vec<int>>())
1051 } 1168 }
1052 } 1169 }
1053 } 1170
1171 #[test]
1172 fn iteration_for_loop() {
1173 let options = AlgIteratorOptions{
1174 max_iter : 10,
1175 verbose_iter : Verbose::Every(3),
1176 .. Default::default()
1177 };
1178
1179 {
1180 let mut start = 1 as int;
1181 for state in options.iter() {
1182 start = start * 2;
1183 state.if_verbose(|| start)
1184 }
1185 assert_eq!(start, (2 as int).pow(10));
1186 }
1187
1188 {
1189 let mut start = 1 as int;
1190 let mut log = Logger::new();
1191 let factory = options.instantiate()
1192 .with_iteration_number()
1193 .into_log(&mut log);
1194 for state in factory.iter() {
1195 start = start * 2;
1196 state.if_verbose(|| start)
1197 }
1198 assert_eq!(start, (2 as int).pow(10));
1199 assert_eq!(log.data()
1200 .iter()
1201 .map(|LogItem{ data : v, iter : _ }| v.clone())
1202 .collect::<Vec<int>>(),
1203 (1..10).map(|i| (2 as int).pow(i))
1204 .skip(2)
1205 .step_by(3)
1206 .collect::<Vec<int>>())
1207 }
1208 }
1209
1210 }

mercurial