Mercurial > hg > audiostuff
comparison spandsp-0.0.6pre17/src/bit_operations.c @ 4:26cd8f1ef0b1
import spandsp-0.0.6pre17
author | Peter Meerwald <pmeerw@cosy.sbg.ac.at> |
---|---|
date | Fri, 25 Jun 2010 15:50:58 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
3:c6c5a16ce2f2 | 4:26cd8f1ef0b1 |
---|---|
1 /* | |
2 * SpanDSP - a series of DSP components for telephony | |
3 * | |
4 * bit_operations.c - Various bit level operations, such as bit reversal | |
5 * | |
6 * Written by Steve Underwood <steveu@coppice.org> | |
7 * | |
8 * Copyright (C) 2006 Steve Underwood | |
9 * | |
10 * All rights reserved. | |
11 * | |
12 * This program is free software; you can redistribute it and/or modify | |
13 * it under the terms of the GNU Lesser General Public License version 2.1, | |
14 * as published by the Free Software Foundation. | |
15 * | |
16 * This program is distributed in the hope that it will be useful, | |
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 * GNU Lesser General Public License for more details. | |
20 * | |
21 * You should have received a copy of the GNU Lesser General Public | |
22 * License along with this program; if not, write to the Free Software | |
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
24 * | |
25 * $Id: bit_operations.c,v 1.16 2009/02/03 16:28:39 steveu Exp $ | |
26 */ | |
27 | |
28 /*! \file */ | |
29 | |
30 #if defined(HAVE_CONFIG_H) | |
31 #include "config.h" | |
32 #endif | |
33 | |
34 #include <inttypes.h> | |
35 #include <stdlib.h> | |
36 #include <fcntl.h> | |
37 #include <string.h> | |
38 #include <assert.h> | |
39 #include <memory.h> | |
40 | |
41 #include "spandsp/telephony.h" | |
42 #include "spandsp/bit_operations.h" | |
43 | |
44 SPAN_DECLARE(uint16_t) bit_reverse16(uint16_t x) | |
45 { | |
46 x = (x >> 8) | (x << 8); | |
47 x = ((x & 0xF0F0) >> 4) | ((x & 0x0F0F) << 4); | |
48 x = ((x & 0xCCCC) >> 2) | ((x & 0x3333) << 2); | |
49 return ((x & 0xAAAA) >> 1) | ((x & 0x5555) << 1); | |
50 } | |
51 /*- End of function --------------------------------------------------------*/ | |
52 | |
53 SPAN_DECLARE(uint32_t) bit_reverse32(uint32_t x) | |
54 { | |
55 x = (x >> 16) | (x << 16); | |
56 x = ((x & 0xFF00FF00) >> 8) | ((x & 0x00FF00FF) << 8); | |
57 x = ((x & 0xF0F0F0F0) >> 4) | ((x & 0x0F0F0F0F) << 4); | |
58 x = ((x & 0xCCCCCCCC) >> 2) | ((x & 0x33333333) << 2); | |
59 return ((x & 0xAAAAAAAA) >> 1) | ((x & 0x55555555) << 1); | |
60 } | |
61 /*- End of function --------------------------------------------------------*/ | |
62 | |
63 SPAN_DECLARE(uint32_t) bit_reverse_4bytes(uint32_t x) | |
64 { | |
65 x = ((x & 0xF0F0F0F0) >> 4) | ((x & 0x0F0F0F0F) << 4); | |
66 x = ((x & 0xCCCCCCCC) >> 2) | ((x & 0x33333333) << 2); | |
67 return ((x & 0xAAAAAAAA) >> 1) | ((x & 0x55555555) << 1); | |
68 } | |
69 /*- End of function --------------------------------------------------------*/ | |
70 | |
71 #if defined(__x86_64__) | |
72 SPAN_DECLARE(uint64_t) bit_reverse_8bytes(uint64_t x) | |
73 { | |
74 x = ((x & 0xF0F0F0F0F0F0F0F0LLU) >> 4) | ((x & 0x0F0F0F0F0F0F0F0FLLU) << 4); | |
75 x = ((x & 0xCCCCCCCCCCCCCCCCLLU) >> 2) | ((x & 0x3333333333333333LLU) << 2); | |
76 return ((x & 0xAAAAAAAAAAAAAAAALLU) >> 1) | ((x & 0x5555555555555555LLU) << 1); | |
77 } | |
78 /*- End of function --------------------------------------------------------*/ | |
79 #endif | |
80 | |
81 SPAN_DECLARE(void) bit_reverse(uint8_t to[], const uint8_t from[], int len) | |
82 { | |
83 #if defined(SPANDSP_MISALIGNED_ACCESS_FAILS) | |
84 int i; | |
85 #else | |
86 const uint8_t *y1; | |
87 uint8_t *z1; | |
88 const uint32_t *y4; | |
89 uint32_t *z4; | |
90 uint32_t x4; | |
91 #if defined(__x86_64__) | |
92 const uint64_t *y8; | |
93 uint64_t *z8; | |
94 uint64_t x8; | |
95 #endif | |
96 #endif | |
97 | |
98 #if defined(SPANDSP_MISALIGNED_ACCESS_FAILS) | |
99 /* This code works byte by byte, so it works on machines where misalignment | |
100 is either desperately slow (its a bit slow on practically any machine, but | |
101 some machines make it desparately slow) or fails. */ | |
102 for (i = 0; i < len; i++) | |
103 to[i] = bit_reverse8(from[i]); | |
104 #else | |
105 /* This code is this is based on the woolly assumption that the start of the buffers | |
106 is memory aligned. If it isn't, the routine will be less efficient on some machines, | |
107 but might not work at all on others. */ | |
108 #if defined(__x86_64__) | |
109 y8 = (const uint64_t *) from; | |
110 z8 = (uint64_t *) to; | |
111 while (len >= sizeof(uint64_t)) | |
112 { | |
113 x8 = *y8++; | |
114 x8 = ((x8 & 0xF0F0F0F0F0F0F0F0LLU) >> 4) | ((x8 & 0x0F0F0F0F0F0F0F0FLLU) << 4); | |
115 x8 = ((x8 & 0xCCCCCCCCCCCCCCCCLLU) >> 2) | ((x8 & 0x3333333333333333LLU) << 2); | |
116 *z8++ = ((x8 & 0xAAAAAAAAAAAAAAAALLU) >> 1) | ((x8 & 0x5555555555555555LLU) << 1); | |
117 len -= sizeof(uint64_t); | |
118 } | |
119 y4 = (const uint32_t *) y8; | |
120 z4 = (uint32_t *) z8; | |
121 #else | |
122 y4 = (const uint32_t *) from; | |
123 z4 = (uint32_t *) to; | |
124 #endif | |
125 while (len >= sizeof(uint32_t)) | |
126 { | |
127 x4 = *y4++; | |
128 x4 = ((x4 & 0xF0F0F0F0) >> 4) | ((x4 & 0x0F0F0F0F) << 4); | |
129 x4 = ((x4 & 0xCCCCCCCC) >> 2) | ((x4 & 0x33333333) << 2); | |
130 *z4++ = ((x4 & 0xAAAAAAAA) >> 1) | ((x4 & 0x55555555) << 1); | |
131 len -= sizeof(uint32_t); | |
132 } | |
133 y1 = (const uint8_t *) y4; | |
134 z1 = (uint8_t *) z4; | |
135 while (len-- > 0) | |
136 *z1++ = bit_reverse8(*y1++); | |
137 #endif | |
138 } | |
139 /*- End of function --------------------------------------------------------*/ | |
140 | |
141 SPAN_DECLARE(int) one_bits32(uint32_t x) | |
142 { | |
143 x = x - ((x >> 1) & 0x55555555); | |
144 /* We now have 16 2-bit counts */ | |
145 x = (x & 0x33333333) + ((x >> 2) & 0x33333333); | |
146 /* We now have 8 4-bit counts */ | |
147 x = (x + (x >> 4)) & 0x0F0F0F0F; | |
148 /* We now have 4 8-bit counts */ | |
149 #if defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || defined(__powerpc__) | |
150 /* If multiply is fast */ | |
151 return (x*0x01010101) >> 24; | |
152 #else | |
153 /* If multiply is slow */ | |
154 x += (x >> 8); | |
155 x += (x >> 16); | |
156 return (x & 0x0000003F); | |
157 #endif | |
158 } | |
159 /*- End of function --------------------------------------------------------*/ | |
160 | |
161 SPAN_DECLARE(uint32_t) make_mask32(uint32_t x) | |
162 { | |
163 x |= (x >> 1); | |
164 x |= (x >> 2); | |
165 x |= (x >> 4); | |
166 x |= (x >> 8); | |
167 x |= (x >> 16); | |
168 return x; | |
169 } | |
170 /*- End of function --------------------------------------------------------*/ | |
171 | |
172 SPAN_DECLARE(uint16_t) make_mask16(uint16_t x) | |
173 { | |
174 x |= (x >> 1); | |
175 x |= (x >> 2); | |
176 x |= (x >> 4); | |
177 x |= (x >> 8); | |
178 return x; | |
179 } | |
180 /*- End of function --------------------------------------------------------*/ | |
181 /*- End of file ------------------------------------------------------------*/ |