1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  package org.apache.commons.math4.legacy.analysis.differentiation;
18  
19  import java.util.Arrays;
20  
21  import org.apache.commons.numbers.core.Sum;
22  import org.apache.commons.math4.legacy.core.Field;
23  import org.apache.commons.math4.legacy.core.FieldElement;
24  import org.apache.commons.math4.legacy.core.RealFieldElement;
25  import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
26  import org.apache.commons.math4.legacy.exception.NumberIsTooLargeException;
27  import org.apache.commons.math4.core.jdkmath.JdkMath;
28  import org.apache.commons.math4.legacy.core.MathArrays;
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  public class DerivativeStructure implements RealFieldElement<DerivativeStructure> {
61      
62      private DSCompiler compiler;
63  
64      
65      private final double[] data;
66  
67      
68  
69  
70      private DerivativeStructure(final DSCompiler compiler) {
71          this.compiler = compiler;
72          this.data     = new double[compiler.getSize()];
73      }
74  
75      
76  
77  
78  
79  
80      public DerivativeStructure(final int parameters, final int order) {
81          this(DSCompiler.getCompiler(parameters, order));
82      }
83  
84      
85  
86  
87  
88  
89  
90  
91      public DerivativeStructure(final int parameters, final int order, final double value) {
92          this(parameters, order);
93          this.data[0] = value;
94      }
95  
96      
97  
98  
99  
100 
101 
102 
103 
104 
105 
106 
107 
108     public DerivativeStructure(final int parameters, final int order,
109                                final int index, final double value) {
110         this(parameters, order, value);
111 
112         if (index >= parameters) {
113             throw new NumberIsTooLargeException(index, parameters, false);
114         }
115 
116         if (order > 0) {
117             
118             data[DSCompiler.getCompiler(index, order).getSize()] = 1.0;
119         }
120     }
121 
122     
123 
124 
125 
126 
127 
128 
129 
130 
131     public DerivativeStructure(final double a1, final DerivativeStructure ds1,
132                                final double a2, final DerivativeStructure ds2) {
133         this(ds1.compiler);
134         compiler.checkCompatibility(ds2.compiler);
135         compiler.linearCombination(a1, ds1.data, 0, a2, ds2.data, 0, data, 0);
136     }
137 
138     
139 
140 
141 
142 
143 
144 
145 
146 
147 
148 
149     public DerivativeStructure(final double a1, final DerivativeStructure ds1,
150                                final double a2, final DerivativeStructure ds2,
151                                final double a3, final DerivativeStructure ds3) {
152         this(ds1.compiler);
153         compiler.checkCompatibility(ds2.compiler);
154         compiler.checkCompatibility(ds3.compiler);
155         compiler.linearCombination(a1, ds1.data, 0, a2, ds2.data, 0, a3, ds3.data, 0, data, 0);
156     }
157 
158     
159 
160 
161 
162 
163 
164 
165 
166 
167 
168 
169 
170     public DerivativeStructure(final double a1, final DerivativeStructure ds1,
171                                final double a2, final DerivativeStructure ds2,
172                                final double a3, final DerivativeStructure ds3,
173                                final double a4, final DerivativeStructure ds4) {
174         this(ds1.compiler);
175         compiler.checkCompatibility(ds2.compiler);
176         compiler.checkCompatibility(ds3.compiler);
177         compiler.checkCompatibility(ds4.compiler);
178         compiler.linearCombination(a1, ds1.data, 0, a2, ds2.data, 0,
179                                    a3, ds3.data, 0, a4, ds4.data, 0,
180                                    data, 0);
181     }
182 
183     
184 
185 
186 
187 
188 
189 
190 
191 
192 
193     public DerivativeStructure(final int parameters, final int order, final double ... derivatives) {
194         this(parameters, order);
195         if (derivatives.length != data.length) {
196             throw new DimensionMismatchException(derivatives.length, data.length);
197         }
198         System.arraycopy(derivatives, 0, data, 0, data.length);
199     }
200 
201     
202 
203 
204     private DerivativeStructure(final DerivativeStructure ds) {
205         this.compiler = ds.compiler;
206         this.data     = ds.data.clone();
207     }
208 
209     
210 
211 
212     public int getFreeParameters() {
213         return compiler.getFreeParameters();
214     }
215 
216     
217 
218 
219     public int getOrder() {
220         return compiler.getOrder();
221     }
222 
223     
224 
225 
226 
227 
228 
229 
230 
231 
232 
233     public DerivativeStructure createConstant(final double c) {
234         return new DerivativeStructure(getFreeParameters(), getOrder(), c);
235     }
236 
237     
238 
239 
240     @Override
241     public double getReal() {
242         return data[0];
243     }
244 
245     
246 
247 
248 
249     public double getValue() {
250         return data[0];
251     }
252 
253     
254 
255 
256 
257 
258 
259 
260 
261 
262 
263     public double getPartialDerivative(final int ... orders) {
264         return data[compiler.getPartialDerivativeIndex(orders)];
265     }
266 
267     
268 
269 
270 
271     public double[] getAllDerivatives() {
272         return data.clone();
273     }
274 
275     
276 
277 
278     @Override
279     public DerivativeStructure add(final double a) {
280         final DerivativeStructure ds = new DerivativeStructure(this);
281         ds.data[0] += a;
282         return ds;
283     }
284 
285     
286 
287 
288 
289     @Override
290     public DerivativeStructure add(final DerivativeStructure a) {
291         compiler.checkCompatibility(a.compiler);
292         final DerivativeStructure ds = new DerivativeStructure(this);
293         compiler.add(data, 0, a.data, 0, ds.data, 0);
294         return ds;
295     }
296 
297     
298 
299 
300     @Override
301     public DerivativeStructure subtract(final double a) {
302         return add(-a);
303     }
304 
305     
306 
307 
308 
309     @Override
310     public DerivativeStructure subtract(final DerivativeStructure a) {
311         compiler.checkCompatibility(a.compiler);
312         final DerivativeStructure ds = new DerivativeStructure(this);
313         compiler.subtract(data, 0, a.data, 0, ds.data, 0);
314         return ds;
315     }
316 
317     
318     @Override
319     public DerivativeStructure multiply(final int n) {
320         return multiply((double) n);
321     }
322 
323     
324 
325 
326     @Override
327     public DerivativeStructure multiply(final double a) {
328         final DerivativeStructure ds = new DerivativeStructure(this);
329         for (int i = 0; i < ds.data.length; ++i) {
330             ds.data[i] *= a;
331         }
332         return ds;
333     }
334 
335     
336 
337 
338 
339     @Override
340     public DerivativeStructure multiply(final DerivativeStructure a) {
341         compiler.checkCompatibility(a.compiler);
342         final DerivativeStructure result = new DerivativeStructure(compiler);
343         compiler.multiply(data, 0, a.data, 0, result.data, 0);
344         return result;
345     }
346 
347     
348 
349 
350     @Override
351     public DerivativeStructure divide(final double a) {
352         final DerivativeStructure ds = new DerivativeStructure(this);
353         for (int i = 0; i < ds.data.length; ++i) {
354             ds.data[i] /= a;
355         }
356         return ds;
357     }
358 
359     
360 
361 
362 
363     @Override
364     public DerivativeStructure divide(final DerivativeStructure a) {
365         compiler.checkCompatibility(a.compiler);
366         final DerivativeStructure result = new DerivativeStructure(compiler);
367         compiler.divide(data, 0, a.data, 0, result.data, 0);
368         return result;
369     }
370 
371     
372     @Override
373     public DerivativeStructure remainder(final double a) {
374         final DerivativeStructure ds = new DerivativeStructure(this);
375         ds.data[0] = JdkMath.IEEEremainder(ds.data[0], a);
376         return ds;
377     }
378 
379     
380 
381 
382 
383 
384     @Override
385     public DerivativeStructure remainder(final DerivativeStructure a) {
386         compiler.checkCompatibility(a.compiler);
387         final DerivativeStructure result = new DerivativeStructure(compiler);
388         compiler.remainder(data, 0, a.data, 0, result.data, 0);
389         return result;
390     }
391 
392     
393     @Override
394     public DerivativeStructure negate() {
395         final DerivativeStructure ds = new DerivativeStructure(compiler);
396         for (int i = 0; i < ds.data.length; ++i) {
397             ds.data[i] = -data[i];
398         }
399         return ds;
400     }
401 
402     
403 
404 
405     @Override
406     public DerivativeStructure abs() {
407         if (Double.doubleToLongBits(data[0]) < 0) {
408             
409             return negate();
410         } else {
411             return this;
412         }
413     }
414 
415     
416 
417 
418     @Override
419     public DerivativeStructure ceil() {
420         return new DerivativeStructure(compiler.getFreeParameters(),
421                                        compiler.getOrder(),
422                                        JdkMath.ceil(data[0]));
423     }
424 
425     
426 
427 
428     @Override
429     public DerivativeStructure floor() {
430         return new DerivativeStructure(compiler.getFreeParameters(),
431                                        compiler.getOrder(),
432                                        JdkMath.floor(data[0]));
433     }
434 
435     
436 
437 
438     @Override
439     public DerivativeStructure rint() {
440         return new DerivativeStructure(compiler.getFreeParameters(),
441                                        compiler.getOrder(),
442                                        JdkMath.rint(data[0]));
443     }
444 
445     
446     @Override
447     public long round() {
448         return JdkMath.round(data[0]);
449     }
450 
451     
452 
453 
454     @Override
455     public DerivativeStructure signum() {
456         return new DerivativeStructure(compiler.getFreeParameters(),
457                                        compiler.getOrder(),
458                                        JdkMath.signum(data[0]));
459     }
460 
461     
462 
463 
464     @Override
465     public DerivativeStructure copySign(final DerivativeStructure sign){
466         long m = Double.doubleToLongBits(data[0]);
467         long s = Double.doubleToLongBits(sign.data[0]);
468         if ((m >= 0 && s >= 0) || (m < 0 && s < 0)) { 
469             return this;
470         }
471         return negate(); 
472     }
473 
474     
475 
476 
477     @Override
478     public DerivativeStructure copySign(final double sign) {
479         long m = Double.doubleToLongBits(data[0]);
480         long s = Double.doubleToLongBits(sign);
481         if ((m >= 0 && s >= 0) || (m < 0 && s < 0)) { 
482             return this;
483         }
484         return negate(); 
485     }
486 
487     
488 
489 
490 
491 
492 
493 
494 
495     public int getExponent() {
496         return JdkMath.getExponent(data[0]);
497     }
498 
499     
500 
501 
502     @Override
503     public DerivativeStructure scalb(final int n) {
504         final DerivativeStructure ds = new DerivativeStructure(compiler);
505         for (int i = 0; i < ds.data.length; ++i) {
506             ds.data[i] = JdkMath.scalb(data[i], n);
507         }
508         return ds;
509     }
510 
511     
512 
513 
514 
515 
516     @Override
517     public DerivativeStructure hypot(final DerivativeStructure y) {
518         compiler.checkCompatibility(y.compiler);
519 
520         if (Double.isInfinite(data[0]) || Double.isInfinite(y.data[0])) {
521             return new DerivativeStructure(compiler.getFreeParameters(),
522                                            compiler.getFreeParameters(),
523                                            Double.POSITIVE_INFINITY);
524         } else if (Double.isNaN(data[0]) || Double.isNaN(y.data[0])) {
525             return new DerivativeStructure(compiler.getFreeParameters(),
526                                            compiler.getFreeParameters(),
527                                            Double.NaN);
528         } else {
529 
530             final int expX = getExponent();
531             final int expY = y.getExponent();
532             if (expX > expY + 27) {
533                 
534                 return abs();
535             } else if (expY > expX + 27) {
536                 
537                 return y.abs();
538             } else {
539 
540                 
541                 final int middleExp = (expX + expY) / 2;
542 
543                 
544                 final DerivativeStructure scaledX = scalb(-middleExp);
545                 final DerivativeStructure scaledY = y.scalb(-middleExp);
546 
547                 
548                 final DerivativeStructure scaledH =
549                         scaledX.multiply(scaledX).add(scaledY.multiply(scaledY)).sqrt();
550 
551                 
552                 return scaledH.scalb(middleExp);
553             }
554         }
555     }
556 
557     
558 
559 
560 
561 
562 
563 
564 
565 
566 
567 
568 
569 
570 
571 
572 
573 
574     public static DerivativeStructure hypot(final DerivativeStructure x, final DerivativeStructure y) {
575         return x.hypot(y);
576     }
577 
578     
579 
580 
581 
582 
583 
584 
585 
586     public DerivativeStructure compose(final double ... f) {
587         if (f.length != getOrder() + 1) {
588             throw new DimensionMismatchException(f.length, getOrder() + 1);
589         }
590         final DerivativeStructure result = new DerivativeStructure(compiler);
591         compiler.compose(data, 0, f, result.data, 0);
592         return result;
593     }
594 
595     
596     @Override
597     public DerivativeStructure reciprocal() {
598         final DerivativeStructure result = new DerivativeStructure(compiler);
599         compiler.pow(data, 0, -1, result.data, 0);
600         return result;
601     }
602 
603     
604 
605 
606     @Override
607     public DerivativeStructure sqrt() {
608         return rootN(2);
609     }
610 
611     
612 
613 
614     @Override
615     public DerivativeStructure cbrt() {
616         return rootN(3);
617     }
618 
619     
620 
621 
622     @Override
623     public DerivativeStructure rootN(final int n) {
624         final DerivativeStructure result = new DerivativeStructure(compiler);
625         compiler.rootN(data, 0, n, result.data, 0);
626         return result;
627     }
628 
629     
630     @Override
631     public Field<DerivativeStructure> getField() {
632         return new Field<DerivativeStructure>() {
633 
634             
635             @Override
636             public DerivativeStructure getZero() {
637                 return new DerivativeStructure(compiler.getFreeParameters(), compiler.getOrder(), 0.0);
638             }
639 
640             
641             @Override
642             public DerivativeStructure getOne() {
643                 return new DerivativeStructure(compiler.getFreeParameters(), compiler.getOrder(), 1.0);
644             }
645 
646             
647             @Override
648             public Class<? extends FieldElement<DerivativeStructure>> getRuntimeClass() {
649                 return DerivativeStructure.class;
650             }
651         };
652     }
653 
654     
655 
656 
657 
658 
659 
660     public static DerivativeStructure pow(final double a, final DerivativeStructure x) {
661         final DerivativeStructure result = new DerivativeStructure(x.compiler);
662         x.compiler.pow(a, x.data, 0, result.data, 0);
663         return result;
664     }
665 
666     
667 
668 
669     @Override
670     public DerivativeStructure pow(final double p) {
671         final DerivativeStructure result = new DerivativeStructure(compiler);
672         compiler.pow(data, 0, p, result.data, 0);
673         return result;
674     }
675 
676     
677 
678 
679     @Override
680     public DerivativeStructure pow(final int n) {
681         final DerivativeStructure result = new DerivativeStructure(compiler);
682         compiler.pow(data, 0, n, result.data, 0);
683         return result;
684     }
685 
686     
687 
688 
689 
690 
691     @Override
692     public DerivativeStructure pow(final DerivativeStructure e) {
693         compiler.checkCompatibility(e.compiler);
694         final DerivativeStructure result = new DerivativeStructure(compiler);
695         compiler.pow(data, 0, e.data, 0, result.data, 0);
696         return result;
697     }
698 
699     
700 
701 
702     @Override
703     public DerivativeStructure exp() {
704         final DerivativeStructure result = new DerivativeStructure(compiler);
705         compiler.exp(data, 0, result.data, 0);
706         return result;
707     }
708 
709     
710 
711 
712     @Override
713     public DerivativeStructure expm1() {
714         final DerivativeStructure result = new DerivativeStructure(compiler);
715         compiler.expm1(data, 0, result.data, 0);
716         return result;
717     }
718 
719     
720 
721 
722     @Override
723     public DerivativeStructure log() {
724         final DerivativeStructure result = new DerivativeStructure(compiler);
725         compiler.log(data, 0, result.data, 0);
726         return result;
727     }
728 
729     
730 
731 
732     @Override
733     public DerivativeStructure log1p() {
734         final DerivativeStructure result = new DerivativeStructure(compiler);
735         compiler.log1p(data, 0, result.data, 0);
736         return result;
737     }
738 
739     
740 
741 
742     @Override
743     public DerivativeStructure log10() {
744         final DerivativeStructure result = new DerivativeStructure(compiler);
745         compiler.log10(data, 0, result.data, 0);
746         return result;
747     }
748 
749     
750 
751 
752     @Override
753     public DerivativeStructure cos() {
754         final DerivativeStructure result = new DerivativeStructure(compiler);
755         compiler.cos(data, 0, result.data, 0);
756         return result;
757     }
758 
759     
760 
761 
762     @Override
763     public DerivativeStructure sin() {
764         final DerivativeStructure result = new DerivativeStructure(compiler);
765         compiler.sin(data, 0, result.data, 0);
766         return result;
767     }
768 
769     
770 
771 
772     @Override
773     public DerivativeStructure tan() {
774         final DerivativeStructure result = new DerivativeStructure(compiler);
775         compiler.tan(data, 0, result.data, 0);
776         return result;
777     }
778 
779     
780 
781 
782     @Override
783     public DerivativeStructure acos() {
784         final DerivativeStructure result = new DerivativeStructure(compiler);
785         compiler.acos(data, 0, result.data, 0);
786         return result;
787     }
788 
789     
790 
791 
792     @Override
793     public DerivativeStructure asin() {
794         final DerivativeStructure result = new DerivativeStructure(compiler);
795         compiler.asin(data, 0, result.data, 0);
796         return result;
797     }
798 
799     
800 
801 
802     @Override
803     public DerivativeStructure atan() {
804         final DerivativeStructure result = new DerivativeStructure(compiler);
805         compiler.atan(data, 0, result.data, 0);
806         return result;
807     }
808 
809     
810 
811 
812     @Override
813     public DerivativeStructure atan2(final DerivativeStructure x) {
814         compiler.checkCompatibility(x.compiler);
815         final DerivativeStructure result = new DerivativeStructure(compiler);
816         compiler.atan2(data, 0, x.data, 0, result.data, 0);
817         return result;
818     }
819 
820     
821 
822 
823 
824 
825 
826 
827 
828     public static DerivativeStructure atan2(final DerivativeStructure y, final DerivativeStructure x) {
829         return y.atan2(x);
830     }
831 
832     
833 
834 
835     @Override
836     public DerivativeStructure cosh() {
837         final DerivativeStructure result = new DerivativeStructure(compiler);
838         compiler.cosh(data, 0, result.data, 0);
839         return result;
840     }
841 
842     
843 
844 
845     @Override
846     public DerivativeStructure sinh() {
847         final DerivativeStructure result = new DerivativeStructure(compiler);
848         compiler.sinh(data, 0, result.data, 0);
849         return result;
850     }
851 
852     
853 
854 
855     @Override
856     public DerivativeStructure tanh() {
857         final DerivativeStructure result = new DerivativeStructure(compiler);
858         compiler.tanh(data, 0, result.data, 0);
859         return result;
860     }
861 
862     
863 
864 
865     @Override
866     public DerivativeStructure acosh() {
867         final DerivativeStructure result = new DerivativeStructure(compiler);
868         compiler.acosh(data, 0, result.data, 0);
869         return result;
870     }
871 
872     
873 
874 
875     @Override
876     public DerivativeStructure asinh() {
877         final DerivativeStructure result = new DerivativeStructure(compiler);
878         compiler.asinh(data, 0, result.data, 0);
879         return result;
880     }
881 
882     
883 
884 
885     @Override
886     public DerivativeStructure atanh() {
887         final DerivativeStructure result = new DerivativeStructure(compiler);
888         compiler.atanh(data, 0, result.data, 0);
889         return result;
890     }
891 
892     
893 
894 
895     public DerivativeStructure toDegrees() {
896         final DerivativeStructure ds = new DerivativeStructure(compiler);
897         for (int i = 0; i < ds.data.length; ++i) {
898             ds.data[i] = JdkMath.toDegrees(data[i]);
899         }
900         return ds;
901     }
902 
903     
904 
905 
906     public DerivativeStructure toRadians() {
907         final DerivativeStructure ds = new DerivativeStructure(compiler);
908         for (int i = 0; i < ds.data.length; ++i) {
909             ds.data[i] = JdkMath.toRadians(data[i]);
910         }
911         return ds;
912     }
913 
914     
915 
916 
917 
918 
919 
920     public double taylor(final double ... delta) {
921         return compiler.taylor(data, 0, delta);
922     }
923 
924     
925 
926 
927 
928 
929     @Override
930     public DerivativeStructure linearCombination(final DerivativeStructure[] a, final DerivativeStructure[] b) {
931         
932         final double[] aDouble = new double[a.length];
933         for (int i = 0; i < a.length; ++i) {
934             aDouble[i] = a[i].getValue();
935         }
936         final double[] bDouble = new double[b.length];
937         for (int i = 0; i < b.length; ++i) {
938             bDouble[i] = b[i].getValue();
939         }
940         final double accurateValue = Sum.ofProducts(aDouble, bDouble).getAsDouble();
941 
942         
943         DerivativeStructure simpleValue = a[0].getField().getZero();
944         for (int i = 0; i < a.length; ++i) {
945             simpleValue = simpleValue.add(a[i].multiply(b[i]));
946         }
947 
948         
949         final double[] all = simpleValue.getAllDerivatives();
950         all[0] = accurateValue;
951         return new DerivativeStructure(simpleValue.getFreeParameters(), simpleValue.getOrder(), all);
952     }
953 
954     
955 
956 
957 
958 
959     @Override
960     public DerivativeStructure linearCombination(final double[] a, final DerivativeStructure[] b) {
961         
962         final double[] bDouble = new double[b.length];
963         for (int i = 0; i < b.length; ++i) {
964             bDouble[i] = b[i].getValue();
965         }
966         final double accurateValue = Sum.ofProducts(a, bDouble).getAsDouble();
967 
968         
969         DerivativeStructure simpleValue = b[0].getField().getZero();
970         for (int i = 0; i < a.length; ++i) {
971             simpleValue = simpleValue.add(b[i].multiply(a[i]));
972         }
973 
974         
975         final double[] all = simpleValue.getAllDerivatives();
976         all[0] = accurateValue;
977         return new DerivativeStructure(simpleValue.getFreeParameters(), simpleValue.getOrder(), all);
978     }
979 
980     
981 
982 
983 
984 
985     @Override
986     public DerivativeStructure linearCombination(final DerivativeStructure a1, final DerivativeStructure b1,
987                                                  final DerivativeStructure a2, final DerivativeStructure b2) {
988         
989         final double accurateValue = Sum.create()
990             .addProduct(a1.getValue(), b1.getValue())
991             .addProduct(a2.getValue(), b2.getValue()).getAsDouble();
992 
993         
994         final DerivativeStructure simpleValue = a1.multiply(b1).add(a2.multiply(b2));
995 
996         
997         final double[] all = simpleValue.getAllDerivatives();
998         all[0] = accurateValue;
999         return new DerivativeStructure(getFreeParameters(), getOrder(), all);
1000     }
1001 
1002     
1003 
1004 
1005 
1006 
1007     @Override
1008     public DerivativeStructure linearCombination(final double a1, final DerivativeStructure b1,
1009                                                  final double a2, final DerivativeStructure b2) {
1010         
1011         final double accurateValue = Sum.create()
1012             .addProduct(a1, b1.getValue())
1013             .addProduct(a2, b2.getValue()).getAsDouble();
1014 
1015         
1016         final DerivativeStructure simpleValue = b1.multiply(a1).add(b2.multiply(a2));
1017 
1018         
1019         final double[] all = simpleValue.getAllDerivatives();
1020         all[0] = accurateValue;
1021         return new DerivativeStructure(getFreeParameters(), getOrder(), all);
1022     }
1023 
1024     
1025 
1026 
1027 
1028 
1029     @Override
1030     public DerivativeStructure linearCombination(final DerivativeStructure a1, final DerivativeStructure b1,
1031                                                  final DerivativeStructure a2, final DerivativeStructure b2,
1032                                                  final DerivativeStructure a3, final DerivativeStructure b3) {
1033         
1034         final double accurateValue = Sum.create()
1035             .addProduct(a1.getValue(), b1.getValue())
1036             .addProduct(a2.getValue(), b2.getValue())
1037             .addProduct(a3.getValue(), b3.getValue()).getAsDouble();
1038 
1039         
1040         final DerivativeStructure simpleValue = a1.multiply(b1).add(a2.multiply(b2)).add(a3.multiply(b3));
1041 
1042         
1043         final double[] all = simpleValue.getAllDerivatives();
1044         all[0] = accurateValue;
1045         return new DerivativeStructure(getFreeParameters(), getOrder(), all);
1046     }
1047 
1048     
1049 
1050 
1051 
1052 
1053     @Override
1054     public DerivativeStructure linearCombination(final double a1, final DerivativeStructure b1,
1055                                                  final double a2, final DerivativeStructure b2,
1056                                                  final double a3, final DerivativeStructure b3) {
1057         
1058         final double accurateValue = Sum.create()
1059             .addProduct(a1, b1.getValue())
1060             .addProduct(a2, b2.getValue())
1061             .addProduct(a3, b3.getValue()).getAsDouble();
1062 
1063         
1064         final DerivativeStructure simpleValue = b1.multiply(a1).add(b2.multiply(a2)).add(b3.multiply(a3));
1065 
1066         
1067         final double[] all = simpleValue.getAllDerivatives();
1068         all[0] = accurateValue;
1069         return new DerivativeStructure(getFreeParameters(), getOrder(), all);
1070     }
1071 
1072     
1073 
1074 
1075 
1076 
1077     @Override
1078     public DerivativeStructure linearCombination(final DerivativeStructure a1, final DerivativeStructure b1,
1079                                                  final DerivativeStructure a2, final DerivativeStructure b2,
1080                                                  final DerivativeStructure a3, final DerivativeStructure b3,
1081                                                  final DerivativeStructure a4, final DerivativeStructure b4) {
1082         
1083         final double accurateValue = Sum.create()
1084             .addProduct(a1.getValue(), b1.getValue())
1085             .addProduct(a2.getValue(), b2.getValue())
1086             .addProduct(a3.getValue(), b3.getValue())
1087             .addProduct(a4.getValue(), b4.getValue()).getAsDouble();
1088 
1089         
1090         final DerivativeStructure simpleValue = a1.multiply(b1).add(a2.multiply(b2)).add(a3.multiply(b3)).add(a4.multiply(b4));
1091 
1092         
1093         final double[] all = simpleValue.getAllDerivatives();
1094         all[0] = accurateValue;
1095         return new DerivativeStructure(getFreeParameters(), getOrder(), all);
1096     }
1097 
1098     
1099 
1100 
1101 
1102 
1103     @Override
1104     public DerivativeStructure linearCombination(final double a1, final DerivativeStructure b1,
1105                                                  final double a2, final DerivativeStructure b2,
1106                                                  final double a3, final DerivativeStructure b3,
1107                                                  final double a4, final DerivativeStructure b4) {
1108         
1109         final double accurateValue = Sum.create()
1110             .addProduct(a1, b1.getValue())
1111             .addProduct(a2, b2.getValue())
1112             .addProduct(a3, b3.getValue())
1113             .addProduct(a4, b4.getValue()).getAsDouble();
1114 
1115         
1116         final DerivativeStructure simpleValue = b1.multiply(a1).add(b2.multiply(a2)).add(b3.multiply(a3)).add(b4.multiply(a4));
1117 
1118         
1119         final double[] all = simpleValue.getAllDerivatives();
1120         all[0] = accurateValue;
1121         return new DerivativeStructure(getFreeParameters(), getOrder(), all);
1122     }
1123 
1124     
1125 
1126 
1127 
1128 
1129 
1130 
1131 
1132 
1133 
1134     @Override
1135     public boolean equals(Object other) {
1136 
1137         if (this == other) {
1138             return true;
1139         }
1140 
1141         if (other instanceof DerivativeStructure) {
1142             final DerivativeStructure rhs = (DerivativeStructure)other;
1143             return getFreeParameters() == rhs.getFreeParameters() &&
1144                    getOrder() == rhs.getOrder() &&
1145                    MathArrays.equals(data, rhs.data);
1146         }
1147 
1148         return false;
1149     }
1150 
1151     
1152 
1153 
1154 
1155 
1156     @Override
1157     public int hashCode() {
1158         return 227 + 229 * getFreeParameters() + 233 * getOrder() + 239 * Arrays.hashCode(data);
1159     }
1160 }