-
Notifications
You must be signed in to change notification settings - Fork 0
/
int_roots.c
159 lines (146 loc) · 3.91 KB
/
int_roots.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*-------------------------------------------------------------------------
* INTEL CONFIDENTIAL
*
* Copyright 2012 Intel Corporation All Rights Reserved.
*
* This source code and all documentation related to the source code
* ("Material") contains trade secrets and proprietary and confidential
* information of Intel and its suppliers and licensors. The Material is
* deemed highly confidential, and is protected by worldwide copyright and
* trade secret laws and treaty provisions. No part of the Material may be
* used, copied, reproduced, modified, published, uploaded, posted,
* transmitted, distributed, or disclosed in any way without Intel's prior
* express written permission.
*
* No license under any patent, copyright, trade secret or other
* intellectual property right is granted to or conferred upon you by
* disclosure or delivery of the Materials, either expressly, by
* implication, inducement, estoppel or otherwise. Any license under such
* intellectual property rights must be express and approved by Intel in
* writing.
*-------------------------------------------------------------------------
*/
/*
* Version: 1.1
* Author: Han, He <[email protected]>
* Date: Jun 11th, 2012
* Update: Nov 27th, 2013 : Add cubic root function
*/
#include "int_roots.h"
unsigned int int_sqrt(unsigned int squared) {
static const unsigned int D[5] = {0, 268435456, 1073741824, 2415919104U, 4294967295U};
static const unsigned int d[5] = {0, 16384, 32768, 49152, 65536};
unsigned int P = 8192;
unsigned int R = 67108864;
unsigned int A = 0, a = 0, C = 0, c = 0, B = 0, b = 0, K = 0;
B = squared;
if( B >= D[4] ) {
b = d[4];
goto finish;
}
else if( B >= D[3] ) {
if( B == D[3] ) {
b = d[3];
goto finish;
}
A = D[3];
a = d[3];
C = D[4];
c = d[4];
}
else if( B >= D[2] ) {
if( B == D[2] ) {
b = d[2];
goto finish;
}
A = D[2];
a = d[2];
C = D[3];
c = d[3];
}
else if( B >= D[1] ) {
if( B == D[1] ) {
b = d[1];
goto finish;
}
A = D[1];
a = d[1];
C = D[2];
c = d[2];
}
else if( B >= D[0] ) {
if( B == D[0] ) {
b = d[0];
goto finish;
}
A = D[0];
a = d[0];
C = D[1];
c = d[1];
}
else {
// psh_err2(PSH_ITSELF, "Number given error! Number: %d\n", squared);
return -1;
}
while(1) {
b = a + P;
B = C - (C - A) / 2 - R;
if(B == squared) {
goto finish;
}
else if(B < squared) {
A = B;
a = b;
}
else {
C = B;
c = b;
}
if(c-a == 2) {
/* Now c = a + 2.
* If squared > (a+1)*(a+2) , b = a+2 ;
* If squared <= a*(a+1), b = a ;
* Else b = a+1.
*/
K=(C - A)/4;
if(squared >= C - K) {
b = c;
}
else if(squared < A + K) {
b = a;
}
else {
b = a + 1;
}
goto finish;
}
P /= 2;
R /= 4;
}
finish:
return b;
}
uint32_t int_cbrt(uint64_t cubic)
{
uint64_t left = cubic;
uint64_t root = 1;
int i, digits = 0;
if (left == 0)
return 0;
while (left != 0) {
digits++;
left >>= 3;
}
/* Original algorithm is from "Nine Chapters on Arithmetic".
* The improved algorithm is modify Decimal to Binary.
*/
for (i = 1; i < digits; i++) {
left = cubic >> ((digits - 1 - i) * 3);
left -= (root << 1) * (root << 1) * (root << 1);
if (left > (12 * root * root + 6 * root))
root = (root << 1) + 1;
else
root <<= 1;
}
return root;
}