File: | src/ten/qglox.c |
Location: | line 498, column 3 |
Description: | Value stored to 'dsum' is never read |
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 | /* |
29 | ** computes (r1 - r0)/(log(r1) - log(r0)) |
30 | */ |
31 | double |
32 | _tenQGL_blah(double rr0, double rr1) { |
33 | double bb, ret; |
34 | |
35 | if (rr1 > rr0) { |
36 | /* the bb calculation below could blow up, so we recurse |
37 | with flipped order */ |
38 | ret = _tenQGL_blah(rr1, rr0); |
39 | } else { |
40 | /* rr1 <= rr0 --> rr1/rr0 <= 1 --> rr1/rr0 - 1 <= 0 --> bb <= 0 */ |
41 | /* and rr1 >= 0 --> rr1/rr0 >= 0 --> rr1/rr0 - 1 >= -1 --> bb >= -1 */ |
42 | bb = rr0 ? (rr1/rr0 - 1) : 0; |
43 | if (bb > -0.0001) { |
44 | ret = rr0*(1 + bb*(0.5001249976477329 |
45 | - bb*(7.0/6 + bb*(1.0/6 - bb/720.0)))); |
46 | } else { |
47 | /* had trouble finding a high-quality approximation for b near -1 */ |
48 | bb = AIR_MAX(bb, -1 + 100*FLT_EPSILON)((bb) > (-1 + 100*1.19209290e-7F) ? (bb) : (-1 + 100*1.19209290e-7F )); |
49 | ret = rr0*bb/log(bb + 1); |
50 | } |
51 | } |
52 | return ret; |
53 | } |
54 | |
55 | #define rr0 (RThZA[0]) |
56 | #define rr1 (RThZB[0]) |
57 | #define rr (oRThZ[0]) |
58 | #define th0 (RThZA[1]) |
59 | #define th1 (RThZB[1]) |
60 | #define th (oRThZ[1]) |
61 | #define zz0 (RThZA[2]) |
62 | #define zz1 (RThZB[2]) |
63 | #define zz (oRThZ[2]) |
64 | |
65 | void |
66 | tenQGLInterpTwoEvalK(double oeval[3], |
67 | const double evalA[3], const double evalB[3], |
68 | const double tt) { |
69 | double RThZA[3], RThZB[3], oRThZ[3], bb; |
70 | |
71 | tenTripleConvertSingle_d(RThZA, tenTripleTypeRThetaZ, |
72 | evalA, tenTripleTypeEigenvalue); |
73 | tenTripleConvertSingle_d(RThZB, tenTripleTypeRThetaZ, |
74 | evalB, tenTripleTypeEigenvalue); |
75 | if (rr1 > rr0) { |
76 | /* the bb calculation below could blow up, so we recurse |
77 | with flipped order */ |
78 | tenQGLInterpTwoEvalK(oeval, evalB, evalA, 1-tt); |
79 | } else { |
80 | rr = AIR_LERP(tt, rr0, rr1)((tt)*((rr1) - (rr0)) + (rr0)); |
81 | zz = AIR_LERP(tt, zz0, zz1)((tt)*((zz1) - (zz0)) + (zz0)); |
82 | bb = rr0 ? (rr1/rr0 - 1) : 0; |
83 | /* bb can't be positive, because rr1 <= rr0 enforced above, so below |
84 | is really test for -0.001 < bb <= 0 */ |
85 | if (bb > -0.0001) { |
86 | double dth; |
87 | dth = th1 - th0; |
88 | /* rr0 and rr1 are similar, use stable approximation */ |
89 | th = th0 + tt*(dth |
90 | + (0.5 - tt/2)*dth*bb |
91 | + (-1.0/12 - tt/4 + tt*tt/3)*dth*bb*bb |
92 | + (1.0/24 + tt/24 + tt*tt/6 - tt*tt*tt/4)*dth*bb*bb*bb); |
93 | } else { |
94 | /* use original formula */ |
95 | /* have to clamp value of b so that log() values don't explode */ |
96 | bb = AIR_MAX(bb, -1 + 100*FLT_EPSILON)((bb) > (-1 + 100*1.19209290e-7F) ? (bb) : (-1 + 100*1.19209290e-7F )); |
97 | th = th0 + (th1 - th0)*log(1 + bb*tt)/log(1 + bb); |
98 | } |
99 | tenTripleConvertSingle_d(oeval, tenTripleTypeEigenvalue, |
100 | oRThZ, tenTripleTypeRThetaZ); |
101 | /* |
102 | fprintf(stderr, "%s: (b = %g) %g %g %g <-- %g %g %g\n", "blah", bb, |
103 | oeval[0], oeval[1], oeval[2], |
104 | oRThZ[0], oRThZ[1], oRThZ[2]); |
105 | */ |
106 | } |
107 | } |
108 | |
109 | double |
110 | _tenQGL_Kdist(const double RThZA[3], const double RThZB[3]) { |
111 | double dr, dth, dz, bl, dist; |
112 | |
113 | dr = rr1 - rr0; |
114 | bl = _tenQGL_blah(rr0, rr1); |
115 | dth = th1 - th0; |
116 | dz = zz1 - zz0; |
117 | dist = sqrt(dr*dr + bl*bl*dth*dth + dz*dz); |
118 | return dist; |
119 | } |
120 | |
121 | void |
122 | _tenQGL_Klog(double klog[3], |
123 | const double RThZA[3], const double RThZB[3]) { |
124 | double dr, bl, dth, dz; |
125 | |
126 | dr = rr1 - rr0; |
127 | bl = _tenQGL_blah(rr0, rr1); |
128 | dth = th1 - th0; |
129 | dz = zz1 - zz0; |
130 | ELL_3V_SET(klog, dr, bl*dth, dz)((klog)[0] = (dr), (klog)[1] = (bl*dth), (klog)[2] = (dz)); |
131 | return; |
132 | } |
133 | |
134 | void |
135 | _tenQGL_Kexp(double RThZB[3], |
136 | const double RThZA[3], const double klog[3]) { |
137 | double bl; |
138 | |
139 | rr1 = rr0 + klog[0]; |
140 | bl = _tenQGL_blah(rr0, rr1); |
141 | th1 = th0 + (bl ? klog[1]/bl : 0); |
142 | zz1 = zz0 + klog[2]; |
143 | return; |
144 | } |
145 | |
146 | #undef rr0 |
147 | #undef rr1 |
148 | #undef rr |
149 | #undef th0 |
150 | #undef th1 |
151 | #undef th |
152 | #undef zz0 |
153 | #undef zz1 |
154 | #undef zz |
155 | |
156 | /* |
157 | ** stable computation of (ph1 - ph0)/(log(tan(ph1/2)) - log(tan(ph0/2))) |
158 | */ |
159 | double |
160 | _tenQGL_fooo(double ph1, double ph0) { |
161 | double ret; |
162 | |
163 | if (ph0 > ph1) { |
164 | ret = _tenQGL_fooo(ph0, ph1); |
165 | } else if (0 == ph0/2) { |
166 | ret = 0; |
167 | } else { |
168 | /* ph1 >= ph0 > 0 */ |
169 | if (ph1 - ph0 < 0.0001) { |
170 | double dph, ss, cc; |
171 | dph = ph1 - ph0; |
172 | ss = sin(ph1); |
173 | cc = cos(ph1); |
174 | ret = (ss |
175 | + cc*dph/2 |
176 | + ((cos(2*ph1) - 3)/ss)*dph*dph/24 |
177 | + (cc/(ss*ss))*dph*dph*dph/24); |
178 | } else { |
179 | ret = (ph1 - ph0)/(log(tan(ph1/2)) - log(tan(ph0/2))); |
180 | } |
181 | } |
182 | return ret; |
183 | } |
184 | |
185 | #define rr0 (RThPhA[0]) |
186 | #define rr1 (RThPhB[0]) |
187 | #define rr (oRThPh[0]) |
188 | #define th0 (RThPhA[1]) |
189 | #define th1 (RThPhB[1]) |
190 | #define th (oRThPh[1]) |
191 | #define ph0 (RThPhA[2]) |
192 | #define ph1 (RThPhB[2]) |
193 | #define ph (oRThPh[2]) |
194 | |
195 | void |
196 | _tenQGL_Rlog(double rlog[3], |
197 | const double RThPhA[3], const double RThPhB[3]) { |
198 | double dr, dth, dph, bl, fo; |
199 | |
200 | dr = rr1 - rr0; |
201 | dth = th1 - th0; |
202 | dph = ph1 - ph0; |
203 | bl = _tenQGL_blah(rr0, rr1); |
204 | fo = _tenQGL_fooo(ph0, ph1); |
205 | /* rlog[0] rlog[1] rlog[2] */ |
206 | ELL_3V_SET(rlog, dr, bl*dth*fo, dph*bl)((rlog)[0] = (dr), (rlog)[1] = (bl*dth*fo), (rlog)[2] = (dph* bl)); |
207 | } |
208 | |
209 | void |
210 | _tenQGL_Rexp(double RThPhB[3], |
211 | const double RThPhA[3], const double rlog[3]) { |
212 | double bl, fo; |
213 | |
214 | rr1 = rr0 + rlog[0]; |
215 | bl = _tenQGL_blah(rr0, rr1); |
216 | ph1 = ph0 + (bl ? rlog[2]/bl : 0); |
217 | fo = _tenQGL_fooo(ph0, ph1); |
218 | th1 = th0 + (bl*fo ? rlog[1]/(bl*fo) : 0); |
219 | return; |
220 | } |
221 | |
222 | /* unlike with the K stuff, with the R stuff I seemed to have more luck |
223 | implementing pair-wise interpolation in terms of log and exp |
224 | */ |
225 | void |
226 | tenQGLInterpTwoEvalR(double oeval[3], |
227 | const double evalA[3], const double evalB[3], |
228 | const double tt) { |
229 | double RThPhA[3], RThPhB[3], rlog[3], oRThPh[3]; |
230 | |
231 | tenTripleConvertSingle_d(RThPhA, tenTripleTypeRThetaPhi, |
232 | evalA, tenTripleTypeEigenvalue); |
233 | tenTripleConvertSingle_d(RThPhB, tenTripleTypeRThetaPhi, |
234 | evalB, tenTripleTypeEigenvalue); |
235 | _tenQGL_Rlog(rlog, RThPhA, RThPhB); |
236 | ELL_3V_SCALE(rlog, tt, rlog)((rlog)[0] = (tt)*(rlog)[0], (rlog)[1] = (tt)*(rlog)[1], (rlog )[2] = (tt)*(rlog)[2]); |
237 | _tenQGL_Rexp(oRThPh, RThPhA, rlog); |
238 | tenTripleConvertSingle_d(oeval, tenTripleTypeEigenvalue, |
239 | oRThPh, tenTripleTypeRThetaPhi); |
240 | return; |
241 | } |
242 | |
243 | double |
244 | _tenQGL_Rdist(const double RThPhA[3], const double RThPhB[3]) { |
245 | double dr, dth, dph, bl, fo; |
246 | |
247 | dr = rr1 - rr0; |
248 | dth = th1 - th0; |
249 | dph = ph1 - ph0; |
250 | bl = _tenQGL_blah(rr0, rr1); |
251 | fo = _tenQGL_fooo(ph0, ph1); |
252 | return sqrt(dr*dr + bl*bl*(dth*dth*fo*fo + dph*dph)); |
253 | } |
254 | |
255 | #undef rr0 |
256 | #undef rr1 |
257 | #undef rr |
258 | #undef th0 |
259 | #undef th1 |
260 | #undef th |
261 | #undef ph0 |
262 | #undef ph1 |
263 | #undef ph |
264 | |
265 | /* returns the index into unitq[] of the quaternion that led to the |
266 | right alignment. If it was already aligned, this will be 0, |
267 | because unitq[0] is the identity quaternion */ |
268 | int |
269 | _tenQGL_q_align(double qOut[4], const double qRef[4], const double qIn[4]) { |
270 | unsigned int ii, maxDotIdx; |
271 | double unitq[8][4] = {{+1, 0, 0, 0}, |
272 | {-1, 0, 0, 0}, |
273 | {0, +1, 0, 0}, |
274 | {0, -1, 0, 0}, |
275 | {0, 0, +1, 0}, |
276 | {0, 0, -1, 0}, |
277 | {0, 0, 0, +1}, |
278 | {0, 0, 0, -1}}; |
279 | double dot[8], qInMul[8][4], maxDot; |
280 | |
281 | for (ii=0; ii<8; ii++) { |
282 | ell_q_mul_d(qInMul[ii], qIn, unitq[ii]); |
283 | dot[ii] = ELL_4V_DOT(qRef, qInMul[ii])((qRef)[0]*(qInMul[ii])[0] + (qRef)[1]*(qInMul[ii])[1] + (qRef )[2]*(qInMul[ii])[2] + (qRef)[3]*(qInMul[ii])[3]); |
284 | } |
285 | maxDotIdx = 0; |
286 | maxDot = dot[maxDotIdx]; |
287 | for (ii=1; ii<8; ii++) { |
288 | if (dot[ii] > maxDot) { |
289 | maxDotIdx = ii; |
290 | maxDot = dot[maxDotIdx]; |
291 | } |
292 | } |
293 | ELL_4V_COPY(qOut, qInMul[maxDotIdx])((qOut)[0] = (qInMul[maxDotIdx])[0], (qOut)[1] = (qInMul[maxDotIdx ])[1], (qOut)[2] = (qInMul[maxDotIdx])[2], (qOut)[3] = (qInMul [maxDotIdx])[3]); |
294 | return maxDotIdx; |
295 | } |
296 | |
297 | void |
298 | tenQGLInterpTwoEvec(double oevec[9], |
299 | const double evecA[9], const double evecB[9], |
300 | double tt) { |
301 | double rotA[9], rotB[9], orot[9], |
302 | oq[4], qA[4], qB[4], _qB[4], qdiv[4], angle, axis[3], qq[4]; |
303 | |
304 | ELL_3M_TRANSPOSE(rotA, evecA)((rotA)[0] = (evecA)[0], (rotA)[1] = (evecA)[3], (rotA)[2] = ( evecA)[6], (rotA)[3] = (evecA)[1], (rotA)[4] = (evecA)[4], (rotA )[5] = (evecA)[7], (rotA)[6] = (evecA)[2], (rotA)[7] = (evecA )[5], (rotA)[8] = (evecA)[8]); |
305 | ELL_3M_TRANSPOSE(rotB, evecB)((rotB)[0] = (evecB)[0], (rotB)[1] = (evecB)[3], (rotB)[2] = ( evecB)[6], (rotB)[3] = (evecB)[1], (rotB)[4] = (evecB)[4], (rotB )[5] = (evecB)[7], (rotB)[6] = (evecB)[2], (rotB)[7] = (evecB )[5], (rotB)[8] = (evecB)[8]); |
306 | ell_3m_to_q_d(qA, rotA); |
307 | ell_3m_to_q_d(_qB, rotB); |
308 | _tenQGL_q_align(qB, qA, _qB); |
309 | /* there's probably a faster way to do this slerp qA --> qB */ |
310 | ell_q_div_d(qdiv, qA, qB); /* div = A^-1 * B */ |
311 | angle = ell_q_to_aa_d(axis, qdiv); |
312 | ell_aa_to_q_d(qq, angle*tt, axis); |
313 | ell_q_mul_d(oq, qA, qq); |
314 | ell_q_to_3m_d(orot, oq); |
315 | ELL_3M_TRANSPOSE(oevec, orot)((oevec)[0] = (orot)[0], (oevec)[1] = (orot)[3], (oevec)[2] = (orot)[6], (oevec)[3] = (orot)[1], (oevec)[4] = (orot)[4], ( oevec)[5] = (orot)[7], (oevec)[6] = (orot)[2], (oevec)[7] = ( orot)[5], (oevec)[8] = (orot)[8]); |
316 | } |
317 | |
318 | void |
319 | tenQGLInterpTwo(double oten[7], |
320 | const double tenA[7], const double tenB[7], |
321 | int ptype, double tt, tenInterpParm *tip) { |
322 | double oeval[3], evalA[3], evalB[3], oevec[9], evecA[9], evecB[9], cc; |
323 | |
324 | AIR_UNUSED(tip)(void)(tip); |
325 | tenEigensolve_d(evalA, evecA, tenA); |
326 | tenEigensolve_d(evalB, evecB, tenB); |
327 | cc = AIR_LERP(tt, tenA[0], tenB[0])((tt)*((tenB[0]) - (tenA[0])) + (tenA[0])); |
328 | |
329 | if (tenInterpTypeQuatGeoLoxK == ptype) { |
330 | tenQGLInterpTwoEvalK(oeval, evalA, evalB, tt); |
331 | } else { |
332 | tenQGLInterpTwoEvalR(oeval, evalA, evalB, tt); |
333 | } |
334 | tenQGLInterpTwoEvec(oevec, evecA, evecB, tt); |
335 | tenMakeSingle_d(oten, cc, oeval, oevec); |
336 | |
337 | return; |
338 | } |
339 | |
340 | /* |
341 | ** This does (non-optionally) use biff, to report convergence failures |
342 | ** |
343 | ** we do in fact require non-NULL tip, because it holds the buffers we need |
344 | */ |
345 | int |
346 | _tenQGLInterpNEval(double evalOut[3], |
347 | const double *evalIn, /* size 3 -by- NN */ |
348 | const double *wght, /* size NN */ |
349 | unsigned int NN, |
350 | int ptype, tenInterpParm *tip) { |
351 | static const char me[]="_tenQGLInterpNEval"; |
352 | double RTh_Out[3], elen; |
353 | unsigned int ii, iter; |
354 | int rttype; |
355 | void (*llog)(double lg[3], const double RTh_A[3], const double RTh_B[3]); |
356 | void (*lexp)(double RTh_B[3], const double RTh_A[3], const double lg[3]); |
357 | |
358 | if (!(evalOut && evalIn && tip)) { |
359 | biffAddf(TENtenBiffKey, "%s: got NULL pointer", me); |
360 | return 1; |
361 | } |
362 | /* convert to (R,Th,_) and initialize RTh_Out */ |
363 | if (tenInterpTypeQuatGeoLoxK == ptype) { |
364 | rttype = tenTripleTypeRThetaZ; |
365 | llog = _tenQGL_Klog; |
366 | lexp = _tenQGL_Kexp; |
367 | } else { |
368 | rttype = tenTripleTypeRThetaPhi; |
369 | llog = _tenQGL_Rlog; |
370 | lexp = _tenQGL_Rexp; |
371 | } |
372 | ELL_3V_SET(RTh_Out, 0, 0, 0)((RTh_Out)[0] = (0), (RTh_Out)[1] = (0), (RTh_Out)[2] = (0)); |
373 | for (ii=0; ii<NN; ii++) { |
374 | double ww; |
375 | tenTripleConvertSingle_d(tip->rtIn + 3*ii, rttype, |
376 | evalIn + 3*ii, tenTripleTypeEigenvalue); |
377 | ww = wght ? wght[ii] : 1.0/NN; |
378 | ELL_3V_SCALE_INCR(RTh_Out, ww, tip->rtIn + 3*ii)((RTh_Out)[0] += (ww)*(tip->rtIn + 3*ii)[0], (RTh_Out)[1] += (ww)*(tip->rtIn + 3*ii)[1], (RTh_Out)[2] += (ww)*(tip-> rtIn + 3*ii)[2]); |
379 | } |
380 | |
381 | /* compute iterated weighted mean, stored in RTh_Out */ |
382 | iter = 0; |
383 | do { |
384 | double logavg[3]; |
385 | /* take log of everyone */ |
386 | for (ii=0; ii<NN; ii++) { |
387 | llog(tip->rtLog + 3*ii, RTh_Out, tip->rtIn + 3*ii); |
388 | } |
389 | /* average, and find length */ |
390 | ELL_3V_SET(logavg, 0, 0, 0)((logavg)[0] = (0), (logavg)[1] = (0), (logavg)[2] = (0)); |
391 | for (ii=0; ii<NN; ii++) { |
392 | double ww; |
393 | ww = wght ? wght[ii] : 1.0/NN; |
394 | ELL_3V_SCALE_INCR(logavg, ww, tip->rtLog + 3*ii)((logavg)[0] += (ww)*(tip->rtLog + 3*ii)[0], (logavg)[1] += (ww)*(tip->rtLog + 3*ii)[1], (logavg)[2] += (ww)*(tip-> rtLog + 3*ii)[2]); |
395 | } |
396 | elen = ELL_3V_LEN(logavg)(sqrt((((logavg))[0]*((logavg))[0] + ((logavg))[1]*((logavg)) [1] + ((logavg))[2]*((logavg))[2]))); |
397 | lexp(RTh_Out, RTh_Out, logavg); |
398 | iter++; |
399 | } while ((!tip->maxIter || iter < tip->maxIter) && elen > tip->convEps); |
400 | |
401 | if (elen > tip->convEps) { |
402 | ELL_3V_SET(evalOut, AIR_NAN, AIR_NAN, AIR_NAN)((evalOut)[0] = ((airFloatQNaN.f)), (evalOut)[1] = ((airFloatQNaN .f)), (evalOut)[2] = ((airFloatQNaN.f))); |
403 | biffAddf(TENtenBiffKey, "%s: still have error %g (> eps %g) after max %d iters", me, |
404 | elen, tip->convEps, tip->maxIter); |
405 | return 1; |
406 | } |
407 | |
408 | /* finish, convert to eval */ |
409 | tenTripleConvertSingle_d(evalOut, tenTripleTypeEigenvalue, |
410 | RTh_Out, rttype); |
411 | |
412 | return 0; |
413 | } |
414 | |
415 | double |
416 | _tenQGL_q_interdot(unsigned int *centerIdxP, |
417 | double *qq, double *inter, unsigned int NN) { |
418 | unsigned int ii, jj; |
419 | double sum, dot, max; |
420 | |
421 | for (jj=0; jj<NN; jj++) { |
422 | for (ii=0; ii<NN; ii++) { |
423 | inter[ii + NN*jj] = 0; |
424 | } |
425 | } |
426 | sum = 0; |
427 | for (jj=0; jj<NN; jj++) { |
428 | inter[jj + NN*jj] = 1.0; |
429 | for (ii=jj+1; ii<NN; ii++) { |
430 | dot = ELL_4V_DOT(qq + 4*ii, qq + 4*jj)((qq + 4*ii)[0]*(qq + 4*jj)[0] + (qq + 4*ii)[1]*(qq + 4*jj)[1 ] + (qq + 4*ii)[2]*(qq + 4*jj)[2] + (qq + 4*ii)[3]*(qq + 4*jj )[3]); |
431 | inter[ii + NN*jj] = dot; |
432 | inter[jj + NN*ii] = dot; |
433 | sum += dot; |
434 | } |
435 | } |
436 | for (jj=0; jj<NN; jj++) { |
437 | for (ii=1; ii<NN; ii++) { |
438 | inter[0 + NN*jj] += inter[ii + NN*jj]; |
439 | } |
440 | } |
441 | *centerIdxP = 0; |
442 | max = inter[0 + NN*(*centerIdxP)]; |
443 | for (jj=1; jj<NN; jj++) { |
444 | if (inter[0 + NN*jj] > max) { |
445 | *centerIdxP = jj; |
446 | max = inter[0 + NN*(*centerIdxP)]; |
447 | } |
448 | } |
449 | return sum; |
450 | } |
451 | |
452 | /* |
453 | ** This does (non-optionally) use biff, to report convergence failures |
454 | ** |
455 | ** we do in fact require non-NULL tip, because it holds the buffers we need |
456 | */ |
457 | int |
458 | _tenQGLInterpNEvec(double evecOut[9], |
459 | const double *evecIn, /* size 9 -by- NN */ |
460 | const double *wght, /* size NN */ |
461 | unsigned int NN, |
462 | tenInterpParm *tip) { |
463 | static const char me[]="_tenQGLInterpNEvec"; |
464 | double qOut[4], maxWght, len, /* odsum, */ dsum, rot[9]; |
465 | unsigned int ii, centerIdx=0, fix, qiter; |
466 | |
467 | if (!( evecOut && evecIn && tip )) { |
468 | biffAddf(TENtenBiffKey, "%s: got NULL pointer", me); |
469 | return 1; |
470 | } |
471 | /* convert to quaternions */ |
472 | for (ii=0; ii<NN; ii++) { |
473 | ELL_3M_TRANSPOSE(rot, evecIn + 9*ii)((rot)[0] = (evecIn + 9*ii)[0], (rot)[1] = (evecIn + 9*ii)[3] , (rot)[2] = (evecIn + 9*ii)[6], (rot)[3] = (evecIn + 9*ii)[1 ], (rot)[4] = (evecIn + 9*ii)[4], (rot)[5] = (evecIn + 9*ii)[ 7], (rot)[6] = (evecIn + 9*ii)[2], (rot)[7] = (evecIn + 9*ii) [5], (rot)[8] = (evecIn + 9*ii)[8]); |
474 | ell_3m_to_q_d(tip->qIn + 4*ii, rot); |
475 | } |
476 | /* HEY: what should this be used for? variable odsum set but not used */ |
477 | /* odsum = _tenQGL_q_interdot(¢erIdx, tip->qIn, tip->qInter, NN); */ |
478 | |
479 | /* find quaternion with maximal weight, use it as is (decree that |
480 | its the right representative), and then align rest with that. |
481 | This is actually principled; symmetry allows it */ |
482 | centerIdx = 0; |
483 | if (wght) { |
484 | maxWght = wght[centerIdx]; |
485 | for (ii=1; ii<NN; ii++) { |
486 | if (wght[ii] > maxWght) { |
487 | centerIdx = ii; |
488 | maxWght = wght[centerIdx]; |
489 | } |
490 | } |
491 | } |
492 | for (ii=0; ii<NN; ii++) { |
493 | if (ii == centerIdx) { |
494 | continue; |
495 | } |
496 | _tenQGL_q_align(tip->qIn + 4*ii, tip->qIn + 4*centerIdx, tip->qIn + 4*ii); |
497 | } |
498 | dsum = _tenQGL_q_interdot(¢erIdx, tip->qIn, tip->qInter, NN); |
Value stored to 'dsum' is never read | |
499 | |
500 | /* try to settle on tightest set of representatives */ |
501 | qiter = 0; |
502 | do { |
503 | fix = 0; |
504 | for (ii=0; ii<NN; ii++) { |
505 | unsigned int ff; |
506 | if (ii == centerIdx) { |
507 | continue; |
508 | } |
509 | ff = _tenQGL_q_align(tip->qIn + 4*ii, tip->qIn + 4*centerIdx, |
510 | tip->qIn + 4*ii); |
511 | fix = AIR_MAX(fix, ff)((fix) > (ff) ? (fix) : (ff)); |
512 | } |
513 | dsum = _tenQGL_q_interdot(¢erIdx, tip->qIn, tip->qInter, NN); |
514 | if (tip->maxIter && qiter > tip->maxIter) { |
515 | biffAddf(TENtenBiffKey, "%s: q tightening unconverged after %u iters; " |
516 | "interdot = %g -> maxfix = %u; center = %u\n", |
517 | me, tip->maxIter, dsum, fix, centerIdx); |
518 | return 1; |
519 | } |
520 | qiter++; |
521 | } while (fix); |
522 | /* |
523 | fprintf(stderr, "!%s: dsum %g --%u--> %g\n", me, odsum, qiter, dsum); |
524 | */ |
525 | /* make sure they're normalized */ |
526 | for (ii=0; ii<NN; ii++) { |
527 | ELL_4V_NORM(tip->qIn + 4*ii, tip->qIn + 4*ii, len)(len = (sqrt((((tip->qIn + 4*ii))[0]*((tip->qIn + 4*ii) )[0] + ((tip->qIn + 4*ii))[1]*((tip->qIn + 4*ii))[1] + ( (tip->qIn + 4*ii))[2]*((tip->qIn + 4*ii))[2] + ((tip-> qIn + 4*ii))[3]*((tip->qIn + 4*ii))[3]))), ((tip->qIn + 4*ii)[0] = (tip->qIn + 4*ii)[0]*1.0/len, (tip->qIn + 4 *ii)[1] = (tip->qIn + 4*ii)[1]*1.0/len, (tip->qIn + 4*ii )[2] = (tip->qIn + 4*ii)[2]*1.0/len, (tip->qIn + 4*ii)[ 3] = (tip->qIn + 4*ii)[3]*1.0/len)); |
528 | } |
529 | |
530 | /* compute iterated weighted mean, stored in qOut */ |
531 | if (ell_q_avgN_d(qOut, &qiter, tip->qIn, tip->qBuff, wght, |
532 | NN, tip->convEps, tip->maxIter)) { |
533 | biffMovef(TENtenBiffKey, ELLell_biff_key, "%s: problem doing quaternion mean", me); |
534 | return 1; |
535 | } |
536 | /* |
537 | fprintf(stderr, "!%s: q avg converged in %u\n", me, qiter); |
538 | */ |
539 | |
540 | /* finish, convert back to evec */ |
541 | ell_q_to_3m_d(rot, qOut); |
542 | ELL_3M_TRANSPOSE(evecOut, rot)((evecOut)[0] = (rot)[0], (evecOut)[1] = (rot)[3], (evecOut)[ 2] = (rot)[6], (evecOut)[3] = (rot)[1], (evecOut)[4] = (rot)[ 4], (evecOut)[5] = (rot)[7], (evecOut)[6] = (rot)[2], (evecOut )[7] = (rot)[5], (evecOut)[8] = (rot)[8]); |
543 | |
544 | return 0; |
545 | } |
546 |