1 /*
2 * Copyright 2006-2008 The FLWOR Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "stdafx.h"
18
19 #include <cerrno>
20 #include <cstdlib>
21
22 #include "util/cxx_util.h"
23 #include "util/string_util.h"
24
25 #include "integer.h"
26 #include "decimal.h"
27 #include "floatimpl.h"
28 #include "numconversions.h"
29
30 #ifdef ZORBA_WITH_BIG_INTEGER
31 # define TEMPLATE_DECL(T) /* nothing */
32 # define INTEGER_IMPL(T) IntegerImpl
33 #else
34 # define TEMPLATE_DECL(T) template<typename T> /* spacer */
35 # define INTEGER_IMPL(T) IntegerImpl<T> /* spacer */
36 #endif /* ZORBA_WITH_BIG_INTEGER */
37 #define INTEGER_IMPL_LL INTEGER_IMPL(long long)
38 #define INTEGER_IMPL_ULL INTEGER_IMPL(unsigned long long)
39
40 using namespace std;
41
42 #ifndef ZORBA_WITH_BIG_INTEGER
43 unsigned long long MaxUIntegerValue = ~0ull >> 1;
44
is_too_big(long long)45 inline bool is_too_big( long long ) {
46 return false;
47 }
48
is_too_big(unsigned long long n)49 inline bool is_too_big( unsigned long long n ) {
50 return n > MaxUIntegerValue;
51 }
52 #endif /* ZORBA_WITH_BIG_INTEGER */
53
54 namespace zorba {
55
56 ///////////////////////////////////////////////////////////////////////////////
57
TEMPLATE_DECL(I)58 TEMPLATE_DECL(I)
59 void INTEGER_IMPL(I)::parse( char const *s ) {
60 #ifdef ZORBA_WITH_BIG_INTEGER
61 Decimal::parse( s, &value_, Decimal::parse_integer );
62 #else
63 value_type const temp( ztd::aton<value_type>( s ) );
64 if ( is_too_big( temp ) )
65 throw std::invalid_argument(
66 BUILD_STRING( '"', temp, "\": unsigned integer too big" )
67 );
68 value_ = temp;
69 #endif /* ZORBA_WITH_BIG_INTEGER */
70 }
71
72 ////////// constructors ///////////////////////////////////////////////////////
73
74 #ifdef ZORBA_WITH_BIG_INTEGER
IntegerImpl(long long n)75 IntegerImpl::IntegerImpl( long long n ) {
76 ztd::itoa_buf_type buf;
77 value_ = ztd::itoa( n, buf );
78 }
79
IntegerImpl(unsigned long n)80 IntegerImpl::IntegerImpl( unsigned long n ) {
81 ztd::itoa_buf_type buf;
82 value_ = ztd::itoa( n, buf );
83 }
84
IntegerImpl(unsigned long long n)85 IntegerImpl::IntegerImpl( unsigned long long n ) {
86 ztd::itoa_buf_type buf;
87 value_ = ztd::itoa( n, buf );
88 }
89 #endif /* ZORBA_WITH_BIG_INTEGER */
90
91 TEMPLATE_DECL(T)
INTEGER_IMPL(T)92 INTEGER_IMPL(T)::IntegerImpl( Decimal const &d ) {
93 value_ = ftoi( d.value_ );
94 }
95
96 TEMPLATE_DECL(T)
INTEGER_IMPL(T)97 INTEGER_IMPL(T)::IntegerImpl( Double const &d ) {
98 if ( !d.isFinite() )
99 throw std::invalid_argument( "not finite" );
100 value_ = ftoi( d.getNumber() );
101 }
102
103 TEMPLATE_DECL(T)
INTEGER_IMPL(T)104 INTEGER_IMPL(T)::IntegerImpl( Float const &f ) {
105 if ( !f.isFinite() )
106 throw std::invalid_argument( "not finite" );
107 value_ = ftoi( f.getNumber() );
108 }
109
110 ////////// assignment operators ///////////////////////////////////////////////
111
112 #ifdef ZORBA_WITH_BIG_INTEGER
operator =(long long n)113 IntegerImpl& IntegerImpl::operator=( long long n ) {
114 ztd::itoa_buf_type buf;
115 value_ = ztd::itoa( n, buf );
116 return *this;
117 }
118
operator =(unsigned long n)119 IntegerImpl& IntegerImpl::operator=( unsigned long n ) {
120 ztd::itoa_buf_type buf;
121 value_ = ztd::itoa( n, buf );
122 return *this;
123 }
124
operator =(unsigned long long n)125 IntegerImpl& IntegerImpl::operator=( unsigned long long n ) {
126 ztd::itoa_buf_type buf;
127 value_ = ztd::itoa( n, buf );
128 return *this;
129 }
130 #endif /* ZORBA_WITH_BIG_INTEGER */
131
132 TEMPLATE_DECL(T)
INTEGER_IMPL(T)133 INTEGER_IMPL(T)& INTEGER_IMPL(T)::operator=( Decimal const &d ) {
134 value_ = ftoi( d.value_ );
135 return *this;
136 }
137
138 TEMPLATE_DECL(T)
INTEGER_IMPL(T)139 INTEGER_IMPL(T)& INTEGER_IMPL(T)::operator=( Double const &d ) {
140 if ( !d.isFinite() )
141 throw std::invalid_argument( "not finite" );
142 value_ = ftoi( d.getNumber() );
143 return *this;
144 }
145
146 TEMPLATE_DECL(T)
INTEGER_IMPL(T)147 INTEGER_IMPL(T)& INTEGER_IMPL(T)::operator=( Float const &f ) {
148 if ( !f.isFinite() )
149 throw std::invalid_argument( "not finite" );
150 value_ = ftoi( f.getNumber() );
151 return *this;
152 }
153
154 ////////// arithmetic operators ///////////////////////////////////////////////
155
156 #ifdef ZORBA_WITH_BIG_INTEGER
157 # define ZORBA_INSTANTIATE(OP) /* nothing */
158 #else
159 # define ZORBA_INSTANTIATE(OP) \
160 template Decimal operator OP( INTEGER_IMPL_LL const&, Decimal const& ); \
161 template Decimal operator OP( INTEGER_IMPL_ULL const&, Decimal const& );
162 #endif /* ZORBA_WITH_BIG_INTEGER */
163
164 #define ZORBA_INTEGER_OP(OP) \
165 TEMPLATE_DECL(T) \
166 Decimal operator OP( INTEGER_IMPL(T) const &i, Decimal const &d ) { \
167 return i.itod() OP d.value_; \
168 } \
169 ZORBA_INSTANTIATE(OP)
170
171 ZORBA_INTEGER_OP(+)
172 ZORBA_INTEGER_OP(-)
173 ZORBA_INTEGER_OP(*)
174 ZORBA_INTEGER_OP(/)
175 ZORBA_INTEGER_OP(%)
176 #undef ZORBA_INTEGER_OP
177 #undef ZORBA_INSTANTIATE
178
179 #ifdef ZORBA_WITH_BIG_INTEGER
180
181 #define ZORBA_INTEGER_OP(OP,T) \
182 IntegerImpl operator OP( IntegerImpl const &i, T n ) { \
183 ztd::itoa_buf_type buf; \
184 return i.value_ OP IntegerImpl::value_type( ztd::itoa( n, buf ) ); \
185 } \
186 IntegerImpl operator OP( T n, IntegerImpl const &i ) { \
187 ztd::itoa_buf_type buf; \
188 return IntegerImpl::value_type( ztd::itoa( n, buf ) ) OP i.value_; \
189 }
190
191 ZORBA_INTEGER_OP(+,long long)
192 ZORBA_INTEGER_OP(-,long long)
193 ZORBA_INTEGER_OP(*,long long)
194 ZORBA_INTEGER_OP(%,long long)
195 ZORBA_INTEGER_OP(+,unsigned long)
196 ZORBA_INTEGER_OP(-,unsigned long)
197 ZORBA_INTEGER_OP(*,unsigned long)
198 ZORBA_INTEGER_OP(%,unsigned long)
199 ZORBA_INTEGER_OP(+,unsigned long long)
200 ZORBA_INTEGER_OP(-,unsigned long long)
201 ZORBA_INTEGER_OP(*,unsigned long long)
202 ZORBA_INTEGER_OP(%,unsigned long long)
203 #undef ZORBA_INTEGER_OP
204
205 #define ZORBA_INTEGER_OP(T) \
206 IntegerImpl operator/( IntegerImpl const &i, T n ) { \
207 ztd::itoa_buf_type buf; \
208 IntegerImpl::value_type const temp( ztd::itoa( n, buf ) ); \
209 return IntegerImpl::ftoi( i.value_ / temp ); \
210 } \
211 IntegerImpl operator/( T n, IntegerImpl const &i ) { \
212 ztd::itoa_buf_type buf; \
213 IntegerImpl::value_type const temp( ztd::itoa( n, buf ) ); \
214 return IntegerImpl::ftoi( temp / i.value_ ); \
215 }
216
217 ZORBA_INTEGER_OP(long long)
218 ZORBA_INTEGER_OP(unsigned long)
219 ZORBA_INTEGER_OP(unsigned long long)
220 #undef ZORBA_INTEGER_OP
221
222 #define ZORBA_INTEGER_OP(OP,T) \
223 IntegerImpl& IntegerImpl::operator OP( T n ) { \
224 ztd::itoa_buf_type buf; \
225 value_type const temp( ztd::itoa( n, buf ) ); \
226 value_ OP temp; \
227 return *this; \
228 }
229
230 ZORBA_INTEGER_OP(+=,long long)
231 ZORBA_INTEGER_OP(-=,long long)
232 ZORBA_INTEGER_OP(*=,long long)
233 ZORBA_INTEGER_OP(%=,long long)
234 ZORBA_INTEGER_OP(+=,unsigned long)
235 ZORBA_INTEGER_OP(-=,unsigned long)
236 ZORBA_INTEGER_OP(*=,unsigned long)
237 ZORBA_INTEGER_OP(%=,unsigned long)
238 ZORBA_INTEGER_OP(+=,unsigned long long)
239 ZORBA_INTEGER_OP(-=,unsigned long long)
240 ZORBA_INTEGER_OP(*=,unsigned long long)
241 ZORBA_INTEGER_OP(%=,unsigned long long)
242 #undef ZORBA_INTEGER_OP
243
244 #define ZORBA_INTEGER_OP(T) \
245 IntegerImpl& IntegerImpl::operator/=( T n ) { \
246 ztd::itoa_buf_type buf; \
247 value_type const temp( ztd::itoa( n, buf ) ); \
248 value_ = ftoi( value_ / temp ); \
249 return *this; \
250 }
251
252 ZORBA_INTEGER_OP(long long)
253 ZORBA_INTEGER_OP(unsigned long)
254 ZORBA_INTEGER_OP(unsigned long long)
255 #undef ZORBA_INTEGER_OP
256 #endif /* ZORBA_WITH_BIG_INTEGER */
257
258 ////////// relational operators ///////////////////////////////////////////////
259
260 TEMPLATE_DECL(T)
261 bool operator==( INTEGER_IMPL(T) const &i, Decimal const &d ) {
262 return d.is_xs_integer() && i.itod() == d.value_;
263 }
264
265 #define ZORBA_INTEGER_OP(OP) \
266 TEMPLATE_DECL(T) \
267 bool operator OP( INTEGER_IMPL(T) const &i, Decimal const &d ) { \
268 return i.itod() OP d.value_; \
269 }
270
271 ZORBA_INTEGER_OP(!=)
272 ZORBA_INTEGER_OP(< )
273 ZORBA_INTEGER_OP(<=)
274 ZORBA_INTEGER_OP(> )
275 ZORBA_INTEGER_OP(>=)
276 #undef ZORBA_INTEGER_OP
277
278 #ifdef ZORBA_WITH_BIG_INTEGER
279
280 #define ZORBA_INTEGER_OP(OP,T) \
281 bool operator OP( IntegerImpl const &i, T n ) { \
282 ztd::itoa_buf_type buf; \
283 return i.value_ OP IntegerImpl::value_type( ztd::itoa( n, buf ) ); \
284 } \
285 \
286 bool operator OP( T n, IntegerImpl const &i ) { \
287 ztd::itoa_buf_type buf; \
288 return IntegerImpl::value_type( ztd::itoa( n, buf ) ) OP i.value_; \
289 }
290
291 ZORBA_INTEGER_OP(==,long long)
292 ZORBA_INTEGER_OP(!=,long long)
293 ZORBA_INTEGER_OP(< ,long long)
294 ZORBA_INTEGER_OP(<=,long long)
295 ZORBA_INTEGER_OP(> ,long long)
296 ZORBA_INTEGER_OP(>=,long long)
297 ZORBA_INTEGER_OP(==,unsigned long)
298 ZORBA_INTEGER_OP(!=,unsigned long)
299 ZORBA_INTEGER_OP(< ,unsigned long)
300 ZORBA_INTEGER_OP(<=,unsigned long)
301 ZORBA_INTEGER_OP(> ,unsigned long)
302 ZORBA_INTEGER_OP(>=,unsigned long)
303 ZORBA_INTEGER_OP(==,unsigned long long)
304 ZORBA_INTEGER_OP(!=,unsigned long long)
305 ZORBA_INTEGER_OP(< ,unsigned long long)
306 ZORBA_INTEGER_OP(<=,unsigned long long)
307 ZORBA_INTEGER_OP(> ,unsigned long long)
308 ZORBA_INTEGER_OP(>=,unsigned long long)
309
310 #else /* ZORBA_WITH_BIG_INTEGER */
311
312 #define ZORBA_INSTANTIATE(OP) \
313 template bool operator OP( INTEGER_IMPL_LL const&, Decimal const& ); \
314 template bool operator OP( INTEGER_IMPL_ULL const&, Decimal const& )
315
316 ZORBA_INSTANTIATE(==);
317 ZORBA_INSTANTIATE(!=);
318 ZORBA_INSTANTIATE(< );
319 ZORBA_INSTANTIATE(<=);
320 ZORBA_INSTANTIATE(> );
321 ZORBA_INSTANTIATE(>=);
322 #undef ZORBA_INSTANTIATE
323
324 #endif /* ZORBA_WITH_BIG_INTEGER */
325
326 ////////// math functions /////////////////////////////////////////////////////
327
TEMPLATE_DECL(T)328 TEMPLATE_DECL(T)
329 Double INTEGER_IMPL(T)::pow( INTEGER_IMPL(T) const &power ) const {
330 #ifdef ZORBA_WITH_BIG_INTEGER
331 value_type const result( value_.pow( power.value_, 15 ) );
332 char buf[300];
333 result.toFixPtString( buf, 15 );
334 return Double( buf );
335 #else
336 return Double(
337 // The casts are needed for disambiguation with MSVC++.
338 ::pow( static_cast<double>( value_ ), static_cast<double>( power.value_ ) )
339 );
340 #endif /* ZORBA_WITH_BIG_INTEGER */
341 }
342
343 TEMPLATE_DECL(T)
INTEGER_IMPL(T)344 INTEGER_IMPL(T) INTEGER_IMPL(T)::round( IntegerImpl const &precision ) const {
345 return IntegerImpl( Decimal::round2( itod(), precision.itod() ) );
346 }
347
348 TEMPLATE_DECL(T)
INTEGER_IMPL(T)349 INTEGER_IMPL(T)
350 INTEGER_IMPL(T)::roundHalfToEven( IntegerImpl const &precision ) const {
351 return IntegerImpl( Decimal::roundHalfToEven2( itod(), precision.itod() ) );
352 }
353
354 ////////// miscellaneous //////////////////////////////////////////////////////
355
356 #ifndef ZORBA_WITH_BIG_INTEGER
TEMPLATE_DECL(T)357 TEMPLATE_DECL(T)
358 typename INTEGER_IMPL(T)::value_type INTEGER_IMPL(T)::ftoi( MAPM const &d ) {
359 MAPM const temp( d.sign() >= 0 ? d.floor() : d.ceil() );
360 char *const buf = new char[ temp.exponent() + 3 ];
361 temp.toIntegerString( buf );
362 value_type const result( ztd::aton<value_type>( buf ) );
363 delete[] buf;
364 return result;
365 }
366
TEMPLATE_DECL(T)367 TEMPLATE_DECL(T)
368 MAPM INTEGER_IMPL(T)::itod() const {
369 if ( is_cxx_long() )
370 return static_cast<long>( value_ );
371 ztd::itoa_buf_type buf;
372 return ztd::itoa( value_, buf );
373 }
374 #endif /* ZORBA_WITH_BIG_INTEGER */
375
376 #ifdef ZORBA_WITH_BIG_INTEGER
hash() const377 uint32_t IntegerImpl::hash() const {
378 return Decimal::hash( value_ );
379 }
380
is_xs_byte() const381 bool IntegerImpl::is_xs_byte() const {
382 static MAPM xs_byte_min( "-128" );
383 static MAPM xs_byte_max( "127" );
384 return value_ >= xs_byte_min && value_ <= xs_byte_max;
385 }
386
is_xs_short() const387 bool IntegerImpl::is_xs_short() const {
388 static MAPM xs_short_min( "-32768" );
389 static MAPM xs_short_max( "32767" );
390 return value_ >= xs_short_min && value_ <= xs_short_max;
391 }
392
is_xs_unsignedByte() const393 bool IntegerImpl::is_xs_unsignedByte() const {
394 static MAPM xs_unsignedByte_max( "256" );
395 return value_.sign() >= 0 && value_ <= xs_unsignedByte_max;
396 }
397
is_xs_unsignedInt() const398 bool IntegerImpl::is_xs_unsignedInt() const {
399 static MAPM xs_unsignedInt_max( "4294967295" );
400 return value_.sign() >= 0 && value_ <= xs_unsignedInt_max;
401 }
402
is_xs_unsignedLong() const403 bool IntegerImpl::is_xs_unsignedLong() const {
404 static MAPM xs_unsignedLong_max( "18446744073709551615" );
405 return value_.sign() >= 0 && value_ <= xs_unsignedLong_max;
406 }
407
is_xs_unsignedShort() const408 bool IntegerImpl::is_xs_unsignedShort() const {
409 static MAPM xs_unsignedShort_max( "65536" );
410 return value_.sign() >= 0 && value_ <= xs_unsignedShort_max;
411 }
412 #endif /* ZORBA_WITH_BIG_INTEGER */
413
414 TEMPLATE_DECL(T)
INTEGER_IMPL(T) const415 INTEGER_IMPL(T) const& INTEGER_IMPL(T)::one() {
416 static INTEGER_IMPL(T) const i(1);
417 return i;
418 }
419
TEMPLATE_DECL(T)420 TEMPLATE_DECL(T)
421 zstring INTEGER_IMPL(T)::toString() const {
422 #ifdef ZORBA_WITH_BIG_INTEGER
423 char *const buf = new char[ value_.exponent() + 3 ];
424 value_.toIntegerString( buf );
425 zstring const result( buf );
426 delete[] buf;
427 return result;
428 #else
429 ztd::itoa_buf_type buf;
430 return ztd::itoa( value_, buf );
431 #endif /* ZORBA_WITH_BIG_INTEGER */
432 }
433
434 TEMPLATE_DECL(T)
INTEGER_IMPL(T) const435 INTEGER_IMPL(T) const& INTEGER_IMPL(T)::zero() {
436 static INTEGER_IMPL(T) const i(0);
437 return i;
438 }
439
440 ///////////////////////////////////////////////////////////////////////////////
441
442 #ifndef ZORBA_WITH_BIG_INTEGER
443 template class IntegerImpl<long long>;
444 template class IntegerImpl<unsigned long long>;
445 #endif /* ZORBA_WITH_BIG_INTEGER */
446
447 } // namespace zorba
448 /* vim:set et sw=2 ts=2: */
449