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