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