Remove all lines containing cvs/svn "$Id$" keyword.
[wxWidgets.git] / tests / longlong / longlongtest.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: tests/longlong/longlong.cpp
3 // Purpose: wxLongLong unit test
4 // Author: Vadim Zeitlin, Wlodzimierz ABX Skiba
5 // Created: 2004-04-01
6 // Copyright: (c) 2004 Vadim Zeitlin, Wlodzimierz Skiba
7 ///////////////////////////////////////////////////////////////////////////////
8
9 // ----------------------------------------------------------------------------
10 // headers
11 // ----------------------------------------------------------------------------
12
13 #include "testprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #ifndef WX_PRECOMP
20 #include "wx/wx.h"
21 #endif // WX_PRECOMP
22
23 #include "wx/longlong.h"
24 #include "wx/timer.h"
25
26 #if wxUSE_LONGLONG
27
28 // ----------------------------------------------------------------------------
29 // helpers for testing
30 // ----------------------------------------------------------------------------
31
32 // number of iterations in loops
33 #define ITEMS 1000
34
35 // make a 64 bit number from 4 16 bit ones
36 #define MAKE_LL(x1, x2, x3, x4) wxLongLong((x1 << 16) | x2, (x3 << 16) | x3)
37
38 // get a random 64 bit number
39 #define RAND_LL() MAKE_LL(rand(), rand(), rand(), rand())
40
41 static const long testLongs[] =
42 {
43 0,
44 1,
45 -1,
46 LONG_MAX,
47 LONG_MIN,
48 0x1234,
49 -0x1234
50 };
51
52 // ----------------------------------------------------------------------------
53 // test class
54 // ----------------------------------------------------------------------------
55
56 class LongLongTestCase : public CppUnit::TestCase
57 {
58 public:
59 LongLongTestCase();
60
61 private:
62 CPPUNIT_TEST_SUITE( LongLongTestCase );
63 CPPUNIT_TEST( Conversion );
64 CPPUNIT_TEST( Comparison );
65 CPPUNIT_TEST( Addition );
66 CPPUNIT_TEST( Multiplication );
67 CPPUNIT_TEST( Division );
68 CPPUNIT_TEST( BitOperations );
69 CPPUNIT_TEST( ToString );
70 CPPUNIT_TEST( LoHi );
71 CPPUNIT_TEST( Limits );
72 CPPUNIT_TEST_SUITE_END();
73
74 void Conversion();
75 void Comparison();
76 void Addition();
77 void Multiplication();
78 void Division();
79 void BitOperations();
80 void ToString();
81 void LoHi();
82 void Limits();
83
84 DECLARE_NO_COPY_CLASS(LongLongTestCase)
85 };
86
87 // register in the unnamed registry so that these tests are run by default
88 CPPUNIT_TEST_SUITE_REGISTRATION( LongLongTestCase );
89
90 // also include in its own registry so that these tests can be run alone
91 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( LongLongTestCase, "LongLongTestCase" );
92
93 LongLongTestCase::LongLongTestCase()
94 {
95 srand((unsigned)time(NULL));
96 }
97
98 void LongLongTestCase::Conversion()
99 {
100 for ( size_t n = 0; n < ITEMS; n++ )
101 {
102 wxLongLong a = RAND_LL();
103
104 wxLongLong b(a.GetHi(), a.GetLo());
105 CPPUNIT_ASSERT( a == b );
106
107 #if wxUSE_LONGLONG_WX
108 wxLongLongWx c(a.GetHi(), a.GetLo());
109 CPPUNIT_ASSERT( a == c );
110 #endif
111
112 #if wxUSE_LONGLONG_NATIVE
113 wxLongLongNative d(a.GetHi(), a.GetLo());
114 CPPUNIT_ASSERT( a == d );
115 #endif
116 }
117 }
118
119 void LongLongTestCase::Comparison()
120 {
121 static const long ls[2] =
122 {
123 0x1234,
124 -0x1234,
125 };
126
127 wxLongLong lls[2];
128 lls[0] = ls[0];
129 lls[1] = ls[1];
130
131 for ( size_t n = 0; n < WXSIZEOF(testLongs); n++ )
132 {
133 for ( size_t m = 0; m < WXSIZEOF(lls); m++ )
134 {
135 CPPUNIT_ASSERT( (lls[m] < testLongs[n]) == (ls[m] < testLongs[n]) );
136 CPPUNIT_ASSERT( (lls[m] > testLongs[n]) == (ls[m] > testLongs[n]) );
137 CPPUNIT_ASSERT( (lls[m] <= testLongs[n]) == (ls[m] <= testLongs[n]) );
138 CPPUNIT_ASSERT( (lls[m] >= testLongs[n]) == (ls[m] >= testLongs[n]) );
139 CPPUNIT_ASSERT( (lls[m] != testLongs[n]) == (ls[m] != testLongs[n]) );
140 CPPUNIT_ASSERT( (lls[m] == testLongs[n]) == (ls[m] == testLongs[n]) );
141 }
142 }
143 }
144
145 void LongLongTestCase::Addition()
146 {
147 for ( size_t n = 0; n < ITEMS; n++ )
148 {
149 wxLongLong a = RAND_LL();
150 wxLongLong b = RAND_LL();
151 wxLongLong c = a + b;
152
153 #if wxUSE_LONGLONG_NATIVE
154 wxLongLongNative a1 = a;
155 wxLongLongNative b1 = b;
156 wxLongLongNative c1 = a1 + b1;
157 CPPUNIT_ASSERT( c == c1 );
158 #endif
159
160 #if wxUSE_LONGLONG_WX
161 wxLongLongWx a2 = a;
162 wxLongLongWx b2 = b;
163 wxLongLongWx c2 = a2 + b2;
164 CPPUNIT_ASSERT( c == c2 );
165 #endif
166 }
167 }
168
169 void LongLongTestCase::Multiplication()
170 {
171 for ( size_t n = 0; n < ITEMS; n++ )
172 {
173 wxLongLong a = RAND_LL();
174 wxLongLong b = RAND_LL();
175 wxLongLong c = a*b;
176
177 wxLongLong a1(a.GetHi(), a.GetLo());
178 wxLongLong b1(b.GetHi(), b.GetLo());
179 wxLongLong c1 = a1*b1;
180 CPPUNIT_ASSERT( c1 == c );
181
182 #if wxUSE_LONGLONG_WX
183 wxLongLongWx a2(a.GetHi(), a.GetLo());
184 wxLongLongWx b2(b.GetHi(), b.GetLo());
185 wxLongLongWx c2 = a2*b2;
186 CPPUNIT_ASSERT( c2 == c );
187 #endif
188
189 #if wxUSE_LONGLONG_NATIVE
190 wxLongLongNative a3(a.GetHi(), a.GetLo());
191 wxLongLongNative b3(b.GetHi(), b.GetLo());
192 wxLongLongNative c3 = a3*b3;
193 CPPUNIT_ASSERT( c3 == c );
194 #endif
195 }
196 }
197
198 void LongLongTestCase::Division()
199 {
200 for ( size_t n = 0; n < ITEMS; n++ )
201 {
202 // get a random wxLongLong (shifting by 12 the MSB ensures that the
203 // multiplication will not overflow)
204 wxLongLong a = MAKE_LL((rand() >> 12), rand(), rand(), rand());
205
206 // get a random (but non null) long (not wxLongLong for now) divider
207 long l;
208 do
209 {
210 l = rand();
211 }
212 while ( !l );
213
214 wxLongLong q = a / l;
215 wxLongLong r = a % l;
216
217 CPPUNIT_ASSERT( a == ( q * l + r ) );
218
219 #if wxUSE_LONGLONG_WX
220 wxLongLongWx a1(a.GetHi(), a.GetLo());
221 wxLongLongWx q1 = a1 / l;
222 wxLongLongWx r1 = a1 % l;
223 CPPUNIT_ASSERT( q == q1 );
224 CPPUNIT_ASSERT( r == r1 );
225 CPPUNIT_ASSERT( a1 == ( q1 * l + r1 ) );
226 #endif
227
228 #if wxUSE_LONGLONG_NATIVE
229 wxLongLongNative a2(a.GetHi(), a.GetLo());
230 wxLongLongNative q2 = a2 / l;
231 wxLongLongNative r2 = a2 % l;
232 CPPUNIT_ASSERT( q == q2 );
233 CPPUNIT_ASSERT( r == r2 );
234 CPPUNIT_ASSERT( a2 == ( q2 * l + r2 ) );
235 #endif
236 }
237 }
238
239 void LongLongTestCase::BitOperations()
240 {
241 for ( size_t m = 0; m < ITEMS; m++ )
242 {
243 wxLongLong a = RAND_LL();
244
245 for ( size_t n = 0; n < 33; n++ )
246 {
247 wxLongLong b(a.GetHi(), a.GetLo()), c, d = b, e;
248 d >>= n;
249 c = b >> n;
250 CPPUNIT_ASSERT( c == d );
251 d <<= n;
252 e = c << n;
253 CPPUNIT_ASSERT( d == e );
254
255 #if wxUSE_LONGLONG_WX
256 wxLongLongWx b1(a.GetHi(), a.GetLo()), c1, d1 = b1, e1;
257 d1 >>= n;
258 c1 = b1 >> n;
259 CPPUNIT_ASSERT( c1 == d1 );
260 d1 <<= n;
261 e1 = c1 << n;
262 CPPUNIT_ASSERT( d1 == e1 );
263 #endif
264
265 #if wxUSE_LONGLONG_NATIVE
266 wxLongLongNative b2(a.GetHi(), a.GetLo()), c2, d2 = b2, e2;
267 d2 >>= n;
268 c2 = b2 >> n;
269 CPPUNIT_ASSERT( c2 == d2 );
270 d2 <<= n;
271 e2 = c2 << n;
272 CPPUNIT_ASSERT( d2 == e2 );
273 #endif
274 }
275 }
276 }
277
278 void LongLongTestCase::ToString()
279 {
280 wxString s1, s2;
281
282 for ( size_t n = 0; n < WXSIZEOF(testLongs); n++ )
283 {
284 wxLongLong a = testLongs[n];
285 s1 = wxString::Format(wxT("%ld"), testLongs[n]);
286 s2 = a.ToString();
287 CPPUNIT_ASSERT( s1 == s2 );
288
289 s2 = wxEmptyString;
290 s2 << a;
291 CPPUNIT_ASSERT( s1 == s2 );
292
293 #if wxUSE_LONGLONG_WX
294 wxLongLongWx a1 = testLongs[n];
295 s2 = a1.ToString();
296 CPPUNIT_ASSERT( s1 == s2 );
297 #endif
298
299 #if wxUSE_LONGLONG_NATIVE
300 wxLongLongNative a2 = testLongs[n];
301 s2 = a2.ToString();
302 CPPUNIT_ASSERT( s1 == s2 );
303 #endif
304 }
305
306 wxLongLong a(0x12345678, 0x87654321);
307 CPPUNIT_ASSERT( a.ToString() == wxT("1311768467139281697") );
308 a.Negate();
309 CPPUNIT_ASSERT( a.ToString() == wxT("-1311768467139281697") );
310
311 wxLongLong llMin(-2147483647L - 1L, 0);
312 CPPUNIT_ASSERT( llMin.ToString() == wxT("-9223372036854775808") );
313
314 #if wxUSE_LONGLONG_WX
315 wxLongLongWx a1(a.GetHi(), a.GetLo());
316 CPPUNIT_ASSERT( a1.ToString() == wxT("-1311768467139281697") );
317 a1.Negate();
318 CPPUNIT_ASSERT( a1.ToString() == wxT("1311768467139281697") );
319 #endif
320
321 #if wxUSE_LONGLONG_NATIVE
322 wxLongLongNative a2(a.GetHi(), a.GetLo());
323 CPPUNIT_ASSERT( a2.ToString() == wxT("-1311768467139281697") );
324 a2.Negate();
325 CPPUNIT_ASSERT( a2.ToString() == wxT("1311768467139281697") );
326 #endif
327
328 }
329
330 void LongLongTestCase::LoHi()
331 {
332 wxLongLong ll(123, 456);
333 CPPUNIT_ASSERT_EQUAL( 456u, ll.GetLo() );
334 CPPUNIT_ASSERT_EQUAL( 123, ll.GetHi() );
335
336 wxULongLong ull(987, 654);
337 CPPUNIT_ASSERT_EQUAL( 654u, ull.GetLo() );
338 CPPUNIT_ASSERT_EQUAL( 987u, ull.GetHi() );
339 }
340
341 void LongLongTestCase::Limits()
342 {
343 // VC6 doesn't specialize numeric_limits<> for __int64 so skip this test
344 // for it.
345 #ifndef __VISUALC6__
346 #if wxUSE_LONGLONG_NATIVE
347 CPPUNIT_ASSERT( std::numeric_limits<wxLongLong>::is_specialized );
348 CPPUNIT_ASSERT( std::numeric_limits<wxULongLong>::is_specialized );
349
350 wxULongLong maxval = std::numeric_limits<wxULongLong>::max();
351 CPPUNIT_ASSERT( maxval.ToDouble() > 0 );
352 #endif // wxUSE_LONGLONG_NATIVE
353 #endif // !__VISUALC6__
354 }
355
356 #endif // wxUSE_LONGLONG