1use 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 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}