1 // ==========================================================================
2 //                 SeqAn - The Library for Sequence Analysis
3 // ==========================================================================
4 // Copyright (c) 2006-2018, Knut Reinert, FU Berlin
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are met:
9 //
10 //     * Redistributions of source code must retain the above copyright
11 //       notice, this list of conditions and the following disclaimer.
12 //     * Redistributions in binary form must reproduce the above copyright
13 //       notice, this list of conditions and the following disclaimer in the
14 //       documentation and/or other materials provided with the distribution.
15 //     * Neither the name of Knut Reinert or the FU Berlin nor the names of
16 //       its contributors may be used to endorse or promote products derived
17 //       from this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
23 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
29 // DAMAGE.
30 //
31 // ==========================================================================
32 // Author: Andreas Gogol-Doering <andreas.doering@mdc-berlin.de>
33 // Author: Manuel Holtgrewe <manuel.holtgrewe@fu-berlin.de>
34 // ==========================================================================
35 // Storage-related alphabet interface part.  This means both
36 // construction type (simple, non-simple) and storage size.
37 // ==========================================================================
38 
39 #ifndef SEQAN_INCLUDE_SEQAN_BASIC_ALPHABET_STORAGE_H_
40 #define SEQAN_INCLUDE_SEQAN_BASIC_ALPHABET_STORAGE_H_
41 
42 #include <float.h>
43 
44 namespace seqan {
45 
46 // ============================================================================
47 // Forwards
48 // ============================================================================
49 
50 template <typename TValue, typename TSpec>
51 class SimpleType;
52 
53 // ============================================================================
54 // Tags, Classes, Enums
55 // ============================================================================
56 
57 // ============================================================================
58 // Metafunctions
59 // ============================================================================
60 
61 // ----------------------------------------------------------------------------
62 // Metafunction BitsPerValue
63 // ----------------------------------------------------------------------------
64 
65 template <typename TValue>
66 struct BitsPerValue
67 {
68     static const unsigned VALUE = sizeof(TValue) * 8;
69     typedef unsigned Type;
70 };
71 
72 template <typename TValue>
73 struct BitsPerValue<TValue const> : public BitsPerValue<TValue>
74 {};
75 
76 // template <typename TValue>
77 // const unsigned BitsPerValue<TValue>::VALUE = ;
78 
79 // ----------------------------------------------------------------------------
80 // Metafunction ValueSize
81 // ----------------------------------------------------------------------------
82 
83 // TODO(holtgrew): Enable default implementation only for integers? Move to adapt builtins?
84 
85 template <typename T>
86 struct ValueSize
87 {
88     typedef uint64_t  Type;
89     static const Type VALUE = (BitsPerValue<T>::VALUE < 64)? 1ull << (BitsPerValue<T>::VALUE & 63) : 0ull;
90 };
91 
92 template <typename T>
93 struct ValueSize<T const> : ValueSize<T>
94 {};
95 
96 // TODO(holtgrew): Use static assertion to make sure that ValueSize is never called on floating point numbers? Include assertion for int64_t and uint64_t?
97 
98 template <>
99 struct ValueSize<int64_t>
100 {
101     typedef uint64_t  Type;
102     static const Type VALUE = 0;
103 };
104 
105 template <>
106 struct ValueSize<uint64_t>
107 {
108     typedef uint64_t  Type;
109     static const Type VALUE = 0;
110 };
111 
112 template <>
113 struct ValueSize<double>
114 {
115     typedef uint64_t  Type;
116     static const Type VALUE = 0;
117 };
118 
119 template <>
120 struct ValueSize<float>
121 {
122     typedef uint64_t  Type;
123     static const Type VALUE = 0;
124 };
125 
126 
127 // The internal value size is used for alphabets with piggyback qualities,
128 // for example Dna5Q.  Here, the public value size is 5 but the internal
129 // value size is 256.
130 
131 template <typename TValue>
132 struct InternalValueSize_
133         : public ValueSize<TValue>
134 {};
135 
136 // ----------------------------------------------------------------------------
137 // Metafunction BytesPerValue
138 // ----------------------------------------------------------------------------
139 
140 /*!
141  * @mfn BytesPerValue
142  * @headerfile <seqan/basic.h>
143  * @brief Number of bytes needed to store a value.
144  *
145  * @signature BytesPerValue<T>::VALUE
146  *
147  * @tparam T The type to query.
148  *
149  * @return VALUE The number of bytes to store on T object.
150  *
151  * By default, this function returns <tt>ceil(BitsPerValue&lt;T&gt;::VALUE)</tt>.  For built-in types, this is the same
152  * as <tt>sizeof(T)</tt>.
153  *
154  * @see FiniteOrderedAlphabetConcept#ValueSize
155  * @see AlphabetConcept#BitsPerValue
156  * @see IntegralForValue
157  */
158 
159 template <typename TValue>
160 struct BytesPerValue
161 {
162     enum { VALUE = (BitsPerValue<TValue>::VALUE + 7) / 8 };
163 };
164 
165 // ----------------------------------------------------------------------------
166 // Metafunction IntegralForValue
167 // ----------------------------------------------------------------------------
168 
169 /*!
170  * @mfn IntegralForValue
171  * @headerfile <seqan/basic.h>
172  * @brief Returns an itegral type that provides sufficient space to store a value.
173  *
174  * @signature IntegralForValue<T>::Type;
175  *
176  * @tparam T The type to query.
177  *
178  * @return Type An integral type.
179  *
180  * The type is the smallest unsigned integral type that has a size of at least BytesPerValue bytes.
181  *
182  * <table>
183  *   <tr>
184  *     <th>sizeof(T) in bytes</th>
185  *     <th>integral types</th>
186  *   </tr>
187  *   <tr>
188  *     <td>1</td>
189  *     <td><tt>unsigned char</tt></td>
190  *   </tr>
191  *   <tr>
192  *     <td>2</td>
193  *     <td><tt>unsigned short</tt></td>
194  *   </tr>
195  *   <tr>
196  *     <td>3</td>
197  *     <td><tt>unsigned int</tt></td>
198  *   </tr>
199  *   <tr>
200  *     <td>4</td>
201  *     <td><tt>unsigned int</tt></td>
202  *   </tr>
203  *   <tr>
204  *     <td>&gt; 4</td>
205  *     <td><tt>int64_t</tt></td>
206  *   </tr>
207  * </table>
208  *
209  * Note that the returned integral type cannot store <tt>T</tt> values, if <tt>T</tt> takes more than 8 bytes, since
210  * there exists no integral type that provides sufficient space to store types of this size.
211  *
212  * @see FiniteOrderedAlphabetConcept#ValueSize
213  * @see AlphabetConcept#BitsPerValue
214  * @see BytesPerValue
215  */
216 
217 template <int SIZE>
218 struct IntegralForValueImpl_
219 {
220     typedef int64_t Type;
221 };
222 
223 // TODO(holtgrew): Switch to uint8_t, uint16_t, uint32_t?
224 template <>
225 struct IntegralForValueImpl_<1>
226 {
227     typedef unsigned char Type;
228 };
229 
230 template <>
231 struct IntegralForValueImpl_<2>
232 {
233     typedef unsigned short Type;
234 };
235 
236 template <>
237 struct IntegralForValueImpl_<3>
238 {
239     typedef unsigned int Type;
240 };
241 
242 template <>
243 struct IntegralForValueImpl_<4>
244 {
245     typedef unsigned int Type;
246 };
247 
248 template <typename TValue>
249 struct IntegralForValue : IntegralForValueImpl_<BytesPerValue<TValue>::VALUE>
250 {};
251 
252 // ============================================================================
253 // Functions
254 // ============================================================================
255 
256 // ----------------------------------------------------------------------------
257 // Function ordValue()
258 // ----------------------------------------------------------------------------
259 
260 // TODO(holtgrew): Enable only for integers, move to adapt builtins?
261 
262 template <typename TValue>
263 inline typename ValueSize<TValue>::Type
264 ordValue(TValue const & c)
265 {
266     return convert<unsigned>(static_cast<typename MakeUnsigned_<TValue>::Type const &>(c));
267 }
268 
269 // The internal ord value is used for alphabets with piggyback qualities.
270 
271 template <typename TValue>
272 inline typename ValueSize<TValue>::Type
273 _internalOrdValue(TValue const & c)
274 {
275     return ordValue(c);
276 }
277 
278 // ----------------------------------------------------------------------------
279 // Function valueSize<T>()
280 // ----------------------------------------------------------------------------
281 
282 template <typename T>
283 inline typename ValueSize<T>::Type
284 valueSize()
285 {
286     return +ValueSize<T>::VALUE;
287 }
288 
289 }  // namespace seqan
290 
291 #endif  // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_ALPHABET_STORAGE_H_
292