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 ------------------------------------------------------------*/

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.