1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.math4.legacy.analysis.interpolation;
18
19 import org.apache.commons.math4.legacy.analysis.TrivariateFunction;
20 import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
21 import org.apache.commons.math4.legacy.exception.NoDataException;
22 import org.apache.commons.math4.legacy.exception.NonMonotonicSequenceException;
23 import org.apache.commons.math4.legacy.exception.OutOfRangeException;
24 import org.apache.commons.math4.legacy.core.MathArrays;
25
26
27
28
29
30
31
32
33
34
35
36
37
38 public class TricubicInterpolatingFunction
39 implements TrivariateFunction {
40
41
42
43
44 private static final double[][] AINV = {
45 { 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
46 { 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
47 { -3,3,0,0,0,0,0,0,-2,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
48 { 2,-2,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
49 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
50 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
51 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-2,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
52 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
53 { -3,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,-2,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
54 { 0,0,0,0,0,0,0,0,-3,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-2,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
55 { 9,-9,-9,9,0,0,0,0,6,3,-6,-3,0,0,0,0,6,-6,3,-3,0,0,0,0,0,0,0,0,0,0,0,0,4,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
56 { -6,6,6,-6,0,0,0,0,-3,-3,3,3,0,0,0,0,-4,4,-2,2,0,0,0,0,0,0,0,0,0,0,0,0,-2,-2,-1,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
57 { 2,0,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
58 { 0,0,0,0,0,0,0,0,2,0,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
59 { -6,6,6,-6,0,0,0,0,-4,-2,4,2,0,0,0,0,-3,3,-3,3,0,0,0,0,0,0,0,0,0,0,0,0,-2,-1,-2,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
60 { 4,-4,-4,4,0,0,0,0,2,2,-2,-2,0,0,0,0,2,-2,2,-2,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
61 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
62 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
63 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-2,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
64 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
65 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
66 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0 },
67 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-3,3,0,0,0,0,0,0,-2,-1,0,0,0,0,0,0 },
68 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,-2,0,0,0,0,0,0,1,1,0,0,0,0,0,0 },
69 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-3,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-2,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0 },
70 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-3,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,-2,0,-1,0,0,0,0,0 },
71 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,-9,-9,9,0,0,0,0,0,0,0,0,0,0,0,0,6,3,-6,-3,0,0,0,0,6,-6,3,-3,0,0,0,0,4,2,2,1,0,0,0,0 },
72 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-6,6,6,-6,0,0,0,0,0,0,0,0,0,0,0,0,-3,-3,3,3,0,0,0,0,-4,4,-2,2,0,0,0,0,-2,-2,-1,-1,0,0,0,0 },
73 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0 },
74 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0 },
75 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-6,6,6,-6,0,0,0,0,0,0,0,0,0,0,0,0,-4,-2,4,2,0,0,0,0,-3,3,-3,3,0,0,0,0,-2,-1,-2,-1,0,0,0,0 },
76 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,-4,-4,4,0,0,0,0,0,0,0,0,0,0,0,0,2,2,-2,-2,0,0,0,0,2,-2,2,-2,0,0,0,0,1,1,1,1,0,0,0,0 },
77 {-3,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-2,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
78 { 0,0,0,0,0,0,0,0,-3,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-2,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
79 { 9,-9,0,0,-9,9,0,0,6,3,0,0,-6,-3,0,0,0,0,0,0,0,0,0,0,6,-6,0,0,3,-3,0,0,0,0,0,0,0,0,0,0,4,2,0,0,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
80 { -6,6,0,0,6,-6,0,0,-3,-3,0,0,3,3,0,0,0,0,0,0,0,0,0,0,-4,4,0,0,-2,2,0,0,0,0,0,0,0,0,0,0,-2,-2,0,0,-1,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
81 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-3,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-2,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0 },
82 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-3,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-2,0,0,0,-1,0,0,0 },
83 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,-9,0,0,-9,9,0,0,0,0,0,0,0,0,0,0,6,3,0,0,-6,-3,0,0,0,0,0,0,0,0,0,0,6,-6,0,0,3,-3,0,0,4,2,0,0,2,1,0,0 },
84 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-6,6,0,0,6,-6,0,0,0,0,0,0,0,0,0,0,-3,-3,0,0,3,3,0,0,0,0,0,0,0,0,0,0,-4,4,0,0,-2,2,0,0,-2,-2,0,0,-1,-1,0,0 },
85 { 9,0,-9,0,-9,0,9,0,0,0,0,0,0,0,0,0,6,0,3,0,-6,0,-3,0,6,0,-6,0,3,0,-3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,2,0,2,0,1,0,0,0,0,0,0,0,0,0 },
86 { 0,0,0,0,0,0,0,0,9,0,-9,0,-9,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,3,0,-6,0,-3,0,6,0,-6,0,3,0,-3,0,0,0,0,0,0,0,0,0,4,0,2,0,2,0,1,0 },
87 { -27,27,27,-27,27,-27,-27,27,-18,-9,18,9,18,9,-18,-9,-18,18,-9,9,18,-18,9,-9,-18,18,18,-18,-9,9,9,-9,-12,-6,-6,-3,12,6,6,3,-12,-6,12,6,-6,-3,6,3,-12,12,-6,6,-6,6,-3,3,-8,-4,-4,-2,-4,-2,-2,-1 },
88 { 18,-18,-18,18,-18,18,18,-18,9,9,-9,-9,-9,-9,9,9,12,-12,6,-6,-12,12,-6,6,12,-12,-12,12,6,-6,-6,6,6,6,3,3,-6,-6,-3,-3,6,6,-6,-6,3,3,-3,-3,8,-8,4,-4,4,-4,2,-2,4,4,2,2,2,2,1,1 },
89 { -6,0,6,0,6,0,-6,0,0,0,0,0,0,0,0,0,-3,0,-3,0,3,0,3,0,-4,0,4,0,-2,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-2,0,-2,0,-1,0,-1,0,0,0,0,0,0,0,0,0 },
90 { 0,0,0,0,0,0,0,0,-6,0,6,0,6,0,-6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-3,0,-3,0,3,0,3,0,-4,0,4,0,-2,0,2,0,0,0,0,0,0,0,0,0,-2,0,-2,0,-1,0,-1,0 },
91 { 18,-18,-18,18,-18,18,18,-18,12,6,-12,-6,-12,-6,12,6,9,-9,9,-9,-9,9,-9,9,12,-12,-12,12,6,-6,-6,6,6,3,6,3,-6,-3,-6,-3,8,4,-8,-4,4,2,-4,-2,6,-6,6,-6,3,-3,3,-3,4,2,4,2,2,1,2,1 },
92 { -12,12,12,-12,12,-12,-12,12,-6,-6,6,6,6,6,-6,-6,-6,6,-6,6,6,-6,6,-6,-8,8,8,-8,-4,4,4,-4,-3,-3,-3,-3,3,3,3,3,-4,-4,4,4,-2,-2,2,2,-4,4,-4,4,-2,2,-2,2,-2,-2,-2,-2,-1,-1,-1,-1 },
93 { 2,0,0,0,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
94 { 0,0,0,0,0,0,0,0,2,0,0,0,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
95 { -6,6,0,0,6,-6,0,0,-4,-2,0,0,4,2,0,0,0,0,0,0,0,0,0,0,-3,3,0,0,-3,3,0,0,0,0,0,0,0,0,0,0,-2,-1,0,0,-2,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
96 { 4,-4,0,0,-4,4,0,0,2,2,0,0,-2,-2,0,0,0,0,0,0,0,0,0,0,2,-2,0,0,2,-2,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
97 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0 },
98 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0 },
99 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-6,6,0,0,6,-6,0,0,0,0,0,0,0,0,0,0,-4,-2,0,0,4,2,0,0,0,0,0,0,0,0,0,0,-3,3,0,0,-3,3,0,0,-2,-1,0,0,-2,-1,0,0 },
100 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,-4,0,0,-4,4,0,0,0,0,0,0,0,0,0,0,2,2,0,0,-2,-2,0,0,0,0,0,0,0,0,0,0,2,-2,0,0,2,-2,0,0,1,1,0,0,1,1,0,0 },
101 { -6,0,6,0,6,0,-6,0,0,0,0,0,0,0,0,0,-4,0,-2,0,4,0,2,0,-3,0,3,0,-3,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-2,0,-1,0,-2,0,-1,0,0,0,0,0,0,0,0,0 },
102 { 0,0,0,0,0,0,0,0,-6,0,6,0,6,0,-6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-4,0,-2,0,4,0,2,0,-3,0,3,0,-3,0,3,0,0,0,0,0,0,0,0,0,-2,0,-1,0,-2,0,-1,0 },
103 { 18,-18,-18,18,-18,18,18,-18,12,6,-12,-6,-12,-6,12,6,12,-12,6,-6,-12,12,-6,6,9,-9,-9,9,9,-9,-9,9,8,4,4,2,-8,-4,-4,-2,6,3,-6,-3,6,3,-6,-3,6,-6,3,-3,6,-6,3,-3,4,2,2,1,4,2,2,1 },
104 { -12,12,12,-12,12,-12,-12,12,-6,-6,6,6,6,6,-6,-6,-8,8,-4,4,8,-8,4,-4,-6,6,6,-6,-6,6,6,-6,-4,-4,-2,-2,4,4,2,2,-3,-3,3,3,-3,-3,3,3,-4,4,-2,2,-4,4,-2,2,-2,-2,-1,-1,-2,-2,-1,-1 },
105 { 4,0,-4,0,-4,0,4,0,0,0,0,0,0,0,0,0,2,0,2,0,-2,0,-2,0,2,0,-2,0,2,0,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0 },
106 { 0,0,0,0,0,0,0,0,4,0,-4,0,-4,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,2,0,-2,0,-2,0,2,0,-2,0,2,0,-2,0,0,0,0,0,0,0,0,0,1,0,1,0,1,0,1,0 },
107 { -12,12,12,-12,12,-12,-12,12,-8,-4,8,4,8,4,-8,-4,-6,6,-6,6,6,-6,6,-6,-6,6,6,-6,-6,6,6,-6,-4,-2,-4,-2,4,2,4,2,-4,-2,4,2,-4,-2,4,2,-3,3,-3,3,-3,3,-3,3,-2,-1,-2,-1,-2,-1,-2,-1 },
108 { 8,-8,-8,8,-8,8,8,-8,4,4,-4,-4,-4,-4,4,4,4,-4,4,-4,-4,4,-4,4,4,-4,-4,4,4,-4,-4,4,2,2,2,2,-2,-2,-2,-2,2,2,-2,-2,2,2,-2,-2,2,-2,2,-2,2,-2,2,-2,1,1,1,1,1,1,1,1 }
109 };
110
111
112 private final double[] xval;
113
114 private final double[] yval;
115
116 private final double[] zval;
117
118 private final TricubicFunction[][][] splines;
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136 public TricubicInterpolatingFunction(double[] x,
137 double[] y,
138 double[] z,
139 double[][][] f,
140 double[][][] dFdX,
141 double[][][] dFdY,
142 double[][][] dFdZ,
143 double[][][] d2FdXdY,
144 double[][][] d2FdXdZ,
145 double[][][] d2FdYdZ,
146 double[][][] d3FdXdYdZ)
147 throws NoDataException,
148 DimensionMismatchException,
149 NonMonotonicSequenceException {
150 final int xLen = x.length;
151 final int yLen = y.length;
152 final int zLen = z.length;
153
154 if (xLen == 0 || yLen == 0 || z.length == 0 || f.length == 0 || f[0].length == 0) {
155 throw new NoDataException();
156 }
157 if (xLen != f.length) {
158 throw new DimensionMismatchException(xLen, f.length);
159 }
160 if (xLen != dFdX.length) {
161 throw new DimensionMismatchException(xLen, dFdX.length);
162 }
163 if (xLen != dFdY.length) {
164 throw new DimensionMismatchException(xLen, dFdY.length);
165 }
166 if (xLen != dFdZ.length) {
167 throw new DimensionMismatchException(xLen, dFdZ.length);
168 }
169 if (xLen != d2FdXdY.length) {
170 throw new DimensionMismatchException(xLen, d2FdXdY.length);
171 }
172 if (xLen != d2FdXdZ.length) {
173 throw new DimensionMismatchException(xLen, d2FdXdZ.length);
174 }
175 if (xLen != d2FdYdZ.length) {
176 throw new DimensionMismatchException(xLen, d2FdYdZ.length);
177 }
178 if (xLen != d3FdXdYdZ.length) {
179 throw new DimensionMismatchException(xLen, d3FdXdYdZ.length);
180 }
181
182 MathArrays.checkOrder(x);
183 MathArrays.checkOrder(y);
184 MathArrays.checkOrder(z);
185
186 xval = x.clone();
187 yval = y.clone();
188 zval = z.clone();
189
190 final int lastI = xLen - 1;
191 final int lastJ = yLen - 1;
192 final int lastK = zLen - 1;
193 splines = new TricubicFunction[lastI][lastJ][lastK];
194
195 for (int i = 0; i < lastI; i++) {
196 if (f[i].length != yLen) {
197 throw new DimensionMismatchException(f[i].length, yLen);
198 }
199 if (dFdX[i].length != yLen) {
200 throw new DimensionMismatchException(dFdX[i].length, yLen);
201 }
202 if (dFdY[i].length != yLen) {
203 throw new DimensionMismatchException(dFdY[i].length, yLen);
204 }
205 if (dFdZ[i].length != yLen) {
206 throw new DimensionMismatchException(dFdZ[i].length, yLen);
207 }
208 if (d2FdXdY[i].length != yLen) {
209 throw new DimensionMismatchException(d2FdXdY[i].length, yLen);
210 }
211 if (d2FdXdZ[i].length != yLen) {
212 throw new DimensionMismatchException(d2FdXdZ[i].length, yLen);
213 }
214 if (d2FdYdZ[i].length != yLen) {
215 throw new DimensionMismatchException(d2FdYdZ[i].length, yLen);
216 }
217 if (d3FdXdYdZ[i].length != yLen) {
218 throw new DimensionMismatchException(d3FdXdYdZ[i].length, yLen);
219 }
220
221 final int ip1 = i + 1;
222 final double xR = xval[ip1] - xval[i];
223 for (int j = 0; j < lastJ; j++) {
224 if (f[i][j].length != zLen) {
225 throw new DimensionMismatchException(f[i][j].length, zLen);
226 }
227 if (dFdX[i][j].length != zLen) {
228 throw new DimensionMismatchException(dFdX[i][j].length, zLen);
229 }
230 if (dFdY[i][j].length != zLen) {
231 throw new DimensionMismatchException(dFdY[i][j].length, zLen);
232 }
233 if (dFdZ[i][j].length != zLen) {
234 throw new DimensionMismatchException(dFdZ[i][j].length, zLen);
235 }
236 if (d2FdXdY[i][j].length != zLen) {
237 throw new DimensionMismatchException(d2FdXdY[i][j].length, zLen);
238 }
239 if (d2FdXdZ[i][j].length != zLen) {
240 throw new DimensionMismatchException(d2FdXdZ[i][j].length, zLen);
241 }
242 if (d2FdYdZ[i][j].length != zLen) {
243 throw new DimensionMismatchException(d2FdYdZ[i][j].length, zLen);
244 }
245 if (d3FdXdYdZ[i][j].length != zLen) {
246 throw new DimensionMismatchException(d3FdXdYdZ[i][j].length, zLen);
247 }
248
249 final int jp1 = j + 1;
250 final double yR = yval[jp1] - yval[j];
251 final double xRyR = xR * yR;
252 for (int k = 0; k < lastK; k++) {
253 final int kp1 = k + 1;
254 final double zR = zval[kp1] - zval[k];
255 final double xRzR = xR * zR;
256 final double yRzR = yR * zR;
257 final double xRyRzR = xR * yRzR;
258
259 final double[] beta = new double[] {
260 f[i][j][k], f[ip1][j][k],
261 f[i][jp1][k], f[ip1][jp1][k],
262 f[i][j][kp1], f[ip1][j][kp1],
263 f[i][jp1][kp1], f[ip1][jp1][kp1],
264
265 dFdX[i][j][k] * xR, dFdX[ip1][j][k] * xR,
266 dFdX[i][jp1][k] * xR, dFdX[ip1][jp1][k] * xR,
267 dFdX[i][j][kp1] * xR, dFdX[ip1][j][kp1] * xR,
268 dFdX[i][jp1][kp1] * xR, dFdX[ip1][jp1][kp1] * xR,
269
270 dFdY[i][j][k] * yR, dFdY[ip1][j][k] * yR,
271 dFdY[i][jp1][k] * yR, dFdY[ip1][jp1][k] * yR,
272 dFdY[i][j][kp1] * yR, dFdY[ip1][j][kp1] * yR,
273 dFdY[i][jp1][kp1] * yR, dFdY[ip1][jp1][kp1] * yR,
274
275 dFdZ[i][j][k] * zR, dFdZ[ip1][j][k] * zR,
276 dFdZ[i][jp1][k] * zR, dFdZ[ip1][jp1][k] * zR,
277 dFdZ[i][j][kp1] * zR, dFdZ[ip1][j][kp1] * zR,
278 dFdZ[i][jp1][kp1] * zR, dFdZ[ip1][jp1][kp1] * zR,
279
280 d2FdXdY[i][j][k] * xRyR, d2FdXdY[ip1][j][k] * xRyR,
281 d2FdXdY[i][jp1][k] * xRyR, d2FdXdY[ip1][jp1][k] * xRyR,
282 d2FdXdY[i][j][kp1] * xRyR, d2FdXdY[ip1][j][kp1] * xRyR,
283 d2FdXdY[i][jp1][kp1] * xRyR, d2FdXdY[ip1][jp1][kp1] * xRyR,
284
285 d2FdXdZ[i][j][k] * xRzR, d2FdXdZ[ip1][j][k] * xRzR,
286 d2FdXdZ[i][jp1][k] * xRzR, d2FdXdZ[ip1][jp1][k] * xRzR,
287 d2FdXdZ[i][j][kp1] * xRzR, d2FdXdZ[ip1][j][kp1] * xRzR,
288 d2FdXdZ[i][jp1][kp1] * xRzR, d2FdXdZ[ip1][jp1][kp1] * xRzR,
289
290 d2FdYdZ[i][j][k] * yRzR, d2FdYdZ[ip1][j][k] * yRzR,
291 d2FdYdZ[i][jp1][k] * yRzR, d2FdYdZ[ip1][jp1][k] * yRzR,
292 d2FdYdZ[i][j][kp1] * yRzR, d2FdYdZ[ip1][j][kp1] * yRzR,
293 d2FdYdZ[i][jp1][kp1] * yRzR, d2FdYdZ[ip1][jp1][kp1] * yRzR,
294
295 d3FdXdYdZ[i][j][k] * xRyRzR, d3FdXdYdZ[ip1][j][k] * xRyRzR,
296 d3FdXdYdZ[i][jp1][k] * xRyRzR, d3FdXdYdZ[ip1][jp1][k] * xRyRzR,
297 d3FdXdYdZ[i][j][kp1] * xRyRzR, d3FdXdYdZ[ip1][j][kp1] * xRyRzR,
298 d3FdXdYdZ[i][jp1][kp1] * xRyRzR, d3FdXdYdZ[ip1][jp1][kp1] * xRyRzR,
299 };
300
301 splines[i][j][k] = new TricubicFunction(computeCoefficients(beta));
302 }
303 }
304 }
305 }
306
307
308
309
310
311
312 @Override
313 public double value(double x, double y, double z)
314 throws OutOfRangeException {
315 final int i = searchIndex(x, xval);
316 if (i == -1) {
317 throw new OutOfRangeException(x, xval[0], xval[xval.length - 1]);
318 }
319 final int j = searchIndex(y, yval);
320 if (j == -1) {
321 throw new OutOfRangeException(y, yval[0], yval[yval.length - 1]);
322 }
323 final int k = searchIndex(z, zval);
324 if (k == -1) {
325 throw new OutOfRangeException(z, zval[0], zval[zval.length - 1]);
326 }
327
328 final double xN = (x - xval[i]) / (xval[i + 1] - xval[i]);
329 final double yN = (y - yval[j]) / (yval[j + 1] - yval[j]);
330 final double zN = (z - zval[k]) / (zval[k + 1] - zval[k]);
331
332 return splines[i][j][k].value(xN, yN, zN);
333 }
334
335
336
337
338
339
340
341
342
343 public boolean isValidPoint(double x, double y, double z) {
344 return !(x < xval[0] ||
345 x > xval[xval.length - 1] ||
346 y < yval[0] ||
347 y > yval[yval.length - 1] ||
348 z < zval[0] ||
349 z > zval[zval.length - 1]);
350 }
351
352
353
354
355
356
357
358 private int searchIndex(double c, double[] val) {
359 if (c < val[0]) {
360 return -1;
361 }
362
363 final int max = val.length;
364 for (int i = 1; i < max; i++) {
365 if (c <= val[i]) {
366 return i - 1;
367 }
368 }
369
370 return -1;
371 }
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421 private double[] computeCoefficients(double[] beta) {
422 final int sz = 64;
423 final double[] a = new double[sz];
424
425 for (int i = 0; i < sz; i++) {
426 double result = 0;
427 final double[] row = AINV[i];
428 for (int j = 0; j < sz; j++) {
429 result += row[j] * beta[j];
430 }
431 a[i] = result;
432 }
433
434 return a;
435 }
436 }
437
438
439
440
441
442 class TricubicFunction
443 implements TrivariateFunction {
444
445 private static final short N = 4;
446
447 private final double[][][] a = new double[N][N][N];
448
449
450
451
452 TricubicFunction(double[] aV) {
453 for (int i = 0; i < N; i++) {
454 for (int j = 0; j < N; j++) {
455 for (int k = 0; k < N; k++) {
456 a[i][j][k] = aV[i + N * (j + N * k)];
457 }
458 }
459 }
460 }
461
462
463
464
465
466
467
468
469
470 @Override
471 public double value(double x, double y, double z) throws OutOfRangeException {
472 if (x < 0 || x > 1) {
473 throw new OutOfRangeException(x, 0, 1);
474 }
475 if (y < 0 || y > 1) {
476 throw new OutOfRangeException(y, 0, 1);
477 }
478 if (z < 0 || z > 1) {
479 throw new OutOfRangeException(z, 0, 1);
480 }
481
482 final double x2 = x * x;
483 final double x3 = x2 * x;
484 final double[] pX = { 1, x, x2, x3 };
485
486 final double y2 = y * y;
487 final double y3 = y2 * y;
488 final double[] pY = { 1, y, y2, y3 };
489
490 final double z2 = z * z;
491 final double z3 = z2 * z;
492 final double[] pZ = { 1, z, z2, z3 };
493
494 double result = 0;
495 for (int i = 0; i < N; i++) {
496 for (int j = 0; j < N; j++) {
497 for (int k = 0; k < N; k++) {
498 result += a[i][j][k] * pX[i] * pY[j] * pZ[k];
499 }
500 }
501 }
502
503 return result;
504 }
505 }