NVBIO
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
vectorized_string.h
Go to the documentation of this file.
1 /*
2  * nvbio
3  * Copyright (c) 2011-2014, NVIDIA CORPORATION. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the NVIDIA CORPORATION nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #pragma once
29 
30 #include <nvbio/basic/types.h>
35 #include <nvbio/strings/string.h>
36 #include <string.h>
37 
38 
39 namespace nvbio {
40 
43 
101 
104 
107 template <typename string_type>
109 {
111 
112  static const uint32 VECTOR_WIDTH = 1u;
113 
116  template <uint32 VECTOR_WIDTH_T>
118  static uint2 range(const string_type& string)
119  {
120  const uint32 rounded_length = (uint32)util::round_z( length( string ), VECTOR_WIDTH_T );
121  return make_uint2( 0, rounded_length );
122  }
123 
126  template <uint32 VECTOR_WIDTH_T>
128  static void load(
129  const string_type& string,
130  const uint32 offset,
132  {
133  // fill the vector with a simple loop
134  #pragma unroll
135  for (uint32 j = 0; j < VECTOR_WIDTH_T; ++j)
136  vector[j] = string[offset + j];
137  }
138 
142  static uint2 range(const string_type& string)
143  {
144  return range<VECTOR_WIDTH>( string );
145  }
146 
150  static void load(
151  const string_type& string,
152  const uint32 offset,
154  {
155  load<VECTOR_WIDTH>( string, offset, vector );
156  }
157 };
158 
161 template <typename string_type>
163 uint2 vectorized_string_range(const string_type& string)
164 {
165  return vectorized_string<string_type>::range( string );
166 }
167 
170 template <typename string_type>
172 void vectorized_string_load(const string_type& string, const uint32 i, typename string_traits<string_type>::value_type* vector)
173 {
174  vectorized_string<string_type>::load( string, i, vector );
175 }
176 
177 //
178 // --- const char* specialization------------------------------------------------------------------------
179 //
180 
183 template <>
185 {
186  typedef const char* string_type;
187  typedef char value_type;
189 
190  static const uint32 VECTOR_WIDTH = maximum_vector_width<char>::VALUE;
191 
194  template <uint32 VECTOR_WIDTH_T>
196  static uint2 range(const char* string)
197  {
198  const uint64 offset = uint64( string ) % VECTOR_WIDTH_T;
199  const uint64 len = length( string );
200 
201  const uint64 aligned_begin = util::round_i( offset, VECTOR_WIDTH );
202  const uint64 aligned_end = util::round_z( offset + len, VECTOR_WIDTH );
203 
204  return aligned_begin < aligned_end ?
205  make_uint2( aligned_begin - offset, aligned_end - offset ) :
206  make_uint2( len, len );
207  }
208 
211  template <uint32 VECTOR_WIDTH_T>
213  static void load(
214  const char* string,
215  const uint32 offset,
216  char* vector)
217  {
218  const char* base_ptr = string + offset;
219  vector_load<VECTOR_WIDTH_T>( base_ptr, vector );
220  }
221 
225  static uint2 range(const char* string)
226  {
227  return range<VECTOR_WIDTH>( string );
228  }
229 
233  static void load(
234  const char* string,
235  const uint32 offset,
236  char* vector)
237  {
238  load<VECTOR_WIDTH>( string, offset, vector );
239  }
240 };
241 
242 //
243 // --- vector_view<const T*> specialization------------------------------------------------------------------------
244 //
245 
248 template <typename T, typename IndexType>
249 struct vectorized_string< vector_view<const T*,IndexType> >
250 {
252  typedef T value_type;
253  typedef IndexType index_type;
254 
255  static const uint32 VECTOR_WIDTH = maximum_vector_width<T>::VALUE;
256 
259  template <uint32 VECTOR_WIDTH_T>
261  static uint2 range(const string_type& string)
262  {
263  const uint64 offset = (uint64(string.base()) / sizeof(T)) % VECTOR_WIDTH_T;
264 
265  const uint64 aligned_begin = util::round_i( offset, VECTOR_WIDTH );
266  const uint64 aligned_end = util::round_z( offset + string.size(), VECTOR_WIDTH );
267 
268  return aligned_begin < aligned_end ?
269  make_uint2( aligned_begin - offset, aligned_end - offset ) :
270  make_uint2( string.size(), string.size() );
271  }
272 
275  template <uint32 VECTOR_WIDTH_T>
277  static void load(
278  const string_type& string,
279  const uint32 offset,
280  T* vector)
281  {
282  const T* base_ptr = string.base() + offset;
283  vector_load<VECTOR_WIDTH_T>( base_ptr, vector );
284  }
285 
289  static uint2 range(const string_type& string)
290  {
291  return range<VECTOR_WIDTH>( string );
292  }
293 
297  static void load(
298  const string_type& string,
299  const uint32 offset,
300  T* vector)
301  {
302  load<VECTOR_WIDTH>( string, offset, vector );
303  }
304 };
305 
306 //
307 // --- vector_view< PackedStream > specialization---------------------------------------------------------------------
308 //
309 
312 template <typename InputStream, typename Symbol, uint32 SYMBOL_SIZE_T, bool BIG_ENDIAN_T, typename IndexType>
313 struct vectorized_string< vector_view< PackedStream<InputStream,Symbol,SYMBOL_SIZE_T,BIG_ENDIAN_T,IndexType> > >
314 {
316  typedef Symbol value_type;
317  typedef IndexType index_type;
319  typedef InputStream storage_iterator;
321 
322  static const uint32 SYMBOL_SIZE = SYMBOL_SIZE_T;
323  static const uint32 SYMBOL_COUNT = 1u << SYMBOL_SIZE_T;
324  static const uint32 VECTOR_WIDTH = packed_stream_type::VECTOR_WIDTH;
325 
329  static uint2 range(const string_type& string)
330  {
331  const index_type offset = string.base().index();
332 
333  const index_type aligned_begin = util::round_i( offset, VECTOR_WIDTH );
334  const index_type aligned_end = util::round_z( offset + string.size(), VECTOR_WIDTH );
335 
336  return aligned_begin < aligned_end ?
337  make_uint2( aligned_begin - offset, aligned_end - offset ) :
338  make_uint2( string.size(), string.size() );
339  }
340 
344  static void load(
345  const string_type& string,
346  const uint32 offset,
348  {
349  const storage_iterator storage = string.base().stream();
350 
351  // find the proper word containing the vector we are after
352  const index_type word_idx = (string.base().index() + offset) / VECTOR_WIDTH;
353 
354  const storage_type word = storage[ word_idx ];
355 
356  // unpack the entire word
357  if (BIG_ENDIAN_T)
358  {
359  const uint32 SYMBOL_OFFSET = (VECTOR_WIDTH-1) * SYMBOL_SIZE;
360 
361  #pragma unroll
362  for (uint32 j = 0; j < VECTOR_WIDTH; ++j)
363  vector[j] = (word >> (SYMBOL_OFFSET - SYMBOL_SIZE * j)) & (SYMBOL_COUNT-1);
364  }
365  else
366  {
367  #pragma unroll
368  for (uint32 j = 0; j < VECTOR_WIDTH; ++j)
369  vector[j] = (word >> (SYMBOL_SIZE * j)) & (SYMBOL_COUNT-1);
370  }
371  }
372 };
373 
376 
377 } // namespace nvbio