1/* -*- c++ -*- */
2/*
3 * Copyright (C) 2010 The Android Open Source Project
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *  * Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 *  * Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in
13 *    the documentation and/or other materials provided with the
14 *    distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
23 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#ifndef ANDROID_ASTL_LIMITS__
31#define ANDROID_ASTL_LIMITS__
32
33#include <limits.h>
34// GNU C++ compiler?
35#ifndef __GNUG__
36#error "__GNUG__ is not defined"
37#endif
38
39#ifdef _T
40#error "_T is defined"
41#endif
42
43// This is very incomplete partial implementation of the standard
44// <limits>. Only partial support for float and double is provided.
45
46namespace {
47// Template to return the number of decimal digits in a number
48// representation based on the number of bits and sign.
49// e.g  digits10<int,64,true>::value == 19
50template<typename T, T bits, bool is_signed> struct digits10 {
51    static const int value = 0;
52};
53
54// Specialization that can be used to initialize static constant at
55// compile time.
56template<> struct digits10<int,  8, false> { static const int value = 3; };
57template<> struct digits10<int,  8, true>  { static const int value = 3; };
58template<> struct digits10<int, 16, false> { static const int value = 5; };
59template<> struct digits10<int, 16, true>  { static const int value = 5; };
60template<> struct digits10<int, 32, false> { static const int value = 10; };
61template<> struct digits10<int, 32, true>  { static const int value = 10; };
62template<> struct digits10<int, 64, false> { static const int value = 20; };
63template<> struct digits10<int, 64, true>  { static const int value = 19; };
64}
65
66namespace std {
67
68struct __numeric_limits_base
69{
70    // True for all fundamental types.
71    static const bool is_specialized = false;
72
73    // True if the type is signed.
74    static const bool is_signed = false;
75
76    // True if the type is integer.
77    static const bool is_integer = false;
78
79    // The number of radix digits that be represented without change. For
80    // integer types, the number of non-sign bits in the representation; for
81    // floating-point types, the number of radix digits in the mantissa.
82    // Equivalent to FLT_MANT_DIG, DBL_MANT_DIG.
83    static const int digits = 0;
84
85    // The number of base 10 digits that can be represented without change.
86    // Equivalent to FLT_DIG, DBL_DIG, LDBL_MANT_DIG.
87    static const int digits10 = 0;
88};
89
90
91// Properties of fundamental types.
92// Only a subset of the properties is supported.
93template<typename _T>
94struct numeric_limits : public __numeric_limits_base
95{
96    // The minimum finite value.
97    static _T min() { return static_cast<_T>(0); }
98
99    // The maximum finite value.
100    static _T max() { return static_cast<_T>(0); }
101};
102
103// Specializations for some fundamental types.
104
105// numeric_limits<float>
106template<>
107struct numeric_limits<float>
108{
109    static const bool is_specialized = true;
110
111    static float min() { return __FLT_MIN__; }
112    static float max() { return __FLT_MAX__; }
113
114    static const bool is_signed = true;
115    static const bool is_integer = false;
116
117    static const int digits = __FLT_MANT_DIG__;
118    static const int digits10 = __FLT_DIG__;
119};
120
121// numeric_limits<double>
122template<>
123struct numeric_limits<double>
124{
125    static const bool is_specialized = true;
126
127    static double min() { return __DBL_MIN__; }
128    static double max() { return __DBL_MAX__; }
129
130    static const bool is_signed = true;
131    static const bool is_integer = false;
132
133    static const int digits = __DBL_MANT_DIG__;
134    static const int digits10 = __DBL_DIG__;
135};
136
137// numeric_limits<int>
138template<>
139struct numeric_limits<int>
140{
141    static const bool is_specialized = true;
142
143    static int min() { return INT_MIN; }
144    static int max() { return INT_MAX; }
145
146    static const bool is_signed = true;
147    static const bool is_integer = true;
148
149    static const int digits = static_cast<int>(sizeof(int) * CHAR_BIT);
150    static const int digits10 = digits10<int, digits, is_signed>::value;
151};
152
153// numeric_limits<unsigned int>
154template<>
155struct numeric_limits<unsigned int>
156{
157    static const bool is_specialized = true;
158
159    static unsigned int min() { return 0; }
160    static unsigned int max() { return UINT_MAX; }
161
162    static const bool is_signed = false;
163    static const bool is_integer = true;
164
165    static const int digits = static_cast<int>(sizeof(unsigned int) * CHAR_BIT);
166    static const int digits10 = digits10<int, digits, is_signed>::value;
167};
168
169// numeric_limits<long>
170template<>
171struct numeric_limits<long>
172{
173    static const bool is_specialized = true;
174
175    static long min() { return LONG_MIN; }
176    static long max() { return LONG_MAX; }
177
178    static const bool is_signed = true;
179    static const bool is_integer = true;
180
181    static const int digits = LONG_BIT;
182    static const int digits10 = digits10<int, digits, is_signed>::value;
183};
184
185// numeric_limits<unsigned long>
186template<>
187struct numeric_limits<unsigned long>
188{
189    static const bool is_specialized = true;
190
191    static unsigned long min() { return 0; }
192    static unsigned long max() { return ULONG_MAX; }
193
194    static const bool is_signed = true;
195    static const bool is_integer = true;
196
197    static const int digits = LONG_BIT;
198    static const int digits10 = digits10<int, digits, is_signed>::value;
199};
200
201// numeric_limits<long long>
202template<>
203struct numeric_limits<long long>
204{
205    static const bool is_specialized = true;
206
207    static long long min() { return LLONG_MIN; }
208    static long long max() { return LLONG_MAX; }
209
210    static const bool is_signed = true;
211    static const bool is_integer = true;
212
213    static const int digits = static_cast<int>(sizeof(long long) * CHAR_BIT);
214    static const int digits10 = digits10<int, digits, is_signed>::value;
215};
216
217// numeric_limits<unsigned long long>
218template<>
219struct numeric_limits<unsigned long long>
220{
221    static const bool is_specialized = true;
222
223    static unsigned long long min() { return 0; }
224    static unsigned long long max() { return ULLONG_MAX; }
225
226    static const bool is_signed = true;
227    static const bool is_integer = true;
228
229    static const int digits = static_cast<int>(sizeof(unsigned long long) * CHAR_BIT);
230    static const int digits10 = digits10<int, digits, is_signed>::value;
231};
232
233}  // namespace std
234
235
236#endif
237