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