sipxmedialib  Version 3.3
MpDspUtilsIntSqrt.h
Go to the documentation of this file.
1 //
2 // Copyright (C) 2008 SIPfoundry Inc.
3 // Licensed by SIPfoundry under the LGPL license.
4 //
5 // Copyright (C) 2008 SIPez LLC.
6 // Licensed to SIPfoundry under a Contributor Agreement.
7 //
8 // $$
10 
11 // Author: Alexander Chemeris <Alexander DOT Chemeris AT SIPez DOT com>
12 
13 #ifndef _MpDspUtilsIntSqrt_h_
14 #define _MpDspUtilsIntSqrt_h_
15 
28 /* ============================ INLINE METHODS ============================ */
29 
30 
31 #if !defined(_WIN32) || !defined(_MSC_VER) || defined(_WIN64)
32 // Use plain C implementation.
33 uint32_t MpDspUtils::sqrt(uint32_t val)
34 {
35  uint32_t temp;
36  uint32_t g = 0;
37 
38  if (val >= 0x40000000)
39  {
40  g = 0x8000;
41  val -= 0x40000000;
42  }
43 
44 #define INNER_ISQRT(s) \
45  temp = (g << (s)) + (1 << ((s) * 2 - 2)); \
46  if (val >= temp) \
47  { \
48  g += 1 << ((s)-1); \
49  val -= temp; \
50  }
51 
52  INNER_ISQRT (15);
53  INNER_ISQRT (14);
54  INNER_ISQRT (13);
55  INNER_ISQRT (12);
56  INNER_ISQRT (11);
57  INNER_ISQRT (10);
58  INNER_ISQRT ( 9);
59  INNER_ISQRT ( 8);
60  INNER_ISQRT ( 7);
61  INNER_ISQRT ( 6);
62  INNER_ISQRT ( 5);
63  INNER_ISQRT ( 4);
64  INNER_ISQRT ( 3);
65  INNER_ISQRT ( 2);
66 
67 #undef INNER_ISQRT
68 
69  temp = g+g+1;
70  if (val >= temp)
71  {
72  g++;
73  }
74  return g;
75 }
76 #else
77 // Use asm-optimized version
78 
79 /* by Norbert Juffa */
80 static inline
81 __declspec (naked) uint32_t __stdcall MpDspUtils_sqrt(uint32_t x) {
82  /* based on posting by Wilco Dijkstra in comp.sys.arm in 1996 */
83 
84  /*
85  * For processors that provide single cycle latency
86  * LEA, the first four instructions of the following
87  * macro could be replaced as follows
88  * __asm lea edx, [eax+(1<<(N))]
89  * __asm lea ebx, [eax+(2<<(N))]
90  */
91 #if CPU == ATHLON || CPU == ATHLON64
92 #define iterasm(N) \
93  __asm mov edx, (1 << (N)) \
94  __asm mov ebx, (2 << (N)) \
95  __asm or edx, eax \
96  __asm or ebx, eax \
97  __asm shl edx, (N) \
98  __asm mov esi, ecx \
99  __asm sub ecx, edx \
100  __asm cmovnc eax, ebx \
101  __asm cmovc ecx, esi
102 #else /* generic 386+ */
103 #define iterasm(N) \
104  __asm mov edx, (1 << (N)) \
105  __asm mov ebx, (2 << (N)) \
106  __asm or edx, eax \
107  __asm or ebx, eax \
108  __asm shl edx, (N) \
109  __asm sub ecx, edx \
110  __asm sbb esi, esi \
111  __asm sub eax, ebx \
112  __asm and eax, esi \
113  __asm add eax, ebx \
114  __asm and edx, esi \
115  __asm add ecx, edx
116 #endif
117 
118  __asm {
119  mov ecx, [esp+4] ; x
120  push ebx ; save as per calling convention
121  push esi ; save as per calling convention
122  xor eax, eax ; 2*root
123  /* iteration 15 */
124  mov ebx, (2 << (15))
125  mov esi, ecx
126  sub ecx, (1 << (30))
127  cmovnc eax, ebx
128  cmovc ecx, esi
129  iterasm (14);
130  iterasm (13);
131  iterasm (12);
132  iterasm (11);
133  iterasm (10);
134  iterasm (9);
135  iterasm (8);
136  iterasm (7);
137  iterasm (6);
138  iterasm (5);
139  iterasm (4);
140  iterasm (3);
141  iterasm (2);
142  iterasm (1);
143  /* iteration 0 */
144  mov edx, 1
145  mov ebx, 2
146  add edx, eax
147  add ebx, eax
148  sub ecx, edx
149  cmovnc eax, ebx
150  shr eax, 1
151  mov esi, [esp] ; restore as per calling convention
152  mov ebx, [esp+4] ; restore as per calling convention
153  add esp, 8 ; remove temp variables
154  ret 4 ; pop one DWORD arg and return
155  }
156 #undef iterasm
157 }
158 
159 uint32_t MpDspUtils::sqrt(uint32_t x)
160 {
161  return MpDspUtils_sqrt(x);
162 }
163 
164 #endif
165 
166 #endif // _MpDspUtilsIntSqrt_h_
static uint32_t sqrt(uint32_t val)
Integer square root.
Definition: MpDspUtilsIntSqrt.h:33
static int16_t add(int16_t a, int16_t b)
Return (a+b) saturated (16-bit).
Definition: MpDspUtilsSum.h:22
#define INNER_ISQRT(s)