pcp/term/
addition.rs

1// Copyright 2015 Pierre Talbot (IRCAM)
2
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6
7//     http://www.apache.org/licenses/LICENSE-2.0
8
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use kernel::*;
16use model::*;
17use propagation::events::*;
18use term::ops::*;
19use gcollections::kind::*;
20use std::ops::*;
21use std::fmt::{Debug, Formatter, Result};
22use concept::*;
23
24pub struct Addition<VStore> where
25 VStore: VStoreConcept,
26 VStore::Item: Collection
27{
28  x: Var<VStore>,
29  v: <VStore::Item as Collection>::Item
30}
31
32impl<VStore, Domain, Bound> Addition<VStore> where
33  VStore: VStoreConcept<Item=Domain>,
34  Domain: Collection<Item=Bound>
35{
36  pub fn new(x: Var<VStore>, v: Bound) -> Self {
37    Addition {
38      x: x,
39      v: v
40    }
41  }
42}
43
44impl<VStore, Domain, Bound> Debug for Addition<VStore> where
45  VStore: VStoreConcept<Item=Domain>,
46  Domain: Collection<Item=Bound>,
47  Bound: Debug
48{
49  fn fmt(&self, fmt: &mut Formatter) -> Result {
50    fmt.debug_struct("Addition")
51      .field("x", &self.x)
52      .field("v", &self.v)
53      .finish()
54  }
55}
56
57impl<VStore, Domain, Bound> Clone for Addition<VStore> where
58  VStore: VStoreConcept<Item=Domain>,
59  Domain: Collection<Item=Bound>,
60  Bound: Clone
61{
62  fn clone(&self) -> Self {
63    Addition::new(self.x.bclone(), self.v.clone())
64  }
65}
66
67impl<VStore, Domain, Bound> DisplayStateful<Model> for Addition<VStore> where
68 VStore: VStoreConcept<Item=Domain>,
69 Domain: Collection<Item=Bound>,
70 Bound: Debug
71{
72  fn display(&self, model: &Model) {
73    self.x.display(model);
74    print!(" + {:?}", self.v);
75  }
76}
77
78impl<VStore, Domain, Bound> StoreMonotonicUpdate<VStore> for Addition<VStore> where
79 VStore: VStoreConcept<Item=Domain>,
80 Domain: Collection<Item=Bound> + Sub<Bound, Output=Domain>,
81 Bound: Clone
82{
83  fn update(&mut self, store: &mut VStore, value: Domain) -> bool {
84    self.x.update(store, value - self.v.clone())
85  }
86}
87
88impl<VStore, Domain, Bound> StoreRead<VStore> for Addition<VStore> where
89 VStore: VStoreConcept<Item=Domain>,
90 Domain: Collection<Item=Bound> +  Add<Bound, Output=Domain>,
91 Bound: Clone
92{
93  fn read(&self, store: &VStore) -> VStore::Item {
94    self.x.read(store) + self.v.clone()
95  }
96}
97
98impl<VStore> ViewDependencies<FDEvent> for Addition<VStore> where
99 VStore: VStoreConcept,
100 VStore::Item: Collection
101{
102  fn dependencies(&self, event: FDEvent) -> Vec<(usize, FDEvent)> {
103    self.x.dependencies(event)
104  }
105}
106
107#[cfg(test)]
108mod test {
109  use super::*;
110  use gcollections::ops::*;
111  use trilean::SKleene;
112  use trilean::SKleene::*;
113  use variable::VStoreFD;
114  use propagation::events::FDEvent;
115  use propagation::events::FDEvent::*;
116  use propagators::test::*;
117  use propagators::cmp::XLessY;
118  use interval::interval::*;
119
120  type Domain = Interval<i32>;
121  type VStore = VStoreFD;
122
123  #[test]
124  fn x_less_y_plus_c() {
125    let dom0_10 = (0,10).to_interval();
126    let dom10_20 = (10,20).to_interval();
127    let dom5_15 = (5,15).to_interval();
128    let dom1_1 = (1,1).to_interval();
129
130    // Same test as `x < y` but we add `c` to `y`.
131    x_less_y_plus_c_test_one(1, dom0_10, dom5_15, -5, Unknown, Unknown, vec![(0, Bound), (1, Bound)], true);
132    x_less_y_plus_c_test_one(2, dom0_10, dom0_10, 10, Unknown, Unknown, vec![], true);
133    x_less_y_plus_c_test_one(3, dom5_15, dom5_15, 5, Unknown, Unknown, vec![], true);
134    x_less_y_plus_c_test_one(4, dom5_15, dom10_20, -10, Unknown, Unknown, vec![(0, Bound), (1, Bound)], true);
135    x_less_y_plus_c_test_one(5, dom0_10, dom0_10, 11, True, True, vec![], true);
136    x_less_y_plus_c_test_one(6, dom0_10, dom0_10, -11, False, False, vec![], false);
137    x_less_y_plus_c_test_one(7, dom1_1, dom5_15, -5, Unknown, True, vec![(1, Bound)], true);
138  }
139
140  fn x_less_y_plus_c_test_one(id: u32, x: Domain, y: Domain, c: i32,
141    before: SKleene, after: SKleene, expected: Vec<(usize, FDEvent)>, update_success: bool)
142  {
143    let mut store = VStore::empty();
144    let x = Box::new(store.alloc(x)) as Var<VStore>;
145    let y = Box::new(store.alloc(y)) as Var<VStore>;
146    let x_less_y_plus_c = XLessY::new(x, Box::new(Addition::new(y, c)));
147    test_propagation(id, x_less_y_plus_c, &mut store, before, after, expected, update_success);
148  }
149}