xref: /aosp_15_r20/external/XNNPACK/src/math/sqrt-u64-scalar-cvtu64-sqrt-llrint.c (revision 4bdc94577ba0e567308109d787f7fec7b531ce36)
1 // Copyright 2022 Google LLC
2 //
3 // This source code is licensed under the BSD-style license found in the
4 // LICENSE file in the root directory of this source tree.
5 
6 #include <assert.h>
7 #include <stddef.h>
8 #include <math.h>
9 
10 #include <xnnpack/common.h>
11 #include <xnnpack/math.h>
12 #include <xnnpack/math-stubs.h>
13 
14 
xnn_math_u64_sqrt__scalar_cvtu64_sqrt_llrint(size_t n,const uint64_t * input,uint64_t * output)15 void xnn_math_u64_sqrt__scalar_cvtu64_sqrt_llrint(
16     size_t n,
17     const uint64_t* input,
18     uint64_t* output)
19 {
20   assert(n % sizeof(uint32_t) == 0);
21 
22   for (; n != 0; n -= sizeof(uint64_t)) {
23     const uint64_t vx = *input++;
24 
25     uint64_t vy = vx;
26     if XNN_LIKELY(vx != 0) {
27       double vf = (double) vx;
28       vf = sqrt(vf);
29       vy = (uint64_t) (int64_t) llrint(vf);
30       #if XNN_ARCH_ARM || XNN_ARCH_X86
31         const uint64_t vsquared_y_less_x = math_mulext_u32((uint32_t) vy, (uint32_t) vy) - vx;
32       #else
33         const uint64_t vsquared_y_less_x = vy * vy - vx;
34       #endif
35       if XNN_UNPREDICTABLE((int64_t) (vsquared_y_less_x + vy) < 0) {
36         vy += 1;
37       } else if XNN_UNPREDICTABLE((int64_t) (vsquared_y_less_x - vy) >= 0) {
38         vy -= 1;
39       }
40     }
41 
42     *output++ = vy;
43   }
44 }
45