arm_spline_interp_init_f32.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /* ----------------------------------------------------------------------
  2. * Project: CMSIS DSP Library
  3. * Title: arm_spline_interp_init_f32.c
  4. * Description: Floating-point cubic spline initialization function
  5. *
  6. * $Date: 23 April 2021
  7. * $Revision: V1.9.0
  8. *
  9. * Target Processor: Cortex-M and Cortex-A cores
  10. * -------------------------------------------------------------------- */
  11. /*
  12. * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved.
  13. *
  14. * SPDX-License-Identifier: Apache-2.0
  15. *
  16. * Licensed under the Apache License, Version 2.0 (the License); you may
  17. * not use this file except in compliance with the License.
  18. * You may obtain a copy of the License at
  19. *
  20. * www.apache.org/licenses/LICENSE-2.0
  21. *
  22. * Unless required by applicable law or agreed to in writing, software
  23. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  24. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  25. * See the License for the specific language governing permissions and
  26. * limitations under the License.
  27. */
  28. #include "dsp/interpolation_functions.h"
  29. /**
  30. @ingroup groupInterpolation
  31. */
  32. /**
  33. @addtogroup SplineInterpolate
  34. @{
  35. @par Initialization function
  36. The initialization function takes as input two arrays that the user has to allocate:
  37. <code>coeffs</code> will contain the b, c, and d coefficients for the (n-1) intervals
  38. (n is the number of known points), hence its size must be 3*(n-1); <code>tempBuffer</code>
  39. is temporally used for internal computations and its size is n+n-1.
  40. @par
  41. The x input array must be strictly sorted in ascending order and it must
  42. not contain twice the same value (x(i)<x(i+1)).
  43. */
  44. /**
  45. * @brief Initialization function for the floating-point cubic spline interpolation.
  46. * @param[in,out] S points to an instance of the floating-point spline structure.
  47. * @param[in] type type of cubic spline interpolation (boundary conditions)
  48. * @param[in] x points to the x values of the known data points.
  49. * @param[in] y points to the y values of the known data points.
  50. * @param[in] n number of known data points.
  51. * @param[in] coeffs coefficients array for b, c, and d
  52. * @param[in] tempBuffer buffer array for internal computations
  53. *
  54. */
  55. void arm_spline_init_f32(
  56. arm_spline_instance_f32 * S,
  57. arm_spline_type type,
  58. const float32_t * x,
  59. const float32_t * y,
  60. uint32_t n,
  61. float32_t * coeffs,
  62. float32_t * tempBuffer)
  63. {
  64. /*** COEFFICIENTS COMPUTATION ***/
  65. /* Type (boundary conditions):
  66. - Natural spline ( S1''(x1) = 0 ; Sn''(xn) = 0 )
  67. - Parabolic runout spline ( S1''(x1) = S2''(x2) ; Sn-1''(xn-1) = Sn''(xn) ) */
  68. /* (n-1)-long buffers for b, c, and d coefficients */
  69. float32_t * b = coeffs;
  70. float32_t * c = coeffs+(n-1);
  71. float32_t * d = coeffs+(2*(n-1));
  72. float32_t * u = tempBuffer; /* (n-1)-long scratch buffer for u elements */
  73. float32_t * z = tempBuffer+(n-1); /* n-long scratch buffer for z elements */
  74. float32_t hi, hm1; /* h(i) and h(i-1) */
  75. float32_t Bi; /* B(i), i-th element of matrix B=LZ */
  76. float32_t li; /* l(i), i-th element of matrix L */
  77. float32_t cp1; /* Temporary value for c(i+1) */
  78. int32_t i; /* Loop counter */
  79. S->x = x;
  80. S->y = y;
  81. S->n_x = n;
  82. /* == Solve LZ=B to obtain z(i) and u(i) == */
  83. /* -- Row 1 -- */
  84. /* B(0) = 0, not computed */
  85. /* u(1,2) = a(1,2)/a(1,1) = a(1,2) */
  86. if(type == ARM_SPLINE_NATURAL)
  87. u[0] = 0; /* a(1,2) = 0 */
  88. else if(type == ARM_SPLINE_PARABOLIC_RUNOUT)
  89. u[0] = -1; /* a(1,2) = -1 */
  90. z[0] = 0; /* z(1) = B(1)/a(1,1) = 0 always */
  91. /* -- Rows 2 to N-1 (N=n+1) -- */
  92. hm1 = x[1] - x[0]; /* Initialize h(i-1) = h(1) = x(2)-x(1) */
  93. for (i=1; i<(int32_t)n-1; i++)
  94. {
  95. /* Compute B(i) */
  96. hi = x[i+1]-x[i];
  97. Bi = 3*(y[i+1]-y[i])/hi - 3*(y[i]-y[i-1])/hm1;
  98. /* l(i) = a(i)-a(i,i-1)*u(i-1) = 2[h(i-1)+h(i)]-h(i-1)*u(i-1) */
  99. li = 2*(hi+hm1) - hm1*u[i-1];
  100. /* u(i) = a(i,i+1)/l(i) = h(i)/l(i) */
  101. u[i] = hi/li;
  102. /* z(i) = [B(i)-h(i-1)*z(i-1)]/l(i) */
  103. z[i] = (Bi-hm1*z[i-1])/li;
  104. /* Update h(i-1) for next iteration */
  105. hm1 = hi;
  106. }
  107. /* -- Row N -- */
  108. /* l(N) = a(N,N)-a(N,N-1)u(N-1) */
  109. /* z(N) = [-a(N,N-1)z(N-1)]/l(N) */
  110. if(type == ARM_SPLINE_NATURAL)
  111. {
  112. /* li = 1; a(N,N) = 1; a(N,N-1) = 0 */
  113. z[n-1] = 0; /* a(N,N-1) = 0 */
  114. }
  115. else if(type == ARM_SPLINE_PARABOLIC_RUNOUT)
  116. {
  117. li = 1+u[n-2]; /* a(N,N) = 1; a(N,N-1) = -1 */
  118. z[n-1] = z[n-2]/li; /* a(N,N-1) = -1 */
  119. }
  120. /* == Solve UX = Z to obtain c(i) and */
  121. /* compute b(i) and d(i) from c(i) == */
  122. cp1 = z[n-1]; /* Initialize c(i+1) = c(N) = z(N) */
  123. for (i=n-2; i>=0; i--)
  124. {
  125. /* c(i) = z(i)-u(i+1)c(i+1) */
  126. c[i] = z[i]-u[i]*cp1;
  127. hi = x[i+1]-x[i];
  128. /* b(i) = [y(i+1)-y(i)]/h(i)-h(i)*[c(i+1)+2*c(i)]/3 */
  129. b[i] = (y[i+1]-y[i])/hi-hi*(cp1+2*c[i])/3;
  130. /* d(i) = [c(i+1)-c(i)]/[3*h(i)] */
  131. d[i] = (cp1-c[i])/(3*hi);
  132. /* Update c(i+1) for next iteration */
  133. cp1 = c[i];
  134. }
  135. /* == Finally, store the coefficients in the instance == */
  136. S->coeffs = coeffs;
  137. }
  138. /**
  139. @} end of SplineInterpolate group
  140. */