1 /* ----------------------------------------------------------------------
2  * Project:      CMSIS DSP Library
3  * Title:        arm_sqrt_q15.c
4  * Description:  Q15 square root 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 
29 #include "dsp/fast_math_functions.h"
30 #include "arm_common_tables.h"
31 
32 /**
33   @ingroup groupFastMath
34  */
35 
36 /**
37   @addtogroup SQRT
38   @{
39  */
40 
41 /**
42   @brief         Q15 square root function.
43   @param[in]     in    input value.  The range of the input value is [0 +1) or 0x0000 to 0x7FFF
44   @param[out]    pOut  points to square root of input value
45   @return        execution status
46                    - \ref ARM_MATH_SUCCESS        : input value is positive
47                    - \ref ARM_MATH_ARGUMENT_ERROR : input value is negative; *pOut is set to 0
48  */
49 
arm_sqrt_q15(q15_t in,q15_t * pOut)50 arm_status arm_sqrt_q15(
51   q15_t in,
52   q15_t * pOut)
53 {
54   q31_t bits_val1;
55   q15_t number, temp1, var1, signBits1, half;
56   float32_t temp_float1;
57   union
58   {
59     q31_t fracval;
60     float32_t floatval;
61   } tempconv;
62 
63   number = in;
64 
65   /* If the input is a positive number then compute the signBits. */
66   if (number > 0)
67   {
68     signBits1 = __CLZ(number) - 17;
69 
70     /* Shift by the number of signBits1 */
71     if ((signBits1 % 2) == 0)
72     {
73       number = number << signBits1;
74     }
75     else
76     {
77       number = number << (signBits1 - 1);
78     }
79 
80     /* Calculate half value of the number */
81     half = number >> 1;
82     /* Store the number for later use */
83     temp1 = number;
84 
85     /* Convert to float */
86     temp_float1 = number * 3.051757812500000e-005f;
87     /* Store as integer */
88     tempconv.floatval = temp_float1;
89     bits_val1 = tempconv.fracval;
90     /* Subtract the shifted value from the magic number to give intial guess */
91     bits_val1 = 0x5f3759df - (bits_val1 >> 1);  /* gives initial guess */
92     /* Store as float */
93     tempconv.fracval = bits_val1;
94     temp_float1 = tempconv.floatval;
95     /* Convert to integer format */
96     var1 = (q31_t) (temp_float1 * 16384);
97 
98     /* 1st iteration */
99     var1 = ((q15_t) ((q31_t) var1 * (0x3000 -
100                                      ((q15_t)
101                                       ((((q15_t)
102                                          (((q31_t) var1 * var1) >> 15)) *
103                                         (q31_t) half) >> 15))) >> 15)) << 2;
104     /* 2nd iteration */
105     var1 = ((q15_t) ((q31_t) var1 * (0x3000 -
106                                      ((q15_t)
107                                       ((((q15_t)
108                                          (((q31_t) var1 * var1) >> 15)) *
109                                         (q31_t) half) >> 15))) >> 15)) << 2;
110     /* 3rd iteration */
111     var1 = ((q15_t) ((q31_t) var1 * (0x3000 -
112                                      ((q15_t)
113                                       ((((q15_t)
114                                          (((q31_t) var1 * var1) >> 15)) *
115                                         (q31_t) half) >> 15))) >> 15)) << 2;
116 
117     /* Multiply the inverse square root with the original value */
118     var1 = ((q15_t) (((q31_t) temp1 * var1) >> 15)) << 1;
119 
120     /* Shift the output down accordingly */
121     if ((signBits1 % 2) == 0)
122     {
123       var1 = var1 >> (signBits1 / 2);
124     }
125     else
126     {
127       var1 = var1 >> ((signBits1 - 1) / 2);
128     }
129     *pOut = var1;
130 
131     return (ARM_MATH_SUCCESS);
132   }
133   /* If the number is a negative number then store zero as its square root value */
134   else
135   {
136     *pOut = 0;
137 
138     return (ARM_MATH_ARGUMENT_ERROR);
139   }
140 }
141 
142 /**
143   @} end of SQRT group
144  */
145