18#ifndef itkRecursiveBSplineTransformImplementation_h
19#define itkRecursiveBSplineTransformImplementation_h
45template <
unsigned int OutputDimension,
unsigned int SpaceDimension,
unsigned int SplineOrder,
class TScalar>
57 itkStaticConstMacro(BSplineNumberOfIndices,
unsigned int, RecursiveBSplineWeightFunctionType::NumberOfIndices);
62 const TScalar *
const *
const mu,
63 const OffsetValueType *
const gridOffsetTable,
64 const double *
const weights1D)
67 const TScalar * tmp_mu[OutputDimension];
68 std::copy_n(mu, OutputDimension, tmp_mu);
71 TScalar tmp_opp[OutputDimension];
72 std::fill_n(opp, OutputDimension, 0.0);
74 const OffsetValueType bot = gridOffsetTable[SpaceDimension - 1];
75 for (
unsigned int k = 0; k <= SplineOrder; ++k)
82 for (
unsigned int j = 0; j < OutputDimension; ++j)
84 opp[j] += tmp_opp[j] * weights1D[k + HelperConstVariable];
95 GetJacobian(TScalar *& jacobians,
const double *
const weights1D,
const double value)
97 for (
unsigned int k = 0; k <= SplineOrder; ++k)
101 jacobians, weights1D, value * weights1D[k + HelperConstVariable]);
110 const double *
const weights1D,
113 for (
unsigned int k = 0; k <= SplineOrder; ++k)
118 imageJacobian, movingImageGradient, weights1D, value * weights1D[k + HelperConstVariable]);
126 const unsigned long parametersPerDim,
127 unsigned long currentIndex,
128 const OffsetValueType *
const gridOffsetTable)
130 const OffsetValueType bot = gridOffsetTable[SpaceDimension - 1];
131 for (
unsigned int k = 0; k <= SplineOrder; ++k)
148 const TScalar *
const *
const mu,
149 const OffsetValueType *
const gridOffsetTable,
150 const double *
const weights1D,
151 const double *
const derivativeWeights1D)
154 const TScalar * tmp_mu[OutputDimension];
155 std::copy_n(mu, OutputDimension, tmp_mu);
159 for (
unsigned int n = 0; n < OutputDimension * (SpaceDimension + 1); ++n)
164 const OffsetValueType bot = gridOffsetTable[SpaceDimension - 1];
165 for (
unsigned int k = 0; k <= SplineOrder; ++k)
172 for (
unsigned int n = 0; n < OutputDimension * SpaceDimension; ++n)
174 sj[n] += tmp_sj[n] * weights1D[k + HelperConstVariable];
178 for (
unsigned int j = 0; j < OutputDimension; ++j)
180 sj[OutputDimension * SpaceDimension + j] += tmp_sj[j] * derivativeWeights1D[k + HelperConstVariable];
210 const TScalar *
const *
const mu,
211 const OffsetValueType *
const gridOffsetTable,
212 const double *
const weights1D,
213 const double *
const derivativeWeights1D,
214 const double *
const hessianWeights1D)
216 const unsigned int helperDim1 = OutputDimension * SpaceDimension * (SpaceDimension + 1) / 2;
217 const unsigned int helperDim2 = OutputDimension * (SpaceDimension + 1) * (SpaceDimension + 2) / 2;
220 const TScalar * tmp_mu[OutputDimension];
221 std::copy_n(mu, OutputDimension, tmp_mu);
225 for (
unsigned int n = 0; n < helperDim2; ++n)
230 const OffsetValueType bot = gridOffsetTable[SpaceDimension - 1];
231 for (
unsigned int k = 0; k <= SplineOrder; ++k)
235 GetSpatialHessian(tmp_sh, tmp_mu, gridOffsetTable, weights1D, derivativeWeights1D, hessianWeights1D);
238 for (
unsigned int n = 0; n < helperDim1; ++n)
240 sh[n] += tmp_sh[n] * weights1D[k + HelperConstVariable];
244 for (
unsigned int n = 0; n < SpaceDimension; ++n)
246 for (
unsigned int j = 0; j < OutputDimension; ++j)
248 sh[OutputDimension * n + helperDim1 + j] +=
249 tmp_sh[OutputDimension * n * (n + 1) / 2 + j] * derivativeWeights1D[k + HelperConstVariable];
254 for (
unsigned int j = 0; j < OutputDimension; ++j)
256 sh[helperDim2 - OutputDimension + j] += tmp_sh[j] * hessianWeights1D[k + HelperConstVariable];
270 const double *
const weights1D,
271 const double *
const derivativeWeights1D,
272 const double *
const directionCosines,
275 const unsigned int helperDim = OutputDimension - SpaceDimension + 1;
280 for (
unsigned int k = 0; k <= SplineOrder; ++k)
282 const double w = weights1D[k + HelperConstVariable];
283 const double dw = derivativeWeights1D[k + HelperConstVariable];
286 for (
unsigned int n = 0; n < helperDim; ++n)
288 tmp_jsj[n] = jsj[n] * w;
292 tmp_jsj[helperDim] = jsj[0] * dw;
306 const double *
const weights1D,
307 const double *
const derivativeWeights1D,
308 const double *
const hessianWeights1D,
309 const double *
const directionCosines,
312 const unsigned int helperDim = OutputDimension - SpaceDimension;
313 const unsigned int helperDimW = (helperDim + 1) * (helperDim + 2) / 2;
314 const unsigned int helperDimDW = helperDim + 1;
319 for (
unsigned int k = 0; k <= SplineOrder; ++k)
322 const double w = weights1D[k + HelperConstVariable];
323 const double dw = derivativeWeights1D[k + HelperConstVariable];
324 const double hw = hessianWeights1D[k + HelperConstVariable];
327 for (
unsigned int n = 0; n < helperDimW; ++n)
329 tmp_jsh[n] = jsh[n] * w;
333 for (
unsigned int n = 0; n < helperDimDW; ++n)
335 unsigned int nn = n * (n + 1) / 2;
336 tmp_jsh[n + helperDimW] = jsh[nn] * dw;
340 tmp_jsh[helperDimW + helperDimDW] = jsh[0] * hw;
345 jsh_out, weights1D, derivativeWeights1D, hessianWeights1D, directionCosines, tmp_jsh);
356template <
unsigned int OutputDimension,
unsigned int SplineOrder,
class TScalar>
365 itkStaticConstMacro(BSplineNumberOfIndices,
unsigned int, RecursiveBSplineWeightFunctionType::NumberOfIndices);
370 const TScalar *
const *
const mu,
371 const OffsetValueType *
const itkNotUsed(gridOffsetTable),
372 const double *
const itkNotUsed(weights1D))
374 for (
unsigned int j = 0; j < OutputDimension; ++j)
383 GetJacobian(TScalar *& jacobians,
const double *
const itkNotUsed(weights1D),
const double value)
385 unsigned long offset = 0;
386 for (
unsigned int j = 0; j < OutputDimension; ++j)
388 offset = j * BSplineNumberOfIndices * (OutputDimension + 1);
389 jacobians[offset] = value;
399 const double *
const itkNotUsed(weights1D),
402 for (
unsigned int j = 0; j < OutputDimension; ++j)
404 *(imageJacobian + j * BSplineNumberOfIndices) = value * movingImageGradient[j];
413 const unsigned long parametersPerDim,
414 const unsigned long currentIndex,
415 const OffsetValueType *
const itkNotUsed(gridOffsetTable))
417 for (
unsigned int j = 0; j < OutputDimension; ++j)
419 nzji[j * BSplineNumberOfIndices] = currentIndex + j * parametersPerDim;
428 const TScalar *
const *
const mu,
429 const OffsetValueType *
const itkNotUsed(gridOffsetTable),
430 const double *
const itkNotUsed(weights1D),
431 const double *
const itkNotUsed(derivativeWeights1D))
433 for (
unsigned int j = 0; j < OutputDimension; ++j)
443 const TScalar *
const *
const mu,
444 const OffsetValueType *
const itkNotUsed(gridOffsetTable),
445 const double *
const itkNotUsed(weights1D),
446 const double *
const itkNotUsed(derivativeWeights1D),
447 const double *
const itkNotUsed(hessianWeights1D))
449 for (
unsigned int j = 0; j < OutputDimension; ++j)
459 const double *
const itkNotUsed(weights1D),
460 const double *
const itkNotUsed(derivativeWeights1D),
461 const double *
const directionCosines,
469 for (
unsigned int j = 0; j < OutputDimension; ++j)
471 jsj_out[j] = jsj[OutputDimension] * directionCosines[j];
472 for (
unsigned int k = 1; k < OutputDimension; ++k)
474 jsj_out[k] += jsj[OutputDimension - k] * directionCosines[k * OutputDimension + j];
479 unsigned int offset = 0;
480 for (
unsigned int i = 0; i < OutputDimension; ++i)
482 offset = i * (OutputDimension * (BSplineNumberOfIndices * OutputDimension + 1));
483 for (
unsigned int j = 0; j < OutputDimension; ++j)
485 jsj_out[j + offset] = jsj_out[j];
490 jsj_out += OutputDimension * OutputDimension;
498 const double *
const itkNotUsed(weights1D),
499 const double *
const itkNotUsed(derivativeWeights1D),
500 const double *
const itkNotUsed(hessianWeights1D),
501 const double *
const directionCosines,
504 double jsh_tmp[OutputDimension * OutputDimension];
505 double matrixProduct[OutputDimension * OutputDimension];
513 if constexpr (OutputDimension == 3)
515 const double tmp[] = { jsh[9], jsh[8], jsh[7], jsh[8], jsh[5], jsh[4], jsh[7], jsh[4], jsh[2] };
516 FastBitwiseCopy(jsh_tmp, tmp);
518 else if constexpr (OutputDimension == 2)
520 const double tmp[] = { jsh[5], jsh[4], jsh[4], jsh[2] };
521 FastBitwiseCopy(jsh_tmp, tmp);
525 for (
unsigned int j = 0; j < OutputDimension; ++j)
527 for (
unsigned int i = 0; i <= j; ++i)
529 jsh_tmp[j * OutputDimension + i] =
530 jsh[(OutputDimension - j) + (OutputDimension - i) * (OutputDimension - i + 1) / 2];
533 jsh_tmp[i * OutputDimension + j] = jsh_tmp[j * OutputDimension + i];
540 for (
unsigned int i = 0; i < OutputDimension; ++i)
542 for (
unsigned int j = 0; j < OutputDimension; ++j)
544 double accum = directionCosines[i] * jsh_tmp[j];
545 for (
unsigned int k = 1; k < OutputDimension; ++k)
547 accum += directionCosines[k * OutputDimension + i] * jsh_tmp[k * OutputDimension + j];
549 matrixProduct[i * OutputDimension + j] = accum;
554 for (
unsigned int i = 0; i < OutputDimension; ++i)
556 for (
unsigned int j = 0; j < OutputDimension; ++j)
558 double accum = matrixProduct[i * OutputDimension] * directionCosines[j];
559 for (
unsigned int k = 1; k < OutputDimension; ++k)
561 accum += matrixProduct[i * OutputDimension + k] * directionCosines[k * OutputDimension + j];
563 jsh_out[i * OutputDimension + j] = accum;
568 unsigned long offset = 0;
569 for (
unsigned int i = 0; i < OutputDimension; ++i)
571 offset = i * (OutputDimension * OutputDimension * (BSplineNumberOfIndices * OutputDimension + 1));
572 for (
unsigned int j = 0; j < OutputDimension * OutputDimension; ++j)
574 jsh_out[j + offset] = jsh_out[j];
579 jsh_out += OutputDimension * OutputDimension * OutputDimension;
585 template <
typename T>
589 std::memcpy(&destination, &source,
sizeof(T));
592 template <
typename T1,
typename T2>
596 assert(!
"This FastBitwiseCopy overload should not be called!");
Returns the weights over the support region used for B-spline interpolation/reconstruction.