1///////////////////////////////////////////////////////////////////////////// 2// Name: src/common/longlong.cpp 3// Purpose: implementation of wxLongLongNative 4// Author: Jeffrey C. Ollie <jeff@ollie.clive.ia.us>, Vadim Zeitlin 5// Remarks: this class is not public in wxWidgets 2.0! It is intentionally 6// not documented and is for private use only. 7// Modified by: 8// Created: 10.02.99 9// RCS-ID: $Id: longlong.cpp 40750 2006-08-22 19:04:45Z MW $ 10// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr> 11// Licence: wxWindows licence 12///////////////////////////////////////////////////////////////////////////// 13 14// ============================================================================ 15// headers 16// ============================================================================ 17 18#include "wx/wxprec.h" 19 20#ifdef __BORLANDC__ 21 #pragma hdrstop 22#endif 23 24#if wxUSE_LONGLONG 25 26#include "wx/longlong.h" 27 28#ifndef WX_PRECOMP 29 #include "wx/math.h" // for fabs() 30#endif 31 32#if wxUSE_STREAMS 33 #include "wx/txtstrm.h" 34#endif 35 36#include <string.h> // for memset() 37 38#include "wx/ioswrap.h" 39 40// ============================================================================ 41// implementation 42// ============================================================================ 43 44#if wxUSE_LONGLONG_NATIVE 45 46// ---------------------------------------------------------------------------- 47// misc 48// ---------------------------------------------------------------------------- 49 50void *wxLongLongNative::asArray() const 51{ 52 static unsigned char temp[8]; 53 54 temp[0] = wx_truncate_cast(unsigned char, ((m_ll >> 56) & 0xFF)); 55 temp[1] = wx_truncate_cast(unsigned char, ((m_ll >> 48) & 0xFF)); 56 temp[2] = wx_truncate_cast(unsigned char, ((m_ll >> 40) & 0xFF)); 57 temp[3] = wx_truncate_cast(unsigned char, ((m_ll >> 32) & 0xFF)); 58 temp[4] = wx_truncate_cast(unsigned char, ((m_ll >> 24) & 0xFF)); 59 temp[5] = wx_truncate_cast(unsigned char, ((m_ll >> 16) & 0xFF)); 60 temp[6] = wx_truncate_cast(unsigned char, ((m_ll >> 8) & 0xFF)); 61 temp[7] = wx_truncate_cast(unsigned char, ((m_ll >> 0) & 0xFF)); 62 63 return temp; 64} 65 66void *wxULongLongNative::asArray() const 67{ 68 static unsigned char temp[8]; 69 70 temp[0] = wx_truncate_cast(unsigned char, ((m_ll >> 56) & 0xFF)); 71 temp[1] = wx_truncate_cast(unsigned char, ((m_ll >> 48) & 0xFF)); 72 temp[2] = wx_truncate_cast(unsigned char, ((m_ll >> 40) & 0xFF)); 73 temp[3] = wx_truncate_cast(unsigned char, ((m_ll >> 32) & 0xFF)); 74 temp[4] = wx_truncate_cast(unsigned char, ((m_ll >> 24) & 0xFF)); 75 temp[5] = wx_truncate_cast(unsigned char, ((m_ll >> 16) & 0xFF)); 76 temp[6] = wx_truncate_cast(unsigned char, ((m_ll >> 8) & 0xFF)); 77 temp[7] = wx_truncate_cast(unsigned char, ((m_ll >> 0) & 0xFF)); 78 79 return temp; 80} 81 82#if wxUSE_LONGLONG_WX 83wxLongLongNative::wxLongLongNative(wxLongLongWx ll) 84{ 85 // assign first to avoid precision loss! 86 m_ll = ll.GetHi(); 87 m_ll <<= 32; 88 m_ll |= ll.GetLo(); 89} 90 91wxLongLongNative& wxLongLongNative::operator=(wxLongLongWx ll) 92{ 93 // assign first to avoid precision loss! 94 m_ll = ll.GetHi(); 95 m_ll <<= 32; 96 m_ll |= ll.GetLo(); 97 return *this; 98} 99 100wxLongLongNative& wxLongLongNative::operator=(const class wxULongLongWx &ll) 101{ 102 // assign first to avoid precision loss! 103 m_ll = ll.GetHi(); 104 m_ll <<= 32; 105 m_ll |= ll.GetLo(); 106 return *this; 107} 108 109wxULongLongNative::wxULongLongNative(const class wxULongLongWx &ll) 110{ 111 // assign first to avoid precision loss! 112 m_ll = ll.GetHi(); 113 m_ll <<= 32; 114 m_ll |= ((unsigned long) ll.GetLo()); 115} 116 117wxULongLongNative& wxULongLongNative::operator=(wxLongLongWx ll) 118{ 119 // assign first to avoid precision loss! 120 m_ll = ll.GetHi(); 121 m_ll <<= 32; 122 m_ll |= ((unsigned long) ll.GetLo()); 123 return *this; 124} 125 126wxULongLongNative& wxULongLongNative::operator=(const class wxULongLongWx &ll) 127{ 128 // assign first to avoid precision loss! 129 m_ll = ll.GetHi(); 130 m_ll <<= 32; 131 m_ll |= ((unsigned long) ll.GetLo()); 132 return *this; 133} 134#endif 135 136#endif // wxUSE_LONGLONG_NATIVE 137 138// ============================================================================ 139// wxLongLongWx: emulation of 'long long' using 2 longs 140// ============================================================================ 141 142#if wxUSE_LONGLONG_WX 143 144// Set value from unsigned wxULongLongWx 145wxLongLongWx &wxLongLongWx::operator=(const class wxULongLongWx &ll) 146{ 147 m_hi = (unsigned long) ll.GetHi(); 148 m_lo = ll.GetLo(); 149 return *this; 150} 151 152// assignment 153wxLongLongWx& wxLongLongWx::Assign(double d) 154{ 155 bool positive = d >= 0; 156 d = fabs(d); 157 if ( d <= ULONG_MAX ) 158 { 159 m_hi = 0; 160 m_lo = (long)d; 161 } 162 else 163 { 164 m_hi = (unsigned long)(d / (1.0 + (double)ULONG_MAX)); 165 m_lo = (unsigned long)(d - ((double)m_hi * (1.0 + (double)ULONG_MAX))); 166 } 167 168#ifdef wxLONGLONG_TEST_MODE 169 m_ll = (wxLongLong_t)d; 170 171 Check(); 172#endif // wxLONGLONG_TEST_MODE 173 174 if ( !positive ) 175 Negate(); 176 177 return *this; 178} 179 180double wxLongLongWx::ToDouble() const 181{ 182 double d = m_hi; 183 d *= 1.0 + (double)ULONG_MAX; 184 d += m_lo; 185 186#ifdef wxLONGLONG_TEST_MODE 187 wxASSERT( d == m_ll ); 188#endif // wxLONGLONG_TEST_MODE 189 190 return d; 191} 192 193double wxULongLongWx::ToDouble() const 194{ 195 unsigned double d = m_hi; 196 d *= 1.0 + (double)ULONG_MAX; 197 d += m_lo; 198 199#ifdef wxLONGLONG_TEST_MODE 200 wxASSERT( d == m_ll ); 201#endif // wxLONGLONG_TEST_MODE 202 203 return d; 204} 205 206wxLongLongWx wxLongLongWx::operator<<(int shift) const 207{ 208 wxLongLongWx ll(*this); 209 ll <<= shift; 210 211 return ll; 212} 213 214wxULongLongWx wxULongLongWx::operator<<(int shift) const 215{ 216 wxULongLongWx ll(*this); 217 ll <<= shift; 218 219 return ll; 220} 221 222wxLongLongWx& wxLongLongWx::operator<<=(int shift) 223{ 224 if (shift != 0) 225 { 226 if (shift < 32) 227 { 228 m_hi <<= shift; 229 m_hi |= m_lo >> (32 - shift); 230 m_lo <<= shift; 231 } 232 else 233 { 234 m_hi = m_lo << (shift - 32); 235 m_lo = 0; 236 } 237 } 238 239#ifdef wxLONGLONG_TEST_MODE 240 m_ll <<= shift; 241 242 Check(); 243#endif // wxLONGLONG_TEST_MODE 244 245 return *this; 246} 247 248wxULongLongWx& wxULongLongWx::operator<<=(int shift) 249{ 250 if (shift != 0) 251 { 252 if (shift < 32) 253 { 254 m_hi <<= shift; 255 m_hi |= m_lo >> (32 - shift); 256 m_lo <<= shift; 257 } 258 else 259 { 260 m_hi = m_lo << (shift - 32); 261 m_lo = 0; 262 } 263 } 264 265#ifdef wxLONGLONG_TEST_MODE 266 m_ll <<= shift; 267 268 Check(); 269#endif // wxLONGLONG_TEST_MODE 270 271 return *this; 272} 273 274wxLongLongWx wxLongLongWx::operator>>(int shift) const 275{ 276 wxLongLongWx ll(*this); 277 ll >>= shift; 278 279 return ll; 280} 281 282wxULongLongWx wxULongLongWx::operator>>(int shift) const 283{ 284 wxULongLongWx ll(*this); 285 ll >>= shift; 286 287 return ll; 288} 289 290wxLongLongWx& wxLongLongWx::operator>>=(int shift) 291{ 292 if (shift != 0) 293 { 294 if (shift < 32) 295 { 296 m_lo >>= shift; 297 m_lo |= m_hi << (32 - shift); 298 m_hi >>= shift; 299 } 300 else 301 { 302 m_lo = m_hi >> (shift - 32); 303 m_hi = (m_hi < 0 ? -1L : 0); 304 } 305 } 306 307#ifdef wxLONGLONG_TEST_MODE 308 m_ll >>= shift; 309 310 Check(); 311#endif // wxLONGLONG_TEST_MODE 312 313 return *this; 314} 315 316wxULongLongWx& wxULongLongWx::operator>>=(int shift) 317{ 318 if (shift != 0) 319 { 320 if (shift < 32) 321 { 322 m_lo >>= shift; 323 m_lo |= m_hi << (32 - shift); 324 m_hi >>= shift; 325 } 326 else 327 { 328 m_lo = m_hi >> (shift - 32); 329 m_hi = 0; 330 } 331 } 332 333#ifdef wxLONGLONG_TEST_MODE 334 m_ll >>= shift; 335 336 Check(); 337#endif // wxLONGLONG_TEST_MODE 338 339 return *this; 340} 341 342wxLongLongWx wxLongLongWx::operator+(const wxLongLongWx& ll) const 343{ 344 wxLongLongWx res(*this); 345 res += ll; 346 347 return res; 348} 349 350wxULongLongWx wxULongLongWx::operator+(const wxULongLongWx& ll) const 351{ 352 wxULongLongWx res(*this); 353 res += ll; 354 355 return res; 356} 357 358wxLongLongWx wxLongLongWx::operator+(long l) const 359{ 360 wxLongLongWx res(*this); 361 res += l; 362 363 return res; 364} 365 366wxULongLongWx wxULongLongWx::operator+(unsigned long l) const 367{ 368 wxULongLongWx res(*this); 369 res += l; 370 371 return res; 372} 373 374wxLongLongWx& wxLongLongWx::operator+=(const wxLongLongWx& ll) 375{ 376 unsigned long previous = m_lo; 377 378 m_lo += ll.m_lo; 379 m_hi += ll.m_hi; 380 381 if ((m_lo < previous) || (m_lo < ll.m_lo)) 382 m_hi++; 383 384#ifdef wxLONGLONG_TEST_MODE 385 m_ll += ll.m_ll; 386 387 Check(); 388#endif // wxLONGLONG_TEST_MODE 389 390 return *this; 391} 392 393wxULongLongWx& wxULongLongWx::operator+=(const wxULongLongWx& ll) 394{ 395 unsigned long previous = m_lo; 396 397 m_lo += ll.m_lo; 398 m_hi += ll.m_hi; 399 400 if ((m_lo < previous) || (m_lo < ll.m_lo)) 401 m_hi++; 402 403#ifdef wxLONGLONG_TEST_MODE 404 m_ll += ll.m_ll; 405 406 Check(); 407#endif // wxLONGLONG_TEST_MODE 408 409 return *this; 410} 411 412wxLongLongWx& wxLongLongWx::operator+=(long l) 413{ 414 unsigned long previous = m_lo; 415 416 m_lo += l; 417 if (l < 0) 418 m_hi += -1l; 419 420 if ((m_lo < previous) || (m_lo < (unsigned long)l)) 421 m_hi++; 422 423#ifdef wxLONGLONG_TEST_MODE 424 m_ll += l; 425 426 Check(); 427#endif // wxLONGLONG_TEST_MODE 428 429 return *this; 430} 431 432wxULongLongWx& wxULongLongWx::operator+=(unsigned long l) 433{ 434 unsigned long previous = m_lo; 435 436 m_lo += l; 437 438 if ((m_lo < previous) || (m_lo < l)) 439 m_hi++; 440 441#ifdef wxLONGLONG_TEST_MODE 442 m_ll += l; 443 444 Check(); 445#endif // wxLONGLONG_TEST_MODE 446 447 return *this; 448} 449 450// pre increment 451wxLongLongWx& wxLongLongWx::operator++() 452{ 453 m_lo++; 454 if (m_lo == 0) 455 m_hi++; 456 457#ifdef wxLONGLONG_TEST_MODE 458 m_ll++; 459 460 Check(); 461#endif // wxLONGLONG_TEST_MODE 462 463 return *this; 464} 465 466wxULongLongWx& wxULongLongWx::operator++() 467{ 468 m_lo++; 469 if (m_lo == 0) 470 m_hi++; 471 472#ifdef wxLONGLONG_TEST_MODE 473 m_ll++; 474 475 Check(); 476#endif // wxLONGLONG_TEST_MODE 477 478 return *this; 479} 480 481// negation 482wxLongLongWx wxLongLongWx::operator-() const 483{ 484 wxLongLongWx res(*this); 485 res.Negate(); 486 487 return res; 488} 489 490wxLongLongWx& wxLongLongWx::Negate() 491{ 492 m_hi = ~m_hi; 493 m_lo = ~m_lo; 494 495 m_lo++; 496 if ( m_lo == 0 ) 497 m_hi++; 498 499#ifdef wxLONGLONG_TEST_MODE 500 m_ll = -m_ll; 501 502 Check(); 503#endif // wxLONGLONG_TEST_MODE 504 505 return *this; 506} 507 508// subtraction 509 510wxLongLongWx wxLongLongWx::operator-(const wxLongLongWx& ll) const 511{ 512 wxLongLongWx res(*this); 513 res -= ll; 514 515 return res; 516} 517 518wxLongLongWx wxULongLongWx::operator-(const wxULongLongWx& ll) const 519{ 520 wxASSERT(m_hi <= LONG_MAX ); 521 wxASSERT(ll.m_hi <= LONG_MAX ); 522 523 wxLongLongWx res( (long)m_hi , m_lo ); 524 wxLongLongWx op( (long)ll.m_hi , ll.m_lo ); 525 res -= op; 526 527 return res; 528} 529 530wxLongLongWx& wxLongLongWx::operator-=(const wxLongLongWx& ll) 531{ 532 unsigned long previous = m_lo; 533 534 m_lo -= ll.m_lo; 535 m_hi -= ll.m_hi; 536 537 if (previous < ll.m_lo) 538 m_hi--; 539 540#ifdef wxLONGLONG_TEST_MODE 541 m_ll -= ll.m_ll; 542 543 Check(); 544#endif // wxLONGLONG_TEST_MODE 545 546 return *this; 547} 548 549wxULongLongWx& wxULongLongWx::operator-=(const wxULongLongWx& ll) 550{ 551 unsigned long previous = m_lo; 552 553 m_lo -= ll.m_lo; 554 m_hi -= ll.m_hi; 555 556 if (previous < ll.m_lo) 557 m_hi--; 558 559#ifdef wxLONGLONG_TEST_MODE 560 m_ll -= ll.m_ll; 561 562 Check(); 563#endif // wxLONGLONG_TEST_MODE 564 565 return *this; 566} 567 568// pre decrement 569wxLongLongWx& wxLongLongWx::operator--() 570{ 571 m_lo--; 572 if (m_lo == 0xFFFFFFFF) 573 m_hi--; 574 575#ifdef wxLONGLONG_TEST_MODE 576 m_ll--; 577 578 Check(); 579#endif // wxLONGLONG_TEST_MODE 580 581 return *this; 582} 583 584wxULongLongWx& wxULongLongWx::operator--() 585{ 586 m_lo--; 587 if (m_lo == 0xFFFFFFFF) 588 m_hi--; 589 590#ifdef wxLONGLONG_TEST_MODE 591 m_ll--; 592 593 Check(); 594#endif // wxLONGLONG_TEST_MODE 595 596 return *this; 597} 598 599// comparison operators 600 601bool wxLongLongWx::operator<(const wxLongLongWx& ll) const 602{ 603 if ( m_hi < ll.m_hi ) 604 return true; 605 else if ( m_hi == ll.m_hi ) 606 return m_lo < ll.m_lo; 607 else 608 return false; 609} 610 611bool wxULongLongWx::operator<(const wxULongLongWx& ll) const 612{ 613 if ( m_hi < ll.m_hi ) 614 return true; 615 else if ( m_hi == ll.m_hi ) 616 return m_lo < ll.m_lo; 617 else 618 return false; 619} 620 621bool wxLongLongWx::operator>(const wxLongLongWx& ll) const 622{ 623 if ( m_hi > ll.m_hi ) 624 return true; 625 else if ( m_hi == ll.m_hi ) 626 return m_lo > ll.m_lo; 627 else 628 return false; 629} 630 631bool wxULongLongWx::operator>(const wxULongLongWx& ll) const 632{ 633 if ( m_hi > ll.m_hi ) 634 return true; 635 else if ( m_hi == ll.m_hi ) 636 return m_lo > ll.m_lo; 637 else 638 return false; 639} 640 641// bitwise operators 642 643wxLongLongWx wxLongLongWx::operator&(const wxLongLongWx& ll) const 644{ 645 return wxLongLongWx(m_hi & ll.m_hi, m_lo & ll.m_lo); 646} 647 648wxULongLongWx wxULongLongWx::operator&(const wxULongLongWx& ll) const 649{ 650 return wxULongLongWx(m_hi & ll.m_hi, m_lo & ll.m_lo); 651} 652 653wxLongLongWx wxLongLongWx::operator|(const wxLongLongWx& ll) const 654{ 655 return wxLongLongWx(m_hi | ll.m_hi, m_lo | ll.m_lo); 656} 657 658wxULongLongWx wxULongLongWx::operator|(const wxULongLongWx& ll) const 659{ 660 return wxULongLongWx(m_hi | ll.m_hi, m_lo | ll.m_lo); 661} 662 663wxLongLongWx wxLongLongWx::operator^(const wxLongLongWx& ll) const 664{ 665 return wxLongLongWx(m_hi ^ ll.m_hi, m_lo ^ ll.m_lo); 666} 667 668wxULongLongWx wxULongLongWx::operator^(const wxULongLongWx& ll) const 669{ 670 return wxULongLongWx(m_hi ^ ll.m_hi, m_lo ^ ll.m_lo); 671} 672 673wxLongLongWx& wxLongLongWx::operator&=(const wxLongLongWx& ll) 674{ 675 m_lo &= ll.m_lo; 676 m_hi &= ll.m_hi; 677 678#ifdef wxLONGLONG_TEST_MODE 679 m_ll &= ll.m_ll; 680 681 Check(); 682#endif // wxLONGLONG_TEST_MODE 683 684 return *this; 685} 686 687wxULongLongWx& wxULongLongWx::operator&=(const wxULongLongWx& ll) 688{ 689 m_lo &= ll.m_lo; 690 m_hi &= ll.m_hi; 691 692#ifdef wxLONGLONG_TEST_MODE 693 m_ll &= ll.m_ll; 694 695 Check(); 696#endif // wxLONGLONG_TEST_MODE 697 698 return *this; 699} 700 701wxLongLongWx& wxLongLongWx::operator|=(const wxLongLongWx& ll) 702{ 703 m_lo |= ll.m_lo; 704 m_hi |= ll.m_hi; 705 706#ifdef wxLONGLONG_TEST_MODE 707 m_ll |= ll.m_ll; 708 709 Check(); 710#endif // wxLONGLONG_TEST_MODE 711 712 return *this; 713} 714 715wxULongLongWx& wxULongLongWx::operator|=(const wxULongLongWx& ll) 716{ 717 m_lo |= ll.m_lo; 718 m_hi |= ll.m_hi; 719 720#ifdef wxLONGLONG_TEST_MODE 721 m_ll |= ll.m_ll; 722 723 Check(); 724#endif // wxLONGLONG_TEST_MODE 725 726 return *this; 727} 728 729wxLongLongWx& wxLongLongWx::operator^=(const wxLongLongWx& ll) 730{ 731 m_lo ^= ll.m_lo; 732 m_hi ^= ll.m_hi; 733 734#ifdef wxLONGLONG_TEST_MODE 735 m_ll ^= ll.m_ll; 736 737 Check(); 738#endif // wxLONGLONG_TEST_MODE 739 740 return *this; 741} 742 743wxULongLongWx& wxULongLongWx::operator^=(const wxULongLongWx& ll) 744{ 745 m_lo ^= ll.m_lo; 746 m_hi ^= ll.m_hi; 747 748#ifdef wxLONGLONG_TEST_MODE 749 m_ll ^= ll.m_ll; 750 751 Check(); 752#endif // wxLONGLONG_TEST_MODE 753 754 return *this; 755} 756 757wxLongLongWx wxLongLongWx::operator~() const 758{ 759 return wxLongLongWx(~m_hi, ~m_lo); 760} 761 762wxULongLongWx wxULongLongWx::operator~() const 763{ 764 return wxULongLongWx(~m_hi, ~m_lo); 765} 766 767// multiplication 768 769wxLongLongWx wxLongLongWx::operator*(const wxLongLongWx& ll) const 770{ 771 wxLongLongWx res(*this); 772 res *= ll; 773 774 return res; 775} 776 777wxULongLongWx wxULongLongWx::operator*(const wxULongLongWx& ll) const 778{ 779 wxULongLongWx res(*this); 780 res *= ll; 781 782 return res; 783} 784 785wxLongLongWx& wxLongLongWx::operator*=(const wxLongLongWx& ll) 786{ 787 wxLongLongWx t(m_hi, m_lo); 788 wxLongLongWx q(ll.m_hi, ll.m_lo); 789 790 m_hi = m_lo = 0; 791 792#ifdef wxLONGLONG_TEST_MODE 793 wxLongLong_t llOld = m_ll; 794 m_ll = 0; 795#endif // wxLONGLONG_TEST_MODE 796 797 int counter = 0; 798 do 799 { 800 if ((q.m_lo & 1) != 0) 801 *this += t; 802 q >>= 1; 803 t <<= 1; 804 counter++; 805 } 806 while ((counter < 64) && ((q.m_hi != 0) || (q.m_lo != 0))); 807 808#ifdef wxLONGLONG_TEST_MODE 809 m_ll = llOld * ll.m_ll; 810 811 Check(); 812#endif // wxLONGLONG_TEST_MODE 813 814 return *this; 815} 816 817wxULongLongWx& wxULongLongWx::operator*=(const wxULongLongWx& ll) 818{ 819 wxULongLongWx t(m_hi, m_lo); 820 wxULongLongWx q(ll.m_hi, ll.m_lo); 821 822 m_hi = m_lo = 0; 823 824#ifdef wxLONGLONG_TEST_MODE 825 wxULongLong_t llOld = m_ll; 826 m_ll = 0; 827#endif // wxLONGLONG_TEST_MODE 828 829 int counter = 0; 830 do 831 { 832 if ((q.m_lo & 1) != 0) 833 *this += t; 834 q >>= 1; 835 t <<= 1; 836 counter++; 837 } 838 while ((counter < 64) && ((q.m_hi != 0) || (q.m_lo != 0))); 839 840#ifdef wxLONGLONG_TEST_MODE 841 m_ll = llOld * ll.m_ll; 842 843 Check(); 844#endif // wxLONGLONG_TEST_MODE 845 846 return *this; 847} 848 849// division 850 851#define IS_MSB_SET(ll) ((ll.GetHi()) & (1 << (8*sizeof(long) - 1))) 852 853void wxLongLongWx::Divide(const wxLongLongWx& divisorIn, 854 wxLongLongWx& quotient, 855 wxLongLongWx& remainderIO) const 856{ 857 if ((divisorIn.m_lo == 0) && (divisorIn.m_hi == 0)) 858 { 859 // provoke division by zero error and silence the compilers warnings 860 // about an expression without effect and unused variable 861 long dummy = divisorIn.m_lo/divisorIn.m_hi; 862 dummy += 0; 863 } 864 865 // VZ: I'm writing this in a hurry and it's surely not the fastest way to 866 // do this - any improvements are more than welcome 867 // 868 // code inspired by the snippet at 869 // http://www.bearcave.com/software/divide.htm 870 // 871 // Copyright notice: 872 // 873 // Use of this program, for any purpose, is granted the author, Ian 874 // Kaplan, as long as this copyright notice is included in the source 875 // code or any source code derived from this program. The user assumes 876 // all responsibility for using this code. 877 878 // init everything 879 wxULongLongWx dividend, divisor, remainder; 880 881 quotient = 0l; 882 remainder = 0l; 883 884 // always do unsigned division and adjust the signs later: in C integer 885 // division, the sign of the remainder is the same as the sign of the 886 // dividend, while the sign of the quotient is the product of the signs of 887 // the dividend and divisor. Of course, we also always have 888 // 889 // dividend = quotient*divisor + remainder 890 // 891 // with 0 <= abs(remainder) < abs(divisor) 892 bool negRemainder = GetHi() < 0; 893 bool negQuotient = false; // assume positive 894 if ( GetHi() < 0 ) 895 { 896 negQuotient = !negQuotient; 897 dividend = -*this; 898 } else { 899 dividend = *this; 900 } 901 if ( divisorIn.GetHi() < 0 ) 902 { 903 negQuotient = !negQuotient; 904 divisor = -divisorIn; 905 } else { 906 divisor = divisorIn; 907 } 908 909 // check for some particular cases 910 if ( divisor > dividend ) 911 { 912 remainder = dividend; 913 } 914 else if ( divisor == dividend ) 915 { 916 quotient = 1l; 917 } 918 else 919 { 920 // here: dividend > divisor and both are positive: do unsigned division 921 size_t nBits = 64u; 922 wxLongLongWx d; 923 924 while ( remainder < divisor ) 925 { 926 remainder <<= 1; 927 if ( IS_MSB_SET(dividend) ) 928 { 929 remainder |= 1; 930 } 931 932 d = dividend; 933 dividend <<= 1; 934 935 nBits--; 936 } 937 938 // undo the last loop iteration 939 dividend = d; 940 remainder >>= 1; 941 nBits++; 942 943 for ( size_t i = 0; i < nBits; i++ ) 944 { 945 remainder <<= 1; 946 if ( IS_MSB_SET(dividend) ) 947 { 948 remainder |= 1; 949 } 950 951 wxLongLongWx t = remainder - divisor; 952 dividend <<= 1; 953 quotient <<= 1; 954 if ( !IS_MSB_SET(t) ) 955 { 956 quotient |= 1; 957 958 remainder = t; 959 } 960 } 961 } 962 963 remainderIO = remainder; 964 965 // adjust signs 966 if ( negRemainder ) 967 { 968 remainderIO = -remainderIO; 969 } 970 971 if ( negQuotient ) 972 { 973 quotient = -quotient; 974 } 975} 976 977void wxULongLongWx::Divide(const wxULongLongWx& divisorIn, 978 wxULongLongWx& quotient, 979 wxULongLongWx& remainder) const 980{ 981 if ((divisorIn.m_lo == 0) && (divisorIn.m_hi == 0)) 982 { 983 // provoke division by zero error and silence the compilers warnings 984 // about an expression without effect and unused variable 985 unsigned long dummy = divisorIn.m_lo/divisorIn.m_hi; 986 dummy += 0; 987 } 988 989 // VZ: I'm writing this in a hurry and it's surely not the fastest way to 990 // do this - any improvements are more than welcome 991 // 992 // code inspired by the snippet at 993 // http://www.bearcave.com/software/divide.htm 994 // 995 // Copyright notice: 996 // 997 // Use of this program, for any purpose, is granted the author, Ian 998 // Kaplan, as long as this copyright notice is included in the source 999 // code or any source code derived from this program. The user assumes 1000 // all responsibility for using this code. 1001 1002 // init everything 1003 wxULongLongWx dividend = *this, 1004 divisor = divisorIn; 1005 1006 quotient = 0l; 1007 remainder = 0l; 1008 1009 // check for some particular cases 1010 if ( divisor > dividend ) 1011 { 1012 remainder = dividend; 1013 } 1014 else if ( divisor == dividend ) 1015 { 1016 quotient = 1l; 1017 } 1018 else 1019 { 1020 // here: dividend > divisor 1021 size_t nBits = 64u; 1022 wxULongLongWx d; 1023 1024 while ( remainder < divisor ) 1025 { 1026 remainder <<= 1; 1027 if ( IS_MSB_SET(dividend) ) 1028 { 1029 remainder |= 1; 1030 } 1031 1032 d = dividend; 1033 dividend <<= 1; 1034 1035 nBits--; 1036 } 1037 1038 // undo the last loop iteration 1039 dividend = d; 1040 remainder >>= 1; 1041 nBits++; 1042 1043 for ( size_t i = 0; i < nBits; i++ ) 1044 { 1045 remainder <<= 1; 1046 if ( IS_MSB_SET(dividend) ) 1047 { 1048 remainder |= 1; 1049 } 1050 1051 wxULongLongWx t = remainder - divisor; 1052 dividend <<= 1; 1053 quotient <<= 1; 1054 if ( !IS_MSB_SET(t) ) 1055 { 1056 quotient |= 1; 1057 1058 remainder = t; 1059 } 1060 } 1061 } 1062} 1063 1064wxLongLongWx wxLongLongWx::operator/(const wxLongLongWx& ll) const 1065{ 1066 wxLongLongWx quotient, remainder; 1067 1068 Divide(ll, quotient, remainder); 1069 1070 return quotient; 1071} 1072 1073wxULongLongWx wxULongLongWx::operator/(const wxULongLongWx& ll) const 1074{ 1075 wxULongLongWx quotient, remainder; 1076 1077 Divide(ll, quotient, remainder); 1078 1079 return quotient; 1080} 1081 1082wxLongLongWx& wxLongLongWx::operator/=(const wxLongLongWx& ll) 1083{ 1084 wxLongLongWx quotient, remainder; 1085 1086 Divide(ll, quotient, remainder); 1087 1088 *this = quotient; 1089 1090 return *this; 1091} 1092 1093wxULongLongWx& wxULongLongWx::operator/=(const wxULongLongWx& ll) 1094{ 1095 wxULongLongWx quotient, remainder; 1096 1097 Divide(ll, quotient, remainder); 1098 1099 *this = quotient; 1100 1101 return *this; 1102} 1103 1104wxLongLongWx wxLongLongWx::operator%(const wxLongLongWx& ll) const 1105{ 1106 wxLongLongWx quotient, remainder; 1107 1108 Divide(ll, quotient, remainder); 1109 1110 return remainder; 1111} 1112 1113wxULongLongWx wxULongLongWx::operator%(const wxULongLongWx& ll) const 1114{ 1115 wxULongLongWx quotient, remainder; 1116 1117 Divide(ll, quotient, remainder); 1118 1119 return remainder; 1120} 1121 1122// ---------------------------------------------------------------------------- 1123// misc 1124// ---------------------------------------------------------------------------- 1125 1126// temporary - just for testing 1127void *wxLongLongWx::asArray(void) const 1128{ 1129 static unsigned char temp[8]; 1130 1131 temp[0] = (char)((m_hi >> 24) & 0xFF); 1132 temp[1] = (char)((m_hi >> 16) & 0xFF); 1133 temp[2] = (char)((m_hi >> 8) & 0xFF); 1134 temp[3] = (char)((m_hi >> 0) & 0xFF); 1135 temp[4] = (char)((m_lo >> 24) & 0xFF); 1136 temp[5] = (char)((m_lo >> 16) & 0xFF); 1137 temp[6] = (char)((m_lo >> 8) & 0xFF); 1138 temp[7] = (char)((m_lo >> 0) & 0xFF); 1139 1140 return temp; 1141} 1142 1143void *wxULongLongWx::asArray(void) const 1144{ 1145 static unsigned char temp[8]; 1146 1147 temp[0] = (char)((m_hi >> 24) & 0xFF); 1148 temp[1] = (char)((m_hi >> 16) & 0xFF); 1149 temp[2] = (char)((m_hi >> 8) & 0xFF); 1150 temp[3] = (char)((m_hi >> 0) & 0xFF); 1151 temp[4] = (char)((m_lo >> 24) & 0xFF); 1152 temp[5] = (char)((m_lo >> 16) & 0xFF); 1153 temp[6] = (char)((m_lo >> 8) & 0xFF); 1154 temp[7] = (char)((m_lo >> 0) & 0xFF); 1155 1156 return temp; 1157} 1158 1159#endif // wxUSE_LONGLONG_WX 1160 1161#define LL_TO_STRING(name) \ 1162 wxString name::ToString() const \ 1163 { \ 1164 /* TODO: this is awfully inefficient, anything better? */ \ 1165 wxString result; \ 1166 \ 1167 name ll = *this; \ 1168 \ 1169 bool neg = ll < 0; \ 1170 if ( neg ) \ 1171 { \ 1172 while ( ll != 0 ) \ 1173 { \ 1174 long digit = (ll % 10).ToLong(); \ 1175 result.Prepend((wxChar)(_T('0') - digit)); \ 1176 ll /= 10; \ 1177 } \ 1178 } \ 1179 else \ 1180 { \ 1181 while ( ll != 0 ) \ 1182 { \ 1183 long digit = (ll % 10).ToLong(); \ 1184 result.Prepend((wxChar)(_T('0') + digit)); \ 1185 ll /= 10; \ 1186 } \ 1187 } \ 1188 \ 1189 if ( result.empty() ) \ 1190 result = _T('0'); \ 1191 else if ( neg ) \ 1192 result.Prepend(_T('-')); \ 1193 \ 1194 return result; \ 1195 } 1196 1197#define ULL_TO_STRING(name) \ 1198 wxString name::ToString() const \ 1199 { \ 1200 /* TODO: this is awfully inefficient, anything better? */ \ 1201 wxString result; \ 1202 \ 1203 name ll = *this; \ 1204 \ 1205 while ( ll != 0 ) \ 1206 { \ 1207 result.Prepend((wxChar)(_T('0') + (ll % 10).ToULong())); \ 1208 ll /= 10; \ 1209 } \ 1210 \ 1211 if ( result.empty() ) \ 1212 result = _T('0'); \ 1213 \ 1214 return result; \ 1215 } 1216 1217#if wxUSE_LONGLONG_NATIVE 1218 LL_TO_STRING(wxLongLongNative) 1219 ULL_TO_STRING(wxULongLongNative) 1220#endif 1221 1222#if wxUSE_LONGLONG_WX 1223 LL_TO_STRING(wxLongLongWx) 1224 ULL_TO_STRING(wxULongLongWx) 1225#endif 1226 1227#if wxUSE_STD_IOSTREAM 1228 1229// input/output 1230WXDLLIMPEXP_BASE 1231wxSTD ostream& operator<< (wxSTD ostream& o, const wxLongLong& ll) 1232{ 1233 return o << ll.ToString(); 1234} 1235 1236WXDLLIMPEXP_BASE 1237wxSTD ostream& operator<< (wxSTD ostream& o, const wxULongLong& ll) 1238{ 1239 return o << ll.ToString(); 1240} 1241 1242#endif // wxUSE_STD_IOSTREAM 1243 1244WXDLLIMPEXP_BASE wxString& operator<< (wxString& s, const wxLongLong& ll) 1245{ 1246 return s << ll.ToString(); 1247} 1248 1249WXDLLIMPEXP_BASE wxString& operator<< (wxString& s, const wxULongLong& ll) 1250{ 1251 return s << ll.ToString(); 1252} 1253 1254#if wxUSE_STREAMS 1255 1256WXDLLIMPEXP_BASE wxTextOutputStream& operator<< (wxTextOutputStream& o, const wxULongLong& ll) 1257{ 1258 return o << ll.ToString(); 1259} 1260 1261WXDLLIMPEXP_BASE wxTextOutputStream& operator<< (wxTextOutputStream& o, const wxLongLong& ll) 1262{ 1263 return o << ll.ToString(); 1264} 1265 1266#define READ_STRING_CHAR(s, idx, len) ((wxChar) ((idx!=len) ? s[idx++] : 0)) 1267 1268WXDLLIMPEXP_BASE class wxTextInputStream &operator>>(class wxTextInputStream &o, wxULongLong &ll) 1269{ 1270 wxString s = o.ReadWord(); 1271 1272 ll = wxULongLong(0l, 0l); 1273 size_t length = s.length(); 1274 size_t idx = 0; 1275 1276 wxChar ch = READ_STRING_CHAR(s, idx, length); 1277 1278 // Skip WS 1279 while (ch==wxT(' ') || ch==wxT('\t')) 1280 ch = READ_STRING_CHAR(s, idx, length); 1281 1282 // Read number 1283 wxULongLong multiplier(0l, 10l); 1284 while (ch>=wxT('0') && ch<=wxT('9')) { 1285 long lValue = (unsigned) (ch - wxT('0')); 1286 ll = ll * multiplier + wxULongLong(0l, lValue); 1287 ch = READ_STRING_CHAR(s, idx, length); 1288 } 1289 1290 return o; 1291} 1292 1293WXDLLIMPEXP_BASE class wxTextInputStream &operator>>(class wxTextInputStream &o, wxLongLong &ll) 1294{ 1295 wxString s = o.ReadWord(); 1296 1297 ll = wxLongLong(0l, 0l); 1298 size_t length = s.length(); 1299 size_t idx = 0; 1300 1301 wxChar ch = READ_STRING_CHAR(s, idx, length); 1302 1303 // Skip WS 1304 while (ch==wxT(' ') || ch==wxT('\t')) 1305 ch = READ_STRING_CHAR(s, idx, length); 1306 1307 // Ask for sign 1308 int iSign = 1; 1309 if (ch==wxT('-') || ch==wxT('+')) { 1310 iSign = ((ch==wxT('-')) ? -1 : 1); 1311 ch = READ_STRING_CHAR(s, idx, length); 1312 } 1313 1314 // Read number 1315 wxLongLong multiplier(0l, 10l); 1316 while (ch>=wxT('0') && ch<=wxT('9')) { 1317 long lValue = (unsigned) (ch - wxT('0')); 1318 ll = ll * multiplier + wxLongLong(0l, lValue); 1319 ch = READ_STRING_CHAR(s, idx, length); 1320 } 1321 1322#if wxUSE_LONGLONG_NATIVE 1323 ll = ll * wxLongLong((wxLongLong_t) iSign); 1324#else 1325 ll = ll * wxLongLong((long) iSign); 1326#endif 1327 1328 return o; 1329} 1330 1331#if wxUSE_LONGLONG_NATIVE 1332 1333WXDLLIMPEXP_BASE class wxTextOutputStream &operator<<(class wxTextOutputStream &o, wxULongLong_t value) 1334{ 1335 return o << wxULongLong(value).ToString(); 1336} 1337 1338WXDLLIMPEXP_BASE class wxTextOutputStream &operator<<(class wxTextOutputStream &o, wxLongLong_t value) 1339{ 1340 return o << wxLongLong(value).ToString(); 1341} 1342 1343WXDLLIMPEXP_BASE class wxTextInputStream &operator>>(class wxTextInputStream &o, wxULongLong_t &value) 1344{ 1345 wxULongLong ll; 1346 o >> ll; 1347 value = ll.GetValue(); 1348 return o; 1349} 1350 1351WXDLLIMPEXP_BASE class wxTextInputStream &operator>>(class wxTextInputStream &o, wxLongLong_t &value) 1352{ 1353 wxLongLong ll; 1354 o >> ll; 1355 value = ll.GetValue(); 1356 return o; 1357} 1358 1359#endif // wxUSE_LONGLONG_NATIVE 1360 1361#endif // wxUSE_STREAMS 1362 1363#endif // wxUSE_LONGLONG 1364