1   /* Copyright 2002-2025 CS GROUP
2    * Licensed to CS GROUP (CS) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * CS licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.orekit.utils;
18  
19  import org.hipparchus.CalculusFieldElement;
20  import org.hipparchus.Field;
21  import org.hipparchus.util.Binary64Field;
22  import org.hipparchus.util.MathArrays;
23  import org.junit.jupiter.api.Assertions;
24  import org.junit.jupiter.api.Test;
25  
26  import java.util.HashMap;
27  import java.util.Map;
28  import java.util.function.Consumer;
29  
30  public class FieldArrayDictionaryTest {
31  
32      @Test
33      public void testEmpty() {
34          doTestEmpty(Binary64Field.getInstance());
35      }
36  
37      @Test
38      public void testPutGet() {
39          doTestPutGet(Binary64Field.getInstance());
40      }
41  
42      @Test
43      public void testFromDictionary() {
44          doTestFromDictionary(Binary64Field.getInstance());
45      }
46  
47      @Test
48      public void testFromMap() {
49          doTestFromMap(Binary64Field.getInstance());
50      }
51  
52      @Test
53      public void testArraysAreCopied() {
54          doTestArraysAreCopied(Binary64Field.getInstance());
55      }
56  
57      @Test
58      public void testIncrementField() {
59          doTestIncrementField(Binary64Field.getInstance());
60      }
61  
62      @Test
63      public void testIncrementDouble() {
64          doTestIncrementDouble(Binary64Field.getInstance());
65      }
66  
67      @Test
68      public void testScaledIncrementField() {
69          doTestScaledIncrementField(Binary64Field.getInstance());
70      }
71  
72      @Test
73      public void testScaledIncrementDouble() {
74          doTestScaledIncrementDouble(Binary64Field.getInstance());
75      }
76  
77      @Test
78      public void testZero() {
79          doTestZero(Binary64Field.getInstance());
80      }
81  
82      @Test
83      public void testSize() {
84          doTestSize(Binary64Field.getInstance());
85      }
86  
87      @Test
88      public void testDataManagement() {
89          doTestDataManagement(Binary64Field.getInstance());
90      }
91  
92      @Test
93      public void testReplace() {
94          doTestReplace(Binary64Field.getInstance());
95      }
96  
97      @Test
98      public void testPutAllMap() {
99          doTestPutAllMap(Binary64Field.getInstance());
100     }
101 
102     @Test
103     public void testPutAllDictionary() {
104         doTestPutAllDictionary(Binary64Field.getInstance());
105     }
106 
107     @Test
108     public void testToMap() {
109         doTestToMap(Binary64Field.getInstance());
110     }
111 
112     @Test
113     public void testView() {
114         doTestView(Binary64Field.getInstance());
115     }
116 
117     private <T extends CalculusFieldElement<T>> void doTestEmpty(Field<T> field) {
118         Assertions.assertTrue(new FieldArrayDictionary<>(field).getData().isEmpty());
119     }
120 
121     private <T extends CalculusFieldElement<T>> void doTestPutGet(Field<T> field) {
122 
123         FieldArrayDictionary<T> dictionary = new FieldArrayDictionary<>(field);
124         dictionary.put("a",       new double[] { 1.0, 2.0, 3.0 });
125         dictionary.put("b",       convert(field, new double[] { 4.0 }));
126         dictionary.put("another", convert(field, new double[] { 17.0 }));
127 
128         checkArray(new double[] { 1.0, 2.0, 3.0 }, dictionary.get("a"),       1.0e-15);
129         checkArray(new double[] { 17.0 },          dictionary.get("another"), 1.0e-15);
130         checkArray(new double[] { 4.0 },           dictionary.get("b"),       1.0e-15);
131 
132         Assertions.assertNull(dictionary.get("not-a-key"));
133 
134     }
135 
136     private <T extends CalculusFieldElement<T>> void doTestFromDictionary(Field<T> field) {
137         FieldArrayDictionary<T> original = new FieldArrayDictionary<>(field);
138         original.put("a",       new double[] { 1.0, 2.0, 3.0 });
139         original.put("b",       new double[] { 4.0 });
140         original.put("another", new double[] { 17.0 });
141 
142         FieldArrayDictionary<T> copy = new FieldArrayDictionary<>(original);
143 
144         checkArray(new double[] { 1.0, 2.0, 3.0 }, copy.get("a"),       1.0e-15);
145         checkArray(new double[] { 17.0 },          copy.get("another"), 1.0e-15);
146         checkArray(new double[] { 4.0 },           copy.get("b"),       1.0e-15);
147 
148         Assertions.assertNull(copy.get("not-a-key"));
149 
150     }
151 
152     private <T extends CalculusFieldElement<T>> void doTestFromMap(Field<T> field) {
153         final Map<String, T[]> map = new HashMap<>();
154         map.put("a",       convert(field, new double[] { 1.0, 2.0, 3.0 }));
155         map.put("b",       convert(field, new double[] { 4.0 }));
156         map.put("another", convert(field, new double[] { 17.0 }));
157 
158         FieldArrayDictionary<T> dictionary = new FieldArrayDictionary<>(field, map);
159 
160         checkArray(new double[] { 1.0, 2.0, 3.0 }, dictionary.get("a"),       1.0e-15);
161         checkArray(new double[] { 17.0 },          dictionary.get("another"), 1.0e-15);
162         checkArray(new double[] { 4.0 },           dictionary.get("b"),       1.0e-15);
163 
164         Assertions.assertNull(dictionary.get("not-a-key"));
165 
166     }
167 
168     private <T extends CalculusFieldElement<T>> void doTestArraysAreCopied(Field<T> field) {
169         FieldArrayDictionary<T> dictionary = new FieldArrayDictionary<>(field);
170         T[] original = convert(field, new double[] { 1.0, 2.0, 3.0 });
171         dictionary.put("a", original);
172         T[] retrieved = dictionary.get("a");
173         checkArray(new double[] { 1.0, 2.0, 3.0 }, retrieved, 1.0e-15);
174         Assertions.assertNotSame(original, retrieved);
175     }
176 
177     private <T extends CalculusFieldElement<T>> void doTestIncrementField(Field<T> field) {
178         FieldArrayDictionary<T> dictionary = new FieldArrayDictionary<>(field);
179         dictionary.put("a",       convert(field, new double[] { 1.0, 2.0, 3.0 }));
180         dictionary.getEntry("a").increment(convert(field, new double[] { 2.0, 4.0, 8.0 }));
181         checkArray(new double[] { 3.0, 6.0, 11.0 }, dictionary.get("a"), 1.0e-15);
182     }
183 
184     private <T extends CalculusFieldElement<T>> void doTestIncrementDouble(Field<T> field) {
185         FieldArrayDictionary<T> dictionary = new FieldArrayDictionary<>(field);
186         dictionary.put("a",       convert(field, new double[] { 1.0, 2.0, 3.0 }));
187         dictionary.getEntry("a").increment(new double[] { 2.0, 4.0, 8.0 });
188         checkArray(new double[] { 3.0, 6.0, 11.0 }, dictionary.get("a"), 1.0e-15);
189     }
190 
191     private <T extends CalculusFieldElement<T>> void doTestScaledIncrementField(Field<T> field) {
192         FieldArrayDictionary<T> dictionary = new FieldArrayDictionary<>(field);
193         dictionary.put("a",       convert(field, new double[] { 1.0, 2.0, 3.0 }));
194         FieldArrayDictionary<T> other = new FieldArrayDictionary<>(field);
195         other.put("aDot",       convert(field, new double[] { 3.0, 2.0, 1.0 }));
196         dictionary.getEntry("a").scaledIncrement(field.getZero().newInstance(2.0), other.getEntry("aDot"));
197         checkArray(new double[] { 7.0, 6.0, 5.0 }, dictionary.get("a"), 1.0e-15);
198     }
199 
200     private <T extends CalculusFieldElement<T>> void doTestScaledIncrementDouble(Field<T> field) {
201         FieldArrayDictionary<T> dictionary = new FieldArrayDictionary<>(field);
202         dictionary.put("a",       convert(field, new double[] { 1.0, 2.0, 3.0 }));
203         FieldArrayDictionary<T> other = new FieldArrayDictionary<>(field);
204         other.put("aDot",       convert(field, new double[] { 3.0, 2.0, 1.0 }));
205         dictionary.getEntry("a").scaledIncrement(2.0, other.getEntry("aDot"));
206         checkArray(new double[] { 7.0, 6.0, 5.0 }, dictionary.get("a"), 1.0e-15);
207     }
208 
209     private <T extends CalculusFieldElement<T>> void doTestZero(Field<T> field) {
210         FieldArrayDictionary<T> dictionary = new FieldArrayDictionary<>(field);
211         dictionary.put("a",       new double[] { 1.0, 2.0, 3.0 });
212         dictionary.getEntry("a").zero();
213         checkArray(new double[] { 0.0, 0.0, 0.0 }, dictionary.get("a"), 1.0e-15);
214     }
215 
216     private <T extends CalculusFieldElement<T>> void doTestSize(Field<T> field) {
217         FieldArrayDictionary<T> dictionary = new FieldArrayDictionary<>(field);
218         dictionary.put("a",       new double[] { 1.0, 2.0, 3.0 });
219          Assertions.assertEquals(3, dictionary.getEntry("a").size(), 1.0e-15);
220     }
221 
222     private <T extends CalculusFieldElement<T>> void doTestDataManagement(Field<T> field) {
223         FieldArrayDictionary<T> dictionary = new FieldArrayDictionary<>(field);
224         dictionary.put("a",       new double[] { 1.0, 2.0, 3.0 });
225         dictionary.put("b",       new double[] { 4.0 });
226         dictionary.put("another", new double[] { 17.0 });
227 
228         Assertions.assertEquals(3, dictionary.size());
229         Assertions.assertEquals("{a[3], b[1], another[1]}", dictionary.toString());
230 
231         Assertions.assertTrue(dictionary.remove("another"));
232         Assertions.assertEquals(2, dictionary.size());
233         Assertions.assertFalse(dictionary.remove("not-a-key"));
234         Assertions.assertEquals(2, dictionary.size());
235 
236         Assertions.assertEquals("a", dictionary.getData().get(0).getKey());
237         Assertions.assertEquals("b", dictionary.getData().get(1).getKey());
238 
239         dictionary.clear();
240         Assertions.assertTrue(dictionary.getData().isEmpty());
241 
242         Assertions.assertSame(field, dictionary.getField());
243 
244     }
245 
246     private <T extends CalculusFieldElement<T>> void doTestReplace(Field<T> field) {
247 
248         FieldArrayDictionary<T> dictionary = new FieldArrayDictionary<>(field);
249         dictionary.put("a",       new double[] { 1.0, 2.0, 3.0 });
250         dictionary.put("b",       new double[] { 4.0 });
251         dictionary.put("another", new double[] { 17.0 });
252         Assertions.assertEquals(3, dictionary.size());
253 
254         dictionary.put("b",       new double[] { -1.0, -1.0 });
255         Assertions.assertEquals(3, dictionary.size());
256 
257         checkArray(new double[] { 1.0, 2.0, 3.0 }, dictionary.get("a"),       1.0e-15);
258         checkArray(new double[] { 17.0 },          dictionary.get("another"), 1.0e-15);
259         checkArray(new double[] { -1.0, -1.0 },    dictionary.get("b"),       1.0e-15);
260         Assertions.assertEquals("a",       dictionary.getData().get(0).getKey());
261         Assertions.assertEquals("another", dictionary.getData().get(1).getKey());
262         Assertions.assertEquals("b",       dictionary.getData().get(2).getKey());
263 
264     }
265 
266     private <T extends CalculusFieldElement<T>> void doTestPutAllMap(Field<T> field) {
267 
268         FieldArrayDictionary<T> dictionary = new FieldArrayDictionary<>(field);
269         dictionary.put("a",       new double[] { 1.0, 2.0, 3.0 });
270         dictionary.put("b",       new double[] { 4.0 });
271         dictionary.put("another", new double[] { 17.0 });
272         Assertions.assertEquals(3, dictionary.size());
273 
274         final Map<String, T[]> map = new HashMap<>();
275         map.put("f", convert(field, new double[] {  12.0 }));
276         map.put("g", convert(field, new double[] { -12.0 }));
277         map.put("b", convert(field, new double[] {  19.0 }));
278 
279         dictionary.putAll(map);
280         Assertions.assertEquals(5, dictionary.size());
281 
282         checkArray(new double[] { 1.0, 2.0, 3.0 }, dictionary.get("a"),       1.0e-15);
283         checkArray(new double[] {  19.0 },         dictionary.get("b"),       1.0e-15);
284         checkArray(new double[] {  17.0 },         dictionary.get("another"), 1.0e-15);
285         checkArray(new double[] {  12.0 },         dictionary.get("f"),       1.0e-15);
286         checkArray(new double[] { -12.0 },         dictionary.get("g"),       1.0e-15);
287 
288     }
289 
290     private <T extends CalculusFieldElement<T>> void doTestPutAllDictionary(Field<T> field) {
291 
292         FieldArrayDictionary<T> dictionary = new FieldArrayDictionary<>(field);
293         dictionary.put("a",       new double[] { 1.0, 2.0, 3.0 });
294         dictionary.put("b",       new double[] { 4.0 });
295         dictionary.put("another", new double[] { 17.0 });
296         Assertions.assertEquals(3, dictionary.size());
297 
298         FieldArrayDictionary<T> other = new FieldArrayDictionary<>(field);
299         other.put("f", new double[] {  12.0 });
300         other.put("g", new double[] { -12.0 });
301         other.put("b", new double[] {  19.0 });
302 
303         dictionary.putAll(other);
304         Assertions.assertEquals(5, dictionary.size());
305 
306         checkArray(new double[] { 1.0, 2.0, 3.0 }, dictionary.get("a"),       1.0e-15);
307         checkArray(new double[] {  19.0 },         dictionary.get("b"),       1.0e-15);
308         checkArray(new double[] {  17.0 },         dictionary.get("another"), 1.0e-15);
309         checkArray(new double[] {  12.0 },         dictionary.get("f"),       1.0e-15);
310         checkArray(new double[] { -12.0 },         dictionary.get("g"),       1.0e-15);
311 
312     }
313 
314     private <T extends CalculusFieldElement<T>> void doTestToMap(Field<T> field) {
315         FieldArrayDictionary<T> dictionary = new FieldArrayDictionary<>(field);
316         dictionary.put("a",       new double[] { 1.0, 2.0, 3.0 });
317         dictionary.put("b",       new double[] { 4.0 });
318         dictionary.put("another", new double[] { 17.0 });
319         Assertions.assertEquals(3, dictionary.size());
320 
321         Map<String, T[]> map = dictionary.toMap();
322         Assertions.assertEquals(3, map.size());
323 
324         checkArray(new double[] { 1.0, 2.0, 3.0 }, map.get("a"),       1.0e-15);
325         checkArray(new double[] {   4.0 },         map.get("b"),       1.0e-15);
326         checkArray(new double[] {  17.0 },         map.get("another"), 1.0e-15);
327 
328         dictionary.clear();
329         Assertions.assertEquals(0, dictionary.size());
330         Assertions.assertEquals(3, map.size());
331         map.put("z", MathArrays.buildArray(field, 0));
332         Assertions.assertEquals(4, map.size());
333         Assertions.assertEquals(0, dictionary.size());
334 
335     }
336 
337     private <T extends CalculusFieldElement<T>> void doTestView(Field<T> field) {
338         FieldArrayDictionary<T> dictionary = new FieldArrayDictionary<>(field);
339         dictionary.put("a",       new double[] { 1.0, 2.0, 3.0 });
340         dictionary.put("b",       new double[] { 4.0 });
341         dictionary.put("another", new double[] { 17.0 });
342 
343         FieldArrayDictionary<T> view = dictionary.unmodifiableView();
344         Assertions.assertEquals(3, view.size());
345         Assertions.assertEquals(3, view.getData().size());
346         Assertions.assertEquals(3, view.toMap().size());
347         checkArray(new double[] { 1.0, 2.0, 3.0 }, view.get("a"),       1.0e-15);
348         checkArray(new double[] {   4.0 },         view.get("b"),       1.0e-15);
349         checkArray(new double[] {  17.0 }, view.getEntry("another").getValue(), 1.0e-15);
350 
351         dictionary.put("z", new double[] { 25.0 });
352         Assertions.assertEquals(4, view.size());
353         checkArray(new double[] { 25.0 },         view.get("z"), 1.0e-15);
354 
355         checkUnsupported(view, v -> v.clear());
356         checkUnsupported(view, v -> v.put("tF", convert(field, new double[1])));
357         checkUnsupported(view, v -> v.put("tD", new double[1]));
358         checkUnsupported(view, v -> v.putAll(new FieldArrayDictionary<>(field)));
359         checkUnsupported(view, v -> v.putAll(new HashMap<>()));
360         checkUnsupported(view, v -> v.remove("a"));
361 
362     }
363 
364     private <T extends CalculusFieldElement<T>> void checkArray(final double[] expected, final T[] actual, final double eps) {
365         Assertions.assertEquals(expected.length, actual.length);
366         for (int i = 0; i < expected.length; ++i) {
367             Assertions.assertEquals(expected[i], actual[i].getReal(), eps);
368         }
369     }
370 
371     private <T extends CalculusFieldElement<T>> T[] convert(final Field<T> field, final double[] a) {
372         final T[] converted = MathArrays.buildArray(field, a.length);
373         for (int i = 0; i < a.length; ++i) {
374             converted[i] = field.getZero().newInstance(a[i]);
375         }
376         return converted;
377     }
378 
379     private <T extends CalculusFieldElement<T>> void checkUnsupported(FieldArrayDictionary<T> d, Consumer<FieldArrayDictionary<T>> c) {
380         try {
381             c.accept(d);
382             Assertions.fail("an exception should have been thrown");
383         } catch (UnsupportedOperationException uoe) {
384             // expected
385         }
386     }
387 
388 }