/ Drivers / CMSIS / DSP / Include / dsp / utils.h
utils.h
  1  /******************************************************************************
  2   * @file     arm_math_utils.h
  3   * @brief    Public header file for CMSIS DSP Library
  4   * @version  V1.9.0
  5   * @date     20. July 2020
  6   ******************************************************************************/
  7  /*
  8   * Copyright (c) 2010-2020 Arm Limited or its affiliates. All rights reserved.
  9   *
 10   * SPDX-License-Identifier: Apache-2.0
 11   *
 12   * Licensed under the Apache License, Version 2.0 (the License); you may
 13   * not use this file except in compliance with the License.
 14   * You may obtain a copy of the License at
 15   *
 16   * www.apache.org/licenses/LICENSE-2.0
 17   *
 18   * Unless required by applicable law or agreed to in writing, software
 19   * distributed under the License is distributed on an AS IS BASIS, WITHOUT
 20   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 21   * See the License for the specific language governing permissions and
 22   * limitations under the License.
 23   */
 24  
 25  #ifndef _ARM_MATH_UTILS_H_
 26  
 27  #define _ARM_MATH_UTILS_H_
 28  
 29  #include "arm_math_types.h"
 30  
 31  #ifdef   __cplusplus
 32  extern "C"
 33  {
 34  #endif
 35  
 36    /**
 37     * @brief Macros required for reciprocal calculation in Normalized LMS
 38     */
 39  
 40  #define INDEX_MASK         0x0000003F
 41  
 42  
 43  #define SQ(x) ((x) * (x))
 44  
 45  #define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
 46  
 47  
 48    /**
 49     * @brief Function to Calculates 1/in (reciprocal) value of Q31 Data type.
 50     */
 51    __STATIC_FORCEINLINE uint32_t arm_recip_q31(
 52          q31_t in,
 53          q31_t * dst,
 54    const q31_t * pRecipTable)
 55    {
 56      q31_t out;
 57      uint32_t tempVal;
 58      uint32_t index, i;
 59      uint32_t signBits;
 60  
 61      if (in > 0)
 62      {
 63        signBits = ((uint32_t) (__CLZ( in) - 1));
 64      }
 65      else
 66      {
 67        signBits = ((uint32_t) (__CLZ(-in) - 1));
 68      }
 69  
 70      /* Convert input sample to 1.31 format */
 71      in = (in << signBits);
 72  
 73      /* calculation of index for initial approximated Val */
 74      index = (uint32_t)(in >> 24);
 75      index = (index & INDEX_MASK);
 76  
 77      /* 1.31 with exp 1 */
 78      out = pRecipTable[index];
 79  
 80      /* calculation of reciprocal value */
 81      /* running approximation for two iterations */
 82      for (i = 0U; i < 2U; i++)
 83      {
 84        tempVal = (uint32_t) (((q63_t) in * out) >> 31);
 85        tempVal = 0x7FFFFFFFu - tempVal;
 86        /*      1.31 with exp 1 */
 87        /* out = (q31_t) (((q63_t) out * tempVal) >> 30); */
 88        out = clip_q63_to_q31(((q63_t) out * tempVal) >> 30);
 89      }
 90  
 91      /* write output */
 92      *dst = out;
 93  
 94      /* return num of signbits of out = 1/in value */
 95      return (signBits + 1U);
 96    }
 97  
 98  
 99    /**
100     * @brief Function to Calculates 1/in (reciprocal) value of Q15 Data type.
101     */
102    __STATIC_FORCEINLINE uint32_t arm_recip_q15(
103          q15_t in,
104          q15_t * dst,
105    const q15_t * pRecipTable)
106    {
107      q15_t out = 0;
108      uint32_t tempVal = 0;
109      uint32_t index = 0, i = 0;
110      uint32_t signBits = 0;
111  
112      if (in > 0)
113      {
114        signBits = ((uint32_t)(__CLZ( in) - 17));
115      }
116      else
117      {
118        signBits = ((uint32_t)(__CLZ(-in) - 17));
119      }
120  
121      /* Convert input sample to 1.15 format */
122      in = (in << signBits);
123  
124      /* calculation of index for initial approximated Val */
125      index = (uint32_t)(in >>  8);
126      index = (index & INDEX_MASK);
127  
128      /*      1.15 with exp 1  */
129      out = pRecipTable[index];
130  
131      /* calculation of reciprocal value */
132      /* running approximation for two iterations */
133      for (i = 0U; i < 2U; i++)
134      {
135        tempVal = (uint32_t) (((q31_t) in * out) >> 15);
136        tempVal = 0x7FFFu - tempVal;
137        /*      1.15 with exp 1 */
138        out = (q15_t) (((q31_t) out * tempVal) >> 14);
139        /* out = clip_q31_to_q15(((q31_t) out * tempVal) >> 14); */
140      }
141  
142      /* write output */
143      *dst = out;
144  
145      /* return num of signbits of out = 1/in value */
146      return (signBits + 1);
147    }
148  
149  
150  /**
151   * @brief  64-bit to 32-bit unsigned normalization
152   * @param[in]  in           is input unsigned long long value
153   * @param[out] normalized   is the 32-bit normalized value
154   * @param[out] norm         is norm scale
155   */
156  __STATIC_INLINE  void arm_norm_64_to_32u(uint64_t in, int32_t * normalized, int32_t *norm)
157  {
158      int32_t     n1;
159      int32_t     hi = (int32_t) (in >> 32);
160      int32_t     lo = (int32_t) ((in << 32) >> 32);
161  
162      n1 = __CLZ(hi) - 32;
163      if (!n1)
164      {
165          /*
166           * input fits in 32-bit
167           */
168          n1 = __CLZ(lo);
169          if (!n1)
170          {
171              /*
172               * MSB set, need to scale down by 1
173               */
174              *norm = -1;
175              *normalized = (((uint32_t) lo) >> 1);
176          } else
177          {
178              if (n1 == 32)
179              {
180                  /*
181                   * input is zero
182                   */
183                  *norm = 0;
184                  *normalized = 0;
185              } else
186              {
187                  /*
188                   * 32-bit normalization
189                   */
190                  *norm = n1 - 1;
191                  *normalized = lo << *norm;
192              }
193          }
194      } else
195      {
196          /*
197           * input fits in 64-bit
198           */
199          n1 = 1 - n1;
200          *norm = -n1;
201          /*
202           * 64 bit normalization
203           */
204          *normalized = (((uint32_t) lo) >> n1) | (hi << (32 - n1));
205      }
206  }
207  
208  __STATIC_INLINE q31_t arm_div_q63_to_q31(q63_t num, q31_t den)
209  {
210      q31_t   result;
211      uint64_t   absNum;
212      int32_t   normalized;
213      int32_t   norm;
214  
215      /*
216       * if sum fits in 32bits
217       * avoid costly 64-bit division
218       */
219      absNum = num > 0 ? num : -num;
220      arm_norm_64_to_32u(absNum, &normalized, &norm);
221      if (norm > 0)
222          /*
223           * 32-bit division
224           */
225          result = (q31_t) num / den;
226      else
227          /*
228           * 64-bit division
229           */
230          result = (q31_t) (num / den);
231  
232      return result;
233  }
234  
235  
236  #ifdef   __cplusplus
237  }
238  #endif
239  
240  #endif /*ifndef _ARM_MATH_UTILS_H_ */