| 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 | } |