dypdl/
table_data.rs

1use crate::table;
2use crate::util::ModelErr;
3use crate::variable_type::Element;
4use approx::{AbsDiffEq, RelativeEq};
5use rustc_hash::{FxHashMap, FxHashSet};
6use std::collections::hash_map::Entry;
7use std::marker::PhantomData;
8
9macro_rules! define_table_handle {
10    ($x:ident) => {
11        /// A struct wrapping the id of a table.
12        #[derive(Debug, Clone, Copy, PartialEq, Eq)]
13        pub struct $x<T>(usize, PhantomData<T>);
14
15        impl<T> $x<T> {
16            /// Returns the id
17            pub fn id(&self) -> usize {
18                self.0
19            }
20        }
21    };
22}
23
24define_table_handle!(Table1DHandle);
25define_table_handle!(Table2DHandle);
26define_table_handle!(Table3DHandle);
27define_table_handle!(TableHandle);
28
29/// Trait for adding and updating tables of constants.
30///
31/// # Examples
32///
33/// ```
34/// use dypdl::prelude::*;
35/// use rustc_hash::FxHashMap;
36///
37/// let mut model = Model::default();
38///
39/// assert!(model.add_table_1d("table_1d", vec![1, 2]).is_ok());
40///
41/// assert!(model.add_table_2d("table_2d", vec![vec![1, 2], vec![3, 4]]).is_ok());
42///
43/// assert!(
44///     model.add_table_3d(
45///         "table_3d",
46///         vec![vec![vec![1, 2], vec![3, 4]], vec![vec![5, 6], vec![7, 8]]]
47///     ).is_ok()
48/// );
49///
50/// let map = FxHashMap::from_iter(vec![(vec![0, 0, 0, 0], 1), (vec![1, 1, 1, 1], 2)]);
51/// assert!(
52///     model.add_table("table", map, 0).is_ok()
53/// );
54/// ```
55pub trait TableInterface<T> {
56    /// Adds and returns a 1D table.
57    ///
58    /// # Errors
59    ///
60    /// If the name is already used.
61    fn add_table_1d<U>(&mut self, name: U, v: Vec<T>) -> Result<Table1DHandle<T>, ModelErr>
62    where
63        String: From<U>;
64
65    // Disabled since it conflicts with the simplification of an expression.
66    // /// Set an item in a 1D table.
67    // ///
68    // /// # Errors
69    // ///
70    // /// If the table is not in the model.
71    // fn set_table_1d(&mut self, t: Table1DHandle<T>, x: Element, v: T) -> Result<(), ModelErr>;
72
73    // Disabled since it conflicts with the simplification of an expression.
74    // /// Update a 1D table.
75    // ///
76    // /// # Errors
77    // ///
78    // /// If the table is not in the model.
79    // fn update_table_1d(&mut self, t: Table1DHandle<T>, v: Vec<T>) -> Result<(), ModelErr>;
80
81    /// Adds and returns a 2D table.
82    ///
83    /// # Errors
84    ///
85    /// If the name is already used.
86    fn add_table_2d<U>(&mut self, name: U, v: Vec<Vec<T>>) -> Result<Table2DHandle<T>, ModelErr>
87    where
88        String: From<U>;
89
90    // Disabled since it conflicts with the simplification of an expression.
91    // /// Set an item in a 2D table.
92    // ///
93    // /// # Errors
94    // ///
95    // /// If the table is not in the model.
96    // fn set_table_2d(
97    //     &mut self,
98    //     t: Table2DHandle<T>,
99    //     x: Element,
100    //     y: Element,
101    //     v: T,
102    // ) -> Result<(), ModelErr>;
103
104    // Disabled since it conflicts with the simplification of an expression.
105    // /// Update a 2D table.
106    // ///
107    // /// # Errors
108    // ///
109    // /// If the table is not in the model.
110    // fn update_table_2d(&mut self, t: Table2DHandle<T>, v: Vec<Vec<T>>) -> Result<(), ModelErr>;
111
112    /// Adds and returns a 3D table.
113    ///
114    /// # Errors
115    ///
116    /// If the name is already used.
117    fn add_table_3d<U>(
118        &mut self,
119        name: U,
120        v: Vec<Vec<Vec<T>>>,
121    ) -> Result<Table3DHandle<T>, ModelErr>
122    where
123        String: From<U>;
124
125    // Disabled since it conflicts with the simplification of an expression.
126    // /// Set an item in a 3D table.
127    // ///
128    // /// # Errors
129    // ///
130    // /// If the table is not in the model.
131    // fn set_table_3d(
132    //     &mut self,
133    //     t: Table3DHandle<T>,
134    //     x: Element,
135    //     y: Element,
136    //     z: Element,
137    //     v: T,
138    // ) -> Result<(), ModelErr>;
139
140    // Disabled since it conflicts with the simplification of an expression.
141    // /// Update a 3D table.
142    // ///
143    // /// # Errors
144    // ///
145    // /// If the table is not in the model.
146    // fn update_table_3d(&mut self, t: Table3DHandle<T>, v: Vec<Vec<Vec<T>>>)
147    //     -> Result<(), ModelErr>;
148
149    /// Adds and returns a 3D table.
150    ///
151    /// # Errors
152    ///
153    /// If the name is already used.
154    fn add_table<U>(
155        &mut self,
156        name: U,
157        map: FxHashMap<Vec<Element>, T>,
158        default: T,
159    ) -> Result<TableHandle<T>, ModelErr>
160    where
161        String: From<U>;
162
163    // Disabled since it conflicts with the simplification of an expression.
164    // /// Set an item in a table.
165    // ///
166    // /// # Errors
167    // ///
168    // /// If the table is not in the model.
169    // fn set_table(&mut self, t: TableHandle<T>, key: Vec<Element>, v: T) -> Result<(), ModelErr>;
170
171    // Disabled since it conflicts with the simplification of an expression.
172    // /// Set the default value of a table.
173    // ///
174    // /// # Errors
175    // ///
176    // /// If the table is not in the model.
177    // fn set_default(&mut self, t: TableHandle<T>, default: T) -> Result<(), ModelErr>;
178
179    // Disabled since it conflicts with the simplification of an expression.
180    // /// Update a table.
181    // ///
182    // /// # Errors
183    // ///
184    // /// If the table is not in the model.
185    // fn update_table(
186    //     &mut self,
187    //     t: TableHandle<T>,
188    //     map: FxHashMap<Vec<Element>, T>,
189    //     default: T,
190    // ) -> Result<(), ModelErr>;
191}
192
193/// Tables of constants havint a particular type.
194#[derive(Debug, PartialEq, Clone, Default)]
195pub struct TableData<T> {
196    /// Map from a name to a constant.
197    pub name_to_constant: FxHashMap<String, T>,
198    /// 1-dimensional tables.
199    pub tables_1d: Vec<table::Table1D<T>>,
200    /// Map from a name to a 1-dimensional table.
201    pub name_to_table_1d: FxHashMap<String, usize>,
202    /// 2-dimensional tables.
203    pub tables_2d: Vec<table::Table2D<T>>,
204    /// Map from a name to a 2-dimensional table.
205    pub name_to_table_2d: FxHashMap<String, usize>,
206    /// 3-dimensional tables.
207    pub tables_3d: Vec<table::Table3D<T>>,
208    /// Map from a name to a 3-dimensional table.
209    pub name_to_table_3d: FxHashMap<String, usize>,
210    /// Multi-dimensional tables implemented by a map.
211    pub tables: Vec<table::Table<T>>,
212    /// Map from a name to a multi-dimensional table.
213    pub name_to_table: FxHashMap<String, usize>,
214}
215
216impl<T> TableInterface<T> for TableData<T> {
217    fn add_table_1d<U>(&mut self, name: U, v: Vec<T>) -> Result<Table1DHandle<T>, ModelErr>
218    where
219        String: From<U>,
220    {
221        let name = String::from(name);
222        if v.is_empty() {
223            return Err(ModelErr::new(format!("1D table `{name}` is empty")));
224        }
225        match self.name_to_table_1d.entry(name) {
226            Entry::Vacant(e) => {
227                let id = self.tables_1d.len();
228                self.tables_1d.push(table::Table1D::new(v));
229                e.insert(id);
230                Ok(Table1DHandle(id, PhantomData))
231            }
232            Entry::Occupied(e) => Err(ModelErr::new(format!(
233                "1D table `{key}` already exists",
234                key = e.key()
235            ))),
236        }
237    }
238
239    // fn set_table_1d(&mut self, t: Table1DHandle<T>, x: Element, v: T) -> Result<(), ModelErr> {
240    //     self.check_table_1d(t.id())?;
241    //     self.tables_1d[t.id()].set(x, v);
242    //     Ok(())
243    // }
244
245    // fn update_table_1d(&mut self, t: Table1DHandle<T>, v: Vec<T>) -> Result<(), ModelErr> {
246    //     self.check_table_1d(t.id())?;
247    //     if v.is_empty() {
248    //         return Err(ModelErr::new(format!(
249    //             "1D table with id `{id}` is updated to be empty",
250    //             id = t.id()
251    //         )));
252    //     }
253    //     self.tables_1d[t.id()].update(v);
254    //     Ok(())
255    // }
256
257    fn add_table_2d<U>(&mut self, name: U, v: Vec<Vec<T>>) -> Result<Table2DHandle<T>, ModelErr>
258    where
259        String: From<U>,
260    {
261        let name = String::from(name);
262        if v.is_empty() || v[0].is_empty() {
263            return Err(ModelErr::new(format!("2D table `{name}` is empty")));
264        }
265        match self.name_to_table_2d.entry(name) {
266            Entry::Vacant(e) => {
267                let id = self.tables_2d.len();
268                self.tables_2d.push(table::Table2D::new(v));
269                e.insert(id);
270                Ok(Table2DHandle(id, PhantomData))
271            }
272            Entry::Occupied(e) => Err(ModelErr::new(format!(
273                "2D table `{key}` already exists",
274                key = e.key()
275            ))),
276        }
277    }
278
279    // fn set_table_2d(
280    //     &mut self,
281    //     t: Table2DHandle<T>,
282    //     x: Element,
283    //     y: Element,
284    //     v: T,
285    // ) -> Result<(), ModelErr> {
286    //     self.check_table_2d(t.id())?;
287    //     self.tables_2d[t.id()].set(x, y, v);
288    //     Ok(())
289    // }
290
291    // fn update_table_2d(&mut self, t: Table2DHandle<T>, v: Vec<Vec<T>>) -> Result<(), ModelErr> {
292    //     self.check_table_2d(t.id())?;
293    //     if v.is_empty() || v[0].is_empty() {
294    //         return Err(ModelErr::new(format!(
295    //             "2D table with id `{id}` is updated to be empty",
296    //             id = t.id()
297    //         )));
298    //     }
299    //     self.tables_2d[t.id()].update(v);
300    //     Ok(())
301    // }
302
303    fn add_table_3d<U>(
304        &mut self,
305        name: U,
306        v: Vec<Vec<Vec<T>>>,
307    ) -> Result<Table3DHandle<T>, ModelErr>
308    where
309        String: From<U>,
310    {
311        let name = String::from(name);
312        if v.is_empty() || v[0].is_empty() || v[0][0].is_empty() {
313            return Err(ModelErr::new(format!("3D table {name} is empy")));
314        }
315        match self.name_to_table_3d.entry(name) {
316            Entry::Vacant(e) => {
317                let id = self.tables_3d.len();
318                self.tables_3d.push(table::Table3D::new(v));
319                e.insert(id);
320                Ok(Table3DHandle(id, PhantomData))
321            }
322            Entry::Occupied(e) => Err(ModelErr::new(format!(
323                "3D table `{key}` already exists",
324                key = e.key()
325            ))),
326        }
327    }
328
329    // fn set_table_3d(
330    //     &mut self,
331    //     t: Table3DHandle<T>,
332    //     x: Element,
333    //     y: Element,
334    //     z: Element,
335    //     v: T,
336    // ) -> Result<(), ModelErr> {
337    //     self.check_table_3d(t.id())?;
338    //     self.tables_3d[t.id()].set(x, y, z, v);
339    //     Ok(())
340    // }
341
342    // fn update_table_3d(
343    //     &mut self,
344    //     t: Table3DHandle<T>,
345    //     v: Vec<Vec<Vec<T>>>,
346    // ) -> Result<(), ModelErr> {
347    //     self.check_table_3d(t.id())?;
348    //     if v.is_empty() || v[0].is_empty() || v[0][0].is_empty() {
349    //         return Err(ModelErr::new(format!(
350    //             "3D table with id `{id}` is updated to be empty",
351    //             id = t.id()
352    //         )));
353    //     }
354    //     self.tables_3d[t.id()].update(v);
355    //     Ok(())
356    // }
357
358    fn add_table<U>(
359        &mut self,
360        name: U,
361        map: FxHashMap<Vec<Element>, T>,
362        default: T,
363    ) -> Result<TableHandle<T>, ModelErr>
364    where
365        String: From<U>,
366    {
367        let name = String::from(name);
368        match self.name_to_table.entry(name) {
369            Entry::Vacant(e) => {
370                let id = self.tables.len();
371                self.tables.push(table::Table::new(map, default));
372                e.insert(id);
373                Ok(TableHandle(id, PhantomData))
374            }
375            Entry::Occupied(e) => Err(ModelErr::new(format!(
376                "table `{key}` already exists",
377                key = e.key()
378            ))),
379        }
380    }
381
382    // fn set_table(&mut self, t: TableHandle<T>, key: Vec<Element>, v: T) -> Result<(), ModelErr> {
383    //     self.check_table(t.id())?;
384    //     self.tables[t.id()].set(key, v);
385    //     Ok(())
386    // }
387
388    // fn set_default(&mut self, t: TableHandle<T>, default: T) -> Result<(), ModelErr> {
389    //     self.check_table(t.id())?;
390    //     self.tables[t.id()].set_default(default);
391    //     Ok(())
392    // }
393
394    // fn update_table(
395    //     &mut self,
396    //     t: TableHandle<T>,
397    //     map: FxHashMap<Vec<Element>, T>,
398    //     default: T,
399    // ) -> Result<(), ModelErr> {
400    //     self.check_table(t.id())?;
401    //     self.tables[t.id()].update(map, default);
402    //     Ok(())
403    // }
404}
405
406impl<T> TableData<T> {
407    /// Returns the set of names used by constants and tables.
408    pub fn get_name_set(&self) -> FxHashSet<String> {
409        let mut name_set = FxHashSet::default();
410        for name in self.name_to_constant.keys() {
411            name_set.insert(name.clone());
412        }
413        for name in self.name_to_table_1d.keys() {
414            name_set.insert(name.clone());
415        }
416        for name in self.name_to_table_2d.keys() {
417            name_set.insert(name.clone());
418        }
419        for name in self.name_to_table_3d.keys() {
420            name_set.insert(name.clone());
421        }
422        for name in self.name_to_table.keys() {
423            name_set.insert(name.clone());
424        }
425        name_set
426    }
427
428    /// Checks if the id of a 1D table is valid.
429    ///
430    /// # Errors
431    ///
432    /// If the id is not used.
433    pub fn check_table_1d(&self, id: usize) -> Result<(), ModelErr> {
434        let n = self.tables_1d.len();
435        if id >= n {
436            Err(ModelErr::new(format!("table 1d id {id} >= #tables ({n})",)))
437        } else {
438            Ok(())
439        }
440    }
441
442    /// Checks if the id of a 2D table is valid.
443    ///
444    /// # Errors
445    ///
446    /// If the id is not used.
447    pub fn check_table_2d(&self, id: usize) -> Result<(), ModelErr> {
448        let n = self.tables_2d.len();
449        if id >= n {
450            Err(ModelErr::new(format!("table 2d id {id} >= #tables ({n})",)))
451        } else {
452            Ok(())
453        }
454    }
455
456    /// Checks if the id of a 3D table is valid.
457    ///
458    /// # Errors
459    ///
460    /// If the id is not used.
461    pub fn check_table_3d(&self, id: usize) -> Result<(), ModelErr> {
462        let n = self.tables_3d.len();
463        if id >= n {
464            Err(ModelErr::new(format!("table 3d id {id} >= #tables ({n})",)))
465        } else {
466            Ok(())
467        }
468    }
469
470    /// Checks if the id of a table is valid.
471    ///
472    /// # Errors
473    ///
474    /// If the id is not used.
475    pub fn check_table(&self, id: usize) -> Result<(), ModelErr> {
476        let n = self.tables.len();
477        if id >= n {
478            Err(ModelErr::new(format!("table id {id} >= #tables ({n})",)))
479        } else {
480            Ok(())
481        }
482    }
483}
484
485impl<T: AbsDiffEq> AbsDiffEq for TableData<T>
486where
487    T::Epsilon: Copy,
488{
489    type Epsilon = T::Epsilon;
490
491    fn default_epsilon() -> T::Epsilon {
492        T::default_epsilon()
493    }
494
495    fn abs_diff_eq(&self, other: &Self, epsilon: T::Epsilon) -> bool {
496        if self.name_to_constant.len() != other.name_to_constant.len() {
497            return false;
498        }
499        for (key, x) in &self.name_to_constant {
500            match other.name_to_constant.get(key) {
501                Some(y) if x.abs_diff_eq(y, epsilon) => {}
502                _ => return false,
503            }
504        }
505        self.name_to_table_1d == other.name_to_table_1d
506            && self.name_to_table_2d == other.name_to_table_2d
507            && self.name_to_table_3d == other.name_to_table_3d
508            && self.name_to_table == other.name_to_table
509            && self
510                .tables_1d
511                .iter()
512                .zip(other.tables_1d.iter())
513                .all(|(x, y)| x.abs_diff_eq(y, epsilon))
514            && self
515                .tables_2d
516                .iter()
517                .zip(other.tables_2d.iter())
518                .all(|(x, y)| x.abs_diff_eq(y, epsilon))
519            && self
520                .tables_3d
521                .iter()
522                .zip(other.tables_3d.iter())
523                .all(|(x, y)| x.abs_diff_eq(y, epsilon))
524            && self
525                .tables
526                .iter()
527                .zip(other.tables.iter())
528                .all(|(x, y)| x.abs_diff_eq(y, epsilon))
529    }
530}
531
532impl<T: RelativeEq> RelativeEq for TableData<T>
533where
534    T::Epsilon: Copy,
535{
536    fn default_max_relative() -> T::Epsilon {
537        T::default_max_relative()
538    }
539
540    fn relative_eq(&self, other: &Self, epsilon: T::Epsilon, max_relative: T::Epsilon) -> bool {
541        if self.name_to_constant.len() != other.name_to_constant.len() {
542            return false;
543        }
544        for (key, x) in &self.name_to_constant {
545            match other.name_to_constant.get(key) {
546                Some(y) if x.relative_eq(y, epsilon, max_relative) => {}
547                _ => return false,
548            }
549        }
550        self.name_to_table_1d == other.name_to_table_1d
551            && self.name_to_table_2d == other.name_to_table_2d
552            && self.name_to_table_3d == other.name_to_table_3d
553            && self.name_to_table == other.name_to_table
554            && self
555                .tables_1d
556                .iter()
557                .zip(other.tables_1d.iter())
558                .all(|(x, y)| x.relative_eq(y, epsilon, max_relative))
559            && self
560                .tables_2d
561                .iter()
562                .zip(other.tables_2d.iter())
563                .all(|(x, y)| x.relative_eq(y, epsilon, max_relative))
564            && self
565                .tables_3d
566                .iter()
567                .zip(other.tables_3d.iter())
568                .all(|(x, y)| x.relative_eq(y, epsilon, max_relative))
569            && self
570                .tables
571                .iter()
572                .zip(other.tables.iter())
573                .all(|(x, y)| x.relative_eq(y, epsilon, max_relative))
574    }
575}
576
577#[cfg(test)]
578mod tests {
579    use super::*;
580    use approx::{assert_relative_eq, assert_relative_ne};
581    use table::*;
582
583    #[test]
584    fn add_table_1d_ok() {
585        let mut table_data = TableData::default();
586        let t = table_data.add_table_1d(String::from("t1"), vec![0, 1]);
587        assert!(t.is_ok());
588        let t = t.unwrap();
589        assert_eq!(t.id(), 0);
590        assert_eq!(table_data.tables_1d, vec![Table1D::new(vec![0, 1])]);
591        let mut name_to_table = FxHashMap::default();
592        name_to_table.insert(String::from("t1"), 0);
593        assert_eq!(table_data.name_to_table_1d, name_to_table);
594        let t = table_data.add_table_1d(String::from("t2"), vec![0, 2]);
595        assert!(t.is_ok());
596        let t = t.unwrap();
597        assert_eq!(t.id(), 1);
598        assert_eq!(
599            table_data.tables_1d,
600            vec![Table1D::new(vec![0, 1]), Table1D::new(vec![0, 2])]
601        );
602        name_to_table.insert(String::from("t2"), 1);
603        assert_eq!(table_data.name_to_table_1d, name_to_table);
604    }
605
606    #[test]
607    fn add_table_1d_err() {
608        let mut table_data = TableData::default();
609        let t = table_data.add_table_1d(String::from("t1"), vec![0, 1]);
610        assert!(t.is_ok());
611        let t = table_data.add_table_1d(String::from("t1"), vec![0, 1]);
612        assert!(t.is_err());
613        assert_eq!(table_data.tables_1d, vec![Table1D::new(vec![0, 1])]);
614        let mut name_to_table = FxHashMap::default();
615        name_to_table.insert(String::from("t1"), 0);
616        assert_eq!(table_data.name_to_table_1d, name_to_table);
617    }
618
619    #[test]
620    fn add_table_1d_empty_err() {
621        let mut table_data: TableData<Element> = TableData::default();
622        let t = table_data.add_table_1d(String::from("t1"), vec![]);
623        assert!(t.is_err());
624        assert_eq!(table_data.tables_1d, vec![]);
625        let name_to_table = FxHashMap::default();
626        assert_eq!(table_data.name_to_table_1d, name_to_table);
627    }
628
629    // #[test]
630    // fn set_table_1d_ok() {
631    //     let mut table_data = TableData::default();
632    //     let t = table_data.add_table_1d(String::from("t1"), vec![0, 1]);
633    //     assert!(t.is_ok());
634    //     let t = t.unwrap();
635    //     let result = table_data.set_table_1d(t, 0, 1);
636    //     assert!(result.is_ok());
637    //     assert_eq!(table_data.tables_1d, vec![Table1D::new(vec![1, 1])]);
638    // }
639
640    // #[test]
641    // fn set_table_1d_err() {
642    //     let mut table_data = TableData::default();
643    //     let t = table_data.add_table_1d(String::from("t1"), vec![0, 1]);
644    //     assert!(t.is_ok());
645
646    //     let mut table_data1 = TableData::default();
647    //     let t = table_data1.add_table_1d(String::from("t1"), vec![0, 1]);
648    //     assert!(t.is_ok());
649    //     let t = table_data1.add_table_1d(String::from("t2"), vec![0, 1]);
650    //     assert!(t.is_ok());
651    //     let t = t.unwrap();
652    //     let result = table_data.set_table_1d(t, 0, 1);
653    //     assert!(result.is_err());
654    //     assert_eq!(table_data.tables_1d, vec![Table1D::new(vec![0, 1])]);
655    // }
656
657    // #[test]
658    // fn update_table_1d_ok() {
659    //     let mut table_data = TableData::default();
660    //     let t = table_data.add_table_1d(String::from("t1"), vec![0, 1]);
661    //     assert!(t.is_ok());
662    //     let t = t.unwrap();
663    //     let result = table_data.update_table_1d(t, vec![1, 1]);
664    //     assert!(result.is_ok());
665    //     assert_eq!(table_data.tables_1d, vec![Table1D::new(vec![1, 1])]);
666    // }
667
668    // #[test]
669    // fn update_table_1d_err() {
670    //     let mut table_data = TableData::default();
671    //     let t = table_data.add_table_1d(String::from("t1"), vec![0, 1]);
672    //     assert!(t.is_ok());
673
674    //     let mut table_data1 = TableData::default();
675    //     let t = table_data1.add_table_1d(String::from("t1"), vec![0, 1]);
676    //     assert!(t.is_ok());
677    //     let t = table_data1.add_table_1d(String::from("t2"), vec![0, 1]);
678    //     assert!(t.is_ok());
679    //     let t = t.unwrap();
680    //     let result = table_data.update_table_1d(t, vec![1, 1]);
681    //     assert!(result.is_err());
682    //     assert_eq!(table_data.tables_1d, vec![Table1D::new(vec![0, 1])]);
683    // }
684
685    // #[test]
686    // fn update_table_1d_empty_err() {
687    //     let mut table_data = TableData::default();
688    //     let t = table_data.add_table_1d(String::from("t1"), vec![0, 1]);
689    //     assert!(t.is_ok());
690    //     let t = t.unwrap();
691    //     let result = table_data.update_table_1d(t, vec![]);
692    //     assert!(result.is_err());
693    //     assert_eq!(table_data.tables_1d, vec![Table1D::new(vec![0, 1])]);
694    // }
695
696    #[test]
697    fn add_table_2d_ok() {
698        let mut table_data = TableData::default();
699        let t = table_data.add_table_2d(String::from("t1"), vec![vec![0, 1]]);
700        assert!(t.is_ok());
701        let t = t.unwrap();
702        assert_eq!(t.id(), 0);
703        assert_eq!(table_data.tables_2d, vec![Table2D::new(vec![vec![0, 1]])]);
704        let mut name_to_table = FxHashMap::default();
705        name_to_table.insert(String::from("t1"), 0);
706        assert_eq!(table_data.name_to_table_2d, name_to_table);
707        let t = table_data.add_table_2d(String::from("t2"), vec![vec![0, 2]]);
708        assert!(t.is_ok());
709        let t = t.unwrap();
710        assert_eq!(t.id(), 1);
711        assert_eq!(
712            table_data.tables_2d,
713            vec![
714                Table2D::new(vec![vec![0, 1]]),
715                Table2D::new(vec![vec![0, 2]])
716            ]
717        );
718        name_to_table.insert(String::from("t2"), 1);
719        assert_eq!(table_data.name_to_table_2d, name_to_table);
720    }
721
722    #[test]
723    fn add_table_2d_err() {
724        let mut table_data = TableData::default();
725        let t = table_data.add_table_2d(String::from("t1"), vec![vec![0, 1]]);
726        assert!(t.is_ok());
727        let t = table_data.add_table_2d(String::from("t1"), vec![vec![0, 1]]);
728        assert!(t.is_err());
729        assert_eq!(table_data.tables_2d, vec![Table2D::new(vec![vec![0, 1]])]);
730        let mut name_to_table = FxHashMap::default();
731        name_to_table.insert(String::from("t1"), 0);
732        assert_eq!(table_data.name_to_table_2d, name_to_table);
733    }
734
735    #[test]
736    fn add_table_2d_empty_1d_err() {
737        let mut table_data: TableData<Element> = TableData::default();
738        let t = table_data.add_table_2d(String::from("t1"), vec![]);
739        assert!(t.is_err());
740        assert_eq!(table_data.tables_2d, vec![]);
741        let name_to_table = FxHashMap::default();
742        assert_eq!(table_data.name_to_table_2d, name_to_table);
743    }
744
745    #[test]
746    fn add_table_2d_empty_2d_err() {
747        let mut table_data: TableData<Element> = TableData::default();
748        let t = table_data.add_table_2d(String::from("t1"), vec![vec![]]);
749        assert!(t.is_err());
750        assert_eq!(table_data.tables_2d, vec![]);
751        let name_to_table = FxHashMap::default();
752        assert_eq!(table_data.name_to_table_2d, name_to_table);
753    }
754
755    // #[test]
756    // fn set_table_2d_ok() {
757    //     let mut table_data = TableData::default();
758    //     let t = table_data.add_table_2d(String::from("t1"), vec![vec![0, 1]]);
759    //     assert!(t.is_ok());
760    //     let t = t.unwrap();
761    //     let result = table_data.set_table_2d(t, 0, 0, 1);
762    //     assert!(result.is_ok());
763    //     assert_eq!(table_data.tables_2d, vec![Table2D::new(vec![vec![1, 1]])]);
764    // }
765
766    // #[test]
767    // fn set_table_2d_err() {
768    //     let mut table_data = TableData::default();
769    //     let t = table_data.add_table_2d(String::from("t1"), vec![vec![0, 1]]);
770    //     assert!(t.is_ok());
771
772    //     let mut table_data1 = TableData::default();
773    //     let t = table_data1.add_table_2d(String::from("t1"), vec![vec![0, 1]]);
774    //     assert!(t.is_ok());
775    //     let t = table_data1.add_table_2d(String::from("t2"), vec![vec![0, 1]]);
776    //     assert!(t.is_ok());
777    //     let t = t.unwrap();
778    //     let result = table_data.set_table_2d(t, 0, 0, 1);
779    //     assert!(result.is_err());
780    //     assert_eq!(table_data.tables_2d, vec![Table2D::new(vec![vec![0, 1]])]);
781    // }
782
783    // #[test]
784    // fn update_table_2d_ok() {
785    //     let mut table_data = TableData::default();
786    //     let t = table_data.add_table_2d(String::from("t1"), vec![vec![0, 1]]);
787    //     assert!(t.is_ok());
788    //     let t = t.unwrap();
789    //     let result = table_data.update_table_2d(t, vec![vec![1, 1]]);
790    //     assert!(result.is_ok());
791    //     assert_eq!(table_data.tables_2d, vec![Table2D::new(vec![vec![1, 1]])]);
792    // }
793
794    // #[test]
795    // fn update_table_2d_err() {
796    //     let mut table_data = TableData::default();
797    //     let t = table_data.add_table_2d(String::from("t1"), vec![vec![0, 1]]);
798    //     assert!(t.is_ok());
799
800    //     let mut table_data1 = TableData::default();
801    //     let t = table_data1.add_table_2d(String::from("t1"), vec![vec![0, 1]]);
802    //     assert!(t.is_ok());
803    //     let t = table_data1.add_table_2d(String::from("t2"), vec![vec![0, 1]]);
804    //     assert!(t.is_ok());
805    //     let t = t.unwrap();
806    //     let result = table_data.update_table_2d(t, vec![vec![1, 1]]);
807    //     assert!(result.is_err());
808    //     assert_eq!(table_data.tables_2d, vec![Table2D::new(vec![vec![0, 1]])]);
809    // }
810
811    // #[test]
812    // fn update_table_2d_empty_1d_ok() {
813    //     let mut table_data = TableData::default();
814    //     let t = table_data.add_table_2d(String::from("t1"), vec![vec![0, 1]]);
815    //     assert!(t.is_ok());
816    //     let t = t.unwrap();
817    //     let result = table_data.update_table_2d(t, vec![]);
818    //     assert!(result.is_err());
819    //     assert_eq!(table_data.tables_2d, vec![Table2D::new(vec![vec![0, 1]])]);
820    // }
821
822    // #[test]
823    // fn update_table_2d_empty_2d_ok() {
824    //     let mut table_data = TableData::default();
825    //     let t = table_data.add_table_2d(String::from("t1"), vec![vec![0, 1]]);
826    //     assert!(t.is_ok());
827    //     let t = t.unwrap();
828    //     let result = table_data.update_table_2d(t, vec![vec![]]);
829    //     assert!(result.is_err());
830    //     assert_eq!(table_data.tables_2d, vec![Table2D::new(vec![vec![0, 1]])]);
831    // }
832
833    #[test]
834    fn add_table_3d_ok() {
835        let mut table_data = TableData::default();
836        let t = table_data.add_table_3d(String::from("t1"), vec![vec![vec![0, 1]]]);
837        assert!(t.is_ok());
838        let t = t.unwrap();
839        assert_eq!(t.id(), 0);
840        assert_eq!(
841            table_data.tables_3d,
842            vec![Table3D::new(vec![vec![vec![0, 1]]])]
843        );
844        let mut name_to_table = FxHashMap::default();
845        name_to_table.insert(String::from("t1"), 0);
846        assert_eq!(table_data.name_to_table_3d, name_to_table);
847        let t = table_data.add_table_3d(String::from("t2"), vec![vec![vec![0, 2]]]);
848        assert!(t.is_ok());
849        let t = t.unwrap();
850        assert_eq!(t.id(), 1);
851        assert_eq!(
852            table_data.tables_3d,
853            vec![
854                Table3D::new(vec![vec![vec![0, 1]]]),
855                Table3D::new(vec![vec![vec![0, 2]]])
856            ]
857        );
858        name_to_table.insert(String::from("t2"), 1);
859        assert_eq!(table_data.name_to_table_3d, name_to_table);
860    }
861
862    #[test]
863    fn add_table_3d_err() {
864        let mut table_data = TableData::default();
865        let t = table_data.add_table_3d(String::from("t1"), vec![vec![vec![0, 1]]]);
866        assert!(t.is_ok());
867        let t = table_data.add_table_3d(String::from("t1"), vec![vec![vec![0, 1]]]);
868        assert!(t.is_err());
869        assert_eq!(
870            table_data.tables_3d,
871            vec![Table3D::new(vec![vec![vec![0, 1]]])]
872        );
873        let mut name_to_table = FxHashMap::default();
874        name_to_table.insert(String::from("t1"), 0);
875        assert_eq!(table_data.name_to_table_3d, name_to_table);
876    }
877
878    #[test]
879    fn add_table_3d_empty_1d_err() {
880        let mut table_data: TableData<Element> = TableData::default();
881        let t = table_data.add_table_3d(String::from("t1"), vec![]);
882        assert!(t.is_err());
883        assert_eq!(table_data.tables_3d, vec![]);
884        let name_to_table = FxHashMap::default();
885        assert_eq!(table_data.name_to_table_3d, name_to_table);
886    }
887
888    #[test]
889    fn add_table_3d_empty_2d_err() {
890        let mut table_data: TableData<Element> = TableData::default();
891        let t = table_data.add_table_3d(String::from("t1"), vec![vec![]]);
892        assert!(t.is_err());
893        assert_eq!(table_data.tables_3d, vec![]);
894        let name_to_table = FxHashMap::default();
895        assert_eq!(table_data.name_to_table_3d, name_to_table);
896    }
897
898    #[test]
899    fn add_table_3d_empty_3d_err() {
900        let mut table_data: TableData<Element> = TableData::default();
901        let t = table_data.add_table_3d(String::from("t1"), vec![vec![vec![]]]);
902        assert!(t.is_err());
903        assert_eq!(table_data.tables_3d, vec![]);
904        let name_to_table = FxHashMap::default();
905        assert_eq!(table_data.name_to_table_3d, name_to_table);
906    }
907
908    // #[test]
909    // fn set_table_3d_ok() {
910    //     let mut table_data = TableData::default();
911    //     let t = table_data.add_table_3d(String::from("t1"), vec![vec![vec![0, 1]]]);
912    //     assert!(t.is_ok());
913    //     let t = t.unwrap();
914    //     let result = table_data.set_table_3d(t, 0, 0, 0, 1);
915    //     assert!(result.is_ok());
916    //     assert_eq!(
917    //         table_data.tables_3d,
918    //         vec![Table3D::new(vec![vec![vec![1, 1]]])]
919    //     );
920    // }
921
922    // #[test]
923    // fn set_table_3d_err() {
924    //     let mut table_data = TableData::default();
925    //     let t = table_data.add_table_3d(String::from("t1"), vec![vec![vec![0, 1]]]);
926    //     assert!(t.is_ok());
927
928    //     let mut table_data1 = TableData::default();
929    //     let t = table_data1.add_table_3d(String::from("t1"), vec![vec![vec![0, 1]]]);
930    //     assert!(t.is_ok());
931    //     let t = table_data1.add_table_3d(String::from("t2"), vec![vec![vec![0, 1]]]);
932    //     assert!(t.is_ok());
933    //     let t = t.unwrap();
934    //     let result = table_data.set_table_3d(t, 0, 0, 0, 1);
935    //     assert!(result.is_err());
936    //     assert_eq!(
937    //         table_data.tables_3d,
938    //         vec![Table3D::new(vec![vec![vec![0, 1]]])]
939    //     );
940    // }
941
942    // #[test]
943    // fn update_table_3d_ok() {
944    //     let mut table_data = TableData::default();
945    //     let t = table_data.add_table_3d(String::from("t1"), vec![vec![vec![0, 1]]]);
946    //     assert!(t.is_ok());
947    //     let t = t.unwrap();
948    //     let result = table_data.update_table_3d(t, vec![vec![vec![1, 1]]]);
949    //     assert!(result.is_ok());
950    //     assert_eq!(
951    //         table_data.tables_3d,
952    //         vec![Table3D::new(vec![vec![vec![1, 1]]])]
953    //     );
954    // }
955
956    // #[test]
957    // fn update_table_3d_err() {
958    //     let mut table_data = TableData::default();
959    //     let t = table_data.add_table_3d(String::from("t1"), vec![vec![vec![0, 1]]]);
960    //     assert!(t.is_ok());
961
962    //     let mut table_data1 = TableData::default();
963    //     let t = table_data1.add_table_3d(String::from("t1"), vec![vec![vec![0, 1]]]);
964    //     assert!(t.is_ok());
965    //     let t = table_data1.add_table_3d(String::from("t2"), vec![vec![vec![0, 1]]]);
966    //     assert!(t.is_ok());
967    //     let t = t.unwrap();
968    //     let result = table_data.update_table_3d(t, vec![vec![vec![1, 1]]]);
969    //     assert!(result.is_err());
970    //     assert_eq!(
971    //         table_data.tables_3d,
972    //         vec![Table3D::new(vec![vec![vec![0, 1]]])]
973    //     );
974    // }
975
976    // #[test]
977    // fn update_table_3d_empty_1d_err() {
978    //     let mut table_data = TableData::default();
979    //     let t = table_data.add_table_3d(String::from("t1"), vec![vec![vec![0, 1]]]);
980    //     assert!(t.is_ok());
981    //     let t = table_data.add_table_3d(String::from("t2"), vec![]);
982    //     assert!(t.is_err());
983    //     assert_eq!(
984    //         table_data.tables_3d,
985    //         vec![Table3D::new(vec![vec![vec![0, 1]]])]
986    //     );
987    // }
988
989    // #[test]
990    // fn update_table_3d_empty_2d_err() {
991    //     let mut table_data = TableData::default();
992    //     let t = table_data.add_table_3d(String::from("t1"), vec![vec![vec![0, 1]]]);
993    //     assert!(t.is_ok());
994    //     let t = table_data.add_table_3d(String::from("t2"), vec![vec![]]);
995    //     assert!(t.is_err());
996    //     assert_eq!(
997    //         table_data.tables_3d,
998    //         vec![Table3D::new(vec![vec![vec![0, 1]]])]
999    //     );
1000    // }
1001
1002    // #[test]
1003    // fn update_table_3d_empty_3d_err() {
1004    //     let mut table_data = TableData::default();
1005    //     let t = table_data.add_table_3d(String::from("t1"), vec![vec![vec![0, 1]]]);
1006    //     assert!(t.is_ok());
1007    //     let t = table_data.add_table_3d(String::from("t2"), vec![vec![vec![]]]);
1008    //     assert!(t.is_err());
1009    //     assert_eq!(
1010    //         table_data.tables_3d,
1011    //         vec![Table3D::new(vec![vec![vec![0, 1]]])]
1012    //     );
1013    // }
1014
1015    #[test]
1016    fn add_table_ok() {
1017        let mut table_data = TableData::default();
1018        let mut map = FxHashMap::default();
1019        map.insert(vec![0, 0, 0, 1], 1);
1020        let t = table_data.add_table(String::from("t1"), map.clone(), 0);
1021        assert!(t.is_ok());
1022        let t = t.unwrap();
1023        assert_eq!(t.id(), 0);
1024        assert_eq!(table_data.tables, vec![Table::new(map.clone(), 0)]);
1025        let mut name_to_table = FxHashMap::default();
1026        name_to_table.insert(String::from("t1"), 0);
1027        assert_eq!(table_data.name_to_table, name_to_table);
1028        let mut map2 = FxHashMap::default();
1029        map2.insert(vec![0, 0, 0, 1], 2);
1030        let t = table_data.add_table(String::from("t2"), map2.clone(), 1);
1031        assert!(t.is_ok());
1032        let t = t.unwrap();
1033        assert_eq!(t.id(), 1);
1034        assert_eq!(
1035            table_data.tables,
1036            vec![Table::new(map, 0), Table::new(map2, 1)]
1037        );
1038        name_to_table.insert(String::from("t2"), 1);
1039        assert_eq!(table_data.name_to_table, name_to_table);
1040    }
1041
1042    #[test]
1043    fn add_table_err() {
1044        let mut table_data = TableData::default();
1045        let mut map = FxHashMap::default();
1046        map.insert(vec![0, 0, 0, 1], 1);
1047        let t = table_data.add_table(String::from("t1"), map.clone(), 0);
1048        assert!(t.is_ok());
1049        let t = table_data.add_table(String::from("t1"), map.clone(), 1);
1050        assert!(t.is_err());
1051        assert_eq!(table_data.tables, vec![Table::new(map, 0)]);
1052        let mut name_to_table = FxHashMap::default();
1053        name_to_table.insert(String::from("t1"), 0);
1054        assert_eq!(table_data.name_to_table, name_to_table);
1055    }
1056
1057    // #[test]
1058    // fn set_table_ok() {
1059    //     let mut table_data = TableData::default();
1060    //     let mut map = FxHashMap::default();
1061    //     map.insert(vec![0, 0, 0, 1], 1);
1062    //     let t = table_data.add_table(String::from("t1"), map.clone(), 0);
1063    //     assert!(t.is_ok());
1064    //     let t = t.unwrap();
1065    //     let result = table_data.set_table(t, vec![0, 0, 0, 0], 1);
1066    //     assert!(result.is_ok());
1067    //     map.insert(vec![0, 0, 0, 0], 1);
1068    //     assert_eq!(table_data.tables, vec![Table::new(map, 0)]);
1069    // }
1070
1071    // #[test]
1072    // fn set_table_err() {
1073    //     let mut table_data = TableData::default();
1074    //     let mut map = FxHashMap::default();
1075    //     map.insert(vec![0, 0, 0, 1], 1);
1076    //     let t = table_data.add_table(String::from("t1"), map.clone(), 0);
1077    //     assert!(t.is_ok());
1078
1079    //     let mut table_data1 = TableData::default();
1080    //     let t = table_data1.add_table(String::from("t1"), map.clone(), 1);
1081    //     assert!(t.is_ok());
1082    //     let t = table_data1.add_table(String::from("t2"), map.clone(), 2);
1083    //     assert!(t.is_ok());
1084    //     let t = t.unwrap();
1085    //     let result = table_data.set_table(t, vec![0, 0, 0, 0], 1);
1086    //     assert!(result.is_err());
1087    //     assert_eq!(table_data.tables, vec![Table::new(map, 0)]);
1088    // }
1089
1090    // #[test]
1091    // fn set_default_ok() {
1092    //     let mut table_data = TableData::default();
1093    //     let mut map = FxHashMap::default();
1094    //     map.insert(vec![0, 0, 0, 1], 1);
1095    //     let t = table_data.add_table(String::from("t1"), map.clone(), 0);
1096    //     assert!(t.is_ok());
1097    //     let t = t.unwrap();
1098    //     let result = table_data.set_default(t, 1);
1099    //     assert!(result.is_ok());
1100    //     assert_eq!(table_data.tables, vec![Table::new(map, 1)]);
1101    // }
1102
1103    // #[test]
1104    // fn set_default_err() {
1105    //     let mut table_data = TableData::default();
1106    //     let mut map = FxHashMap::default();
1107    //     map.insert(vec![0, 0, 0, 1], 1);
1108    //     let t = table_data.add_table(String::from("t1"), map.clone(), 0);
1109    //     assert!(t.is_ok());
1110
1111    //     let mut table_data1 = TableData::default();
1112    //     let t = table_data1.add_table(String::from("t1"), map.clone(), 0);
1113    //     assert!(t.is_ok());
1114    //     let t = table_data1.add_table(String::from("t2"), map.clone(), 0);
1115    //     assert!(t.is_ok());
1116    //     let t = t.unwrap();
1117    //     let result = table_data.set_default(t, 1);
1118    //     assert!(result.is_err());
1119    //     assert_eq!(table_data.tables, vec![Table::new(map, 0)]);
1120    // }
1121
1122    // #[test]
1123    // fn update_table_ok() {
1124    //     let mut table_data = TableData::default();
1125    //     let mut map = FxHashMap::default();
1126    //     map.insert(vec![0, 0, 0, 1], 1);
1127    //     let t = table_data.add_table(String::from("t1"), map.clone(), 0);
1128    //     assert!(t.is_ok());
1129    //     let t = t.unwrap();
1130    //     let mut map = FxHashMap::default();
1131    //     map.insert(vec![0, 0, 0, 1], 2);
1132    //     let result = table_data.update_table(t, map.clone(), 1);
1133    //     assert!(result.is_ok());
1134    //     assert_eq!(table_data.tables, vec![Table::new(map, 1)]);
1135    // }
1136
1137    // #[test]
1138    // fn update_table_err() {
1139    //     let mut table_data = TableData::default();
1140    //     let mut map = FxHashMap::default();
1141    //     map.insert(vec![0, 0, 0, 1], 1);
1142    //     let t = table_data.add_table(String::from("t1"), map.clone(), 0);
1143    //     assert!(t.is_ok());
1144
1145    //     let mut table_data1 = TableData::default();
1146    //     let t = table_data1.add_table(String::from("t1"), map.clone(), 1);
1147    //     assert!(t.is_ok());
1148    //     let t = table_data1.add_table(String::from("t2"), map.clone(), 2);
1149    //     assert!(t.is_ok());
1150    //     let t = t.unwrap();
1151    //     let mut map2 = FxHashMap::default();
1152    //     map2.insert(vec![0, 0, 0, 1], 2);
1153    //     let result = table_data.update_table(t, map2, 3);
1154    //     assert!(result.is_err());
1155    //     assert_eq!(table_data.tables, vec![Table::new(map, 0)]);
1156    // }
1157
1158    #[test]
1159    fn get_name_set() {
1160        let mut name_to_constant = FxHashMap::default();
1161        name_to_constant.insert(String::from("i0"), 0);
1162
1163        let tables_1d = vec![table::Table1D::new(vec![10, 20, 30])];
1164        let mut name_to_table_1d = FxHashMap::default();
1165        name_to_table_1d.insert(String::from("i1"), 0);
1166
1167        let tables_2d = vec![table::Table2D::new(vec![
1168            vec![10, 20, 30],
1169            vec![10, 10, 10],
1170            vec![10, 10, 10],
1171        ])];
1172        let mut name_to_table_2d = FxHashMap::default();
1173        name_to_table_2d.insert(String::from("i2"), 0);
1174
1175        let tables_3d = vec![table::Table3D::new(vec![
1176            vec![vec![10, 20, 30], vec![0, 0, 0], vec![0, 0, 0]],
1177            vec![vec![0, 0, 0], vec![0, 0, 0], vec![0, 0, 0]],
1178            vec![vec![0, 0, 0], vec![0, 0, 0], vec![0, 0, 0]],
1179        ])];
1180        let mut name_to_table_3d = FxHashMap::default();
1181        name_to_table_3d.insert(String::from("i3"), 0);
1182
1183        let mut map = FxHashMap::default();
1184        let key = vec![0, 1, 0, 0];
1185        map.insert(key, 100);
1186        let key = vec![0, 1, 0, 1];
1187        map.insert(key, 200);
1188        let key = vec![0, 1, 2, 0];
1189        map.insert(key, 300);
1190        let key = vec![0, 1, 2, 1];
1191        map.insert(key, 400);
1192        let tables = vec![table::Table::new(map, 0)];
1193        let mut name_to_table = FxHashMap::default();
1194        name_to_table.insert(String::from("i4"), 0);
1195
1196        let integer_tables = TableData {
1197            name_to_constant,
1198            tables_1d,
1199            name_to_table_1d,
1200            tables_2d,
1201            name_to_table_2d,
1202            tables_3d,
1203            name_to_table_3d,
1204            tables,
1205            name_to_table,
1206        };
1207        let mut expected = FxHashSet::default();
1208        expected.insert(String::from("i0"));
1209        expected.insert(String::from("i1"));
1210        expected.insert(String::from("i2"));
1211        expected.insert(String::from("i3"));
1212        expected.insert(String::from("i4"));
1213        assert_eq!(integer_tables.get_name_set(), expected);
1214    }
1215
1216    #[test]
1217    fn check_table_1d() {
1218        let mut table_data = TableData::default();
1219        let result = table_data.check_table_1d(0);
1220        assert!(result.is_err());
1221        let t = table_data.add_table_1d(String::from("t"), vec![0, 1]);
1222        assert!(t.is_ok());
1223        let result = table_data.check_table_1d(0);
1224        assert!(result.is_ok());
1225        let result = table_data.check_table_1d(1);
1226        assert!(result.is_err());
1227    }
1228
1229    #[test]
1230    fn check_table_2d() {
1231        let mut table_data = TableData::default();
1232        let result = table_data.check_table_2d(0);
1233        assert!(result.is_err());
1234        let t = table_data.add_table_2d(String::from("t"), vec![vec![0, 1]]);
1235        assert!(t.is_ok());
1236        let result = table_data.check_table_2d(0);
1237        assert!(result.is_ok());
1238        let result = table_data.check_table_2d(1);
1239        assert!(result.is_err());
1240    }
1241
1242    #[test]
1243    fn check_table_3d() {
1244        let mut table_data = TableData::default();
1245        let result = table_data.check_table_3d(0);
1246        assert!(result.is_err());
1247        let t = table_data.add_table_3d(String::from("t"), vec![vec![vec![0, 1]]]);
1248        assert!(t.is_ok());
1249        let result = table_data.check_table_3d(0);
1250        assert!(result.is_ok());
1251        let result = table_data.check_table_3d(1);
1252        assert!(result.is_err());
1253    }
1254
1255    #[test]
1256    fn check_table() {
1257        let mut table_data = TableData::default();
1258        let result = table_data.check_table(0);
1259        assert!(result.is_err());
1260        let t = table_data.add_table(String::from("t"), FxHashMap::default(), 0);
1261        assert!(t.is_ok());
1262        let result = table_data.check_table(0);
1263        assert!(result.is_ok());
1264        let result = table_data.check_table(1);
1265        assert!(result.is_err());
1266    }
1267
1268    #[test]
1269    fn relative_eq() {
1270        let mut name_to_table_1d = FxHashMap::default();
1271        name_to_table_1d.insert(String::from("t0"), 0);
1272        name_to_table_1d.insert(String::from("t1"), 1);
1273        let t1 = TableData {
1274            tables_1d: vec![
1275                table::Table1D::new(vec![1.0, 2.0]),
1276                table::Table1D::new(vec![2.0, 3.0]),
1277            ],
1278            name_to_table_1d: name_to_table_1d.clone(),
1279            ..Default::default()
1280        };
1281        let t2 = TableData {
1282            tables_1d: vec![
1283                table::Table1D::new(vec![1.0, 2.0]),
1284                table::Table1D::new(vec![2.0, 3.0]),
1285            ],
1286            name_to_table_1d: name_to_table_1d.clone(),
1287            ..Default::default()
1288        };
1289        assert_relative_eq!(t1, t2);
1290        let t2 = TableData {
1291            tables_1d: vec![
1292                table::Table1D::new(vec![1.0, 2.0]),
1293                table::Table1D::new(vec![3.0, 3.0]),
1294            ],
1295            name_to_table_1d,
1296            ..Default::default()
1297        };
1298        assert_relative_ne!(t1, t2);
1299        let mut name_to_table_1d = FxHashMap::default();
1300        name_to_table_1d.insert(String::from("t0"), 0);
1301        let t2 = TableData {
1302            tables_1d: vec![table::Table1D::new(vec![1.0, 2.0])],
1303            name_to_table_1d,
1304            ..Default::default()
1305        };
1306        assert_relative_ne!(t1, t2);
1307    }
1308}