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