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