View Javadoc
1   /*
2    * Licensed to the Hipparchus project under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The Hipparchus project 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    *      https://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.hipparchus.analysis.differentiation;
18  
19  import org.hipparchus.Field;
20  import org.hipparchus.CalculusFieldElement;
21  import org.hipparchus.CalculusFieldElementAbstractTest;
22  import org.hipparchus.analysis.FieldUnivariateFunction;
23  import org.hipparchus.exception.LocalizedCoreFormats;
24  import org.hipparchus.exception.MathIllegalArgumentException;
25  import org.hipparchus.util.FastMath;
26  import org.hipparchus.util.FieldSinCos;
27  import org.hipparchus.util.MathArrays;
28  import org.junit.Assert;
29  import org.junit.Test;
30  
31  /**
32   * Test for class {@link FieldGradient}.
33   */
34  public abstract class FieldGradientAbstractTest<T extends CalculusFieldElement<T>>
35      extends CalculusFieldElementAbstractTest<FieldGradient<T>> {
36  
37      protected abstract Field<T> getValueField();
38  
39      protected FieldGradient<T> build(final double x) {
40          // the function is really a two variables function : f(x) = g(x, 0) with g(x, y) = x + y / 1024
41          return build(x, 1.0, FastMath.scalb(1.0, -10));
42      }
43  
44      protected FieldGradient<T> build(final double x, final double... derivatives) {
45          final Field<T> valueField = getValueField();
46          final T[] gradient = MathArrays.buildArray(valueField, derivatives.length);
47          for (int i = 0; i < gradient.length;++i) {
48              gradient[i] = valueField.getZero().newInstance(derivatives[i]);
49          }
50          return new FieldGradient<>(valueField.getZero().newInstance(x), gradient);
51      }
52  
53      protected T buildScalar(double value) {
54          return getValueField().getZero().newInstance(value);
55      }
56  
57      @Test
58      public void testFieldAdd() {
59          check(build(1.0).add(buildScalar(5.0)), 6.0, 1.0);
60      }
61  
62      @Test
63      public void testFieldSubtract() {
64          check(build(1.0).subtract(buildScalar(5.0)), -4.0, 1.0);
65      }
66  
67      @Test
68      public void testFieldMultiply() {
69          check(build(1.0).multiply(buildScalar(5.0)), 5.0, 5.0);
70      }
71  
72      @Test
73      public void testFieldDivide() {
74          check(build(1.0).divide(buildScalar(5.0)), 0.2, 0.2);
75      }
76  
77      @Test
78      public void testgetGradient() {
79          FieldGradient<T> g = build(-0.5, 2.5, 10.0, -1.0);
80          Assert.assertEquals(-0.5, g.getReal(), 1.0e-15);
81          Assert.assertEquals(-0.5, g.getValue().getReal(), 1.0e-15);
82          Assert.assertEquals(+2.5, g.getGradient()[0].getReal(), 1.0e-15);
83          Assert.assertEquals(10.0, g.getGradient()[1].getReal(), 1.0e-15);
84          Assert.assertEquals(-1.0, g.getGradient()[2].getReal(), 1.0e-15);
85          Assert.assertEquals(+2.5, g.getPartialDerivative(0).getReal(), 1.0e-15);
86          Assert.assertEquals(10.0, g.getPartialDerivative(1).getReal(), 1.0e-15);
87          Assert.assertEquals(-1.0, g.getPartialDerivative(2).getReal(), 1.0e-15);
88          Assert.assertEquals(3, g.getFreeParameters());
89          try {
90              g.getPartialDerivative(-1);
91              Assert.fail("an exception should have been thrown");
92          } catch (MathIllegalArgumentException miae) {
93              Assert.assertEquals(LocalizedCoreFormats.OUT_OF_RANGE_SIMPLE, miae.getSpecifier());
94          }
95          try {
96              g.getPartialDerivative(+3);
97              Assert.fail("an exception should have been thrown");
98          } catch (MathIllegalArgumentException miae) {
99              Assert.assertEquals(LocalizedCoreFormats.OUT_OF_RANGE_SIMPLE, miae.getSpecifier());
100         }
101     }
102 
103     @Test
104     public void testConstant() {
105         FieldGradient<T> g = FieldGradient.constant(5, getValueField().getZero().newInstance(-4.5));
106         Assert.assertEquals(5, g.getFreeParameters());
107         Assert.assertEquals(getValueField(), g.getValue().getField());
108         Assert.assertEquals(-4.5, g.getValue().getReal(), 1.0e-15);
109         for (int i = 0 ; i < g.getFreeParameters(); ++i) {
110             Assert.assertEquals(0.0, g.getPartialDerivative(i).getReal(), 1.0e-15);
111         }
112     }
113 
114     @Test
115     public void testVariable() {
116         FieldGradient<T> g = FieldGradient.variable(5, 1, getValueField().getZero().newInstance(-4.5));
117         Assert.assertEquals(5, g.getFreeParameters());
118         Assert.assertEquals(getValueField(), g.getValue().getField());
119         Assert.assertEquals(-4.5, g.getValue().getReal(), 1.0e-15);
120         for (int i = 0 ; i < g.getFreeParameters(); ++i) {
121             Assert.assertEquals(i == 1 ? 1.0 : 0.0, g.getPartialDerivative(i).getReal(), 1.0e-15);
122         }
123     }
124 
125     @Test
126     public void testDoublePow() {
127         Assert.assertSame(build(3).getField().getZero(), FieldGradient.pow(0.0, build(1.5)));
128         FieldGradient<T> g = FieldGradient.pow(2.0, build(1.5));
129         FDSFactory<T> factory = new FDSFactory<>(getValueField(), 2, 1);
130         FieldDerivativeStructure<T> ds = factory.constant(2.0).pow(factory.build(1.5, 1.0, FastMath.scalb(1.0, -10)));
131         Assert.assertEquals(ds.getValue().getReal(), g.getValue().getReal(), 1.0e-15);
132         final int[] indices = new int[ds.getFreeParameters()];
133         for (int i = 0; i < g.getFreeParameters(); ++i) {
134             indices[i] = 1;
135             Assert.assertEquals(ds.getPartialDerivative(indices).getReal(), g.getPartialDerivative(i).getReal(), 1.0e-15);
136             indices[i] = 0;
137         }
138     }
139 
140     @Test
141     public void testTaylor() {
142         Assert.assertEquals(2.75, build(2, 1, 0.125).taylor(0.5, 2.0).getReal(), 1.0e-15);
143     }
144 
145     @Test
146     public void testOrder() {
147         Assert.assertEquals(1, build(2).getOrder());
148     }
149 
150     @Test
151     public void testGetPartialDerivative() {
152         final FieldGradient<T> g = build(2);
153         Assert.assertEquals(2.0,        g.getPartialDerivative(0, 0).getReal(), 1.0e-15); // f(x,y)
154         Assert.assertEquals(1.0,        g.getPartialDerivative(1, 0).getReal(), 1.0e-15); // ∂f/∂x
155         Assert.assertEquals(1.0 / 1024, g.getPartialDerivative(0, 1).getReal(), 1.0e-15); // ∂f/∂y
156     }
157 
158     @Test
159     public void testGetPartialDerivativeErrors() {
160         final FieldGradient<T> g = build(2);
161         try {
162             g.getPartialDerivative(0, 0, 0);
163             Assert.fail("an exception should have been thrown");
164         } catch (MathIllegalArgumentException miae) {
165             Assert.assertEquals(LocalizedCoreFormats.DIMENSIONS_MISMATCH, miae.getSpecifier());
166             Assert.assertEquals(3, ((Integer) miae.getParts()[0]).intValue());
167             Assert.assertEquals(2, ((Integer) miae.getParts()[1]).intValue());
168         }
169         try {
170             g.getPartialDerivative(0, 5);
171             Assert.fail("an exception should have been thrown");
172         } catch (MathIllegalArgumentException miae) {
173             Assert.assertEquals(LocalizedCoreFormats.DERIVATION_ORDER_NOT_ALLOWED, miae.getSpecifier());
174             Assert.assertEquals(5, ((Integer) miae.getParts()[0]).intValue());
175         }
176         try {
177             g.getPartialDerivative(1, 1);
178             Assert.fail("an exception should have been thrown");
179         } catch (MathIllegalArgumentException miae) {
180             Assert.assertEquals(LocalizedCoreFormats.DERIVATION_ORDER_NOT_ALLOWED, miae.getSpecifier());
181             Assert.assertEquals(1, ((Integer) miae.getParts()[0]).intValue());
182         }
183     }
184 
185     @Test
186     public void testHashcode() {
187         Assert.assertEquals(1608501298, build(2, 1, -0.25).hashCode());
188     }
189 
190     @Test
191     public void testEquals() {
192         FieldGradient<T> g = build(12, -34, 56);
193         Assert.assertEquals(g, g);
194         Assert.assertNotEquals(g, "");
195         Assert.assertEquals(g, build(12, -34, 56));
196         Assert.assertNotEquals(g, build(21, -34, 56));
197         Assert.assertNotEquals(g, build(12, -43, 56));
198         Assert.assertNotEquals(g, build(12, -34, 65));
199         Assert.assertNotEquals(g, build(21, -43, 65));
200     }
201 
202     @Test
203     public void testRunTimeClass() {
204         Field<FieldGradient<T>> field = build(0.0).getField();
205         Assert.assertEquals(FieldGradient.class, field.getRuntimeClass());
206     }
207 
208     @Test
209     public void testConversion() {
210         FieldGradient<T> gA = build(-0.5, 2.5, 4.5);
211         FieldDerivativeStructure<T> ds = gA.toDerivativeStructure();
212         Assert.assertEquals(2, ds.getFreeParameters());
213         Assert.assertEquals(1, ds.getOrder());
214         Assert.assertEquals(-0.5, ds.getValue().getReal(), 1.0e-15);
215         Assert.assertEquals(-0.5, ds.getPartialDerivative(0, 0).getReal(), 1.0e-15);
216         Assert.assertEquals( 2.5, ds.getPartialDerivative(1, 0).getReal(), 1.0e-15);
217         Assert.assertEquals( 4.5, ds.getPartialDerivative(0, 1).getReal(), 1.0e-15);
218         FieldGradient<T> gB = new FieldGradient<>(ds);
219         Assert.assertNotSame(gA, gB);
220         Assert.assertEquals(gA, gB);
221         try {
222             new FieldGradient<>(new FDSFactory<>(getValueField(), 1, 2).variable(0, 1.0));
223             Assert.fail("an exception should have been thrown");
224         } catch (MathIllegalArgumentException miae) {
225             Assert.assertEquals(LocalizedCoreFormats.DIMENSIONS_MISMATCH, miae.getSpecifier());
226         }
227     }
228 
229     @Test
230     public void testNewInstance() {
231         FieldGradient<T> g = build(5.25);
232         Assert.assertEquals(5.25, g.getValue().getReal(), 1.0e-15);
233         Assert.assertEquals(1.0,  g.getPartialDerivative(0).getReal(), 1.0e-15);
234         Assert.assertEquals(0.0009765625,  g.getPartialDerivative(1).getReal(), 1.0e-15);
235         FieldGradient<T> newInstance = g.newInstance(7.5);
236         Assert.assertEquals(7.5, newInstance.getValue().getReal(), 1.0e-15);
237         Assert.assertEquals(0.0, newInstance.getPartialDerivative(0).getReal(), 1.0e-15);
238         Assert.assertEquals(0.0, newInstance.getPartialDerivative(1).getReal(), 1.0e-15);
239     }
240 
241     protected void checkAgainstDS(final double x, final FieldUnivariateFunction f) {
242         final FieldGradient<T> xG = build(x);
243         final FieldGradient<T> yG = f.value(xG);
244         final FieldDerivativeStructure<T> yDS = f.value(xG.toDerivativeStructure());
245         Assert.assertEquals(yDS.getFreeParameters(), yG.getFreeParameters());
246         Assert.assertEquals(yDS.getValue().getReal(), yG.getValue().getReal(), 1.0e-15 * FastMath.abs(yDS.getValue().getReal()));
247         final int[] indices = new int[yDS.getFreeParameters()];
248         for (int i = 0; i < yG.getFreeParameters(); ++i) {
249             indices[i] = 1;
250             Assert.assertEquals(yDS.getPartialDerivative(indices).getReal(),
251                                 yG.getPartialDerivative(i).getReal(),
252                                 4.0e-14* FastMath.abs(yDS.getPartialDerivative(indices).getReal()));
253             indices[i] = 0;
254         }
255     }
256 
257     @Test
258     public void testArithmeticVsDS() {
259         for (double x = -1.25; x < 1.25; x+= 0.5) {
260             checkAgainstDS(x,
261                            new FieldUnivariateFunction() {
262                                public <S extends CalculusFieldElement<S>> S value(S x) {
263                                    final S y = x.add(3).multiply(x).subtract(5).multiply(0.5);
264                                    return y.negate().divide(4).divide(x).add(y).subtract(x).multiply(2).reciprocal();
265                                }
266                            });
267         }
268     }
269 
270     @Test
271     public void testCopySignField() {
272 
273         FieldGradient<T> minusOne = build(-1.0);
274         Assert.assertEquals(+1.0, minusOne.copySign(buildScalar(+1.0)).getReal(), 1.0e-15);
275         Assert.assertEquals(-1.0, minusOne.copySign(buildScalar(-1.0)).getReal(), 1.0e-15);
276         Assert.assertEquals(+1.0, minusOne.copySign(buildScalar(+0.0)).getReal(), 1.0e-15);
277         Assert.assertEquals(-1.0, minusOne.copySign(buildScalar(-0.0)).getReal(), 1.0e-15);
278         Assert.assertEquals(+1.0, minusOne.copySign(buildScalar(Double.NaN)).getReal(), 1.0e-15);
279 
280         FieldGradient<T> plusOne = build(1.0);
281         Assert.assertEquals(+1.0, plusOne.copySign(buildScalar(+1.0)).getReal(), 1.0e-15);
282         Assert.assertEquals(-1.0, plusOne.copySign(buildScalar(-1.0)).getReal(), 1.0e-15);
283         Assert.assertEquals(+1.0, plusOne.copySign(buildScalar(+0.0)).getReal(), 1.0e-15);
284         Assert.assertEquals(-1.0, plusOne.copySign(buildScalar(-0.0)).getReal(), 1.0e-15);
285         Assert.assertEquals(+1.0, plusOne.copySign(buildScalar(Double.NaN)).getReal(), 1.0e-15);
286 
287     }
288 
289     @Test
290     public void testRemainderField() {
291         double epsilon = 2.0e-15;
292         for (double x = -1.7; x < 2; x += 0.2) {
293             FieldGradient<T> dsX = build(x);
294             for (double y = -1.7; y < 2; y += 0.2) {
295                 FieldGradient<T> remainder = dsX.remainder(buildScalar(y));
296                 FieldGradient<T> ref = dsX.subtract(x - FastMath.IEEEremainder(x, y));
297                 FieldGradient<T> zero = remainder.subtract(ref);
298                 Assert.assertEquals(0, zero.getPartialDerivative(0).getReal(), epsilon);
299             }
300         }
301     }
302 
303     @Test
304     public void testRemainderDoubleVsDS() {
305         for (double x = -1.25; x < 1.25; x+= 0.5) {
306             checkAgainstDS(x,
307                            new FieldUnivariateFunction() {
308                                public <S extends CalculusFieldElement<S>> S value(S x) {
309                                    return x.remainder(0.5);
310                                }
311                            });
312         }
313     }
314 
315     @Test
316     public void testRemainderGVsDS() {
317         for (double x = -1.25; x < 1.25; x+= 0.5) {
318             checkAgainstDS(x,
319                            new FieldUnivariateFunction() {
320                               public <S extends CalculusFieldElement<S>> S value(S x) {
321                                   return x.remainder(x.divide(0.7));
322                               }
323                            });
324         }
325     }
326 
327     @Test
328     public void testAbsVsDS() {
329         for (double x = -1.25; x < 1.25; x+= 0.5) {
330             checkAgainstDS(x,
331                            new FieldUnivariateFunction() {
332                                public <S extends CalculusFieldElement<S>> S value(S x) {
333                                    return x.abs();
334                                }
335                            });
336         }
337     }
338 
339     @Test
340     public void testScalbVsDS() {
341         for (int n = -4; n < 4; ++n) {
342             final int theN = n;
343             for (double x = -1.25; x < 1.25; x+= 0.5) {
344                 checkAgainstDS(x,
345                                new FieldUnivariateFunction() {
346                                    public <S extends CalculusFieldElement<S>> S value(S x) {
347                                        return x.scalb(theN);
348                                    }
349                                });
350             }
351         }
352     }
353 
354     @Test
355     public void testHypotVsDS() {
356         for (double x = -3.25; x < 3.25; x+= 0.5) {
357             checkAgainstDS(x,
358                            new FieldUnivariateFunction() {
359                                public <S extends CalculusFieldElement<S>> S value(S x) {
360                                    return x.cos().multiply(5).hypot(x.sin().multiply(2));
361                                }
362                            });
363         }
364     }
365 
366     @Test
367     public void testAtan2VsDS() {
368         for (double x = -3.25; x < 3.25; x+= 0.5) {
369             checkAgainstDS(x,
370                            new FieldUnivariateFunction() {
371                                public <S extends CalculusFieldElement<S>> S value(S x) {
372                                    return x.cos().multiply(5).atan2(x.sin().multiply(2));
373                                }
374                            });
375         }
376     }
377 
378     @Test
379     public void testPowersVsDS() {
380         for (double x = -3.25; x < 3.25; x+= 0.5) {
381             checkAgainstDS(x,
382                            new FieldUnivariateFunction() {
383                                public <S extends CalculusFieldElement<S>> S value(S x) {
384                                    final FieldSinCos<S> sc = x.sinCos();
385                                    return x.pow(3.2).add(x.pow(2)).subtract(sc.cos().abs().pow(sc.sin()));
386                                }
387                            });
388         }
389     }
390 
391     @Test
392     public void testRootsVsDS() {
393         for (double x = 0.001; x < 3.25; x+= 0.5) {
394             checkAgainstDS(x,
395                            new FieldUnivariateFunction() {
396                                public <S extends CalculusFieldElement<S>> S value(S x) {
397                                    return x.rootN(5);//x.sqrt().add(x.cbrt()).subtract(x.rootN(5));
398                                }
399                            });
400         }
401     }
402 
403     @Test
404     public void testExpsLogsVsDS() {
405         for (double x = 2.5; x < 3.25; x+= 0.125) {
406             checkAgainstDS(x,
407                            new FieldUnivariateFunction() {
408                                public <S extends CalculusFieldElement<S>> S value(S x) {
409                                    return x.exp().add(x.multiply(0.5).expm1()).log().log10().log1p();
410                                }
411                            });
412         }
413     }
414 
415     @Test
416     public void testTrigonometryVsDS() {
417         for (double x = -3.25; x < 3.25; x+= 0.5) {
418             checkAgainstDS(x,
419                            new FieldUnivariateFunction() {
420                                public <S extends CalculusFieldElement<S>> S value(S x) {
421                                    return x.cos().multiply(x.sin()).atan().divide(12).asin().multiply(0.1).acos().tan();
422                                }
423                            });
424         }
425     }
426 
427     @Test
428     public void testHyperbolicVsDS() {
429         for (double x = -1.25; x < 1.25; x+= 0.5) {
430             checkAgainstDS(x,
431                            new FieldUnivariateFunction() {
432                                public <S extends CalculusFieldElement<S>> S value(S x) {
433                                    return x.cosh().multiply(x.sinh()).multiply(12).abs().acosh().asinh().divide(7).tanh().multiply(0.1).atanh();
434                                }
435                            });
436         }
437     }
438 
439     @Test
440     public void testConvertersVsDS() {
441         for (double x = -1.25; x < 1.25; x+= 0.5) {
442             checkAgainstDS(x,
443                            new FieldUnivariateFunction() {
444                                public <S extends CalculusFieldElement<S>> S value(S x) {
445                                    return x.multiply(5).toDegrees().subtract(x).toRadians();
446                                }
447                            });
448         }
449     }
450 
451     @Test
452     public void testLinearCombination2D2FVsDS() {
453         for (double x = -1.25; x < 1.25; x+= 0.5) {
454             checkAgainstDS(x,
455                            new FieldUnivariateFunction() {
456                                public <S extends CalculusFieldElement<S>> S value(S x) {
457                                    return x.linearCombination(1.0, x.multiply(0.9),
458                                                               2.0, x.multiply(0.8));
459                                }
460                            });
461         }
462     }
463 
464     @Test
465     public void testLinearCombination2F2FVsDS() {
466         for (double x = -1.25; x < 1.25; x+= 0.5) {
467             checkAgainstDS(x,
468                            new FieldUnivariateFunction() {
469                                public <S extends CalculusFieldElement<S>> S value(S x) {
470                                    return x.linearCombination(x.add(1), x.multiply(0.9),
471                                                               x.add(2), x.multiply(0.8));
472                                }
473                            });
474         }
475     }
476 
477     @Test
478     public void testLinearCombination3D3FVsDS() {
479         for (double x = -1.25; x < 1.25; x+= 0.5) {
480             checkAgainstDS(x,
481                            new FieldUnivariateFunction() {
482                                public <S extends CalculusFieldElement<S>> S value(S x) {
483                                    return x.linearCombination(1.0, x.multiply(0.9),
484                                                               2.0, x.multiply(0.8),
485                                                               3.0, x.multiply(0.7));
486                                }
487                            });
488         }
489     }
490 
491     @Test
492     public void testLinearCombination3F3FVsDS() {
493         for (double x = -1.25; x < 1.25; x+= 0.5) {
494             checkAgainstDS(x,
495                            new FieldUnivariateFunction() {
496                                public <S extends CalculusFieldElement<S>> S value(S x) {
497                                    return x.linearCombination(x.add(1), x.multiply(0.9),
498                                                               x.add(2), x.multiply(0.8),
499                                                               x.add(3), x.multiply(0.7));
500                                }
501                            });
502         }
503     }
504 
505     @Test
506     public void testLinearCombination4D4FVsDS() {
507         for (double x = -1.25; x < 1.25; x+= 0.5) {
508             checkAgainstDS(x,
509                            new FieldUnivariateFunction() {
510                                public <S extends CalculusFieldElement<S>> S value(S x) {
511                                    return x.linearCombination(1.0, x.multiply(0.9),
512                                                               2.0, x.multiply(0.8),
513                                                               3.0, x.multiply(0.7),
514                                                               4.0, x.multiply(0.6));
515                                }
516                            });
517         }
518     }
519 
520     @Test
521     public void testLinearCombination4F4FVsDS() {
522         for (double x = -1.25; x < 1.25; x+= 0.5) {
523             checkAgainstDS(x,
524                            new FieldUnivariateFunction() {
525                                public <S extends CalculusFieldElement<S>> S value(S x) {
526                                    return x.linearCombination(x.add(1), x.multiply(0.9),
527                                                               x.add(2), x.multiply(0.8),
528                                                               x.add(3), x.multiply(0.7),
529                                                               x.add(4), x.multiply(0.6));
530                                }
531                            });
532         }
533     }
534 
535     @Test
536     public void testLinearCombinationnDnFVsDS() {
537         for (double x = -1.25; x < 1.25; x+= 0.5) {
538             checkAgainstDS(x,
539                            new FieldUnivariateFunction() {
540                                public <S extends CalculusFieldElement<S>> S value(S x) {
541                                    final S[] b = MathArrays.buildArray(x.getField(), 4);
542                                    b[0] = x.add(0.9);
543                                    b[1] = x.add(0.8);
544                                    b[2] = x.add(0.7);
545                                    b[3] = x.add(0.6);
546                                    return x.linearCombination(new double[] { 1, 2, 3, 4 }, b);
547                                }
548                            });
549         }
550     }
551 
552     @Test
553     public void testLinearCombinationnFnFVsDS() {
554         for (double x = -1.25; x < 1.25; x+= 0.5) {
555             checkAgainstDS(x,
556                            new FieldUnivariateFunction() {
557                                public <S extends CalculusFieldElement<S>> S value(S x) {
558                                    final S[] a = MathArrays.buildArray(x.getField(), 4);
559                                    a[0] = x.add(1);
560                                    a[1] = x.add(2);
561                                    a[2] = x.add(3);
562                                    a[3] = x.add(4);
563                                    final S[] b = MathArrays.buildArray(x.getField(), 4);
564                                    b[0] = x.add(0.9);
565                                    b[1] = x.add(0.8);
566                                    b[2] = x.add(0.7);
567                                    b[3] = x.add(0.6);
568                                    return x.linearCombination(a, b);
569                                }
570                            });
571         }
572     }
573 
574     @Test
575     public void testLinearCombinationField() {
576         final T[] a = MathArrays.buildArray(getValueField(), 3);
577         a[0] = buildScalar(-1321008684645961.0 / 268435456.0);
578         a[1] = buildScalar(-5774608829631843.0 / 268435456.0);
579         a[2] = buildScalar(-7645843051051357.0 / 8589934592.0);
580         final FieldGradient<T>[] b = MathArrays.buildArray(FieldGradientField.getField(getValueField(), 1), 3);
581         b[0] = build(-5712344449280879.0 / 2097152.0);
582         b[1] = build(-4550117129121957.0 / 2097152.0);
583         b[2] = build(8846951984510141.0 / 131072.0);
584 
585         final FieldGradient<T> abSumInline = b[0].linearCombination(a[0], b[0],
586                                                                     a[1], b[1],
587                                                                     a[2], b[2]);
588         final FieldGradient<T> abSumArray = b[0].linearCombination(a, b);
589         Assert.assertEquals(abSumInline.getReal(), abSumArray.getReal(), 3.0e-8);
590         Assert.assertEquals(-1.8551294182586248737720779899, abSumInline.getReal(), 5.0e-8);
591         Assert.assertEquals(abSumInline.getPartialDerivative(0).getReal(), abSumArray.getPartialDerivative(0).getReal(), 3.0e-8);
592     }
593 
594     @Test
595     public void testZero() {
596         FieldGradient<T> zero = build(17.0).getField().getZero();
597         Assert.assertEquals(0.0, zero.getValue().getReal(), 1.0e-15);
598         for (int i = 0; i < zero.getFreeParameters(); ++i) {
599             Assert.assertEquals(0.0, zero.getPartialDerivative(i).getReal(), 1.0e-15);
600         }
601     }
602 
603     @Test
604     public void testOne() {
605         FieldGradient<T> one = build(17.0).getField().getOne();
606         Assert.assertEquals(1.0, one.getValue().getReal(), 1.0e-15);
607         for (int i = 0; i < one.getFreeParameters(); ++i) {
608             Assert.assertEquals(0.0, one.getPartialDerivative(i).getReal(), 1.0e-15);
609         }
610     }
611 
612     private void check(FieldGradient<T> g, double value, double... derivatives) {
613 
614         // check value
615         Assert.assertEquals(value, g.getReal(), 1.0e-15);
616 
617         // check derivatives
618         for (int i = 0; i < derivatives.length; ++i) {
619             Assert.assertEquals(derivatives[i], g.getPartialDerivative(i).getReal(), 1.0e-15);
620         }
621 
622     }
623 }