File: | src/ten/path.c |
Location: | line 1072, column 3 |
Description: | Potential leak of memory pointed to by 'tbuff' |
1 | /* | |||
2 | Teem: Tools to process and visualize scientific data and images . | |||
3 | Copyright (C) 2013, 2012, 2011, 2010, 2009 University of Chicago | |||
4 | Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann | |||
5 | Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah | |||
6 | ||||
7 | This library is free software; you can redistribute it and/or | |||
8 | modify it under the terms of the GNU Lesser General Public License | |||
9 | (LGPL) as published by the Free Software Foundation; either | |||
10 | version 2.1 of the License, or (at your option) any later version. | |||
11 | The terms of redistributing and/or modifying this software also | |||
12 | include exceptions to the LGPL that facilitate static linking. | |||
13 | ||||
14 | This library is distributed in the hope that it will be useful, | |||
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
17 | Lesser General Public License for more details. | |||
18 | ||||
19 | You should have received a copy of the GNU Lesser General Public License | |||
20 | along with this library; if not, write to Free Software Foundation, Inc., | |||
21 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
22 | */ | |||
23 | ||||
24 | ||||
25 | #include "ten.h" | |||
26 | #include "privateTen.h" | |||
27 | ||||
28 | tenInterpParm * | |||
29 | tenInterpParmNew(void) { | |||
30 | tenInterpParm *tip; | |||
31 | ||||
32 | tip = AIR_CAST(tenInterpParm *, malloc(sizeof(tenInterpParm)))((tenInterpParm *)(malloc(sizeof(tenInterpParm)))); | |||
33 | if (tip) { | |||
34 | tip->verbose = AIR_FALSE0; | |||
35 | tip->convStep = 0.2; | |||
36 | tip->minNorm = 0.0; | |||
37 | tip->convEps = 0.0000000001; | |||
38 | tip->wghtSumEps = 0.0000001; | |||
39 | tip->enableRecurse = AIR_TRUE1; | |||
40 | tip->maxIter = 20; | |||
41 | tip->numSteps = 100; | |||
42 | tip->lengthFancy = AIR_FALSE0; | |||
43 | ||||
44 | tip->allocLen = 0; | |||
45 | tip->eval = NULL((void*)0); | |||
46 | tip->evec = NULL((void*)0); | |||
47 | tip->rtIn = NULL((void*)0); | |||
48 | tip->rtLog = NULL((void*)0); | |||
49 | tip->qIn = NULL((void*)0); | |||
50 | tip->qBuff = NULL((void*)0); | |||
51 | tip->qInter = NULL((void*)0); | |||
52 | ||||
53 | tip->numIter = 0; | |||
54 | tip->convFinal = AIR_NAN(airFloatQNaN.f); | |||
55 | tip->lengthShape = AIR_NAN(airFloatQNaN.f); | |||
56 | tip->lengthOrient = AIR_NAN(airFloatQNaN.f); | |||
57 | } | |||
58 | return tip; | |||
59 | } | |||
60 | ||||
61 | ||||
62 | ||||
63 | /* | |||
64 | ** handles allocating all the various buffers that are needed for QGL | |||
65 | ** interpolation, so that they are repeatedly allocated and freed | |||
66 | ** between calls | |||
67 | */ | |||
68 | int | |||
69 | tenInterpParmBufferAlloc(tenInterpParm *tip, unsigned int num) { | |||
70 | static const char me[]="tenInterpParmBufferAlloc"; | |||
71 | ||||
72 | if (0 == num) { | |||
73 | /* user wants to free buffers for some reason */ | |||
74 | airFree(tip->eval); tip->eval = NULL((void*)0); | |||
75 | airFree(tip->evec); tip->evec = NULL((void*)0); | |||
76 | airFree(tip->rtIn); tip->rtIn = NULL((void*)0); | |||
77 | airFree(tip->rtLog); tip->rtLog = NULL((void*)0); | |||
78 | airFree(tip->qIn); tip->qIn = NULL((void*)0); | |||
79 | airFree(tip->qBuff); tip->qBuff = NULL((void*)0); | |||
80 | airFree(tip->qInter); tip->qInter = NULL((void*)0); | |||
81 | tip->allocLen = 0; | |||
82 | } else if (1 == num) { | |||
83 | biffAddf(TENtenBiffKey, "%s: need num >= 2 (not %u)", me, num); | |||
84 | return 1; | |||
85 | } else if (num != tip->allocLen) { | |||
86 | airFree(tip->eval); tip->eval = NULL((void*)0); | |||
87 | airFree(tip->evec); tip->evec = NULL((void*)0); | |||
88 | airFree(tip->rtIn); tip->rtIn = NULL((void*)0); | |||
89 | airFree(tip->rtLog); tip->rtLog = NULL((void*)0); | |||
90 | airFree(tip->qIn); tip->qIn = NULL((void*)0); | |||
91 | airFree(tip->qBuff); tip->qBuff = NULL((void*)0); | |||
92 | airFree(tip->qInter); tip->qInter = NULL((void*)0); | |||
93 | tip->eval = AIR_CALLOC(3*num, double)(double*)(calloc((3*num), sizeof(double))); | |||
94 | tip->evec = AIR_CALLOC(9*num, double)(double*)(calloc((9*num), sizeof(double))); | |||
95 | tip->rtIn = AIR_CALLOC(3*num, double)(double*)(calloc((3*num), sizeof(double))); | |||
96 | tip->rtLog = AIR_CALLOC(3*num, double)(double*)(calloc((3*num), sizeof(double))); | |||
97 | tip->qIn = AIR_CALLOC(4*num, double)(double*)(calloc((4*num), sizeof(double))); | |||
98 | tip->qBuff = AIR_CALLOC(4*num, double)(double*)(calloc((4*num), sizeof(double))); | |||
99 | tip->qInter = AIR_CALLOC(num*num, double)(double*)(calloc((num*num), sizeof(double))); | |||
100 | if (!(tip->eval && tip->evec && | |||
101 | tip->rtIn && tip->rtLog && | |||
102 | tip->qIn && tip->qBuff && tip->qInter)) { | |||
103 | biffAddf(TENtenBiffKey, "%s: didn't alloc buffers (%p,%p,%p %p %p %p %p)", me, | |||
104 | AIR_VOIDP(tip->eval)((void *)(tip->eval)), AIR_VOIDP(tip->evec)((void *)(tip->evec)), | |||
105 | AIR_VOIDP(tip->rtIn)((void *)(tip->rtIn)), AIR_VOIDP(tip->rtLog)((void *)(tip->rtLog)), | |||
106 | AIR_VOIDP(tip->qIn)((void *)(tip->qIn)), AIR_VOIDP(tip->qBuff)((void *)(tip->qBuff)), | |||
107 | AIR_VOIDP(tip->qInter)((void *)(tip->qInter))); | |||
108 | return 1; | |||
109 | } | |||
110 | tip->allocLen = num; | |||
111 | } | |||
112 | return 0; | |||
113 | } | |||
114 | ||||
115 | tenInterpParm * | |||
116 | tenInterpParmCopy(tenInterpParm *tip) { | |||
117 | static const char me[]="tenInterpParmCopy"; | |||
118 | tenInterpParm *newtip; | |||
119 | unsigned int num; | |||
120 | ||||
121 | num = tip->allocLen; | |||
122 | newtip = tenInterpParmNew(); | |||
123 | if (newtip) { | |||
124 | memcpy(newtip, tip, sizeof(tenInterpParm))__builtin___memcpy_chk (newtip, tip, sizeof(tenInterpParm), __builtin_object_size (newtip, 0)); | |||
125 | /* manually set all pointers */ | |||
126 | newtip->allocLen = 0; | |||
127 | newtip->eval = NULL((void*)0); | |||
128 | newtip->evec = NULL((void*)0); | |||
129 | newtip->rtIn = NULL((void*)0); | |||
130 | newtip->rtLog = NULL((void*)0); | |||
131 | newtip->qIn = NULL((void*)0); | |||
132 | newtip->qBuff = NULL((void*)0); | |||
133 | newtip->qInter = NULL((void*)0); | |||
134 | if (tenInterpParmBufferAlloc(newtip, num)) { | |||
135 | biffAddf(TENtenBiffKey, "%s: trouble allocating output", me); | |||
136 | return NULL((void*)0); | |||
137 | } | |||
138 | memcpy(newtip->eval, tip->eval, 3*num*sizeof(double))__builtin___memcpy_chk (newtip->eval, tip->eval, 3*num* sizeof(double), __builtin_object_size (newtip->eval, 0)); | |||
139 | memcpy(newtip->evec, tip->evec, 9*num*sizeof(double))__builtin___memcpy_chk (newtip->evec, tip->evec, 9*num* sizeof(double), __builtin_object_size (newtip->evec, 0)); | |||
140 | memcpy(newtip->rtIn, tip->rtIn, 3*num*sizeof(double))__builtin___memcpy_chk (newtip->rtIn, tip->rtIn, 3*num* sizeof(double), __builtin_object_size (newtip->rtIn, 0)); | |||
141 | memcpy(newtip->rtLog, tip->rtLog, 3*num*sizeof(double))__builtin___memcpy_chk (newtip->rtLog, tip->rtLog, 3*num *sizeof(double), __builtin_object_size (newtip->rtLog, 0)); | |||
142 | memcpy(newtip->qIn, tip->qIn, 4*num*sizeof(double))__builtin___memcpy_chk (newtip->qIn, tip->qIn, 4*num*sizeof (double), __builtin_object_size (newtip->qIn, 0)); | |||
143 | memcpy(newtip->qBuff, tip->qBuff, 4*num*sizeof(double))__builtin___memcpy_chk (newtip->qBuff, tip->qBuff, 4*num *sizeof(double), __builtin_object_size (newtip->qBuff, 0)); | |||
144 | memcpy(newtip->qInter, tip->qInter, num*num*sizeof(double))__builtin___memcpy_chk (newtip->qInter, tip->qInter, num *num*sizeof(double), __builtin_object_size (newtip->qInter , 0)); | |||
145 | } | |||
146 | return newtip; | |||
147 | } | |||
148 | ||||
149 | tenInterpParm * | |||
150 | tenInterpParmNix(tenInterpParm *tip) { | |||
151 | ||||
152 | if (tip) { | |||
153 | airFree(tip->eval); | |||
154 | airFree(tip->evec); | |||
155 | airFree(tip->rtIn); | |||
156 | airFree(tip->rtLog); | |||
157 | airFree(tip->qIn); | |||
158 | airFree(tip->qBuff); | |||
159 | airFree(tip->qInter); | |||
160 | free(tip); | |||
161 | } | |||
162 | return NULL((void*)0); | |||
163 | } | |||
164 | ||||
165 | /* | |||
166 | ******** tenInterpTwo_d | |||
167 | ** | |||
168 | ** interpolates between two tensors, in various ways | |||
169 | ** | |||
170 | ** this is really only used for demo purposes; its not useful for | |||
171 | ** doing real work in DTI fields. So: its okay that its slow | |||
172 | ** (e.g. for tenInterpTypeQuatGeoLox{K,R}, it recomputes the | |||
173 | ** eigensystems at the endpoints for every call, even though they are | |||
174 | ** apt to be the same between calls. | |||
175 | ** | |||
176 | ** this | |||
177 | */ | |||
178 | void | |||
179 | tenInterpTwo_d(double oten[7], | |||
180 | const double tenA[7], const double tenB[7], | |||
181 | int ptype, double aa, | |||
182 | tenInterpParm *tip) { | |||
183 | static const char me[]="tenInterpTwo_d"; | |||
184 | double logA[7], logB[7], tmp1[7], tmp2[7], logMean[7], | |||
185 | mat1[9], mat2[9], mat3[9], sqrtA[7], isqrtA[7], | |||
186 | mean[7], sqrtB[7], isqrtB[7], | |||
187 | oeval[3], evalA[3], evalB[3], oevec[9], evecA[9], evecB[9]; | |||
188 | ||||
189 | ||||
190 | if (!( oten && tenA && tenB )) { | |||
191 | /* got NULL pointer, but not using biff */ | |||
192 | if (oten) { | |||
193 | TEN_T_SET(oten, AIR_NAN, AIR_NAN, AIR_NAN, AIR_NAN,( (oten)[0] = ((airFloatQNaN.f)), (oten)[1] = ((airFloatQNaN. f)), (oten)[2] = ((airFloatQNaN.f)), (oten)[3] = ((airFloatQNaN .f)), (oten)[4] = ((airFloatQNaN.f)), (oten)[5] = ((airFloatQNaN .f)), (oten)[6] = ((airFloatQNaN.f)) ) | |||
194 | AIR_NAN, AIR_NAN, AIR_NAN)( (oten)[0] = ((airFloatQNaN.f)), (oten)[1] = ((airFloatQNaN. f)), (oten)[2] = ((airFloatQNaN.f)), (oten)[3] = ((airFloatQNaN .f)), (oten)[4] = ((airFloatQNaN.f)), (oten)[5] = ((airFloatQNaN .f)), (oten)[6] = ((airFloatQNaN.f)) ); | |||
195 | } | |||
196 | return; | |||
197 | } | |||
198 | ||||
199 | switch (ptype) { | |||
200 | case tenInterpTypeLinear: | |||
201 | TEN_T_LERP(oten, aa, tenA, tenB)( (oten)[0] = (((aa))*(((tenB)[0]) - ((tenA)[0])) + ((tenA)[0 ])), (oten)[1] = (((aa))*(((tenB)[1]) - ((tenA)[1])) + ((tenA )[1])), (oten)[2] = (((aa))*(((tenB)[2]) - ((tenA)[2])) + ((tenA )[2])), (oten)[3] = (((aa))*(((tenB)[3]) - ((tenA)[3])) + ((tenA )[3])), (oten)[4] = (((aa))*(((tenB)[4]) - ((tenA)[4])) + ((tenA )[4])), (oten)[5] = (((aa))*(((tenB)[5]) - ((tenA)[5])) + ((tenA )[5])), (oten)[6] = (((aa))*(((tenB)[6]) - ((tenA)[6])) + ((tenA )[6]))); | |||
202 | break; | |||
203 | case tenInterpTypeLogLinear: | |||
204 | tenLogSingle_d(logA, tenA); | |||
205 | tenLogSingle_d(logB, tenB); | |||
206 | TEN_T_LERP(logMean, aa, logA, logB)( (logMean)[0] = (((aa))*(((logB)[0]) - ((logA)[0])) + ((logA )[0])), (logMean)[1] = (((aa))*(((logB)[1]) - ((logA)[1])) + ( (logA)[1])), (logMean)[2] = (((aa))*(((logB)[2]) - ((logA)[2] )) + ((logA)[2])), (logMean)[3] = (((aa))*(((logB)[3]) - ((logA )[3])) + ((logA)[3])), (logMean)[4] = (((aa))*(((logB)[4]) - ( (logA)[4])) + ((logA)[4])), (logMean)[5] = (((aa))*(((logB)[5 ]) - ((logA)[5])) + ((logA)[5])), (logMean)[6] = (((aa))*(((logB )[6]) - ((logA)[6])) + ((logA)[6]))); | |||
207 | tenExpSingle_d(oten, logMean); | |||
208 | break; | |||
209 | case tenInterpTypeAffineInvariant: | |||
210 | tenSqrtSingle_d(sqrtA, tenA); | |||
211 | tenInv_d(isqrtA, sqrtA); | |||
212 | TEN_T2M(mat1, tenB)( (mat1)[0] = (tenB)[1], (mat1)[1] = (tenB)[2], (mat1)[2] = ( tenB)[3], (mat1)[3] = (tenB)[2], (mat1)[4] = (tenB)[4], (mat1 )[5] = (tenB)[5], (mat1)[6] = (tenB)[3], (mat1)[7] = (tenB)[5 ], (mat1)[8] = (tenB)[6] ); | |||
213 | TEN_T2M(mat2, isqrtA)( (mat2)[0] = (isqrtA)[1], (mat2)[1] = (isqrtA)[2], (mat2)[2] = (isqrtA)[3], (mat2)[3] = (isqrtA)[2], (mat2)[4] = (isqrtA) [4], (mat2)[5] = (isqrtA)[5], (mat2)[6] = (isqrtA)[3], (mat2) [7] = (isqrtA)[5], (mat2)[8] = (isqrtA)[6] ); | |||
214 | ELL_3M_MUL(mat3, mat1, mat2)((mat3)[0] = (mat1)[0]*(mat2)[0] + (mat1)[1]*(mat2)[3] + (mat1 )[2]*(mat2)[6], (mat3)[1] = (mat1)[0]*(mat2)[1] + (mat1)[1]*( mat2)[4] + (mat1)[2]*(mat2)[7], (mat3)[2] = (mat1)[0]*(mat2)[ 2] + (mat1)[1]*(mat2)[5] + (mat1)[2]*(mat2)[8], (mat3)[3] = ( mat1)[3]*(mat2)[0] + (mat1)[4]*(mat2)[3] + (mat1)[5]*(mat2)[6 ], (mat3)[4] = (mat1)[3]*(mat2)[1] + (mat1)[4]*(mat2)[4] + (mat1 )[5]*(mat2)[7], (mat3)[5] = (mat1)[3]*(mat2)[2] + (mat1)[4]*( mat2)[5] + (mat1)[5]*(mat2)[8], (mat3)[6] = (mat1)[6]*(mat2)[ 0] + (mat1)[7]*(mat2)[3] + (mat1)[8]*(mat2)[6], (mat3)[7] = ( mat1)[6]*(mat2)[1] + (mat1)[7]*(mat2)[4] + (mat1)[8]*(mat2)[7 ], (mat3)[8] = (mat1)[6]*(mat2)[2] + (mat1)[7]*(mat2)[5] + (mat1 )[8]*(mat2)[8]); /* B * is(A) */ | |||
215 | ELL_3M_MUL(mat1, mat2, mat3)((mat1)[0] = (mat2)[0]*(mat3)[0] + (mat2)[1]*(mat3)[3] + (mat2 )[2]*(mat3)[6], (mat1)[1] = (mat2)[0]*(mat3)[1] + (mat2)[1]*( mat3)[4] + (mat2)[2]*(mat3)[7], (mat1)[2] = (mat2)[0]*(mat3)[ 2] + (mat2)[1]*(mat3)[5] + (mat2)[2]*(mat3)[8], (mat1)[3] = ( mat2)[3]*(mat3)[0] + (mat2)[4]*(mat3)[3] + (mat2)[5]*(mat3)[6 ], (mat1)[4] = (mat2)[3]*(mat3)[1] + (mat2)[4]*(mat3)[4] + (mat2 )[5]*(mat3)[7], (mat1)[5] = (mat2)[3]*(mat3)[2] + (mat2)[4]*( mat3)[5] + (mat2)[5]*(mat3)[8], (mat1)[6] = (mat2)[6]*(mat3)[ 0] + (mat2)[7]*(mat3)[3] + (mat2)[8]*(mat3)[6], (mat1)[7] = ( mat2)[6]*(mat3)[1] + (mat2)[7]*(mat3)[4] + (mat2)[8]*(mat3)[7 ], (mat1)[8] = (mat2)[6]*(mat3)[2] + (mat2)[7]*(mat3)[5] + (mat2 )[8]*(mat3)[8]); /* is(A) * B * is(A) */ | |||
216 | TEN_M2T(tmp2, mat1)( (tmp2)[1] = (mat1)[0], (tmp2)[2] = ((mat1)[1]+(mat1)[3])/2.0 , (tmp2)[3] = ((mat1)[2]+(mat1)[6])/2.0, (tmp2)[4] = (mat1)[4 ], (tmp2)[5] = ((mat1)[5]+(mat1)[7])/2.0, (tmp2)[6] = (mat1)[ 8] ); | |||
217 | tenPowSingle_d(tmp1, tmp2, aa); /* m = (is(A) * B * is(A))^aa */ | |||
218 | TEN_T2M(mat1, tmp1)( (mat1)[0] = (tmp1)[1], (mat1)[1] = (tmp1)[2], (mat1)[2] = ( tmp1)[3], (mat1)[3] = (tmp1)[2], (mat1)[4] = (tmp1)[4], (mat1 )[5] = (tmp1)[5], (mat1)[6] = (tmp1)[3], (mat1)[7] = (tmp1)[5 ], (mat1)[8] = (tmp1)[6] ); | |||
219 | TEN_T2M(mat2, sqrtA)( (mat2)[0] = (sqrtA)[1], (mat2)[1] = (sqrtA)[2], (mat2)[2] = (sqrtA)[3], (mat2)[3] = (sqrtA)[2], (mat2)[4] = (sqrtA)[4], ( mat2)[5] = (sqrtA)[5], (mat2)[6] = (sqrtA)[3], (mat2)[7] = (sqrtA )[5], (mat2)[8] = (sqrtA)[6] ); | |||
220 | ELL_3M_MUL(mat3, mat1, mat2)((mat3)[0] = (mat1)[0]*(mat2)[0] + (mat1)[1]*(mat2)[3] + (mat1 )[2]*(mat2)[6], (mat3)[1] = (mat1)[0]*(mat2)[1] + (mat1)[1]*( mat2)[4] + (mat1)[2]*(mat2)[7], (mat3)[2] = (mat1)[0]*(mat2)[ 2] + (mat1)[1]*(mat2)[5] + (mat1)[2]*(mat2)[8], (mat3)[3] = ( mat1)[3]*(mat2)[0] + (mat1)[4]*(mat2)[3] + (mat1)[5]*(mat2)[6 ], (mat3)[4] = (mat1)[3]*(mat2)[1] + (mat1)[4]*(mat2)[4] + (mat1 )[5]*(mat2)[7], (mat3)[5] = (mat1)[3]*(mat2)[2] + (mat1)[4]*( mat2)[5] + (mat1)[5]*(mat2)[8], (mat3)[6] = (mat1)[6]*(mat2)[ 0] + (mat1)[7]*(mat2)[3] + (mat1)[8]*(mat2)[6], (mat3)[7] = ( mat1)[6]*(mat2)[1] + (mat1)[7]*(mat2)[4] + (mat1)[8]*(mat2)[7 ], (mat3)[8] = (mat1)[6]*(mat2)[2] + (mat1)[7]*(mat2)[5] + (mat1 )[8]*(mat2)[8]); /* m * sqrt(A) */ | |||
221 | ELL_3M_MUL(mat1, mat2, mat3)((mat1)[0] = (mat2)[0]*(mat3)[0] + (mat2)[1]*(mat3)[3] + (mat2 )[2]*(mat3)[6], (mat1)[1] = (mat2)[0]*(mat3)[1] + (mat2)[1]*( mat3)[4] + (mat2)[2]*(mat3)[7], (mat1)[2] = (mat2)[0]*(mat3)[ 2] + (mat2)[1]*(mat3)[5] + (mat2)[2]*(mat3)[8], (mat1)[3] = ( mat2)[3]*(mat3)[0] + (mat2)[4]*(mat3)[3] + (mat2)[5]*(mat3)[6 ], (mat1)[4] = (mat2)[3]*(mat3)[1] + (mat2)[4]*(mat3)[4] + (mat2 )[5]*(mat3)[7], (mat1)[5] = (mat2)[3]*(mat3)[2] + (mat2)[4]*( mat3)[5] + (mat2)[5]*(mat3)[8], (mat1)[6] = (mat2)[6]*(mat3)[ 0] + (mat2)[7]*(mat3)[3] + (mat2)[8]*(mat3)[6], (mat1)[7] = ( mat2)[6]*(mat3)[1] + (mat2)[7]*(mat3)[4] + (mat2)[8]*(mat3)[7 ], (mat1)[8] = (mat2)[6]*(mat3)[2] + (mat2)[7]*(mat3)[5] + (mat2 )[8]*(mat3)[8]); /* sqrt(A) * m * sqrt(A) */ | |||
222 | TEN_M2T(oten, mat1)( (oten)[1] = (mat1)[0], (oten)[2] = ((mat1)[1]+(mat1)[3])/2.0 , (oten)[3] = ((mat1)[2]+(mat1)[6])/2.0, (oten)[4] = (mat1)[4 ], (oten)[5] = ((mat1)[5]+(mat1)[7])/2.0, (oten)[6] = (mat1)[ 8] ); | |||
223 | oten[0] = AIR_LERP(aa, tenA[0], tenB[0])((aa)*((tenB[0]) - (tenA[0])) + (tenA[0])); | |||
224 | if (tip->verbose) { | |||
225 | fprintf(stderr__stderrp, "%s:\nA= %g %g %g %g %g %g\n" | |||
226 | "B = %g %g %g %g %g %g\n" | |||
227 | "foo = %g %g %g %g %g %g\n" | |||
228 | "bar(%g) = %g %g %g %g %g %g\n", me, | |||
229 | tenA[1], tenA[2], tenA[3], tenA[4], tenA[5], tenA[6], | |||
230 | tenB[1], tenB[2], tenB[3], tenB[4], tenB[5], tenB[6], | |||
231 | tmp1[1], tmp1[2], tmp1[3], tmp1[4], tmp1[5], tmp1[6], | |||
232 | aa, oten[1], oten[2], oten[3], oten[4], oten[5], oten[6]); | |||
233 | } | |||
234 | break; | |||
235 | case tenInterpTypeWang: | |||
236 | /* HEY: this seems to be broken */ | |||
237 | TEN_T_LERP(mean, aa, tenA, tenB)( (mean)[0] = (((aa))*(((tenB)[0]) - ((tenA)[0])) + ((tenA)[0 ])), (mean)[1] = (((aa))*(((tenB)[1]) - ((tenA)[1])) + ((tenA )[1])), (mean)[2] = (((aa))*(((tenB)[2]) - ((tenA)[2])) + ((tenA )[2])), (mean)[3] = (((aa))*(((tenB)[3]) - ((tenA)[3])) + ((tenA )[3])), (mean)[4] = (((aa))*(((tenB)[4]) - ((tenA)[4])) + ((tenA )[4])), (mean)[5] = (((aa))*(((tenB)[5]) - ((tenA)[5])) + ((tenA )[5])), (mean)[6] = (((aa))*(((tenB)[6]) - ((tenA)[6])) + ((tenA )[6]))); /* "A" = mean */ | |||
238 | tenLogSingle_d(logA, tenA); | |||
239 | tenLogSingle_d(logB, tenB); | |||
240 | TEN_T_LERP(logMean, aa, logA, logB)( (logMean)[0] = (((aa))*(((logB)[0]) - ((logA)[0])) + ((logA )[0])), (logMean)[1] = (((aa))*(((logB)[1]) - ((logA)[1])) + ( (logA)[1])), (logMean)[2] = (((aa))*(((logB)[2]) - ((logA)[2] )) + ((logA)[2])), (logMean)[3] = (((aa))*(((logB)[3]) - ((logA )[3])) + ((logA)[3])), (logMean)[4] = (((aa))*(((logB)[4]) - ( (logA)[4])) + ((logA)[4])), (logMean)[5] = (((aa))*(((logB)[5 ]) - ((logA)[5])) + ((logA)[5])), (logMean)[6] = (((aa))*(((logB )[6]) - ((logA)[6])) + ((logA)[6]))); /* "B" = logMean */ | |||
241 | tenSqrtSingle_d(sqrtB, logMean); | |||
242 | tenInv_d(isqrtB, sqrtB); | |||
243 | TEN_T2M(mat1, mean)( (mat1)[0] = (mean)[1], (mat1)[1] = (mean)[2], (mat1)[2] = ( mean)[3], (mat1)[3] = (mean)[2], (mat1)[4] = (mean)[4], (mat1 )[5] = (mean)[5], (mat1)[6] = (mean)[3], (mat1)[7] = (mean)[5 ], (mat1)[8] = (mean)[6] ); | |||
244 | TEN_T2M(mat2, isqrtB)( (mat2)[0] = (isqrtB)[1], (mat2)[1] = (isqrtB)[2], (mat2)[2] = (isqrtB)[3], (mat2)[3] = (isqrtB)[2], (mat2)[4] = (isqrtB) [4], (mat2)[5] = (isqrtB)[5], (mat2)[6] = (isqrtB)[3], (mat2) [7] = (isqrtB)[5], (mat2)[8] = (isqrtB)[6] ); | |||
245 | ELL_3M_MUL(mat3, mat1, mat2)((mat3)[0] = (mat1)[0]*(mat2)[0] + (mat1)[1]*(mat2)[3] + (mat1 )[2]*(mat2)[6], (mat3)[1] = (mat1)[0]*(mat2)[1] + (mat1)[1]*( mat2)[4] + (mat1)[2]*(mat2)[7], (mat3)[2] = (mat1)[0]*(mat2)[ 2] + (mat1)[1]*(mat2)[5] + (mat1)[2]*(mat2)[8], (mat3)[3] = ( mat1)[3]*(mat2)[0] + (mat1)[4]*(mat2)[3] + (mat1)[5]*(mat2)[6 ], (mat3)[4] = (mat1)[3]*(mat2)[1] + (mat1)[4]*(mat2)[4] + (mat1 )[5]*(mat2)[7], (mat3)[5] = (mat1)[3]*(mat2)[2] + (mat1)[4]*( mat2)[5] + (mat1)[5]*(mat2)[8], (mat3)[6] = (mat1)[6]*(mat2)[ 0] + (mat1)[7]*(mat2)[3] + (mat1)[8]*(mat2)[6], (mat3)[7] = ( mat1)[6]*(mat2)[1] + (mat1)[7]*(mat2)[4] + (mat1)[8]*(mat2)[7 ], (mat3)[8] = (mat1)[6]*(mat2)[2] + (mat1)[7]*(mat2)[5] + (mat1 )[8]*(mat2)[8]); | |||
246 | ELL_3M_MUL(mat1, mat2, mat3)((mat1)[0] = (mat2)[0]*(mat3)[0] + (mat2)[1]*(mat3)[3] + (mat2 )[2]*(mat3)[6], (mat1)[1] = (mat2)[0]*(mat3)[1] + (mat2)[1]*( mat3)[4] + (mat2)[2]*(mat3)[7], (mat1)[2] = (mat2)[0]*(mat3)[ 2] + (mat2)[1]*(mat3)[5] + (mat2)[2]*(mat3)[8], (mat1)[3] = ( mat2)[3]*(mat3)[0] + (mat2)[4]*(mat3)[3] + (mat2)[5]*(mat3)[6 ], (mat1)[4] = (mat2)[3]*(mat3)[1] + (mat2)[4]*(mat3)[4] + (mat2 )[5]*(mat3)[7], (mat1)[5] = (mat2)[3]*(mat3)[2] + (mat2)[4]*( mat3)[5] + (mat2)[5]*(mat3)[8], (mat1)[6] = (mat2)[6]*(mat3)[ 0] + (mat2)[7]*(mat3)[3] + (mat2)[8]*(mat3)[6], (mat1)[7] = ( mat2)[6]*(mat3)[1] + (mat2)[7]*(mat3)[4] + (mat2)[8]*(mat3)[7 ], (mat1)[8] = (mat2)[6]*(mat3)[2] + (mat2)[7]*(mat3)[5] + (mat2 )[8]*(mat3)[8]); | |||
247 | TEN_M2T(tmp1, mat1)( (tmp1)[1] = (mat1)[0], (tmp1)[2] = ((mat1)[1]+(mat1)[3])/2.0 , (tmp1)[3] = ((mat1)[2]+(mat1)[6])/2.0, (tmp1)[4] = (mat1)[4 ], (tmp1)[5] = ((mat1)[5]+(mat1)[7])/2.0, (tmp1)[6] = (mat1)[ 8] ); | |||
248 | tenSqrtSingle_d(oten, tmp1); | |||
249 | oten[0] = AIR_LERP(aa, tenA[0], tenB[0])((aa)*((tenB[0]) - (tenA[0])) + (tenA[0])); | |||
250 | break; | |||
251 | case tenInterpTypeQuatGeoLoxK: | |||
252 | case tenInterpTypeQuatGeoLoxR: | |||
253 | tenEigensolve_d(evalA, evecA, tenA); | |||
254 | tenEigensolve_d(evalB, evecB, tenB); | |||
255 | if (tenInterpTypeQuatGeoLoxK == ptype) { | |||
256 | tenQGLInterpTwoEvalK(oeval, evalA, evalB, aa); | |||
257 | } else { | |||
258 | tenQGLInterpTwoEvalR(oeval, evalA, evalB, aa); | |||
259 | } | |||
260 | tenQGLInterpTwoEvec(oevec, evecA, evecB, aa); | |||
261 | tenMakeSingle_d(oten, AIR_LERP(aa, tenA[0], tenB[0])((aa)*((tenB[0]) - (tenA[0])) + (tenA[0])), oeval, oevec); | |||
262 | break; | |||
263 | case tenInterpTypeGeoLoxK: | |||
264 | case tenInterpTypeGeoLoxR: | |||
265 | case tenInterpTypeLoxK: | |||
266 | case tenInterpTypeLoxR: | |||
267 | /* (currently) no closed-form expression for these */ | |||
268 | TEN_T_SET(oten, AIR_NAN, AIR_NAN, AIR_NAN, AIR_NAN,( (oten)[0] = ((airFloatQNaN.f)), (oten)[1] = ((airFloatQNaN. f)), (oten)[2] = ((airFloatQNaN.f)), (oten)[3] = ((airFloatQNaN .f)), (oten)[4] = ((airFloatQNaN.f)), (oten)[5] = ((airFloatQNaN .f)), (oten)[6] = ((airFloatQNaN.f)) ) | |||
269 | AIR_NAN, AIR_NAN, AIR_NAN)( (oten)[0] = ((airFloatQNaN.f)), (oten)[1] = ((airFloatQNaN. f)), (oten)[2] = ((airFloatQNaN.f)), (oten)[3] = ((airFloatQNaN .f)), (oten)[4] = ((airFloatQNaN.f)), (oten)[5] = ((airFloatQNaN .f)), (oten)[6] = ((airFloatQNaN.f)) ); | |||
270 | break; | |||
271 | case tenInterpTypeRThetaPhiLinear: | |||
272 | if (1) { | |||
273 | double rtpA[3], rtpB[3], rtpM[3], eval[3], tenM[7]; | |||
274 | tenEigensolve_d(eval, NULL((void*)0), tenA); | |||
275 | tenTripleConvertSingle_d(rtpA, tenTripleTypeRThetaPhi, | |||
276 | eval, tenTripleTypeEigenvalue); | |||
277 | tenEigensolve_d(eval, NULL((void*)0), tenB); | |||
278 | tenTripleConvertSingle_d(rtpB, tenTripleTypeRThetaPhi, | |||
279 | eval, tenTripleTypeEigenvalue); | |||
280 | TEN_T_LERP(tenM, aa, tenA, tenB)( (tenM)[0] = (((aa))*(((tenB)[0]) - ((tenA)[0])) + ((tenA)[0 ])), (tenM)[1] = (((aa))*(((tenB)[1]) - ((tenA)[1])) + ((tenA )[1])), (tenM)[2] = (((aa))*(((tenB)[2]) - ((tenA)[2])) + ((tenA )[2])), (tenM)[3] = (((aa))*(((tenB)[3]) - ((tenA)[3])) + ((tenA )[3])), (tenM)[4] = (((aa))*(((tenB)[4]) - ((tenA)[4])) + ((tenA )[4])), (tenM)[5] = (((aa))*(((tenB)[5]) - ((tenA)[5])) + ((tenA )[5])), (tenM)[6] = (((aa))*(((tenB)[6]) - ((tenA)[6])) + ((tenA )[6]))); | |||
281 | tenEigensolve_d(eval, oevec, tenM); | |||
282 | ELL_3V_LERP(rtpM, aa, rtpA, rtpB)((rtpM)[0] = (((aa))*(((rtpB)[0]) - ((rtpA)[0])) + ((rtpA)[0] )), (rtpM)[1] = (((aa))*(((rtpB)[1]) - ((rtpA)[1])) + ((rtpA) [1])), (rtpM)[2] = (((aa))*(((rtpB)[2]) - ((rtpA)[2])) + ((rtpA )[2]))); | |||
283 | tenTripleConvertSingle_d(oeval, tenTripleTypeEigenvalue, | |||
284 | rtpM, tenTripleTypeRThetaPhi); | |||
285 | } | |||
286 | tenMakeSingle_d(oten, AIR_LERP(aa, tenA[0], tenB[0])((aa)*((tenB[0]) - (tenA[0])) + (tenA[0])), oeval, oevec); | |||
287 | break; | |||
288 | default: | |||
289 | /* error */ | |||
290 | TEN_T_SET(oten, AIR_NAN, AIR_NAN, AIR_NAN, AIR_NAN,( (oten)[0] = ((airFloatQNaN.f)), (oten)[1] = ((airFloatQNaN. f)), (oten)[2] = ((airFloatQNaN.f)), (oten)[3] = ((airFloatQNaN .f)), (oten)[4] = ((airFloatQNaN.f)), (oten)[5] = ((airFloatQNaN .f)), (oten)[6] = ((airFloatQNaN.f)) ) | |||
291 | AIR_NAN, AIR_NAN, AIR_NAN)( (oten)[0] = ((airFloatQNaN.f)), (oten)[1] = ((airFloatQNaN. f)), (oten)[2] = ((airFloatQNaN.f)), (oten)[3] = ((airFloatQNaN .f)), (oten)[4] = ((airFloatQNaN.f)), (oten)[5] = ((airFloatQNaN .f)), (oten)[6] = ((airFloatQNaN.f)) ); | |||
292 | break; | |||
293 | } | |||
294 | return; | |||
295 | } | |||
296 | ||||
297 | /* | |||
298 | ** this NON-optionally uses biff | |||
299 | ** | |||
300 | ** for simplicity, a pre-allocated tenInterpParm MUST be passed, | |||
301 | ** regardless of the interpolation requested | |||
302 | */ | |||
303 | int | |||
304 | tenInterpN_d(double tenOut[7], | |||
305 | const double *tenIn, const double *wght, | |||
306 | unsigned int num, int ptype, tenInterpParm *tip) { | |||
307 | static const char me[]="tenInterpN_d"; | |||
308 | unsigned int ii; | |||
309 | double ww, cc, tenErr[7], tmpTen[7], wghtSum, eval[3], evec[9], rtp[3]; | |||
310 | ||||
311 | TEN_T_SET(tenErr, AIR_NAN, AIR_NAN, AIR_NAN, AIR_NAN,( (tenErr)[0] = ((airFloatQNaN.f)), (tenErr)[1] = ((airFloatQNaN .f)), (tenErr)[2] = ((airFloatQNaN.f)), (tenErr)[3] = ((airFloatQNaN .f)), (tenErr)[4] = ((airFloatQNaN.f)), (tenErr)[5] = ((airFloatQNaN .f)), (tenErr)[6] = ((airFloatQNaN.f)) ) | |||
312 | AIR_NAN, AIR_NAN, AIR_NAN)( (tenErr)[0] = ((airFloatQNaN.f)), (tenErr)[1] = ((airFloatQNaN .f)), (tenErr)[2] = ((airFloatQNaN.f)), (tenErr)[3] = ((airFloatQNaN .f)), (tenErr)[4] = ((airFloatQNaN.f)), (tenErr)[5] = ((airFloatQNaN .f)), (tenErr)[6] = ((airFloatQNaN.f)) ); | |||
313 | /* wght can be NULL ==> equal 1/num weight for all */ | |||
314 | if (!(tenOut && tenIn && tip)) { | |||
315 | biffAddf(TENtenBiffKey, "%s: got NULL pointer", me); | |||
316 | return 1; | |||
317 | } | |||
318 | if (!( num >= 2 )) { | |||
319 | biffAddf(TENtenBiffKey, "%s: need num >= 2 (not %u)", me, num); | |||
320 | TEN_T_COPY(tenOut, tenErr)( (tenOut)[0] = (tenErr)[0], (tenOut)[1] = (tenErr)[1], (tenOut )[2] = (tenErr)[2], (tenOut)[3] = (tenErr)[3], (tenOut)[4] = ( tenErr)[4], (tenOut)[5] = (tenErr)[5], (tenOut)[6] = (tenErr) [6] ); return 1; | |||
321 | } | |||
322 | if (airEnumValCheck(tenInterpType, ptype)) { | |||
323 | biffAddf(TENtenBiffKey, "%s: invalid %s %d", me, tenInterpType->name, ptype); | |||
324 | TEN_T_COPY(tenOut, tenErr)( (tenOut)[0] = (tenErr)[0], (tenOut)[1] = (tenErr)[1], (tenOut )[2] = (tenErr)[2], (tenOut)[3] = (tenErr)[3], (tenOut)[4] = ( tenErr)[4], (tenOut)[5] = (tenErr)[5], (tenOut)[6] = (tenErr) [6] ); return 1; | |||
325 | } | |||
326 | wghtSum = 0; | |||
327 | for (ii=0; ii<num; ii++) { | |||
328 | ww = wght ? wght[ii] : 1.0/num; | |||
329 | wghtSum += ww; | |||
330 | } | |||
331 | if (!( AIR_IN_CL(1 - tip->wghtSumEps, wghtSum, 1 + tip->wghtSumEps)((1 - tip->wghtSumEps) <= (wghtSum) && (wghtSum ) <= (1 + tip->wghtSumEps)) )) { | |||
332 | biffAddf(TENtenBiffKey, "%s: wght sum %g not within %g of 1.0", me, | |||
333 | wghtSum, tip->wghtSumEps); | |||
334 | TEN_T_COPY(tenOut, tenErr)( (tenOut)[0] = (tenErr)[0], (tenOut)[1] = (tenErr)[1], (tenOut )[2] = (tenErr)[2], (tenOut)[3] = (tenErr)[3], (tenOut)[4] = ( tenErr)[4], (tenOut)[5] = (tenErr)[5], (tenOut)[6] = (tenErr) [6] ); return 1; | |||
335 | } | |||
336 | ||||
337 | switch (ptype) { | |||
338 | case tenInterpTypeLinear: | |||
339 | TEN_T_SET(tenOut, 0, 0, 0, 0, 0, 0, 0)( (tenOut)[0] = (0), (tenOut)[1] = (0), (tenOut)[2] = (0), (tenOut )[3] = (0), (tenOut)[4] = (0), (tenOut)[5] = (0), (tenOut)[6] = (0) ); | |||
340 | cc = 0; | |||
341 | for (ii=0; ii<num; ii++) { | |||
342 | ww = wght ? wght[ii] : 1.0/num; | |||
343 | TEN_T_SCALE_INCR(tenOut, ww, tenIn + 7*ii)( (tenOut)[0] = (tenIn + 7*ii)[0], (tenOut)[1] += (ww)*(tenIn + 7*ii)[1], (tenOut)[2] += (ww)*(tenIn + 7*ii)[2], (tenOut)[ 3] += (ww)*(tenIn + 7*ii)[3], (tenOut)[4] += (ww)*(tenIn + 7* ii)[4], (tenOut)[5] += (ww)*(tenIn + 7*ii)[5], (tenOut)[6] += (ww)*(tenIn + 7*ii)[6]); | |||
344 | cc += ww*(tenIn + 7*ii)[0]; | |||
345 | } | |||
346 | tenOut[0] = cc; | |||
347 | break; | |||
348 | case tenInterpTypeLogLinear: | |||
349 | TEN_T_SET(tenOut, 0, 0, 0, 0, 0, 0, 0)( (tenOut)[0] = (0), (tenOut)[1] = (0), (tenOut)[2] = (0), (tenOut )[3] = (0), (tenOut)[4] = (0), (tenOut)[5] = (0), (tenOut)[6] = (0) ); | |||
350 | cc = 0; | |||
351 | for (ii=0; ii<num; ii++) { | |||
352 | ww = wght ? wght[ii] : 1.0/num; | |||
353 | tenLogSingle_d(tmpTen, tenIn + 7*ii); | |||
354 | TEN_T_SCALE_INCR(tenOut, ww, tmpTen)( (tenOut)[0] = (tmpTen)[0], (tenOut)[1] += (ww)*(tmpTen)[1], (tenOut)[2] += (ww)*(tmpTen)[2], (tenOut)[3] += (ww)*(tmpTen )[3], (tenOut)[4] += (ww)*(tmpTen)[4], (tenOut)[5] += (ww)*(tmpTen )[5], (tenOut)[6] += (ww)*(tmpTen)[6]); | |||
355 | cc += ww*(tenIn + 7*ii)[0]; | |||
356 | } | |||
357 | tenOut[0] = cc; | |||
358 | TEN_T_COPY(tmpTen, tenOut)( (tmpTen)[0] = (tenOut)[0], (tmpTen)[1] = (tenOut)[1], (tmpTen )[2] = (tenOut)[2], (tmpTen)[3] = (tenOut)[3], (tmpTen)[4] = ( tenOut)[4], (tmpTen)[5] = (tenOut)[5], (tmpTen)[6] = (tenOut) [6] ); | |||
359 | tenExpSingle_d(tenOut, tmpTen); | |||
360 | break; | |||
361 | case tenInterpTypeAffineInvariant: | |||
362 | case tenInterpTypeWang: | |||
363 | biffAddf(TENtenBiffKey, "%s: sorry, not implemented", me); | |||
364 | TEN_T_COPY(tenOut, tenErr)( (tenOut)[0] = (tenErr)[0], (tenOut)[1] = (tenErr)[1], (tenOut )[2] = (tenErr)[2], (tenOut)[3] = (tenErr)[3], (tenOut)[4] = ( tenErr)[4], (tenOut)[5] = (tenErr)[5], (tenOut)[6] = (tenErr) [6] ); return 1; | |||
365 | break; | |||
366 | case tenInterpTypeGeoLoxK: | |||
367 | case tenInterpTypeGeoLoxR: | |||
368 | case tenInterpTypeLoxK: | |||
369 | case tenInterpTypeLoxR: | |||
370 | biffAddf(TENtenBiffKey, "%s: %s doesn't support averaging multiple tensors", me, | |||
371 | airEnumStr(tenInterpType, ptype)); | |||
372 | TEN_T_COPY(tenOut, tenErr)( (tenOut)[0] = (tenErr)[0], (tenOut)[1] = (tenErr)[1], (tenOut )[2] = (tenErr)[2], (tenOut)[3] = (tenErr)[3], (tenOut)[4] = ( tenErr)[4], (tenOut)[5] = (tenErr)[5], (tenOut)[6] = (tenErr) [6] ); return 1; | |||
373 | break; | |||
374 | case tenInterpTypeQuatGeoLoxK: | |||
375 | case tenInterpTypeQuatGeoLoxR: | |||
376 | if (tenInterpParmBufferAlloc(tip, num)) { | |||
377 | biffAddf(TENtenBiffKey, "%s: trouble getting buffers", me); | |||
378 | TEN_T_COPY(tenOut, tenErr)( (tenOut)[0] = (tenErr)[0], (tenOut)[1] = (tenErr)[1], (tenOut )[2] = (tenErr)[2], (tenOut)[3] = (tenErr)[3], (tenOut)[4] = ( tenErr)[4], (tenOut)[5] = (tenErr)[5], (tenOut)[6] = (tenErr) [6] ); return 1; | |||
379 | } else { | |||
380 | cc = 0; | |||
381 | for (ii=0; ii<num; ii++) { | |||
382 | tenEigensolve_d(tip->eval + 3*ii, tip->evec + 9*ii, tenIn + 7*ii); | |||
383 | ww = wght ? wght[ii] : 1.0/num; | |||
384 | cc += ww*(tenIn + 7*ii)[0]; | |||
385 | } | |||
386 | if (_tenQGLInterpNEval(eval, tip->eval, wght, num, ptype, tip) | |||
387 | || _tenQGLInterpNEvec(evec, tip->evec, wght, num, tip)) { | |||
388 | biffAddf(TENtenBiffKey, "%s: trouble computing", me); | |||
389 | TEN_T_COPY(tenOut, tenErr)( (tenOut)[0] = (tenErr)[0], (tenOut)[1] = (tenErr)[1], (tenOut )[2] = (tenErr)[2], (tenOut)[3] = (tenErr)[3], (tenOut)[4] = ( tenErr)[4], (tenOut)[5] = (tenErr)[5], (tenOut)[6] = (tenErr) [6] ); return 1; | |||
390 | } | |||
391 | tenMakeSingle_d(tenOut, cc, eval, evec); | |||
392 | } | |||
393 | break; | |||
394 | case tenInterpTypeRThetaPhiLinear: | |||
395 | TEN_T_SET(tmpTen, 0, 0, 0, 0, 0, 0, 0)( (tmpTen)[0] = (0), (tmpTen)[1] = (0), (tmpTen)[2] = (0), (tmpTen )[3] = (0), (tmpTen)[4] = (0), (tmpTen)[5] = (0), (tmpTen)[6] = (0) ); | |||
396 | ELL_3V_SET(rtp, 0, 0, 0)((rtp)[0] = (0), (rtp)[1] = (0), (rtp)[2] = (0)); | |||
397 | for (ii=0; ii<num; ii++) { | |||
398 | double tmpeval[3], tmprtp[3]; | |||
399 | tenEigensolve_d(tmpeval, NULL((void*)0), tenIn + 7*ii); | |||
400 | tenTripleConvertSingle_d(tmprtp, tenTripleTypeRThetaPhi, | |||
401 | tmpeval, tenTripleTypeEigenvalue); | |||
402 | ww = wght ? wght[ii] : 1.0/num; | |||
403 | TEN_T_SCALE_INCR(tmpTen, ww, tenIn + 7*ii)( (tmpTen)[0] = (tenIn + 7*ii)[0], (tmpTen)[1] += (ww)*(tenIn + 7*ii)[1], (tmpTen)[2] += (ww)*(tenIn + 7*ii)[2], (tmpTen)[ 3] += (ww)*(tenIn + 7*ii)[3], (tmpTen)[4] += (ww)*(tenIn + 7* ii)[4], (tmpTen)[5] += (ww)*(tenIn + 7*ii)[5], (tmpTen)[6] += (ww)*(tenIn + 7*ii)[6]); | |||
404 | ELL_3V_SCALE_INCR(rtp, ww, tmprtp)((rtp)[0] += (ww)*(tmprtp)[0], (rtp)[1] += (ww)*(tmprtp)[1], ( rtp)[2] += (ww)*(tmprtp)[2]); | |||
405 | } | |||
406 | tenEigensolve_d(eval, evec, tmpTen); /* only care about evec */ | |||
407 | tenTripleConvertSingle_d(eval, tenTripleTypeEigenvalue, | |||
408 | rtp, tenTripleTypeRThetaPhi); | |||
409 | tenMakeSingle_d(tenOut, tmpTen[0], eval, evec); | |||
410 | break; | |||
411 | default: | |||
412 | biffAddf(TENtenBiffKey, "%s: sorry, interp type %s (%d) not implemented", | |||
413 | me, airEnumStr(tenInterpType, ptype), ptype); | |||
414 | TEN_T_COPY(tenOut, tenErr)( (tenOut)[0] = (tenErr)[0], (tenOut)[1] = (tenErr)[1], (tenOut )[2] = (tenErr)[2], (tenOut)[3] = (tenErr)[3], (tenOut)[4] = ( tenErr)[4], (tenOut)[5] = (tenErr)[5], (tenOut)[6] = (tenErr) [6] ); | |||
415 | return 1; | |||
416 | } | |||
417 | ||||
418 | return 0; | |||
419 | } | |||
420 | ||||
421 | int | |||
422 | _tenInterpGeoLoxRelaxOne(Nrrd *nodata, Nrrd *ntdata, Nrrd *nigrtdata, | |||
423 | unsigned int ii, int rotnoop, double scl, | |||
424 | tenInterpParm *tip) { | |||
425 | static const char me[]="_tenInterpGeoLoxRelaxOne"; | |||
426 | double *tdata, *odata, *igrtdata, *tt[5], *igrt[5][6], d02[7], d24[7], | |||
427 | len02, len24, tmp, tng[7], correct, update[7]; | |||
428 | unsigned int jj; | |||
429 | ||||
430 | if (tip->verbose) { | |||
431 | fprintf(stderr__stderrp, "---- %u --> %u %u %u %u %u\n", ii, | |||
432 | 2*ii - 2, 2*ii - 1, 2*ii, 2*ii + 1, 2*ii + 2); | |||
433 | } | |||
434 | tdata = AIR_CAST(double *, ntdata->data)((double *)(ntdata->data)); | |||
435 | odata = AIR_CAST(double *, nodata->data)((double *)(nodata->data)); | |||
436 | tt[0] = tdata + 7*(2*ii - 2); | |||
437 | tt[1] = tdata + 7*(2*ii - 1); /* unused */ | |||
438 | tt[2] = tdata + 7*(2*ii + 0); | |||
439 | tt[3] = tdata + 7*(2*ii + 1); /* unused */ | |||
440 | tt[4] = tdata + 7*(2*ii + 2); | |||
441 | igrtdata = AIR_CAST(double *, nigrtdata->data)((double *)(nigrtdata->data)); | |||
442 | for (jj=0; jj<6; jj++) { | |||
443 | igrt[0][jj] = igrtdata + 7*(jj + 6*(2*ii - 2)); /* unused */ | |||
444 | igrt[1][jj] = igrtdata + 7*(jj + 6*(2*ii - 1)); | |||
445 | igrt[2][jj] = igrtdata + 7*(jj + 6*(2*ii + 0)); | |||
446 | igrt[3][jj] = igrtdata + 7*(jj + 6*(2*ii + 1)); | |||
447 | igrt[4][jj] = igrtdata + 7*(jj + 6*(2*ii + 2)); /* unused */ | |||
448 | } | |||
449 | ||||
450 | /* re-align [1] and [3] bases relative to [2] */ | |||
451 | /* HEY: should I be worrying about aligning the mode normal | |||
452 | when it had to be computed from eigenvectors? */ | |||
453 | for (jj=3; jj<6; jj++) { | |||
454 | if (TEN_T_DOT(igrt[1][jj], igrt[2][jj])( (igrt[1][jj])[1]*(igrt[2][jj])[1] + 2*(igrt[1][jj])[2]*(igrt [2][jj])[2] + 2*(igrt[1][jj])[3]*(igrt[2][jj])[3] + (igrt[1][ jj])[4]*(igrt[2][jj])[4] + 2*(igrt[1][jj])[5]*(igrt[2][jj])[5 ] + (igrt[1][jj])[6]*(igrt[2][jj])[6] ) < 0) { | |||
455 | TEN_T_SCALE(igrt[1][jj], -1, igrt[1][jj])( (igrt[1][jj])[0] = (igrt[1][jj])[0], (igrt[1][jj])[1] = (-1 )*(igrt[1][jj])[1], (igrt[1][jj])[2] = (-1)*(igrt[1][jj])[2], (igrt[1][jj])[3] = (-1)*(igrt[1][jj])[3], (igrt[1][jj])[4] = (-1)*(igrt[1][jj])[4], (igrt[1][jj])[5] = (-1)*(igrt[1][jj]) [5], (igrt[1][jj])[6] = (-1)*(igrt[1][jj])[6]); | |||
456 | } | |||
457 | if (TEN_T_DOT(igrt[3][jj], igrt[2][jj])( (igrt[3][jj])[1]*(igrt[2][jj])[1] + 2*(igrt[3][jj])[2]*(igrt [2][jj])[2] + 2*(igrt[3][jj])[3]*(igrt[2][jj])[3] + (igrt[3][ jj])[4]*(igrt[2][jj])[4] + 2*(igrt[3][jj])[5]*(igrt[2][jj])[5 ] + (igrt[3][jj])[6]*(igrt[2][jj])[6] ) < 0) { | |||
458 | TEN_T_SCALE(igrt[3][jj], -1, igrt[1][jj])( (igrt[3][jj])[0] = (igrt[1][jj])[0], (igrt[3][jj])[1] = (-1 )*(igrt[1][jj])[1], (igrt[3][jj])[2] = (-1)*(igrt[1][jj])[2], (igrt[3][jj])[3] = (-1)*(igrt[1][jj])[3], (igrt[3][jj])[4] = (-1)*(igrt[1][jj])[4], (igrt[3][jj])[5] = (-1)*(igrt[1][jj]) [5], (igrt[3][jj])[6] = (-1)*(igrt[1][jj])[6]); | |||
459 | } | |||
460 | } | |||
461 | ||||
462 | TEN_T_SUB(tng, tt[4], tt[0])( (tng)[0] = ((tt[4])[0] + (tt[0])[0])/2.0, (tng)[1] = (tt[4] )[1] - (tt[0])[1], (tng)[2] = (tt[4])[2] - (tt[0])[2], (tng)[ 3] = (tt[4])[3] - (tt[0])[3], (tng)[4] = (tt[4])[4] - (tt[0]) [4], (tng)[5] = (tt[4])[5] - (tt[0])[5], (tng)[6] = (tt[4])[6 ] - (tt[0])[6]); | |||
463 | tmp = 1.0/TEN_T_NORM(tng)(sqrt(( (tng)[1]*(tng)[1] + 2*(tng)[2]*(tng)[2] + 2*(tng)[3]* (tng)[3] + (tng)[4]*(tng)[4] + 2*(tng)[5]*(tng)[5] + (tng)[6] *(tng)[6] ))); | |||
464 | TEN_T_SCALE(tng, tmp, tng)( (tng)[0] = (tng)[0], (tng)[1] = (tmp)*(tng)[1], (tng)[2] = ( tmp)*(tng)[2], (tng)[3] = (tmp)*(tng)[3], (tng)[4] = (tmp)*(tng )[4], (tng)[5] = (tmp)*(tng)[5], (tng)[6] = (tmp)*(tng)[6]); | |||
465 | ||||
466 | TEN_T_SUB(d02, tt[2], tt[0])( (d02)[0] = ((tt[2])[0] + (tt[0])[0])/2.0, (d02)[1] = (tt[2] )[1] - (tt[0])[1], (d02)[2] = (tt[2])[2] - (tt[0])[2], (d02)[ 3] = (tt[2])[3] - (tt[0])[3], (d02)[4] = (tt[2])[4] - (tt[0]) [4], (d02)[5] = (tt[2])[5] - (tt[0])[5], (d02)[6] = (tt[2])[6 ] - (tt[0])[6]); | |||
467 | TEN_T_SUB(d24, tt[4], tt[2])( (d24)[0] = ((tt[4])[0] + (tt[2])[0])/2.0, (d24)[1] = (tt[4] )[1] - (tt[2])[1], (d24)[2] = (tt[4])[2] - (tt[2])[2], (d24)[ 3] = (tt[4])[3] - (tt[2])[3], (d24)[4] = (tt[4])[4] - (tt[2]) [4], (d24)[5] = (tt[4])[5] - (tt[2])[5], (d24)[6] = (tt[4])[6 ] - (tt[2])[6]); | |||
468 | TEN_T_SET(update, 1, 0, 0, 0, 0, 0, 0)( (update)[0] = (1), (update)[1] = (0), (update)[2] = (0), (update )[3] = (0), (update)[4] = (0), (update)[5] = (0), (update)[6] = (0) ); | |||
469 | for (jj=0; jj<(rotnoop ? 3u : 6u); jj++) { | |||
470 | len02 = TEN_T_DOT(igrt[1][jj], d02)( (igrt[1][jj])[1]*(d02)[1] + 2*(igrt[1][jj])[2]*(d02)[2] + 2 *(igrt[1][jj])[3]*(d02)[3] + (igrt[1][jj])[4]*(d02)[4] + 2*(igrt [1][jj])[5]*(d02)[5] + (igrt[1][jj])[6]*(d02)[6] ); | |||
471 | len24 = TEN_T_DOT(igrt[3][jj], d24)( (igrt[3][jj])[1]*(d24)[1] + 2*(igrt[3][jj])[2]*(d24)[2] + 2 *(igrt[3][jj])[3]*(d24)[3] + (igrt[3][jj])[4]*(d24)[4] + 2*(igrt [3][jj])[5]*(d24)[5] + (igrt[3][jj])[6]*(d24)[6] ); | |||
472 | correct = (len24 - len02)/2; | |||
473 | TEN_T_SCALE_INCR(update, correct*scl, igrt[2][jj])( (update)[0] = (igrt[2][jj])[0], (update)[1] += (correct*scl )*(igrt[2][jj])[1], (update)[2] += (correct*scl)*(igrt[2][jj] )[2], (update)[3] += (correct*scl)*(igrt[2][jj])[3], (update) [4] += (correct*scl)*(igrt[2][jj])[4], (update)[5] += (correct *scl)*(igrt[2][jj])[5], (update)[6] += (correct*scl)*(igrt[2] [jj])[6]); | |||
474 | if (tip->verbose) { | |||
475 | fprintf(stderr__stderrp, "igrt[1][%u] = %g %g %g %g %g %g\n", jj, | |||
476 | igrt[1][jj][1], igrt[1][jj][2], igrt[1][jj][3], | |||
477 | igrt[1][jj][4], igrt[1][jj][5], igrt[1][jj][6]); | |||
478 | fprintf(stderr__stderrp, "igrt[3][%u] = %g %g %g %g %g %g\n", jj, | |||
479 | igrt[3][jj][1], igrt[3][jj][2], igrt[3][jj][3], | |||
480 | igrt[3][jj][4], igrt[3][jj][5], igrt[3][jj][6]); | |||
481 | fprintf(stderr__stderrp, "(jj=%u) len = %g %g --> (d = %g) " | |||
482 | "update = %g %g %g %g %g %g\n", | |||
483 | jj, len02, len24, | |||
484 | TEN_T_DOT(igrt[2][0], update)( (igrt[2][0])[1]*(update)[1] + 2*(igrt[2][0])[2]*(update)[2] + 2*(igrt[2][0])[3]*(update)[3] + (igrt[2][0])[4]*(update)[4 ] + 2*(igrt[2][0])[5]*(update)[5] + (igrt[2][0])[6]*(update)[ 6] ), | |||
485 | update[1], update[2], update[3], | |||
486 | update[4], update[5], update[6]); | |||
487 | } | |||
488 | } | |||
489 | if (rotnoop) { | |||
490 | double avg[7], diff[7], len; | |||
491 | TEN_T_LERP(avg, 0.5, tt[0], tt[4])( (avg)[0] = (((0.5))*(((tt[4])[0]) - ((tt[0])[0])) + ((tt[0] )[0])), (avg)[1] = (((0.5))*(((tt[4])[1]) - ((tt[0])[1])) + ( (tt[0])[1])), (avg)[2] = (((0.5))*(((tt[4])[2]) - ((tt[0])[2] )) + ((tt[0])[2])), (avg)[3] = (((0.5))*(((tt[4])[3]) - ((tt[ 0])[3])) + ((tt[0])[3])), (avg)[4] = (((0.5))*(((tt[4])[4]) - ((tt[0])[4])) + ((tt[0])[4])), (avg)[5] = (((0.5))*(((tt[4]) [5]) - ((tt[0])[5])) + ((tt[0])[5])), (avg)[6] = (((0.5))*((( tt[4])[6]) - ((tt[0])[6])) + ((tt[0])[6]))); | |||
492 | TEN_T_SUB(diff, avg, tt[2])( (diff)[0] = ((avg)[0] + (tt[2])[0])/2.0, (diff)[1] = (avg)[ 1] - (tt[2])[1], (diff)[2] = (avg)[2] - (tt[2])[2], (diff)[3] = (avg)[3] - (tt[2])[3], (diff)[4] = (avg)[4] - (tt[2])[4], ( diff)[5] = (avg)[5] - (tt[2])[5], (diff)[6] = (avg)[6] - (tt[ 2])[6]); | |||
493 | for (jj=0; jj<3; jj++) { | |||
494 | len = TEN_T_DOT(igrt[2][jj], diff)( (igrt[2][jj])[1]*(diff)[1] + 2*(igrt[2][jj])[2]*(diff)[2] + 2*(igrt[2][jj])[3]*(diff)[3] + (igrt[2][jj])[4]*(diff)[4] + 2 *(igrt[2][jj])[5]*(diff)[5] + (igrt[2][jj])[6]*(diff)[6] ); | |||
495 | TEN_T_SCALE_INCR(diff, -len, igrt[2][jj])( (diff)[0] = (igrt[2][jj])[0], (diff)[1] += (-len)*(igrt[2][ jj])[1], (diff)[2] += (-len)*(igrt[2][jj])[2], (diff)[3] += ( -len)*(igrt[2][jj])[3], (diff)[4] += (-len)*(igrt[2][jj])[4], (diff)[5] += (-len)*(igrt[2][jj])[5], (diff)[6] += (-len)*(igrt [2][jj])[6]); | |||
496 | } | |||
497 | TEN_T_SCALE_INCR(update, scl*0.2, diff)( (update)[0] = (diff)[0], (update)[1] += (scl*0.2)*(diff)[1] , (update)[2] += (scl*0.2)*(diff)[2], (update)[3] += (scl*0.2 )*(diff)[3], (update)[4] += (scl*0.2)*(diff)[4], (update)[5] += (scl*0.2)*(diff)[5], (update)[6] += (scl*0.2)*(diff)[6]); /* HEY: scaling is a hack */ | |||
498 | if (tip->verbose) { | |||
499 | fprintf(stderr__stderrp, "(rotnoop) (d = %g) " | |||
500 | "update = %g %g %g %g %g %g\n", | |||
501 | TEN_T_DOT(igrt[2][0], update)( (igrt[2][0])[1]*(update)[1] + 2*(igrt[2][0])[2]*(update)[2] + 2*(igrt[2][0])[3]*(update)[3] + (igrt[2][0])[4]*(update)[4 ] + 2*(igrt[2][0])[5]*(update)[5] + (igrt[2][0])[6]*(update)[ 6] ), | |||
502 | update[1], update[2], update[3], | |||
503 | update[4], update[5], update[6]); | |||
504 | } | |||
505 | } | |||
506 | /* | |||
507 | TEN_T_SUB(d02, tt[2], tt[0]); | |||
508 | TEN_T_SUB(d24, tt[4], tt[2]); | |||
509 | len02 = TEN_T_DOT(tng, d02); | |||
510 | len24 = TEN_T_DOT(tng, d24); | |||
511 | correct = (len24 - len02); | |||
512 | TEN_T_SCALE_INCR(update, scl*correct, tng); | |||
513 | */ | |||
514 | ||||
515 | if (!TEN_T_EXISTS(update)( (((int)(!(((update)[0]) - ((update)[0]))))) && (((int )(!(((update)[1]) - ((update)[1]))))) && (((int)(!((( update)[2]) - ((update)[2]))))) && (((int)(!(((update )[3]) - ((update)[3]))))) && (((int)(!(((update)[4]) - ((update)[4]))))) && (((int)(!(((update)[5]) - ((update )[5]))))) && (((int)(!(((update)[6]) - ((update)[6])) ))) )) { | |||
516 | biffAddf(TENtenBiffKey, "%s: computed non-existent update (step-size too big?)", me); | |||
517 | return 1; | |||
518 | } | |||
519 | ||||
520 | TEN_T_ADD(odata + 7*(2*ii + 0), tt[2], update)( (odata + 7*(2*ii + 0))[0] = ((tt[2])[0] + (update)[0])/2.0, (odata + 7*(2*ii + 0))[1] = (tt[2])[1] + (update)[1], (odata + 7*(2*ii + 0))[2] = (tt[2])[2] + (update)[2], (odata + 7*(2 *ii + 0))[3] = (tt[2])[3] + (update)[3], (odata + 7*(2*ii + 0 ))[4] = (tt[2])[4] + (update)[4], (odata + 7*(2*ii + 0))[5] = (tt[2])[5] + (update)[5], (odata + 7*(2*ii + 0))[6] = (tt[2] )[6] + (update)[6]); | |||
521 | ||||
522 | return 0; | |||
523 | } | |||
524 | ||||
525 | void | |||
526 | _tenInterpGeoLoxIGRT(double *igrt, double *ten, int useK, int rotNoop, | |||
527 | double minnorm) { | |||
528 | /* static const char me[]="_tenInterpGeoLoxIGRT"; */ | |||
529 | double eval[3], evec[9]; | |||
530 | ||||
531 | if (useK) { | |||
532 | tenInvariantGradientsK_d(igrt + 7*0, igrt + 7*1, igrt + 7*2, ten, minnorm); | |||
533 | } else { | |||
534 | tenInvariantGradientsR_d(igrt + 7*0, igrt + 7*1, igrt + 7*2, ten, minnorm); | |||
535 | } | |||
536 | if (rotNoop) { | |||
537 | /* these shouldn't be used */ | |||
538 | TEN_T_SET(igrt + 7*3, 1, AIR_NAN, AIR_NAN, AIR_NAN,( (igrt + 7*3)[0] = (1), (igrt + 7*3)[1] = ((airFloatQNaN.f)) , (igrt + 7*3)[2] = ((airFloatQNaN.f)), (igrt + 7*3)[3] = ((airFloatQNaN .f)), (igrt + 7*3)[4] = ((airFloatQNaN.f)), (igrt + 7*3)[5] = ((airFloatQNaN.f)), (igrt + 7*3)[6] = ((airFloatQNaN.f)) ) | |||
539 | AIR_NAN, AIR_NAN, AIR_NAN)( (igrt + 7*3)[0] = (1), (igrt + 7*3)[1] = ((airFloatQNaN.f)) , (igrt + 7*3)[2] = ((airFloatQNaN.f)), (igrt + 7*3)[3] = ((airFloatQNaN .f)), (igrt + 7*3)[4] = ((airFloatQNaN.f)), (igrt + 7*3)[5] = ((airFloatQNaN.f)), (igrt + 7*3)[6] = ((airFloatQNaN.f)) ); | |||
540 | TEN_T_SET(igrt + 7*4, 1, AIR_NAN, AIR_NAN, AIR_NAN,( (igrt + 7*4)[0] = (1), (igrt + 7*4)[1] = ((airFloatQNaN.f)) , (igrt + 7*4)[2] = ((airFloatQNaN.f)), (igrt + 7*4)[3] = ((airFloatQNaN .f)), (igrt + 7*4)[4] = ((airFloatQNaN.f)), (igrt + 7*4)[5] = ((airFloatQNaN.f)), (igrt + 7*4)[6] = ((airFloatQNaN.f)) ) | |||
541 | AIR_NAN, AIR_NAN, AIR_NAN)( (igrt + 7*4)[0] = (1), (igrt + 7*4)[1] = ((airFloatQNaN.f)) , (igrt + 7*4)[2] = ((airFloatQNaN.f)), (igrt + 7*4)[3] = ((airFloatQNaN .f)), (igrt + 7*4)[4] = ((airFloatQNaN.f)), (igrt + 7*4)[5] = ((airFloatQNaN.f)), (igrt + 7*4)[6] = ((airFloatQNaN.f)) ); | |||
542 | TEN_T_SET(igrt + 7*5, 1, AIR_NAN, AIR_NAN, AIR_NAN,( (igrt + 7*5)[0] = (1), (igrt + 7*5)[1] = ((airFloatQNaN.f)) , (igrt + 7*5)[2] = ((airFloatQNaN.f)), (igrt + 7*5)[3] = ((airFloatQNaN .f)), (igrt + 7*5)[4] = ((airFloatQNaN.f)), (igrt + 7*5)[5] = ((airFloatQNaN.f)), (igrt + 7*5)[6] = ((airFloatQNaN.f)) ) | |||
543 | AIR_NAN, AIR_NAN, AIR_NAN)( (igrt + 7*5)[0] = (1), (igrt + 7*5)[1] = ((airFloatQNaN.f)) , (igrt + 7*5)[2] = ((airFloatQNaN.f)), (igrt + 7*5)[3] = ((airFloatQNaN .f)), (igrt + 7*5)[4] = ((airFloatQNaN.f)), (igrt + 7*5)[5] = ((airFloatQNaN.f)), (igrt + 7*5)[6] = ((airFloatQNaN.f)) ); | |||
544 | } else { | |||
545 | tenEigensolve_d(eval, evec, ten); | |||
546 | tenRotationTangents_d(igrt + 7*3, igrt + 7*4, igrt + 7*5, evec); | |||
547 | } | |||
548 | return; | |||
549 | } | |||
550 | ||||
551 | /* | |||
552 | ** if "doubling" is non-zero, this assumes that the real | |||
553 | ** vertices are on the even-numbered indices: | |||
554 | ** (0 1 2 3 4) | |||
555 | ** 0 2 4 6 8 --> size=9 --> NN=4 | |||
556 | ** 1 3 5 7 | |||
557 | */ | |||
558 | double | |||
559 | tenInterpPathLength(Nrrd *ntt, int doubleVerts, int fancy, int shape) { | |||
560 | double *tt, len, diff[7], *tenA, *tenB; | |||
561 | unsigned int ii, NN; | |||
562 | ||||
563 | tt = AIR_CAST(double *, ntt->data)((double *)(ntt->data)); | |||
564 | if (doubleVerts) { | |||
565 | NN = AIR_CAST(unsigned int, (ntt->axis[1].size-1)/2)((unsigned int)((ntt->axis[1].size-1)/2)); | |||
566 | } else { | |||
567 | NN = AIR_CAST(unsigned int, ntt->axis[1].size-1)((unsigned int)(ntt->axis[1].size-1)); | |||
568 | } | |||
569 | len = 0; | |||
570 | for (ii=0; ii<NN; ii++) { | |||
571 | if (doubleVerts) { | |||
572 | tenA = tt + 7*2*(ii + 1); | |||
573 | tenB = tt + 7*2*(ii + 0); | |||
574 | } else { | |||
575 | tenA = tt + 7*(ii + 1); | |||
576 | tenB = tt + 7*(ii + 0); | |||
577 | } | |||
578 | TEN_T_SUB(diff, tenA, tenB)( (diff)[0] = ((tenA)[0] + (tenB)[0])/2.0, (diff)[1] = (tenA) [1] - (tenB)[1], (diff)[2] = (tenA)[2] - (tenB)[2], (diff)[3] = (tenA)[3] - (tenB)[3], (diff)[4] = (tenA)[4] - (tenB)[4], ( diff)[5] = (tenA)[5] - (tenB)[5], (diff)[6] = (tenA)[6] - (tenB )[6]); | |||
579 | if (fancy) { | |||
580 | double mean[7], igrt[7*6], dot, incr; | |||
581 | unsigned int lo, hi; | |||
582 | ||||
583 | TEN_T_LERP(mean, 0.5, tenA, tenB)( (mean)[0] = (((0.5))*(((tenB)[0]) - ((tenA)[0])) + ((tenA)[ 0])), (mean)[1] = (((0.5))*(((tenB)[1]) - ((tenA)[1])) + ((tenA )[1])), (mean)[2] = (((0.5))*(((tenB)[2]) - ((tenA)[2])) + (( tenA)[2])), (mean)[3] = (((0.5))*(((tenB)[3]) - ((tenA)[3])) + ((tenA)[3])), (mean)[4] = (((0.5))*(((tenB)[4]) - ((tenA)[4] )) + ((tenA)[4])), (mean)[5] = (((0.5))*(((tenB)[5]) - ((tenA )[5])) + ((tenA)[5])), (mean)[6] = (((0.5))*(((tenB)[6]) - (( tenA)[6])) + ((tenA)[6]))); | |||
584 | _tenInterpGeoLoxIGRT(igrt, mean, AIR_FALSE0, AIR_FALSE0, 0.0); | |||
585 | if (shape) { | |||
586 | lo = 0; | |||
587 | hi = 2; | |||
588 | } else { | |||
589 | lo = 3; | |||
590 | hi = 5; | |||
591 | } | |||
592 | incr = 0; | |||
593 | for (ii=lo; ii<=hi; ii++) { | |||
594 | dot = TEN_T_DOT(igrt + 7*ii, diff)( (igrt + 7*ii)[1]*(diff)[1] + 2*(igrt + 7*ii)[2]*(diff)[2] + 2*(igrt + 7*ii)[3]*(diff)[3] + (igrt + 7*ii)[4]*(diff)[4] + 2 *(igrt + 7*ii)[5]*(diff)[5] + (igrt + 7*ii)[6]*(diff)[6] ); | |||
595 | incr += dot*dot; | |||
596 | } | |||
597 | len += sqrt(incr); | |||
598 | } else { | |||
599 | len += TEN_T_NORM(diff)(sqrt(( (diff)[1]*(diff)[1] + 2*(diff)[2]*(diff)[2] + 2*(diff )[3]*(diff)[3] + (diff)[4]*(diff)[4] + 2*(diff)[5]*(diff)[5] + (diff)[6]*(diff)[6] ))); | |||
600 | } | |||
601 | } | |||
602 | return len; | |||
603 | } | |||
604 | ||||
605 | double | |||
606 | _tenPathSpacingEqualize(Nrrd *nout, Nrrd *nin) { | |||
607 | /* static const char me[]="_tenPathSpacingEqualize"; */ | |||
608 | double *in, *out, len, diff[7], | |||
609 | lenTotal, /* total length of input */ | |||
610 | lenStep, /* correct length on input polyline between output vertices */ | |||
611 | lenIn, /* length along input processed so far */ | |||
612 | lenHere, /* length of segment associated with current input index */ | |||
613 | lenRmn, /* length along past input segments as yet unmapped to output */ | |||
614 | *tenHere, *tenNext; | |||
615 | unsigned int idxIn, idxOut, NN; | |||
616 | ||||
617 | in = AIR_CAST(double *, nin->data)((double *)(nin->data)); | |||
618 | out = AIR_CAST(double *, nout->data)((double *)(nout->data)); | |||
619 | NN = (nin->axis[1].size-1)/2; | |||
620 | lenTotal = tenInterpPathLength(nin, AIR_TRUE1, AIR_FALSE0, AIR_FALSE0); | |||
621 | lenStep = lenTotal/NN; | |||
622 | /* | |||
623 | fprintf(stderr, "!%s: lenTotal/NN = %g/%u = %g = lenStep\n", me, | |||
624 | lenTotal, NN, lenStep); | |||
625 | */ | |||
626 | TEN_T_COPY(out + 7*2*(0 + 0), in + 7*2*(0 + 0))( (out + 7*2*(0 + 0))[0] = (in + 7*2*(0 + 0))[0], (out + 7*2* (0 + 0))[1] = (in + 7*2*(0 + 0))[1], (out + 7*2*(0 + 0))[2] = (in + 7*2*(0 + 0))[2], (out + 7*2*(0 + 0))[3] = (in + 7*2*(0 + 0))[3], (out + 7*2*(0 + 0))[4] = (in + 7*2*(0 + 0))[4], (out + 7*2*(0 + 0))[5] = (in + 7*2*(0 + 0))[5], (out + 7*2*(0 + 0 ))[6] = (in + 7*2*(0 + 0))[6] ); | |||
627 | lenIn = lenRmn = 0; | |||
628 | idxOut = 1; | |||
629 | for (idxIn=0; idxIn<NN; idxIn++) { | |||
630 | tenNext = in + 7*2*(idxIn + 1); | |||
631 | tenHere = in + 7*2*(idxIn + 0); | |||
632 | TEN_T_SUB(diff, tenNext, tenHere)( (diff)[0] = ((tenNext)[0] + (tenHere)[0])/2.0, (diff)[1] = ( tenNext)[1] - (tenHere)[1], (diff)[2] = (tenNext)[2] - (tenHere )[2], (diff)[3] = (tenNext)[3] - (tenHere)[3], (diff)[4] = (tenNext )[4] - (tenHere)[4], (diff)[5] = (tenNext)[5] - (tenHere)[5], (diff)[6] = (tenNext)[6] - (tenHere)[6]); | |||
633 | lenHere = TEN_T_NORM(diff)(sqrt(( (diff)[1]*(diff)[1] + 2*(diff)[2]*(diff)[2] + 2*(diff )[3]*(diff)[3] + (diff)[4]*(diff)[4] + 2*(diff)[5]*(diff)[5] + (diff)[6]*(diff)[6] ))); | |||
634 | /* | |||
635 | fprintf(stderr, "!%s(%u): %g + %g >(%s)= %g\n", me, idxIn, | |||
636 | lenRmn, lenHere, | |||
637 | (lenRmn + lenHere >= lenStep ? "yes" : "no"), | |||
638 | lenStep); | |||
639 | */ | |||
640 | if (lenRmn + lenHere >= lenStep) { | |||
641 | len = lenRmn + lenHere; | |||
642 | while (len > lenStep) { | |||
643 | len -= lenStep; | |||
644 | /* | |||
645 | fprintf(stderr, "!%s(%u): len = %g -> %g\n", me, idxIn, | |||
646 | len + lenStep, len); | |||
647 | */ | |||
648 | TEN_T_AFFINE(out + 7*(2*idxOut + 0),( (out + 7*(2*idxOut + 0))[0] = ( ((double)((tenNext)[0])-((tenHere )[0]))*((double)((len))-((lenHere))) / ((double)((0))-((lenHere ))) + ((tenHere)[0])), (out + 7*(2*idxOut + 0))[1] = ( ((double )((tenNext)[1])-((tenHere)[1]))*((double)((len))-((lenHere))) / ((double)((0))-((lenHere))) + ((tenHere)[1])), (out + 7*(2 *idxOut + 0))[2] = ( ((double)((tenNext)[2])-((tenHere)[2]))* ((double)((len))-((lenHere))) / ((double)((0))-((lenHere))) + ((tenHere)[2])), (out + 7*(2*idxOut + 0))[3] = ( ((double)(( tenNext)[3])-((tenHere)[3]))*((double)((len))-((lenHere))) / ( (double)((0))-((lenHere))) + ((tenHere)[3])), (out + 7*(2*idxOut + 0))[4] = ( ((double)((tenNext)[4])-((tenHere)[4]))*((double )((len))-((lenHere))) / ((double)((0))-((lenHere))) + ((tenHere )[4])), (out + 7*(2*idxOut + 0))[5] = ( ((double)((tenNext)[5 ])-((tenHere)[5]))*((double)((len))-((lenHere))) / ((double)( (0))-((lenHere))) + ((tenHere)[5])), (out + 7*(2*idxOut + 0)) [6] = ( ((double)((tenNext)[6])-((tenHere)[6]))*((double)((len ))-((lenHere))) / ((double)((0))-((lenHere))) + ((tenHere)[6] ))) | |||
649 | lenHere, len, 0, tenHere, tenNext)( (out + 7*(2*idxOut + 0))[0] = ( ((double)((tenNext)[0])-((tenHere )[0]))*((double)((len))-((lenHere))) / ((double)((0))-((lenHere ))) + ((tenHere)[0])), (out + 7*(2*idxOut + 0))[1] = ( ((double )((tenNext)[1])-((tenHere)[1]))*((double)((len))-((lenHere))) / ((double)((0))-((lenHere))) + ((tenHere)[1])), (out + 7*(2 *idxOut + 0))[2] = ( ((double)((tenNext)[2])-((tenHere)[2]))* ((double)((len))-((lenHere))) / ((double)((0))-((lenHere))) + ((tenHere)[2])), (out + 7*(2*idxOut + 0))[3] = ( ((double)(( tenNext)[3])-((tenHere)[3]))*((double)((len))-((lenHere))) / ( (double)((0))-((lenHere))) + ((tenHere)[3])), (out + 7*(2*idxOut + 0))[4] = ( ((double)((tenNext)[4])-((tenHere)[4]))*((double )((len))-((lenHere))) / ((double)((0))-((lenHere))) + ((tenHere )[4])), (out + 7*(2*idxOut + 0))[5] = ( ((double)((tenNext)[5 ])-((tenHere)[5]))*((double)((len))-((lenHere))) / ((double)( (0))-((lenHere))) + ((tenHere)[5])), (out + 7*(2*idxOut + 0)) [6] = ( ((double)((tenNext)[6])-((tenHere)[6]))*((double)((len ))-((lenHere))) / ((double)((0))-((lenHere))) + ((tenHere)[6] ))); | |||
650 | /* | |||
651 | fprintf(stderr, "!%s(%u): out[%u] ~ %g\n", me, idxIn, idxOut, | |||
652 | AIR_AFFINE(lenHere, len, 0, 0, 1)); | |||
653 | */ | |||
654 | idxOut++; | |||
655 | } | |||
656 | lenRmn = len; | |||
657 | } else { | |||
658 | lenRmn += lenHere; | |||
659 | /* | |||
660 | fprintf(stderr, "!%s(%u): (==> lenRmn = %g -> %g)\n", me, idxIn, | |||
661 | lenRmn - lenHere, lenRmn); | |||
662 | */ | |||
663 | } | |||
664 | /* now lenRmn < lenStep */ | |||
665 | lenIn += lenHere; | |||
666 | } | |||
667 | /* copy very last one in case we didn't get to it somehow */ | |||
668 | TEN_T_COPY(out + 7*2*(NN + 0), in + 7*2*(NN + 0))( (out + 7*2*(NN + 0))[0] = (in + 7*2*(NN + 0))[0], (out + 7* 2*(NN + 0))[1] = (in + 7*2*(NN + 0))[1], (out + 7*2*(NN + 0)) [2] = (in + 7*2*(NN + 0))[2], (out + 7*2*(NN + 0))[3] = (in + 7*2*(NN + 0))[3], (out + 7*2*(NN + 0))[4] = (in + 7*2*(NN + 0 ))[4], (out + 7*2*(NN + 0))[5] = (in + 7*2*(NN + 0))[5], (out + 7*2*(NN + 0))[6] = (in + 7*2*(NN + 0))[6] ); | |||
669 | ||||
670 | /* fill in vertex mid-points */ | |||
671 | for (idxOut=0; idxOut<NN; idxOut++) { | |||
672 | TEN_T_LERP(out + 7*(2*idxOut + 1),( (out + 7*(2*idxOut + 1))[0] = (((0.5))*(((out + 7*(2*idxOut + 2))[0]) - ((out + 7*(2*idxOut + 0))[0])) + ((out + 7*(2*idxOut + 0))[0])), (out + 7*(2*idxOut + 1))[1] = (((0.5))*(((out + 7 *(2*idxOut + 2))[1]) - ((out + 7*(2*idxOut + 0))[1])) + ((out + 7*(2*idxOut + 0))[1])), (out + 7*(2*idxOut + 1))[2] = (((0.5 ))*(((out + 7*(2*idxOut + 2))[2]) - ((out + 7*(2*idxOut + 0)) [2])) + ((out + 7*(2*idxOut + 0))[2])), (out + 7*(2*idxOut + 1 ))[3] = (((0.5))*(((out + 7*(2*idxOut + 2))[3]) - ((out + 7*( 2*idxOut + 0))[3])) + ((out + 7*(2*idxOut + 0))[3])), (out + 7 *(2*idxOut + 1))[4] = (((0.5))*(((out + 7*(2*idxOut + 2))[4]) - ((out + 7*(2*idxOut + 0))[4])) + ((out + 7*(2*idxOut + 0)) [4])), (out + 7*(2*idxOut + 1))[5] = (((0.5))*(((out + 7*(2*idxOut + 2))[5]) - ((out + 7*(2*idxOut + 0))[5])) + ((out + 7*(2*idxOut + 0))[5])), (out + 7*(2*idxOut + 1))[6] = (((0.5))*(((out + 7 *(2*idxOut + 2))[6]) - ((out + 7*(2*idxOut + 0))[6])) + ((out + 7*(2*idxOut + 0))[6]))) | |||
673 | 0.5, out + 7*(2*idxOut + 0), out + 7*(2*idxOut + 2))( (out + 7*(2*idxOut + 1))[0] = (((0.5))*(((out + 7*(2*idxOut + 2))[0]) - ((out + 7*(2*idxOut + 0))[0])) + ((out + 7*(2*idxOut + 0))[0])), (out + 7*(2*idxOut + 1))[1] = (((0.5))*(((out + 7 *(2*idxOut + 2))[1]) - ((out + 7*(2*idxOut + 0))[1])) + ((out + 7*(2*idxOut + 0))[1])), (out + 7*(2*idxOut + 1))[2] = (((0.5 ))*(((out + 7*(2*idxOut + 2))[2]) - ((out + 7*(2*idxOut + 0)) [2])) + ((out + 7*(2*idxOut + 0))[2])), (out + 7*(2*idxOut + 1 ))[3] = (((0.5))*(((out + 7*(2*idxOut + 2))[3]) - ((out + 7*( 2*idxOut + 0))[3])) + ((out + 7*(2*idxOut + 0))[3])), (out + 7 *(2*idxOut + 1))[4] = (((0.5))*(((out + 7*(2*idxOut + 2))[4]) - ((out + 7*(2*idxOut + 0))[4])) + ((out + 7*(2*idxOut + 0)) [4])), (out + 7*(2*idxOut + 1))[5] = (((0.5))*(((out + 7*(2*idxOut + 2))[5]) - ((out + 7*(2*idxOut + 0))[5])) + ((out + 7*(2*idxOut + 0))[5])), (out + 7*(2*idxOut + 1))[6] = (((0.5))*(((out + 7 *(2*idxOut + 2))[6]) - ((out + 7*(2*idxOut + 0))[6])) + ((out + 7*(2*idxOut + 0))[6]))); | |||
674 | } | |||
675 | return lenTotal; | |||
676 | } | |||
677 | ||||
678 | int | |||
679 | _tenInterpGeoLoxPolyLine(Nrrd *ngeod, unsigned int *numIter, | |||
680 | const double tenA[7], const double tenB[7], | |||
681 | unsigned int NN, int useK, int rotnoop, | |||
682 | tenInterpParm *tip) { | |||
683 | static const char me[]="_tenInterpGeoLoxPolyLine"; | |||
684 | Nrrd *nigrt, *ntt, *nss, *nsub; | |||
685 | double *igrt, *geod, *tt, len, newlen; | |||
686 | unsigned int ii; | |||
687 | airArray *mop; | |||
688 | ||||
689 | if (!(ngeod && numIter && tenA && tenB)) { | |||
690 | biffAddf(TENtenBiffKey, "%s: got NULL pointer", me); | |||
691 | return 1; | |||
692 | } | |||
693 | if (!(NN >= 2)) { | |||
694 | biffAddf(TENtenBiffKey, "%s: # steps %u too small", me, NN); | |||
695 | return 1; | |||
696 | } | |||
697 | ||||
698 | mop = airMopNew(); | |||
699 | ntt = nrrdNew(); | |||
700 | airMopAdd(mop, ntt, (airMopper)nrrdNuke, airMopAlways); | |||
701 | nss = nrrdNew(); | |||
702 | airMopAdd(mop, nss, (airMopper)nrrdNuke, airMopAlways); | |||
703 | nigrt = nrrdNew(); | |||
704 | airMopAdd(mop, nigrt, (airMopper)nrrdNuke, airMopAlways); | |||
705 | nsub = nrrdNew(); | |||
706 | airMopAdd(mop, nsub, (airMopper)nrrdNuke, airMopAlways); | |||
707 | if (nrrdMaybeAlloc_va(ngeod, nrrdTypeDouble, 2, | |||
708 | AIR_CAST(size_t, 7)((size_t)(7)), | |||
709 | AIR_CAST(size_t, NN+1)((size_t)(NN+1))) | |||
710 | || nrrdMaybeAlloc_va(ntt, nrrdTypeDouble, 2, | |||
711 | AIR_CAST(size_t, 7)((size_t)(7)), | |||
712 | AIR_CAST(size_t, 2*NN + 1)((size_t)(2*NN + 1))) | |||
713 | || nrrdMaybeAlloc_va(nigrt, nrrdTypeDouble, 3, | |||
714 | AIR_CAST(size_t, 7)((size_t)(7)), | |||
715 | AIR_CAST(size_t, 6)((size_t)(6)), | |||
716 | AIR_CAST(size_t, 2*NN + 1)((size_t)(2*NN + 1)))) { | |||
717 | biffMovef(TENtenBiffKey, NRRDnrrdBiffKey, "%s: couldn't allocate output", me); | |||
718 | airMopError(mop); return 1; | |||
719 | } | |||
720 | geod = AIR_CAST(double *, ngeod->data)((double *)(ngeod->data)); | |||
721 | tt = AIR_CAST(double *, ntt->data)((double *)(ntt->data)); | |||
722 | igrt = AIR_CAST(double *, nigrt->data)((double *)(nigrt->data)); | |||
723 | ||||
724 | *numIter = 0; | |||
725 | if (NN > 14 && tip->enableRecurse) { | |||
726 | unsigned int subIter; | |||
727 | int E; | |||
728 | NrrdResampleContext *rsmc; | |||
729 | double kparm[3] = {1.0, 0.0, 0.5}; | |||
730 | /* recurse and find geodesic with smaller number of vertices */ | |||
731 | if (_tenInterpGeoLoxPolyLine(nsub, &subIter, tenA, tenB, | |||
732 | NN/2, useK, rotnoop, tip)) { | |||
733 | biffAddf(TENtenBiffKey, "%s: problem with recursive call", me); | |||
734 | airMopError(mop); return 1; | |||
735 | } | |||
736 | /* upsample coarse geodesic to higher resolution */ | |||
737 | rsmc = nrrdResampleContextNew(); | |||
738 | airMopAdd(mop, rsmc, (airMopper)nrrdResampleContextNix, airMopAlways); | |||
739 | E = AIR_FALSE0; | |||
740 | if (!E) E |= nrrdResampleDefaultCenterSet(rsmc, nrrdCenterNode); | |||
741 | if (!E) E |= nrrdResampleInputSet(rsmc, nsub); | |||
742 | if (!E) E |= nrrdResampleKernelSet(rsmc, 0, NULL((void*)0), NULL((void*)0)); | |||
743 | if (!E) E |= nrrdResampleKernelSet(rsmc, 1, nrrdKernelTent, kparm); | |||
744 | if (!E) E |= nrrdResampleSamplesSet(rsmc, 1, 2*NN + 1); | |||
745 | if (!E) E |= nrrdResampleRangeFullSet(rsmc, 1); | |||
746 | if (!E) E |= nrrdResampleBoundarySet(rsmc, nrrdBoundaryBleed); | |||
747 | if (!E) E |= nrrdResampleTypeOutSet(rsmc, nrrdTypeDefault); | |||
748 | if (!E) E |= nrrdResampleRenormalizeSet(rsmc, AIR_TRUE1); | |||
749 | if (!E) E |= nrrdResampleExecute(rsmc, ntt); | |||
750 | if (E) { | |||
751 | biffMovef(TENtenBiffKey, NRRDnrrdBiffKey, "%s: problem upsampling course solution", me); | |||
752 | airMopError(mop); return 1; | |||
753 | } | |||
754 | *numIter += subIter; | |||
755 | } else { | |||
756 | /* initialize the path, including all the segment midpoints */ | |||
757 | for (ii=0; ii<=2*NN; ii++) { | |||
758 | TEN_T_AFFINE(tt + 7*ii, 0, ii, 2*NN, tenA, tenB)( (tt + 7*ii)[0] = ( ((double)((tenB)[0])-((tenA)[0]))*((double )((ii))-((0))) / ((double)((2*NN))-((0))) + ((tenA)[0])), (tt + 7*ii)[1] = ( ((double)((tenB)[1])-((tenA)[1]))*((double)(( ii))-((0))) / ((double)((2*NN))-((0))) + ((tenA)[1])), (tt + 7 *ii)[2] = ( ((double)((tenB)[2])-((tenA)[2]))*((double)((ii)) -((0))) / ((double)((2*NN))-((0))) + ((tenA)[2])), (tt + 7*ii )[3] = ( ((double)((tenB)[3])-((tenA)[3]))*((double)((ii))-(( 0))) / ((double)((2*NN))-((0))) + ((tenA)[3])), (tt + 7*ii)[4 ] = ( ((double)((tenB)[4])-((tenA)[4]))*((double)((ii))-((0)) ) / ((double)((2*NN))-((0))) + ((tenA)[4])), (tt + 7*ii)[5] = ( ((double)((tenB)[5])-((tenA)[5]))*((double)((ii))-((0))) / ((double)((2*NN))-((0))) + ((tenA)[5])), (tt + 7*ii)[6] = ( ( (double)((tenB)[6])-((tenA)[6]))*((double)((ii))-((0))) / ((double )((2*NN))-((0))) + ((tenA)[6]))); | |||
759 | } | |||
760 | } | |||
761 | for (ii=0; ii<=2*NN; ii++) { | |||
762 | _tenInterpGeoLoxIGRT(igrt + 7*6*ii, tt + 7*ii, useK, rotnoop, | |||
763 | tip->minNorm); | |||
764 | } | |||
765 | nrrdCopy(nss, ntt); | |||
766 | ||||
767 | newlen = tenInterpPathLength(ntt, AIR_TRUE1, AIR_FALSE0, AIR_FALSE0); | |||
768 | do { | |||
769 | unsigned int lo, hi; | |||
770 | int dd; | |||
771 | len = newlen; | |||
772 | if (0 == *numIter % 2) { | |||
773 | lo = 1; | |||
774 | hi = NN; | |||
775 | dd = 1; | |||
776 | } else { | |||
777 | lo = NN-1; | |||
778 | hi = 0; | |||
779 | dd = -1; | |||
780 | } | |||
781 | if (tip->verbose) { | |||
782 | fprintf(stderr__stderrp, "%s: ======= iter = %u (NN=%u)\n", me, *numIter, NN); | |||
783 | } | |||
784 | for (ii=lo; ii!=hi; ii+=dd) { | |||
785 | double sclHack; | |||
786 | sclHack = ii*4.0/NN - ii*ii*4.0/NN/NN; | |||
787 | if (_tenInterpGeoLoxRelaxOne(nss, ntt, nigrt, ii, rotnoop, | |||
788 | sclHack*tip->convStep, tip)) { | |||
789 | biffAddf(TENtenBiffKey, "%s: problem on vert %u, iter %u\n", me, ii, *numIter); | |||
790 | return 1; | |||
791 | } | |||
792 | } | |||
793 | newlen = _tenPathSpacingEqualize(ntt, nss); | |||
794 | /* try doing this less often */ | |||
795 | for (ii=0; ii<=2*NN; ii++) { | |||
796 | _tenInterpGeoLoxIGRT(igrt + 7*6*ii, tt + 7*ii, useK, rotnoop, | |||
797 | tip->minNorm); | |||
798 | } | |||
799 | *numIter += 1; | |||
800 | } while ((0 == tip->maxIter || *numIter < tip->maxIter) | |||
801 | && 2*AIR_ABS(newlen - len)((newlen - len) > 0.0f ? (newlen - len) : -(newlen - len))/(newlen + len) > tip->convEps); | |||
802 | ||||
803 | /* copy final result to output */ | |||
804 | for (ii=0; ii<=NN; ii++) { | |||
805 | TEN_T_COPY(geod + 7*ii, tt + 7*2*ii)( (geod + 7*ii)[0] = (tt + 7*2*ii)[0], (geod + 7*ii)[1] = (tt + 7*2*ii)[1], (geod + 7*ii)[2] = (tt + 7*2*ii)[2], (geod + 7 *ii)[3] = (tt + 7*2*ii)[3], (geod + 7*ii)[4] = (tt + 7*2*ii)[ 4], (geod + 7*ii)[5] = (tt + 7*2*ii)[5], (geod + 7*ii)[6] = ( tt + 7*2*ii)[6] ); | |||
806 | } | |||
807 | /* values from outer-most recursion will stick */ | |||
808 | tip->numIter = *numIter; | |||
809 | tip->convFinal = 2*AIR_ABS(newlen - len)((newlen - len) > 0.0f ? (newlen - len) : -(newlen - len))/(newlen + len); | |||
810 | ||||
811 | airMopOkay(mop); | |||
812 | return 0; | |||
813 | } | |||
814 | ||||
815 | int | |||
816 | tenInterpTwoDiscrete_d(Nrrd *nout, | |||
817 | const double tenA[7], const double tenB[7], | |||
818 | int ptype, unsigned int num, | |||
819 | tenInterpParm *_tip) { | |||
820 | static const char me[]="tenInterpTwoDiscrete_d"; | |||
821 | double *out; | |||
822 | unsigned int ii; | |||
823 | airArray *mop; | |||
824 | tenInterpParm *tip; | |||
825 | ||||
826 | if (!nout) { | |||
827 | biffAddf(TENtenBiffKey, "%s: got NULL pointer", me); | |||
828 | return 1; | |||
829 | } | |||
830 | if (airEnumValCheck(tenInterpType, ptype)) { | |||
831 | biffAddf(TENtenBiffKey, "%s: path type %d not a valid %s", me, ptype, | |||
832 | tenInterpType->name); | |||
833 | return 1; | |||
834 | } | |||
835 | ||||
836 | mop = airMopNew(); | |||
837 | if (_tip) { | |||
838 | tip = _tip; | |||
839 | } else { | |||
840 | tip = tenInterpParmNew(); | |||
841 | airMopAdd(mop, tip, (airMopper)tenInterpParmNix, airMopAlways); | |||
842 | } | |||
843 | if (!( num >= 2 )) { | |||
844 | biffAddf(TENtenBiffKey, "%s: need num >= 2 (not %u)", me, num); | |||
845 | airMopError(mop); return 1; | |||
846 | } | |||
847 | if (nrrdMaybeAlloc_va(nout, nrrdTypeDouble, 2, | |||
848 | AIR_CAST(size_t, 7)((size_t)(7)), | |||
849 | AIR_CAST(size_t, num)((size_t)(num)))) { | |||
850 | biffMovef(TENtenBiffKey, NRRDnrrdBiffKey, "%s: trouble allocating output", me); | |||
851 | airMopError(mop); return 1; | |||
852 | } | |||
853 | out = AIR_CAST(double *, nout->data)((double *)(nout->data)); | |||
854 | ||||
855 | if (ptype == tenInterpTypeLinear | |||
856 | || ptype == tenInterpTypeLogLinear | |||
857 | || ptype == tenInterpTypeAffineInvariant | |||
858 | || ptype == tenInterpTypeWang | |||
859 | || ptype == tenInterpTypeQuatGeoLoxK | |||
860 | || ptype == tenInterpTypeQuatGeoLoxR | |||
861 | || ptype == tenInterpTypeRThetaPhiLinear) { | |||
862 | /* we have fast ways of doing interpolation | |||
863 | between two tensors for these path types */ | |||
864 | for (ii=0; ii<num; ii++) { | |||
865 | /* yes, this is often doing a lot of needless recomputations. */ | |||
866 | tenInterpTwo_d(out + 7*ii, tenA, tenB, | |||
867 | ptype, (double)ii/(num-1), tip); | |||
868 | } | |||
869 | } else if (ptype == tenInterpTypeGeoLoxK | |||
870 | || ptype == tenInterpTypeGeoLoxR | |||
871 | || ptype == tenInterpTypeLoxK | |||
872 | || ptype == tenInterpTypeLoxR) { | |||
873 | /* we have slow iterative code for these */ | |||
874 | unsigned int numIter; | |||
875 | int useK, rotnoop; | |||
876 | ||||
877 | useK = (tenInterpTypeGeoLoxK == ptype | |||
878 | || tenInterpTypeLoxK == ptype); | |||
879 | rotnoop = (tenInterpTypeGeoLoxK == ptype | |||
880 | || tenInterpTypeGeoLoxR == ptype); | |||
881 | fprintf(stderr__stderrp, "!%s: useK = %d, rotnoop = %d\n", me, useK, rotnoop); | |||
882 | if (_tenInterpGeoLoxPolyLine(nout, &numIter, | |||
883 | tenA, tenB, | |||
884 | num, useK, rotnoop, tip)) { | |||
885 | biffAddf(TENtenBiffKey, "%s: trouble finding path", me); | |||
886 | airMopError(mop); return 1; | |||
887 | } | |||
888 | } else { | |||
889 | biffAddf(TENtenBiffKey, "%s: sorry, interp for path %s not implemented", me, | |||
890 | airEnumStr(tenInterpType, ptype)); | |||
891 | airMopError(mop); return 1; | |||
892 | } | |||
893 | ||||
894 | airMopOkay(mop); | |||
895 | return 0; | |||
896 | } | |||
897 | ||||
898 | double | |||
899 | tenInterpDistanceTwo_d(const double tenA[7], const double tenB[7], | |||
900 | int ptype, tenInterpParm *_tip) { | |||
901 | static const char me[]="tenInterpDistanceTwo_d"; | |||
902 | char *err; | |||
903 | tenInterpParm *tip; | |||
904 | airArray *mop; | |||
905 | double ret, diff[7], logA[7], logB[7], invA[7], det, siA[7], | |||
906 | mat1[9], mat2[9], mat3[9], logDiff[7]; | |||
907 | Nrrd *npath; | |||
908 | ||||
909 | if (!( tenA && tenB && !airEnumValCheck(tenInterpType, ptype) )) { | |||
910 | return AIR_NAN(airFloatQNaN.f); | |||
911 | } | |||
912 | ||||
913 | mop = airMopNew(); | |||
914 | switch (ptype) { | |||
915 | case tenInterpTypeLinear: | |||
916 | TEN_T_SUB(diff, tenA, tenB)( (diff)[0] = ((tenA)[0] + (tenB)[0])/2.0, (diff)[1] = (tenA) [1] - (tenB)[1], (diff)[2] = (tenA)[2] - (tenB)[2], (diff)[3] = (tenA)[3] - (tenB)[3], (diff)[4] = (tenA)[4] - (tenB)[4], ( diff)[5] = (tenA)[5] - (tenB)[5], (diff)[6] = (tenA)[6] - (tenB )[6]); | |||
917 | ret = TEN_T_NORM(diff)(sqrt(( (diff)[1]*(diff)[1] + 2*(diff)[2]*(diff)[2] + 2*(diff )[3]*(diff)[3] + (diff)[4]*(diff)[4] + 2*(diff)[5]*(diff)[5] + (diff)[6]*(diff)[6] ))); | |||
918 | break; | |||
919 | case tenInterpTypeLogLinear: | |||
920 | tenLogSingle_d(logA, tenA); | |||
921 | tenLogSingle_d(logB, tenB); | |||
922 | TEN_T_SUB(diff, logA, logB)( (diff)[0] = ((logA)[0] + (logB)[0])/2.0, (diff)[1] = (logA) [1] - (logB)[1], (diff)[2] = (logA)[2] - (logB)[2], (diff)[3] = (logA)[3] - (logB)[3], (diff)[4] = (logA)[4] - (logB)[4], ( diff)[5] = (logA)[5] - (logB)[5], (diff)[6] = (logA)[6] - (logB )[6]); | |||
923 | ret = TEN_T_NORM(diff)(sqrt(( (diff)[1]*(diff)[1] + 2*(diff)[2]*(diff)[2] + 2*(diff )[3]*(diff)[3] + (diff)[4]*(diff)[4] + 2*(diff)[5]*(diff)[5] + (diff)[6]*(diff)[6] ))); | |||
924 | break; | |||
925 | case tenInterpTypeAffineInvariant: | |||
926 | TEN_T_INV(invA, tenA, det)((det) = ( (tenA)[1]*((tenA)[4]*(tenA)[6] - (tenA)[5]*(tenA)[ 5]) + (tenA)[2]*((tenA)[5]*(tenA)[3] - (tenA)[2]*(tenA)[6]) + (tenA)[3]*((tenA)[2]*(tenA)[5] - (tenA)[3]*(tenA)[4])), (invA )[0] = (tenA)[0], (invA)[1] = (((tenA)[4])*((tenA)[6]) - ((tenA )[5])*((tenA)[5]))/(det), (invA)[2] = -(((tenA)[2])*((tenA)[6 ]) - ((tenA)[5])*((tenA)[3]))/(det), (invA)[3] = (((tenA)[2]) *((tenA)[5]) - ((tenA)[4])*((tenA)[3]))/(det), (invA)[4] = (( (tenA)[1])*((tenA)[6]) - ((tenA)[3])*((tenA)[3]))/(det), (invA )[5] = -(((tenA)[1])*((tenA)[5]) - ((tenA)[2])*((tenA)[3]))/( det), (invA)[6] = (((tenA)[1])*((tenA)[4]) - ((tenA)[2])*((tenA )[2]))/(det)); | |||
927 | tenSqrtSingle_d(siA, invA); | |||
928 | TEN_T2M(mat1, tenB)( (mat1)[0] = (tenB)[1], (mat1)[1] = (tenB)[2], (mat1)[2] = ( tenB)[3], (mat1)[3] = (tenB)[2], (mat1)[4] = (tenB)[4], (mat1 )[5] = (tenB)[5], (mat1)[6] = (tenB)[3], (mat1)[7] = (tenB)[5 ], (mat1)[8] = (tenB)[6] ); | |||
929 | TEN_T2M(mat2, siA)( (mat2)[0] = (siA)[1], (mat2)[1] = (siA)[2], (mat2)[2] = (siA )[3], (mat2)[3] = (siA)[2], (mat2)[4] = (siA)[4], (mat2)[5] = (siA)[5], (mat2)[6] = (siA)[3], (mat2)[7] = (siA)[5], (mat2) [8] = (siA)[6] ); | |||
930 | ell_3m_mul_d(mat3, mat1, mat2); | |||
931 | ell_3m_mul_d(mat1, mat2, mat3); | |||
932 | TEN_M2T(diff, mat1)( (diff)[1] = (mat1)[0], (diff)[2] = ((mat1)[1]+(mat1)[3])/2.0 , (diff)[3] = ((mat1)[2]+(mat1)[6])/2.0, (diff)[4] = (mat1)[4 ], (diff)[5] = ((mat1)[5]+(mat1)[7])/2.0, (diff)[6] = (mat1)[ 8] ); | |||
933 | tenLogSingle_d(logDiff, diff); | |||
934 | ret = TEN_T_NORM(logDiff)(sqrt(( (logDiff)[1]*(logDiff)[1] + 2*(logDiff)[2]*(logDiff)[ 2] + 2*(logDiff)[3]*(logDiff)[3] + (logDiff)[4]*(logDiff)[4] + 2*(logDiff)[5]*(logDiff)[5] + (logDiff)[6]*(logDiff)[6] ))); | |||
935 | break; | |||
936 | case tenInterpTypeGeoLoxK: | |||
937 | case tenInterpTypeGeoLoxR: | |||
938 | case tenInterpTypeLoxK: | |||
939 | case tenInterpTypeLoxR: | |||
940 | case tenInterpTypeQuatGeoLoxK: | |||
941 | case tenInterpTypeQuatGeoLoxR: | |||
942 | npath = nrrdNew(); | |||
943 | airMopAdd(mop, npath, (airMopper)nrrdNuke, airMopAlways); | |||
944 | if (_tip) { | |||
945 | tip = _tip; | |||
946 | } else { | |||
947 | tip = tenInterpParmNew(); | |||
948 | airMopAdd(mop, tip, (airMopper)tenInterpParmNix, airMopAlways); | |||
949 | } | |||
950 | if (tenInterpTwoDiscrete_d(npath, tenA, tenB, ptype, | |||
951 | tip->numSteps, tip)) { | |||
952 | airMopAdd(mop, err = biffGetDone(TENtenBiffKey), airFree, airMopAlways); | |||
953 | fprintf(stderr__stderrp, "%s: trouble computing path:\n%s\n", me, err); | |||
954 | airMopError(mop); return AIR_NAN(airFloatQNaN.f); | |||
955 | } | |||
956 | ret = tenInterpPathLength(npath, AIR_FALSE0, AIR_FALSE0, AIR_FALSE0); | |||
957 | if (tip->lengthFancy) { | |||
958 | tip->lengthShape = tenInterpPathLength(npath, AIR_FALSE0, | |||
959 | AIR_TRUE1, AIR_TRUE1); | |||
960 | tip->lengthOrient = tenInterpPathLength(npath, AIR_FALSE0, | |||
961 | AIR_TRUE1, AIR_FALSE0); | |||
962 | } | |||
963 | break; | |||
964 | case tenInterpTypeWang: | |||
965 | default: | |||
966 | fprintf(stderr__stderrp, "%s: unimplemented %s %d!!!!\n", me, | |||
967 | tenInterpType->name, ptype); | |||
968 | ret = AIR_NAN(airFloatQNaN.f); | |||
969 | break; | |||
970 | } | |||
971 | ||||
972 | airMopOkay(mop); | |||
973 | return ret; | |||
974 | } | |||
975 | ||||
976 | /* | |||
977 | ** actually, the input nrrds don't have to be 3D ... | |||
978 | */ | |||
979 | int | |||
980 | tenInterpMulti3D(Nrrd *nout, const Nrrd *const *nin, const double *wght, | |||
981 | unsigned int ninLen, int ptype, tenInterpParm *_tip) { | |||
982 | static const char me[]="tenInterpMulti3D"; | |||
983 | unsigned int ninIdx; | |||
984 | size_t II, NN; | |||
985 | double (*lup)(const void *, size_t), (*ins)(void *, size_t, double), | |||
986 | *tbuff; | |||
987 | tenInterpParm *tip; | |||
988 | airArray *mop; | |||
989 | ||||
990 | /* allow NULL wght, to signify equal weighting */ | |||
991 | if (!(nout && nin)) { | |||
| ||||
992 | biffAddf(TENtenBiffKey, "%s: got NULL pointer", me); | |||
993 | return 1; | |||
994 | } | |||
995 | if (!( ninLen > 0 )) { | |||
996 | biffAddf(TENtenBiffKey, "%s: need at least 1 nin, not 0", me); | |||
997 | return 1; | |||
998 | } | |||
999 | if (airEnumValCheck(tenInterpType, ptype)) { | |||
1000 | biffAddf(TENtenBiffKey, "%s: invalid %s %d", me, | |||
1001 | tenInterpType->name, ptype); | |||
1002 | return 1; | |||
1003 | } | |||
1004 | ||||
1005 | if (tenTensorCheck(nin[0], nrrdTypeDefault, AIR_FALSE0, AIR_TRUE1)) { | |||
1006 | biffAddf(TENtenBiffKey, "%s: first nrrd not a tensor array", me); | |||
1007 | return 1; | |||
1008 | } | |||
1009 | if (!( nrrdTypeFloat == nin[0]->type || | |||
1010 | nrrdTypeDouble == nin[0]->type )) { | |||
1011 | biffAddf(TENtenBiffKey, "%s: need type %s or %s (not %s) in first nrrd", me, | |||
1012 | airEnumStr(nrrdType, nrrdTypeFloat), | |||
1013 | airEnumStr(nrrdType, nrrdTypeDouble), | |||
1014 | airEnumStr(nrrdType, nin[0]->type)); | |||
1015 | return 1; | |||
1016 | } | |||
1017 | for (ninIdx=1; ninIdx<ninLen; ninIdx++) { | |||
1018 | if (tenTensorCheck(nin[ninIdx], nrrdTypeDefault, AIR_FALSE0, AIR_TRUE1)) { | |||
1019 | biffAddf(TENtenBiffKey, "%s: nin[%u] not a tensor array", me, ninIdx); | |||
1020 | return 1; | |||
1021 | } | |||
1022 | if (!nrrdSameSize(nin[0], nin[ninIdx], AIR_TRUE1)) { | |||
1023 | biffMovef(TENtenBiffKey, NRRDnrrdBiffKey, "%s: nin[0] doesn't match nin[%u]", me, ninIdx); | |||
1024 | return 1; | |||
1025 | } | |||
1026 | if (nin[0]->type != nin[ninIdx]->type) { | |||
1027 | biffAddf(TENtenBiffKey, "%s: nin[0] type (%s) != nin[%u] type (%s)", me, | |||
1028 | airEnumStr(nrrdType, nin[0]->type), | |||
1029 | ninIdx, airEnumStr(nrrdType, nin[ninIdx]->type)); | |||
1030 | return 1; | |||
1031 | } | |||
1032 | } | |||
1033 | ||||
1034 | mop = airMopNew(); | |||
1035 | if (nrrdCopy(nout, nin[0])) { | |||
1036 | biffMovef(TENtenBiffKey, NRRDnrrdBiffKey, "%s: couldn't initialize output", me); | |||
1037 | airMopError(mop); return 1; | |||
1038 | } | |||
1039 | if (_tip) { | |||
1040 | tip = _tip; | |||
1041 | } else { | |||
1042 | tip = tenInterpParmNew(); | |||
1043 | airMopAdd(mop, tip, (airMopper)tenInterpParmNix, airMopAlways); | |||
1044 | } | |||
1045 | tbuff = AIR_CAST(double *, calloc(7*ninLen, sizeof(double)))((double *)(calloc(7*ninLen, sizeof(double)))); | |||
1046 | if (!tbuff) { | |||
1047 | biffAddf(TENtenBiffKey, "%s: couldn't allocate tensor buff", me); | |||
1048 | airMopError(mop); return 1; | |||
1049 | } | |||
1050 | ins = nrrdDInsert[nin[0]->type]; | |||
1051 | lup = nrrdDLookup[nin[0]->type]; | |||
1052 | NN = nrrdElementNumber(nin[0])/7; | |||
1053 | for (II=0; II<NN; II++) { | |||
1054 | double tenOut[7]; | |||
1055 | unsigned int tt; | |||
1056 | for (ninIdx=0; ninIdx<ninLen; ninIdx++) { | |||
1057 | for (tt=0; tt<7; tt++) { | |||
1058 | tbuff[tt + 7*ninIdx] = lup(nin[ninIdx]->data, tt + 7*II); | |||
1059 | } | |||
1060 | } | |||
1061 | if (tenInterpN_d(tenOut, tbuff, wght, ninLen, ptype, tip)) { | |||
1062 | char stmp[AIR_STRLEN_SMALL(128+1)]; | |||
1063 | biffAddf(TENtenBiffKey, "%s: trouble on sample %s", me, | |||
1064 | airSprintSize_t(stmp, II)); | |||
1065 | airMopError(mop); return 1; | |||
1066 | } | |||
1067 | for (tt=0; tt<7; tt++) { | |||
1068 | ins(nout->data, tt + 7*II, tenOut[tt]); | |||
1069 | } | |||
1070 | } | |||
1071 | ||||
1072 | airMopOkay(mop); | |||
| ||||
1073 | return 0; | |||
1074 | } |