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.util;
18  
19  import java.util.Arrays;
20  
21  import org.hipparchus.CalculusFieldElement;
22  import org.hipparchus.Field;
23  import org.hipparchus.exception.MathIllegalArgumentException;
24  
25  /**
26   * This class allows to perform the same computation of all components of a Tuple at once.
27   * @param <T> the type of the field elements
28   * @since 1.2
29   */
30  public class FieldTuple<T extends CalculusFieldElement<T>> implements CalculusFieldElement<FieldTuple<T>> {
31  
32      /** Components of the tuple. */
33      private final T[] values;
34  
35      /** Field the instance belongs to. */
36      private final transient FieldTupleField<T> field;
37  
38      /** Creates a new instance from its components.
39       * @param x components of the tuple
40       */
41      @SafeVarargs
42      public FieldTuple(final T... x) {
43          this(new FieldTupleField<>(x[0].getField(), x.length), x.clone());
44      }
45  
46      /** Creates a new instance from its components.
47       * @param field field the instance belongs to
48       * @param x components of the tuple (beware, it is <em>not</em> copied, it is shared with caller)
49       */
50      private FieldTuple(final FieldTupleField<T> field, final T[] x) { // NOPMD - storing user-supplied array is intentional and documented here
51          this.values = x;
52          this.field  = field;
53      }
54  
55      /** {@inheritDoc} */
56      @Override
57      public FieldTuple<T> newInstance(final double value) {
58          @SuppressWarnings("unchecked")
59          final FieldTuple<T> t = new FieldTuple<>(field, (T[]) MathArrays.buildArray(field, values.length));
60          Arrays.fill(t.values, value);
61          return t;
62      }
63  
64      /** Get the dimension of the tuple.
65       * @return dimension of the tuple
66       */
67      public int getDimension() {
68          return values.length;
69      }
70  
71      /** Get one component of the tuple.
72       * @param index index of the component, between 0 and {@link #getDimension() getDimension()} - 1
73       * @return value of the component
74       */
75      public T getComponent(final int index) {
76          return values[index];
77      }
78  
79      /** Get all components of the tuple.
80       * @return all components
81       */
82      public T[] getComponents() {
83          return values.clone();
84      }
85  
86      /** {@inheritDoc} */
87      @Override
88      public Field<FieldTuple<T>> getField() {
89          return field;
90      }
91  
92      /** {@inheritDoc} */
93      @Override
94      public FieldTuple<T> add(final FieldTuple<T> a) {
95          final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
96          for (int i = 0; i < values.length; ++i) {
97              result.values[i] = values[i].add(a.values[i]);
98          }
99          return result;
100     }
101 
102     /** {@inheritDoc} */
103     @Override
104     public FieldTuple<T> subtract(final FieldTuple<T> a) {
105         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
106         for (int i = 0; i < values.length; ++i) {
107             result.values[i] = values[i].subtract(a.values[i]);
108         }
109         return result;
110     }
111 
112     /** {@inheritDoc} */
113     @Override
114     public FieldTuple<T> negate() {
115         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
116         for (int i = 0; i < values.length; ++i) {
117             result.values[i] = values[i].negate();
118         }
119         return result;
120     }
121 
122     /** {@inheritDoc} */
123     @Override
124     public FieldTuple<T> multiply(final FieldTuple<T> a) {
125         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
126         for (int i = 0; i < values.length; ++i) {
127             result.values[i] = values[i].multiply(a.values[i]);
128         }
129         return result;
130     }
131 
132     /** {@inheritDoc} */
133     @Override
134     public FieldTuple<T> multiply(final int n) {
135         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
136         for (int i = 0; i < values.length; ++i) {
137             result.values[i] = values[i].multiply(n);
138         }
139         return result;
140     }
141 
142     /** {@inheritDoc} */
143     @Override
144     public FieldTuple<T> divide(final FieldTuple<T> a) {
145         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
146         for (int i = 0; i < values.length; ++i) {
147             result.values[i] = values[i].divide(a.values[i]);
148         }
149         return result;
150     }
151 
152     /** {@inheritDoc} */
153     @Override
154     public FieldTuple<T> reciprocal() {
155         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
156         for (int i = 0; i < values.length; ++i) {
157             result.values[i] = values[i].reciprocal();
158         }
159         return result;
160     }
161 
162     /** {@inheritDoc} */
163     @Override
164     public boolean equals(final Object obj) {
165         if (obj instanceof FieldTuple<?> ) {
166             @SuppressWarnings("unchecked")
167             final FieldTuple<T> that = (FieldTuple<T>) obj;
168             if (getDimension() == that.getDimension()) {
169                 boolean equals = true;
170                 for (int i = 0; i < values.length; ++i) {
171                     equals &= values[i].equals(that.values[i]);
172                 }
173                 return equals;
174             }
175         }
176         return false;
177     }
178 
179     /** {@inheritDoc} */
180     @Override
181     public int hashCode() {
182         return  0x58f61de5 + Arrays.hashCode(values);
183     }
184 
185     /** {@inheritDoc} */
186     @Override
187     public double getReal() {
188         return values[0].getReal();
189     }
190 
191     /** {@inheritDoc} */
192     @Override
193     public FieldTuple<T> add(final double a) {
194         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
195         for (int i = 0; i < values.length; ++i) {
196             result.values[i] = values[i].add(a);
197         }
198         return result;
199     }
200 
201     /** {@inheritDoc} */
202     @Override
203     public FieldTuple<T> subtract(final double a) {
204         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
205         for (int i = 0; i < values.length; ++i) {
206             result.values[i] = values[i].subtract(a);
207         }
208         return result;
209     }
210 
211     /** {@inheritDoc} */
212     @Override
213     public FieldTuple<T> multiply(final double a) {
214         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
215         for (int i = 0; i < values.length; ++i) {
216             result.values[i] = values[i].multiply(a);
217         }
218         return result;
219     }
220 
221     /** {@inheritDoc} */
222     @Override
223     public FieldTuple<T> divide(final double a) {
224         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
225         for (int i = 0; i < values.length; ++i) {
226             result.values[i] = values[i].divide(a);
227         }
228         return result;
229     }
230 
231     /** {@inheritDoc} */
232     @Override
233     public FieldTuple<T> remainder(final double a) {
234         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
235         for (int i = 0; i < values.length; ++i) {
236             result.values[i] = values[i].remainder(a);
237         }
238         return result;
239     }
240 
241     /** {@inheritDoc} */
242     @Override
243     public FieldTuple<T> remainder(final FieldTuple<T> a) {
244         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
245         for (int i = 0; i < values.length; ++i) {
246             result.values[i] = values[i].remainder(a.values[i]);
247         }
248         return result;
249     }
250 
251     /** {@inheritDoc} */
252     @Override
253     public FieldTuple<T> abs() {
254         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
255         for (int i = 0; i < values.length; ++i) {
256             result.values[i] = values[i].abs();
257         }
258         return result;
259     }
260 
261     /** {@inheritDoc} */
262     @Override
263     public FieldTuple<T> ceil() {
264         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
265         for (int i = 0; i < values.length; ++i) {
266             result.values[i] = values[i].ceil();
267         }
268         return result;
269     }
270 
271     /** {@inheritDoc} */
272     @Override
273     public FieldTuple<T> floor() {
274         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
275         for (int i = 0; i < values.length; ++i) {
276             result.values[i] = values[i].floor();
277         }
278         return result;
279     }
280 
281     /** {@inheritDoc} */
282     @Override
283     public FieldTuple<T> rint() {
284         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
285         for (int i = 0; i < values.length; ++i) {
286             result.values[i] = values[i].rint();
287         }
288         return result;
289     }
290 
291     /** {@inheritDoc} */
292     @Override
293     public FieldTuple<T> sign() {
294         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
295         for (int i = 0; i < values.length; ++i) {
296             result.values[i] = values[i].sign();
297         }
298         return result;
299     }
300 
301     /** {@inheritDoc} */
302     @Override
303     public FieldTuple<T> copySign(final FieldTuple<T> sign) {
304         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
305         for (int i = 0; i < values.length; ++i) {
306             result.values[i] = values[i].copySign(sign.values[i]);
307         }
308         return result;
309     }
310 
311     /** {@inheritDoc} */
312     @Override
313     public FieldTuple<T> copySign(final double sign) {
314         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
315         for (int i = 0; i < values.length; ++i) {
316             result.values[i] = values[i].copySign(sign);
317         }
318         return result;
319     }
320 
321     /** {@inheritDoc} */
322     @Override
323     public FieldTuple<T> scalb(final int n) {
324         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
325         for (int i = 0; i < values.length; ++i) {
326             result.values[i] = values[i].scalb(n);
327         }
328         return result;
329     }
330 
331     /** {@inheritDoc} */
332     @Override
333     public FieldTuple<T> ulp() {
334         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
335         for (int i = 0; i < values.length; ++i) {
336             result.values[i] = values[i].ulp();
337         }
338         return result;
339     }
340 
341     /** {@inheritDoc} */
342     @Override
343     public FieldTuple<T> hypot(final FieldTuple<T> y) {
344         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
345         for (int i = 0; i < values.length; ++i) {
346             result.values[i] = values[i].hypot(y.values[i]);
347         }
348         return result;
349     }
350 
351     /** {@inheritDoc} */
352     @Override
353     public FieldTuple<T> sqrt() {
354         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
355         for (int i = 0; i < values.length; ++i) {
356             result.values[i] = values[i].sqrt();
357         }
358         return result;
359     }
360 
361     /** {@inheritDoc} */
362     @Override
363     public FieldTuple<T> cbrt() {
364         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
365         for (int i = 0; i < values.length; ++i) {
366             result.values[i] = values[i].cbrt();
367         }
368         return result;
369     }
370 
371     /** {@inheritDoc} */
372     @Override
373     public FieldTuple<T> rootN(final int n) {
374         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
375         for (int i = 0; i < values.length; ++i) {
376             result.values[i] = values[i].rootN(n);
377         }
378         return result;
379     }
380 
381     /** {@inheritDoc} */
382     @Override
383     public FieldTuple<T> pow(final double p) {
384         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
385         for (int i = 0; i < values.length; ++i) {
386             result.values[i] = values[i].pow(p);
387         }
388         return result;
389     }
390 
391     /** {@inheritDoc} */
392     @Override
393     public FieldTuple<T> pow(final int n) {
394         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
395         for (int i = 0; i < values.length; ++i) {
396             result.values[i] = values[i].pow(n);
397         }
398         return result;
399     }
400 
401     /** {@inheritDoc} */
402     @Override
403     public FieldTuple<T> pow(final FieldTuple<T> e) {
404         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
405         for (int i = 0; i < values.length; ++i) {
406             result.values[i] = values[i].pow(e.values[i]);
407         }
408         return result;
409     }
410 
411     /** {@inheritDoc} */
412     @Override
413     public FieldTuple<T> exp() {
414         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
415         for (int i = 0; i < values.length; ++i) {
416             result.values[i] = values[i].exp();
417         }
418         return result;
419     }
420 
421     /** {@inheritDoc} */
422     @Override
423     public FieldTuple<T> expm1() {
424         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
425         for (int i = 0; i < values.length; ++i) {
426             result.values[i] = values[i].expm1();
427         }
428         return result;
429     }
430 
431     /** {@inheritDoc} */
432     @Override
433     public FieldTuple<T> log() {
434         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
435         for (int i = 0; i < values.length; ++i) {
436             result.values[i] = values[i].log();
437         }
438         return result;
439     }
440 
441     /** {@inheritDoc} */
442     @Override
443     public FieldTuple<T> log1p() {
444         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
445         for (int i = 0; i < values.length; ++i) {
446             result.values[i] = values[i].log1p();
447         }
448         return result;
449     }
450 
451     /** {@inheritDoc} */
452     @Override
453     public FieldTuple<T> log10() {
454         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
455         for (int i = 0; i < values.length; ++i) {
456             result.values[i] = values[i].log10();
457         }
458         return result;
459     }
460 
461     /** {@inheritDoc} */
462     @Override
463     public FieldTuple<T> cos() {
464         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
465         for (int i = 0; i < values.length; ++i) {
466             result.values[i] = values[i].cos();
467         }
468         return result;
469     }
470 
471     /** {@inheritDoc} */
472     @Override
473     public FieldTuple<T> sin() {
474         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
475         for (int i = 0; i < values.length; ++i) {
476             result.values[i] = values[i].sin();
477         }
478         return result;
479     }
480 
481     /** {@inheritDoc} */
482     @Override
483     public FieldSinCos<FieldTuple<T>> sinCos() {
484         final FieldTuple<T> sin = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
485         final FieldTuple<T> cos = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
486         for (int i = 0; i < values.length; ++i) {
487             final FieldSinCos<T> sc = FastMath.sinCos(values[i]);
488             sin.values[i] = sc.sin();
489             cos.values[i] = sc.cos();
490         }
491         return new FieldSinCos<>(sin, cos);
492     }
493 
494     /** {@inheritDoc} */
495     @Override
496     public FieldTuple<T> tan() {
497         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
498         for (int i = 0; i < values.length; ++i) {
499             result.values[i] = values[i].tan();
500         }
501         return result;
502     }
503 
504     /** {@inheritDoc} */
505     @Override
506     public FieldTuple<T> acos() {
507         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
508         for (int i = 0; i < values.length; ++i) {
509             result.values[i] = values[i].acos();
510         }
511         return result;
512     }
513 
514     /** {@inheritDoc} */
515     @Override
516     public FieldTuple<T> asin() {
517         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
518         for (int i = 0; i < values.length; ++i) {
519             result.values[i] = values[i].asin();
520         }
521         return result;
522     }
523 
524     /** {@inheritDoc} */
525     @Override
526     public FieldTuple<T> atan() {
527         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
528         for (int i = 0; i < values.length; ++i) {
529             result.values[i] = values[i].atan();
530         }
531         return result;
532     }
533 
534     /** {@inheritDoc} */
535     @Override
536     public FieldTuple<T> atan2(final FieldTuple<T> x) {
537         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
538         for (int i = 0; i < values.length; ++i) {
539             result.values[i] = values[i].atan2(x.values[i]);
540         }
541         return result;
542     }
543 
544     /** {@inheritDoc} */
545     @Override
546     public FieldTuple<T> cosh() {
547         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
548         for (int i = 0; i < values.length; ++i) {
549             result.values[i] = values[i].cosh();
550         }
551         return result;
552     }
553 
554     /** {@inheritDoc} */
555     @Override
556     public FieldTuple<T> sinh() {
557         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
558         for (int i = 0; i < values.length; ++i) {
559             result.values[i] = values[i].sinh();
560         }
561         return result;
562     }
563 
564     /** {@inheritDoc} */
565     @Override
566     public FieldSinhCosh<FieldTuple<T>> sinhCosh() {
567         final FieldTuple<T> sinh = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
568         final FieldTuple<T> cosh = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
569         for (int i = 0; i < values.length; ++i) {
570             final FieldSinhCosh<T> sc = FastMath.sinhCosh(values[i]);
571             sinh.values[i] = sc.sinh();
572             cosh.values[i] = sc.cosh();
573         }
574         return new FieldSinhCosh<>(sinh, cosh);
575     }
576 
577     /** {@inheritDoc} */
578     @Override
579     public FieldTuple<T> tanh() {
580         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
581         for (int i = 0; i < values.length; ++i) {
582             result.values[i] = values[i].tanh();
583         }
584         return result;
585     }
586 
587     /** {@inheritDoc} */
588     @Override
589     public FieldTuple<T> acosh() {
590         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
591         for (int i = 0; i < values.length; ++i) {
592             result.values[i] = values[i].acosh();
593         }
594         return result;
595     }
596 
597     /** {@inheritDoc} */
598     @Override
599     public FieldTuple<T> asinh() {
600         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
601         for (int i = 0; i < values.length; ++i) {
602             result.values[i] = values[i].asinh();
603         }
604         return result;
605     }
606 
607     /** {@inheritDoc} */
608     @Override
609     public FieldTuple<T> atanh() {
610         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
611         for (int i = 0; i < values.length; ++i) {
612             result.values[i] = values[i].atanh();
613         }
614         return result;
615     }
616 
617     /** {@inheritDoc} */
618     @Override
619     public FieldTuple<T> toDegrees() {
620         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
621         for (int i = 0; i < values.length; ++i) {
622             result.values[i] = values[i].toDegrees();
623         }
624         return result;
625     }
626 
627     /** {@inheritDoc} */
628     @Override
629     public FieldTuple<T> toRadians() {
630         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
631         for (int i = 0; i < values.length; ++i) {
632             result.values[i] = values[i].toRadians();
633         }
634         return result;
635     }
636 
637     /** {@inheritDoc} */
638     @Override
639     public FieldTuple<T> linearCombination(final FieldTuple<T>[] a, final FieldTuple<T>[] b)
640         throws MathIllegalArgumentException {
641         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
642         MathUtils.checkDimension(a.length, b.length);
643         final T[] aT = MathArrays.buildArray(values[0].getField(), a.length);
644         final T[] bT = MathArrays.buildArray(values[0].getField(), b.length);
645         for (int i = 0; i < values.length; ++i) {
646             for (int j = 0; j < a.length; ++j) {
647                 aT[j] = a[j].values[i];
648                 bT[j] = b[j].values[i];
649             }
650             result.values[i] = aT[0].linearCombination(aT, bT);
651         }
652         return result;
653     }
654 
655     /** {@inheritDoc} */
656     @Override
657     public FieldTuple<T> linearCombination(final double[] a, final FieldTuple<T>[] b)
658         throws MathIllegalArgumentException {
659         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
660         MathUtils.checkDimension(a.length, b.length);
661         final T[] bT = MathArrays.buildArray(values[0].getField(), b.length);
662         for (int i = 0; i < values.length; ++i) {
663             for (int j = 0; j < a.length; ++j) {
664                 bT[j] = b[j].values[i];
665             }
666             result.values[i] = bT[0].linearCombination(a, bT);
667         }
668         return result;
669     }
670 
671     /** {@inheritDoc} */
672     @Override
673     public FieldTuple<T> linearCombination(final FieldTuple<T> a1, final FieldTuple<T> b1,
674                                            final FieldTuple<T> a2, final FieldTuple<T> b2) {
675         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
676         for (int i = 0; i < values.length; ++i) {
677             result.values[i] = a1.values[0].linearCombination(a1.values[i], b1.values[i],
678                                                               a2.values[i], b2.values[i]);
679         }
680         return result;
681     }
682 
683     /** {@inheritDoc} */
684     @Override
685     public FieldTuple<T> linearCombination(final double a1, final FieldTuple<T> b1,
686                                            final double a2, final FieldTuple<T> b2) {
687         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
688         for (int i = 0; i < values.length; ++i) {
689             result.values[i] = b1.values[0].linearCombination(a1, b1.values[i],
690                                                               a2, b2.values[i]);
691         }
692         return result;
693     }
694 
695     /** {@inheritDoc} */
696     @Override
697     public FieldTuple<T> linearCombination(final FieldTuple<T> a1, final FieldTuple<T> b1,
698                                            final FieldTuple<T> a2, final FieldTuple<T> b2,
699                                            final FieldTuple<T> a3, final FieldTuple<T> b3) {
700         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
701         for (int i = 0; i < values.length; ++i) {
702             result.values[i] = a1.values[0].linearCombination(a1.values[i], b1.values[i],
703                                                               a2.values[i], b2.values[i],
704                                                               a3.values[i], b3.values[i]);
705         }
706         return result;
707     }
708 
709     /** {@inheritDoc} */
710     @Override
711     public FieldTuple<T> linearCombination(final double a1, final FieldTuple<T> b1,
712                                            final double a2, final FieldTuple<T> b2,
713                                            final double a3, final FieldTuple<T> b3) {
714         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
715         for (int i = 0; i < values.length; ++i) {
716             result.values[i] = b1.values[0].linearCombination(a1, b1.values[i],
717                                                               a2, b2.values[i],
718                                                               a3, b3.values[i]);
719         }
720         return result;
721     }
722 
723     /** {@inheritDoc} */
724     @Override
725     public FieldTuple<T> linearCombination(final FieldTuple<T> a1, final FieldTuple<T> b1,
726                                            final FieldTuple<T> a2, final FieldTuple<T> b2,
727                                            final FieldTuple<T> a3, final FieldTuple<T> b3,
728                                            final FieldTuple<T> a4, final FieldTuple<T> b4) {
729         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
730         for (int i = 0; i < values.length; ++i) {
731             result.values[i] = a1.values[0].linearCombination(a1.values[i], b1.values[i],
732                                                               a2.values[i], b2.values[i],
733                                                               a3.values[i], b3.values[i],
734                                                               a4.values[i], b4.values[i]);
735         }
736         return result;
737     }
738 
739     /** {@inheritDoc} */
740     @Override
741     public FieldTuple<T> linearCombination(final double a1, final FieldTuple<T> b1,
742                                            final double a2, final FieldTuple<T> b2,
743                                            final double a3, final FieldTuple<T> b3,
744                                            final double a4, final FieldTuple<T> b4) {
745         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
746         for (int i = 0; i < values.length; ++i) {
747             result.values[i] = b1.values[0].linearCombination(a1, b1.values[i],
748                                                               a2, b2.values[i],
749                                                               a3, b3.values[i],
750                                                               a4, b4.values[i]);
751         }
752         return result;
753     }
754 
755     /** {@inheritDoc} */
756     @Override
757     public FieldTuple<T> getPi() {
758         final FieldTuple<T> result = new FieldTuple<>(field, MathArrays.buildArray(values[0].getField(), values.length));
759         Arrays.fill(result.values, values[0].getPi());
760         return result;
761     }
762 
763     /** Field for {link FieldTuple} instances.
764      * @param <T> the type of the field elements
765      */
766     private static class FieldTupleField<T extends CalculusFieldElement<T>> implements Field<FieldTuple<T>> {
767 
768         /** Constant function evaluating to 0.0. */
769         private final FieldTuple<T> zero;
770 
771         /** Constant function evaluating to 1.0. */
772         private final FieldTuple<T> one;
773 
774         /** Simple constructor.
775          * @param field field to which the elements belong
776          * @param dimension dimension of the tuple
777          */
778         FieldTupleField(final Field<T> field, final int dimension) {
779             final T[] zeroData = MathArrays.buildArray(field, dimension);
780             Arrays.fill(zeroData, field.getZero());
781             final T[] oneData  = MathArrays.buildArray(field, dimension);
782             Arrays.fill(oneData, field.getOne());
783             this.zero = new FieldTuple<>(this, zeroData);
784             this.one  = new FieldTuple<>(this, oneData);
785         }
786 
787         /** {@inheritDoc} */
788         @Override
789         public FieldTuple<T> getZero() {
790             return zero;
791         }
792 
793         /** {@inheritDoc} */
794         @Override
795         public FieldTuple<T> getOne() {
796             return one;
797         }
798 
799         /** {@inheritDoc} */
800         @SuppressWarnings("unchecked")
801         @Override
802         public Class<FieldTuple<T>> getRuntimeClass() {
803             return (Class<FieldTuple<T>>) zero.getClass();
804         }
805 
806         /** {@inheritDoc} */
807         @Override
808         public boolean equals(final Object other) {
809             if (other instanceof FieldTupleField) {
810                 @SuppressWarnings("unchecked")
811                 final FieldTupleField<T> that = (FieldTupleField<T>) other;
812                 return zero.getDimension() == that.zero.getDimension();
813             } else {
814                 return false;
815             }
816         }
817 
818         /** {@inheritDoc} */
819         @Override
820         public int hashCode() {
821             return 0xb4a533e1 ^ zero.getDimension();
822         }
823 
824     }
825 
826 }