1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_tools.hxx" 30 31 #ifndef _LIMITS_H 32 #include <limits.h> 33 #endif 34 #include <tools/debug.hxx> 35 #include <tools/fract.hxx> 36 #include <tools/stream.hxx> 37 38 #include <tools/bigint.hxx> 39 40 /************************************************************************* 41 |* 42 |* GetGGT() 43 |* 44 |* Beschreibung Berechnet den groessten gemeinsamen Teiler von 45 |* nVal1 und nVal2 46 |* Parameter long nVal1, long nVal2 47 |* Ersterstellung DV 20.09.90 48 |* Letzte Aenderung DV 21.12.92 49 |* 50 *************************************************************************/ 51 52 // Die Funktion GetGGT berechnet den groessten gemeinsamen Teiler der 53 // beiden als Parameter uebergebenen Werte nVal1 und nVal2 nach dem 54 // Algorithmus von Euklid. Hat einer der beiden Parameter den Wert 0 oder 55 // 1, so wird als Ergebnis der Wert 1 zur�ckgegeben. Da der Algorithmus 56 // nur mit positiven Zahlen arbeitet, werden die beiden Parameter 57 // entsprechend umgewandelt. 58 // Zum Algorithmus: die beiden Parameter werden solange ducheinander 59 // geteilt, bis sie beide gleich sind oder bis bei der Division 60 // kein Rest bleibt. Der kleinere der beiden Werte ist dann der 61 // GGT. 62 63 static long GetGGT( long nVal1, long nVal2 ) 64 { 65 nVal1 = Abs( nVal1 ); 66 nVal2 = Abs( nVal2 ); 67 68 if ( nVal1 <= 1 || nVal2 <= 1 ) 69 return 1; 70 71 while ( nVal1 != nVal2 ) 72 { 73 if ( nVal1 > nVal2 ) 74 { 75 nVal1 %= nVal2; 76 if ( nVal1 == 0 ) 77 return nVal2; 78 } 79 else 80 { 81 nVal2 %= nVal1; 82 if ( nVal2 == 0 ) 83 return nVal1; 84 } 85 } 86 87 return nVal1; 88 } 89 90 static void Reduce( BigInt &rVal1, BigInt &rVal2 ) 91 { 92 BigInt nA( rVal1 ); 93 BigInt nB( rVal2 ); 94 nA.Abs(); 95 nB.Abs(); 96 97 if ( nA.IsOne() || nB.IsOne() || nA.IsZero() || nB.IsZero() ) 98 return; 99 100 while ( nA != nB ) 101 { 102 if ( nA > nB ) 103 { 104 nA %= nB; 105 if ( nA.IsZero() ) 106 { 107 rVal1 /= nB; 108 rVal2 /= nB; 109 return; 110 } 111 } 112 else 113 { 114 nB %= nA; 115 if ( nB.IsZero() ) 116 { 117 rVal1 /= nA; 118 rVal2 /= nA; 119 return; 120 } 121 } 122 } 123 124 rVal1 /= nA; 125 rVal2 /= nB; 126 } 127 128 /************************************************************************* 129 |* 130 |* Fraction::Fraction() 131 |* 132 |* Beschreibung FRACT.SDW 133 |* Ersterstellung WP 07.03.97 134 |* Letzte Aenderung 135 |* 136 *************************************************************************/ 137 138 Fraction::Fraction( long nN1, long nN2, long nD1, long nD2 ) 139 { 140 long n; 141 int i = 1; 142 143 if( nN1 < 0 ) { i = -i; nN1 = -nN1; } 144 if( nN2 < 0 ) { i = -i; nN2 = -nN2; } 145 if( nD1 < 0 ) { i = -i; nD1 = -nD1; } 146 if( nD2 < 0 ) { i = -i; nD2 = -nD2; } 147 148 n = GetGGT( nN1, nD1 ); if( n > 1 ) { nN1 /= n; nD1 /= n; } 149 n = GetGGT( nN1, nD2 ); if( n > 1 ) { nN1 /= n; nD2 /= n; } 150 n = GetGGT( nN2, nD1 ); if( n > 1 ) { nN2 /= n; nD1 /= n; } 151 n = GetGGT( nN2, nD2 ); if( n > 1 ) { nN2 /= n; nD2 /= n; } 152 153 BigInt nN( nN1 ); 154 nN *= BigInt( nN2 ); 155 156 BigInt nD( nD1 ); 157 nD *= BigInt( nD2 ); 158 159 while ( nN.bIsBig || nD.bIsBig ) 160 { 161 BigInt n1 = 1; 162 BigInt n2 = 2; 163 164 nN += n1; 165 nN /= n2; 166 nD += n1; 167 nD /= n2; 168 169 // Kuerzen ueber Groesste Gemeinsame Teiler 170 Reduce( nN, nD ); 171 } 172 173 nNumerator = i * (long)nN; 174 nDenominator = (long)nD; 175 } 176 177 /************************************************************************* 178 |* 179 |* Fraction::Fraction() 180 |* 181 |* Beschreibung FRACT.SDW 182 |* Ersterstellung DV 20.09.90 183 |* Letzte Aenderung DV 21.12.92 184 |* 185 *************************************************************************/ 186 187 // Zur Initialisierung eines Bruches wird nNum dem Zaehler und nDen dem 188 // Nenner zugewiesen. Da negative Werte des Nenners einen Bruch als 189 // ungueltig kennzeichnen, wird bei der Eingabe eines negativen Nenners 190 // sowohl das Vorzeichen des Nenners und des Zaehlers invertiert um wieder 191 // einen gueltigen Wert fuer den Bruch zu erhalten. 192 193 Fraction::Fraction( long nNum, long nDen ) 194 { 195 nNumerator = nNum; 196 nDenominator = nDen; 197 if ( nDenominator < 0 ) 198 { 199 nDenominator = -nDenominator; 200 nNumerator = -nNumerator; 201 } 202 203 // Kuerzen ueber Groesste Gemeinsame Teiler 204 long n = GetGGT( nNumerator, nDenominator ); 205 nNumerator /= n; 206 nDenominator /= n; 207 } 208 209 /************************************************************************* 210 |* 211 |* Fraction::Fraction() 212 |* 213 |* Beschreibung FRACT.SDW 214 |* Ersterstellung DV 20.09.90 215 |* Letzte Aenderung DV 21.12.92 216 |* 217 *************************************************************************/ 218 219 // Wenn der Wert von dVal groesser ist als LONG_MAX, dann wird der Bruch 220 // auf den Wert ungueltig gesetzt, ansonsten werden dVal und der Nenner 221 // solange mit 10 multipliziert, bis entweder der Zaehler oder der Nenner 222 // groesser als LONG_MAX / 10 ist. Zum Schluss wird der so entstandene Bruch 223 // gekuerzt. 224 225 Fraction::Fraction( double dVal ) 226 { 227 long nDen = 1; 228 long nMAX = LONG_MAX / 10; 229 230 if ( dVal > LONG_MAX || dVal < LONG_MIN ) 231 { 232 nNumerator = 0; 233 nDenominator = -1; 234 return; 235 } 236 237 while ( Abs( (long)dVal ) < nMAX && nDen < nMAX ) 238 { 239 dVal *= 10; 240 nDen *= 10; 241 } 242 nNumerator = (long)dVal; 243 nDenominator = nDen; 244 245 // Kuerzen ueber Groesste Gemeinsame Teiler 246 long n = GetGGT( nNumerator, nDenominator ); 247 nNumerator /= n; 248 nDenominator /= n; 249 } 250 251 /************************************************************************* 252 |* 253 |* Fraction::operator double() 254 |* 255 |* Beschreibung FRACT.SDW 256 |* Ersterstellung DV 20.09.90 257 |* Letzte Aenderung DV 14.05.91 258 |* 259 *************************************************************************/ 260 261 Fraction::operator double() const 262 { 263 if ( nDenominator > 0 ) 264 return (double)nNumerator / (double)nDenominator; 265 else 266 return (double)0; 267 } 268 269 /************************************************************************* 270 |* 271 |* Fraction::operator+=() 272 |* 273 |* Beschreibung FRACT.SDW 274 |* Ersterstellung DV 20.09.90 275 |* Letzte Aenderung DV 21.12.92 276 |* 277 *************************************************************************/ 278 279 // Zunaechst werden die beiden Parameter auf ihre Gueltigkeit ueberprueft. 280 // Ist einer der Parameter ungueltig, dann ist auch des Ergebnis 281 // ungueltig. Zur Addition werden die beiden Brueche erst durch 282 // Erweiterung mit den Nenner des jeweils anderen Bruches auf einen 283 // gemeinsamen Nenner gebracht. Anschliessend werden die beiden Zaehler 284 // addiert und das Ergebnis gekuerzt (durch Division von Zaehler und 285 // Nenner mit nGGT). Innerhalb der Funktion wird mit dem Datentyp SLong 286 // gerechnet, um einen Moeglichen Ueberlauf erkennen zu koennen. Bei 287 // einem Ueberlauf wird das Ergebnis auf den Wert ungueltig gesetzt. 288 289 Fraction& Fraction::operator += ( const Fraction& rVal ) 290 { 291 if ( !rVal.IsValid() ) 292 { 293 nNumerator = 0; 294 nDenominator = -1; 295 } 296 if ( !IsValid() ) 297 return *this; 298 299 // (a/b) + (c/d) = ( (a*d) + (c*b) ) / (b*d) 300 BigInt nN( nNumerator ); 301 nN *= BigInt( rVal.nDenominator ); 302 BigInt nW1Temp( nDenominator ); 303 nW1Temp *= BigInt( rVal.nNumerator ); 304 nN += nW1Temp; 305 306 BigInt nD( nDenominator ); 307 nD *= BigInt( rVal.nDenominator ); 308 309 Reduce( nN, nD ); 310 311 if ( nN.bIsBig || nD.bIsBig ) 312 { 313 nNumerator = 0; 314 nDenominator = -1; 315 } 316 else 317 { 318 nNumerator = (long)nN, 319 nDenominator = (long)nD; 320 } 321 322 return *this; 323 } 324 325 /************************************************************************* 326 |* 327 |* Fraction::operator-=() 328 |* 329 |* Beschreibung FRACT.SDW 330 |* Ersterstellung DV 20.09.90 331 |* Letzte Aenderung DV 21.12.92 332 |* 333 *************************************************************************/ 334 335 // Zunaechst werden die beiden Parameter auf ihre Gueltigkeit ueberprueft. 336 // Ist einer der Parameter ungueltig, dann ist auch des Ergebnis 337 // ungueltig. Zur Subtraktion werden die beiden Brueche erst durch 338 // Erweiterung mit den Nenner des jeweils anderen Bruches auf einen 339 // gemeinsamen Nenner gebracht. Anschliessend werden die beiden Zaehler 340 // subtrahiert und das Ergebnis gekuerzt (durch Division von Zaehler und 341 // Nenner mit nGGT). Innerhalb der Funktion wird mit dem Datentyp BigInt 342 // gerechnet, um einen Moeglichen Ueberlauf erkennen zu koennen. Bei 343 // einem Ueberlauf wird das Ergebnis auf den Wert ungueltig gesetzt. 344 345 Fraction& Fraction::operator -= ( const Fraction& rVal ) 346 { 347 if ( !rVal.IsValid() ) 348 { 349 nNumerator = 0; 350 nDenominator = -1; 351 } 352 if ( !IsValid() ) 353 return *this; 354 355 // (a/b) - (c/d) = ( (a*d) - (c*b) ) / (b*d) 356 BigInt nN( nNumerator ); 357 nN *= BigInt( rVal.nDenominator ); 358 BigInt nW1Temp( nDenominator ); 359 nW1Temp *= BigInt( rVal.nNumerator ); 360 nN -= nW1Temp; 361 362 BigInt nD( nDenominator ); 363 nD *= BigInt( rVal.nDenominator ); 364 365 Reduce( nN, nD ); 366 367 if ( nN.bIsBig || nD.bIsBig ) 368 { 369 nNumerator = 0; 370 nDenominator = -1; 371 } 372 else 373 { 374 nNumerator = (long)nN, 375 nDenominator = (long)nD; 376 } 377 378 return *this; 379 } 380 381 /************************************************************************* 382 |* 383 |* Fraction::operator*=() 384 |* 385 |* Beschreibung FRACT.SDW 386 |* Ersterstellung DV 20.09.90 387 |* Letzte Aenderung TH 19.08.92 388 |* 389 *************************************************************************/ 390 391 // Zunaechst werden die beiden Parameter auf ihre Gueltigkeit ueberprueft. 392 // Ist einer der Parameter ungueltig, dann ist auch des Ergebnis 393 // ungueltig. Zur Multiplikation werden jeweils die beiden Zaehler und 394 // Nenner miteinander multipliziert. Um Ueberlaufe zu vermeiden, werden 395 // vorher jeweils der GGT zwischen dem Zaehler des einen und dem Nenner 396 // des anderen Bruches bestimmt und bei der Multiplikation Zaehler und 397 // Nenner durch die entsprechenden Werte geteilt. 398 // Innerhalb der Funktion wird mit dem Datentyp BigInt gerechnet, um 399 // einen Moeglichen Ueberlauf erkennen zu koennen. Bei einem Ueberlauf 400 // wird das Ergebnis auf den Wert ungueltig gesetzt. 401 402 Fraction& Fraction::operator *= ( const Fraction& rVal ) 403 { 404 if ( !rVal.IsValid() ) 405 { 406 nNumerator = 0; 407 nDenominator = -1; 408 } 409 if ( !IsValid() ) 410 return *this; 411 412 long nGGT1 = GetGGT( nNumerator, rVal.nDenominator ); 413 long nGGT2 = GetGGT( rVal.nNumerator, nDenominator ); 414 BigInt nN( nNumerator / nGGT1 ); 415 nN *= BigInt( rVal.nNumerator / nGGT2 ); 416 BigInt nD( nDenominator / nGGT2 ); 417 nD *= BigInt( rVal.nDenominator / nGGT1 ); 418 419 if ( nN.bIsBig || nD.bIsBig ) 420 { 421 nNumerator = 0; 422 nDenominator = -1; 423 } 424 else 425 { 426 nNumerator = (long)nN, 427 nDenominator = (long)nD; 428 } 429 430 return *this; 431 } 432 433 /************************************************************************* 434 |* 435 |* Fraction::operator/=() 436 |* 437 |* Beschreibung FRACT.SDW 438 |* Ersterstellung DV 20.09.90 439 |* Letzte Aenderung DV 21.12.92 440 |* 441 *************************************************************************/ 442 443 // Zunaechst werden die beiden Parameter auf ihre Gueltigkeit ueberprueft. 444 // Ist einer der Parameter ungueltig, dann ist auch des Ergebnis 445 // ungueltig. 446 // Um den Bruch a durch b zu teilen, wird a mit dem Kehrwert von b 447 // multipliziert. Analog zu Multiplikation wird jezt jeweils der Zaehler 448 // des einen Bruches mit dem Nenner des anderen multipliziert. 449 // Um Ueberlaufe zu vermeiden, werden vorher jeweils der GGT zwischen den 450 // beiden Zaehlern und den beiden Nennern bestimmt und bei der 451 // Multiplikation Zaehler und Nenner durch die entsprechenden Werte 452 // geteilt. 453 // Innerhalb der Funktion wird mit dem Datentyp BigInt gerechnet, um 454 // einen Moeglichen Ueberlauf erkennen zu koennen. Bei einem Ueberlauf 455 // wird das Ergebnis auf den Wert ungueltig gesetzt. 456 457 Fraction& Fraction::operator /= ( const Fraction& rVal ) 458 { 459 if ( !rVal.IsValid() ) 460 { 461 nNumerator = 0; 462 nDenominator = -1; 463 } 464 if ( !IsValid() ) 465 return *this; 466 467 long nGGT1 = GetGGT( nNumerator, rVal.nNumerator ); 468 long nGGT2 = GetGGT( rVal.nDenominator, nDenominator ); 469 BigInt nN( nNumerator / nGGT1 ); 470 nN *= BigInt( rVal.nDenominator / nGGT2 ); 471 BigInt nD( nDenominator / nGGT2 ); 472 nD *= BigInt( rVal.nNumerator / nGGT1 ); 473 474 if ( nN.bIsBig || nD.bIsBig ) 475 { 476 nNumerator = 0; 477 nDenominator = -1; 478 } 479 else 480 { 481 nNumerator = (long)nN, 482 nDenominator = (long)nD; 483 if ( nDenominator < 0 ) 484 { 485 nDenominator = -nDenominator; 486 nNumerator = -nNumerator; 487 } 488 } 489 490 return *this; 491 } 492 493 /************************************************************************* 494 |* 495 |* Fraction::ReduceInaccurate() 496 |* 497 |* Beschreibung FRACT.SDW 498 |* Ersterstellung JOE 17.09.95 499 |* Letzte Aenderung kendy 2007-06-13 500 |* 501 *************************************************************************/ 502 503 504 // Similar to clz_table that can be googled 505 const char nbits_table[32] = 506 { 507 32, 1, 23, 2, 29, 24, 14, 3, 508 30, 27, 25, 18, 20, 15, 10, 4, 509 31, 22, 28, 13, 26, 17, 19, 9, 510 21, 12, 16, 8, 11, 7, 6, 5 511 }; 512 513 static int impl_NumberOfBits( unsigned long nNum ) 514 { 515 // http://en.wikipedia.org/wiki/De_Bruijn_sequence 516 // 517 // background paper: Using de Bruijn Sequences to Index a 1 in a 518 // Computer Word (1998) Charles E. Leiserson, 519 // Harald Prokop, Keith H. Randall 520 // (e.g. http://citeseer.ist.psu.edu/leiserson98using.html) 521 const sal_uInt32 nDeBruijn = 0x7DCD629; 522 523 if ( nNum == 0 ) 524 return 0; 525 526 // Get it to form like 0000001111111111b 527 nNum |= ( nNum >> 1 ); 528 nNum |= ( nNum >> 2 ); 529 nNum |= ( nNum >> 4 ); 530 nNum |= ( nNum >> 8 ); 531 nNum |= ( nNum >> 16 ); 532 533 sal_uInt32 nNumber; 534 int nBonus = 0; 535 536 #if SAL_TYPES_SIZEOFLONG == 4 537 nNumber = nNum; 538 #elif SAL_TYPES_SIZEOFLONG == 8 539 nNum |= ( nNum >> 32 ); 540 541 if ( nNum & 0x80000000 ) 542 { 543 nNumber = sal_uInt32( nNum >> 32 ); 544 nBonus = 32; 545 546 if ( nNumber == 0 ) 547 return 32; 548 } 549 else 550 nNumber = sal_uInt32( nNum & 0xFFFFFFFF ); 551 #else 552 #error "Unknown size of long!" 553 #endif 554 555 // De facto shift left of nDeBruijn using multiplication (nNumber 556 // is all ones from topmost bit, thus nDeBruijn + (nDeBruijn * 557 // nNumber) => nDeBruijn * (nNumber+1) clears all those bits to 558 // zero, sets the next bit to one, and thus effectively shift-left 559 // nDeBruijn by lg2(nNumber+1). This generates a distinct 5bit 560 // sequence in the msb for each distinct position of the last 561 // leading 0 bit - that's the property of a de Bruijn number. 562 nNumber = nDeBruijn + ( nDeBruijn * nNumber ); 563 564 // 5-bit window indexes the result 565 return ( nbits_table[nNumber >> 27] ) + nBonus; 566 } 567 568 /** Inaccurate cancellation for a fraction. 569 570 Clip both nominator and denominator to said number of bits. If 571 either of those already have equal or less number of bits used, 572 this method does nothing. 573 574 @param nSignificantBits denotes, how many significant binary 575 digits to maintain, in both nominator and denominator. 576 577 @example ReduceInaccurate(8) has an error <1% [1/2^(8-1)] - the 578 largest error occurs with the following pair of values: 579 580 binary 1000000011111111111111111111111b/1000000000000000000000000000000b 581 = 1082130431/1073741824 582 = approx. 1.007812499 583 584 A ReduceInaccurate(8) yields 1/1. 585 */ 586 void Fraction::ReduceInaccurate( unsigned nSignificantBits ) 587 { 588 if ( !nNumerator || !nDenominator ) 589 return; 590 591 // Count with unsigned longs only 592 const bool bNeg = ( nNumerator < 0 ); 593 unsigned long nMul = (unsigned long)( bNeg? -nNumerator: nNumerator ); 594 unsigned long nDiv = (unsigned long)( nDenominator ); 595 596 DBG_ASSERT(nSignificantBits<65, "More than 64 bit of significance is overkill!"); 597 598 // How much bits can we lose? 599 const int nMulBitsToLose = Max( ( impl_NumberOfBits( nMul ) - int( nSignificantBits ) ), 0 ); 600 const int nDivBitsToLose = Max( ( impl_NumberOfBits( nDiv ) - int( nSignificantBits ) ), 0 ); 601 602 const int nToLose = Min( nMulBitsToLose, nDivBitsToLose ); 603 604 // Remove the bits 605 nMul >>= nToLose; 606 nDiv >>= nToLose; 607 608 if ( !nMul || !nDiv ) 609 { 610 // Return without reduction 611 DBG_ERROR( "Oops, we reduced too much..." ); 612 return; 613 } 614 615 // Reduce 616 long n1 = GetGGT( nMul, nDiv ); 617 if ( n1 != 1 ) 618 { 619 nMul /= n1; 620 nDiv /= n1; 621 } 622 623 nNumerator = bNeg? -long( nMul ): long( nMul ); 624 nDenominator = nDiv; 625 } 626 627 /************************************************************************* 628 |* 629 |* Fraction::operator ==() 630 |* 631 |* Beschreibung FRACT.SDW 632 |* Ersterstellung DV 20.09.90 633 |* Letzte Aenderung TH 19.08.92 634 |* 635 *************************************************************************/ 636 637 sal_Bool operator == ( const Fraction& rVal1, const Fraction& rVal2 ) 638 { 639 if ( !rVal1.IsValid() || !rVal2.IsValid() ) 640 return sal_False; 641 642 return rVal1.nNumerator == rVal2.nNumerator 643 && rVal1.nDenominator == rVal2.nDenominator; 644 } 645 646 /************************************************************************* 647 |* 648 |* Fraction::operator <() 649 |* 650 |* Beschreibung FRACT.SDW 651 |* Ersterstellung DV 20.09.90 652 |* Letzte Aenderung DV 21.12.92 653 |* 654 *************************************************************************/ 655 656 // Beide Operanden werden zunaechst auf ihre Gueltigkeit ueberprueft und 657 // anschliessend zur Sicherheit noch einmal gekuerzt. Um die Brueche 658 // (a/b) und (c/d) zu vergleichen, werden sie zunaechst auf einen 659 // gemeinsamen Nenner gebracht (b*d), um dann die beiden Zaehler (a*d) 660 // und (c*b) zu vergleichen. Das Ergebnis dieses Vergleichs wird 661 // zurueckgegeben. 662 663 sal_Bool operator < ( const Fraction& rVal1, const Fraction& rVal2 ) 664 { 665 if ( !rVal1.IsValid() || !rVal2.IsValid() ) 666 return sal_False; 667 668 BigInt nN( rVal1.nNumerator ); 669 nN *= BigInt( rVal2.nDenominator ); 670 BigInt nD( rVal1.nDenominator ); 671 nD *= BigInt( rVal2.nNumerator ); 672 673 return nN < nD; 674 } 675 676 /************************************************************************* 677 |* 678 |* Fraction::operator >() 679 |* 680 |* Beschreibung FRACT.SDW 681 |* Ersterstellung DV 20.09.90 682 |* Letzte Aenderung TH 19.08.92 683 |* 684 *************************************************************************/ 685 686 // Beide Operanden werden zunaechst auf ihre Gueltigkeit ueberprueft und 687 // anschliessend zur Sicherheit noch einmal gekuerzt. Um die Brueche 688 // (a/b) und (c/d) zu vergleichen, werden sie zunaechst auf einen 689 // gemeinsamen Nenner gebracht (b*d), um dann die beiden Zaehler (a*d) 690 // und (c*b) zu vergleichen. Das Ergebnis dieses Vergleichs wird 691 // zurueckgegeben. 692 693 sal_Bool operator > ( const Fraction& rVal1, const Fraction& rVal2 ) 694 { 695 if ( !rVal1.IsValid() || !rVal2.IsValid() ) 696 return sal_False; 697 698 BigInt nN( rVal1.nNumerator ); 699 nN *= BigInt( rVal2.nDenominator ); 700 BigInt nD( rVal1.nDenominator); 701 nD *= BigInt( rVal2.nNumerator ); 702 703 return nN > nD; 704 } 705 706 /************************************************************************* 707 |* 708 |* SvStream& operator>>( SvStream& rIStream, Fraction& rFract ) 709 |* 710 |* Beschreibung FRACT.SDW 711 |* Ersterstellung MM 08.01.96 712 |* Letzte Aenderung MM 08.01.96 713 |* 714 *************************************************************************/ 715 SvStream& operator >> ( SvStream& rIStream, Fraction& rFract ) 716 { 717 rIStream >> rFract.nNumerator; 718 rIStream >> rFract.nDenominator; 719 return rIStream; 720 } 721 722 /************************************************************************* 723 |* 724 |* SvStream& operator<<( SvStream& rIStream, Fraction& rFract ) 725 |* 726 |* Beschreibung FRACT.SDW 727 |* Ersterstellung MM 08.01.96 728 |* Letzte Aenderung MM 08.01.96 729 |* 730 *************************************************************************/ 731 SvStream& operator << ( SvStream& rOStream, const Fraction& rFract ) 732 { 733 rOStream << rFract.nNumerator; 734 rOStream << rFract.nDenominator; 735 return rOStream; 736 } 737