fix toolbar import
[ooovba.git] / tools / source / generic / fract.cxx
blobb2a3536a18413c71f575218b331ae032c8821256
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: fract.cxx,v $
10 * $Revision: 1.9 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_tools.hxx"
34 #ifndef _LIMITS_H
35 #include <limits.h>
36 #endif
37 #include <tools/debug.hxx>
38 #include <tools/fract.hxx>
39 #include <tools/stream.hxx>
41 #include <tools/bigint.hxx>
43 /*************************************************************************
45 |* GetGGT()
47 |* Beschreibung Berechnet den groessten gemeinsamen Teiler von
48 |* nVal1 und nVal2
49 |* Parameter long nVal1, long nVal2
50 |* Ersterstellung DV 20.09.90
51 |* Letzte Aenderung DV 21.12.92
53 *************************************************************************/
55 // Die Funktion GetGGT berechnet den groessten gemeinsamen Teiler der
56 // beiden als Parameter uebergebenen Werte nVal1 und nVal2 nach dem
57 // Algorithmus von Euklid. Hat einer der beiden Parameter den Wert 0 oder
58 // 1, so wird als Ergebnis der Wert 1 zurŸckgegeben. Da der Algorithmus
59 // nur mit positiven Zahlen arbeitet, werden die beiden Parameter
60 // entsprechend umgewandelt.
61 // Zum Algorithmus: die beiden Parameter werden solange ducheinander
62 // geteilt, bis sie beide gleich sind oder bis bei der Division
63 // kein Rest bleibt. Der kleinere der beiden Werte ist dann der
64 // GGT.
66 static long GetGGT( long nVal1, long nVal2 )
68 nVal1 = Abs( nVal1 );
69 nVal2 = Abs( nVal2 );
71 if ( nVal1 <= 1 || nVal2 <= 1 )
72 return 1;
74 while ( nVal1 != nVal2 )
76 if ( nVal1 > nVal2 )
78 nVal1 %= nVal2;
79 if ( nVal1 == 0 )
80 return nVal2;
82 else
84 nVal2 %= nVal1;
85 if ( nVal2 == 0 )
86 return nVal1;
90 return nVal1;
93 static void Reduce( BigInt &rVal1, BigInt &rVal2 )
95 BigInt nA( rVal1 );
96 BigInt nB( rVal2 );
97 nA.Abs();
98 nB.Abs();
100 if ( nA.IsOne() || nB.IsOne() || nA.IsZero() || nB.IsZero() )
101 return;
103 while ( nA != nB )
105 if ( nA > nB )
107 nA %= nB;
108 if ( nA.IsZero() )
110 rVal1 /= nB;
111 rVal2 /= nB;
112 return;
115 else
117 nB %= nA;
118 if ( nB.IsZero() )
120 rVal1 /= nA;
121 rVal2 /= nA;
122 return;
127 rVal1 /= nA;
128 rVal2 /= nB;
131 /*************************************************************************
133 |* Fraction::Fraction()
135 |* Beschreibung FRACT.SDW
136 |* Ersterstellung WP 07.03.97
137 |* Letzte Aenderung
139 *************************************************************************/
141 Fraction::Fraction( long nN1, long nN2, long nD1, long nD2 )
143 long n;
144 int i = 1;
146 if( nN1 < 0 ) { i = -i; nN1 = -nN1; }
147 if( nN2 < 0 ) { i = -i; nN2 = -nN2; }
148 if( nD1 < 0 ) { i = -i; nD1 = -nD1; }
149 if( nD2 < 0 ) { i = -i; nD2 = -nD2; }
151 n = GetGGT( nN1, nD1 ); if( n > 1 ) { nN1 /= n; nD1 /= n; }
152 n = GetGGT( nN1, nD2 ); if( n > 1 ) { nN1 /= n; nD2 /= n; }
153 n = GetGGT( nN2, nD1 ); if( n > 1 ) { nN2 /= n; nD1 /= n; }
154 n = GetGGT( nN2, nD2 ); if( n > 1 ) { nN2 /= n; nD2 /= n; }
156 BigInt nN( nN1 );
157 nN *= BigInt( nN2 );
159 BigInt nD( nD1 );
160 nD *= BigInt( nD2 );
162 while ( nN.bIsBig || nD.bIsBig )
164 BigInt n1 = 1;
165 BigInt n2 = 2;
167 nN += n1;
168 nN /= n2;
169 nD += n1;
170 nD /= n2;
172 // Kuerzen ueber Groesste Gemeinsame Teiler
173 Reduce( nN, nD );
176 nNumerator = i * (long)nN;
177 nDenominator = (long)nD;
180 /*************************************************************************
182 |* Fraction::Fraction()
184 |* Beschreibung FRACT.SDW
185 |* Ersterstellung DV 20.09.90
186 |* Letzte Aenderung DV 21.12.92
188 *************************************************************************/
190 // Zur Initialisierung eines Bruches wird nNum dem Zaehler und nDen dem
191 // Nenner zugewiesen. Da negative Werte des Nenners einen Bruch als
192 // ungueltig kennzeichnen, wird bei der Eingabe eines negativen Nenners
193 // sowohl das Vorzeichen des Nenners und des Zaehlers invertiert um wieder
194 // einen gueltigen Wert fuer den Bruch zu erhalten.
196 Fraction::Fraction( long nNum, long nDen )
198 nNumerator = nNum;
199 nDenominator = nDen;
200 if ( nDenominator < 0 )
202 nDenominator = -nDenominator;
203 nNumerator = -nNumerator;
206 // Kuerzen ueber Groesste Gemeinsame Teiler
207 long n = GetGGT( nNumerator, nDenominator );
208 nNumerator /= n;
209 nDenominator /= n;
212 /*************************************************************************
214 |* Fraction::Fraction()
216 |* Beschreibung FRACT.SDW
217 |* Ersterstellung DV 20.09.90
218 |* Letzte Aenderung DV 21.12.92
220 *************************************************************************/
222 // Wenn der Wert von dVal groesser ist als LONG_MAX, dann wird der Bruch
223 // auf den Wert ungueltig gesetzt, ansonsten werden dVal und der Nenner
224 // solange mit 10 multipliziert, bis entweder der Zaehler oder der Nenner
225 // groesser als LONG_MAX / 10 ist. Zum Schluss wird der so entstandene Bruch
226 // gekuerzt.
228 Fraction::Fraction( double dVal )
230 long nDen = 1;
231 long nMAX = LONG_MAX / 10;
233 if ( dVal > LONG_MAX || dVal < LONG_MIN )
235 nNumerator = 0;
236 nDenominator = -1;
237 return;
240 while ( Abs( (long)dVal ) < nMAX && nDen < nMAX )
242 dVal *= 10;
243 nDen *= 10;
245 nNumerator = (long)dVal;
246 nDenominator = nDen;
248 // Kuerzen ueber Groesste Gemeinsame Teiler
249 long n = GetGGT( nNumerator, nDenominator );
250 nNumerator /= n;
251 nDenominator /= n;
254 /*************************************************************************
256 |* Fraction::operator double()
258 |* Beschreibung FRACT.SDW
259 |* Ersterstellung DV 20.09.90
260 |* Letzte Aenderung DV 14.05.91
262 *************************************************************************/
264 Fraction::operator double() const
266 if ( nDenominator > 0 )
267 return (double)nNumerator / (double)nDenominator;
268 else
269 return (double)0;
272 /*************************************************************************
274 |* Fraction::operator+=()
276 |* Beschreibung FRACT.SDW
277 |* Ersterstellung DV 20.09.90
278 |* Letzte Aenderung DV 21.12.92
280 *************************************************************************/
282 // Zunaechst werden die beiden Parameter auf ihre Gueltigkeit ueberprueft.
283 // Ist einer der Parameter ungueltig, dann ist auch des Ergebnis
284 // ungueltig. Zur Addition werden die beiden Brueche erst durch
285 // Erweiterung mit den Nenner des jeweils anderen Bruches auf einen
286 // gemeinsamen Nenner gebracht. Anschliessend werden die beiden Zaehler
287 // addiert und das Ergebnis gekuerzt (durch Division von Zaehler und
288 // Nenner mit nGGT). Innerhalb der Funktion wird mit dem Datentyp SLong
289 // gerechnet, um einen Moeglichen Ueberlauf erkennen zu koennen. Bei
290 // einem Ueberlauf wird das Ergebnis auf den Wert ungueltig gesetzt.
292 Fraction& Fraction::operator += ( const Fraction& rVal )
294 if ( !rVal.IsValid() )
296 nNumerator = 0;
297 nDenominator = -1;
299 if ( !IsValid() )
300 return *this;
302 // (a/b) + (c/d) = ( (a*d) + (c*b) ) / (b*d)
303 BigInt nN( nNumerator );
304 nN *= BigInt( rVal.nDenominator );
305 BigInt nW1Temp( nDenominator );
306 nW1Temp *= BigInt( rVal.nNumerator );
307 nN += nW1Temp;
309 BigInt nD( nDenominator );
310 nD *= BigInt( rVal.nDenominator );
312 Reduce( nN, nD );
314 if ( nN.bIsBig || nD.bIsBig )
316 nNumerator = 0;
317 nDenominator = -1;
319 else
321 nNumerator = (long)nN,
322 nDenominator = (long)nD;
325 return *this;
328 /*************************************************************************
330 |* Fraction::operator-=()
332 |* Beschreibung FRACT.SDW
333 |* Ersterstellung DV 20.09.90
334 |* Letzte Aenderung DV 21.12.92
336 *************************************************************************/
338 // Zunaechst werden die beiden Parameter auf ihre Gueltigkeit ueberprueft.
339 // Ist einer der Parameter ungueltig, dann ist auch des Ergebnis
340 // ungueltig. Zur Subtraktion werden die beiden Brueche erst durch
341 // Erweiterung mit den Nenner des jeweils anderen Bruches auf einen
342 // gemeinsamen Nenner gebracht. Anschliessend werden die beiden Zaehler
343 // subtrahiert und das Ergebnis gekuerzt (durch Division von Zaehler und
344 // Nenner mit nGGT). Innerhalb der Funktion wird mit dem Datentyp BigInt
345 // gerechnet, um einen Moeglichen Ueberlauf erkennen zu koennen. Bei
346 // einem Ueberlauf wird das Ergebnis auf den Wert ungueltig gesetzt.
348 Fraction& Fraction::operator -= ( const Fraction& rVal )
350 if ( !rVal.IsValid() )
352 nNumerator = 0;
353 nDenominator = -1;
355 if ( !IsValid() )
356 return *this;
358 // (a/b) - (c/d) = ( (a*d) - (c*b) ) / (b*d)
359 BigInt nN( nNumerator );
360 nN *= BigInt( rVal.nDenominator );
361 BigInt nW1Temp( nDenominator );
362 nW1Temp *= BigInt( rVal.nNumerator );
363 nN -= nW1Temp;
365 BigInt nD( nDenominator );
366 nD *= BigInt( rVal.nDenominator );
368 Reduce( nN, nD );
370 if ( nN.bIsBig || nD.bIsBig )
372 nNumerator = 0;
373 nDenominator = -1;
375 else
377 nNumerator = (long)nN,
378 nDenominator = (long)nD;
381 return *this;
384 /*************************************************************************
386 |* Fraction::operator*=()
388 |* Beschreibung FRACT.SDW
389 |* Ersterstellung DV 20.09.90
390 |* Letzte Aenderung TH 19.08.92
392 *************************************************************************/
394 // Zunaechst werden die beiden Parameter auf ihre Gueltigkeit ueberprueft.
395 // Ist einer der Parameter ungueltig, dann ist auch des Ergebnis
396 // ungueltig. Zur Multiplikation werden jeweils die beiden Zaehler und
397 // Nenner miteinander multipliziert. Um Ueberlaufe zu vermeiden, werden
398 // vorher jeweils der GGT zwischen dem Zaehler des einen und dem Nenner
399 // des anderen Bruches bestimmt und bei der Multiplikation Zaehler und
400 // Nenner durch die entsprechenden Werte geteilt.
401 // Innerhalb der Funktion wird mit dem Datentyp BigInt gerechnet, um
402 // einen Moeglichen Ueberlauf erkennen zu koennen. Bei einem Ueberlauf
403 // wird das Ergebnis auf den Wert ungueltig gesetzt.
405 Fraction& Fraction::operator *= ( const Fraction& rVal )
407 if ( !rVal.IsValid() )
409 nNumerator = 0;
410 nDenominator = -1;
412 if ( !IsValid() )
413 return *this;
415 long nGGT1 = GetGGT( nNumerator, rVal.nDenominator );
416 long nGGT2 = GetGGT( rVal.nNumerator, nDenominator );
417 BigInt nN( nNumerator / nGGT1 );
418 nN *= BigInt( rVal.nNumerator / nGGT2 );
419 BigInt nD( nDenominator / nGGT2 );
420 nD *= BigInt( rVal.nDenominator / nGGT1 );
422 if ( nN.bIsBig || nD.bIsBig )
424 nNumerator = 0;
425 nDenominator = -1;
427 else
429 nNumerator = (long)nN,
430 nDenominator = (long)nD;
433 return *this;
436 /*************************************************************************
438 |* Fraction::operator/=()
440 |* Beschreibung FRACT.SDW
441 |* Ersterstellung DV 20.09.90
442 |* Letzte Aenderung DV 21.12.92
444 *************************************************************************/
446 // Zunaechst werden die beiden Parameter auf ihre Gueltigkeit ueberprueft.
447 // Ist einer der Parameter ungueltig, dann ist auch des Ergebnis
448 // ungueltig.
449 // Um den Bruch a durch b zu teilen, wird a mit dem Kehrwert von b
450 // multipliziert. Analog zu Multiplikation wird jezt jeweils der Zaehler
451 // des einen Bruches mit dem Nenner des anderen multipliziert.
452 // Um Ueberlaufe zu vermeiden, werden vorher jeweils der GGT zwischen den
453 // beiden Zaehlern und den beiden Nennern bestimmt und bei der
454 // Multiplikation Zaehler und Nenner durch die entsprechenden Werte
455 // geteilt.
456 // Innerhalb der Funktion wird mit dem Datentyp BigInt gerechnet, um
457 // einen Moeglichen Ueberlauf erkennen zu koennen. Bei einem Ueberlauf
458 // wird das Ergebnis auf den Wert ungueltig gesetzt.
460 Fraction& Fraction::operator /= ( const Fraction& rVal )
462 if ( !rVal.IsValid() )
464 nNumerator = 0;
465 nDenominator = -1;
467 if ( !IsValid() )
468 return *this;
470 long nGGT1 = GetGGT( nNumerator, rVal.nNumerator );
471 long nGGT2 = GetGGT( rVal.nDenominator, nDenominator );
472 BigInt nN( nNumerator / nGGT1 );
473 nN *= BigInt( rVal.nDenominator / nGGT2 );
474 BigInt nD( nDenominator / nGGT2 );
475 nD *= BigInt( rVal.nNumerator / nGGT1 );
477 if ( nN.bIsBig || nD.bIsBig )
479 nNumerator = 0;
480 nDenominator = -1;
482 else
484 nNumerator = (long)nN,
485 nDenominator = (long)nD;
486 if ( nDenominator < 0 )
488 nDenominator = -nDenominator;
489 nNumerator = -nNumerator;
493 return *this;
496 /*************************************************************************
498 |* Fraction::ReduceInaccurate()
500 |* Beschreibung FRACT.SDW
501 |* Ersterstellung JOE 17.09.95
502 |* Letzte Aenderung kendy 2007-06-13
504 *************************************************************************/
507 // Similar to clz_table that can be googled
508 const char nbits_table[32] =
510 32, 1, 23, 2, 29, 24, 14, 3,
511 30, 27, 25, 18, 20, 15, 10, 4,
512 31, 22, 28, 13, 26, 17, 19, 9,
513 21, 12, 16, 8, 11, 7, 6, 5
516 static int impl_NumberOfBits( unsigned long nNum )
518 // http://en.wikipedia.org/wiki/De_Bruijn_sequence
520 // background paper: Using de Bruijn Sequences to Index a 1 in a
521 // Computer Word (1998) Charles E. Leiserson,
522 // Harald Prokop, Keith H. Randall
523 // (e.g. http://citeseer.ist.psu.edu/leiserson98using.html)
524 const sal_uInt32 nDeBruijn = 0x7DCD629;
526 if ( nNum == 0 )
527 return 0;
529 // Get it to form like 0000001111111111b
530 nNum |= ( nNum >> 1 );
531 nNum |= ( nNum >> 2 );
532 nNum |= ( nNum >> 4 );
533 nNum |= ( nNum >> 8 );
534 nNum |= ( nNum >> 16 );
536 sal_uInt32 nNumber;
537 int nBonus = 0;
539 #if SAL_TYPES_SIZEOFLONG == 4
540 nNumber = nNum;
541 #elif SAL_TYPES_SIZEOFLONG == 8
542 nNum |= ( nNum >> 32 );
544 if ( nNum & 0x80000000 )
546 nNumber = sal_uInt32( nNum >> 32 );
547 nBonus = 32;
549 if ( nNumber == 0 )
550 return 32;
552 else
553 nNumber = sal_uInt32( nNum & 0xFFFFFFFF );
554 #else
555 #error "Unknown size of long!"
556 #endif
558 // De facto shift left of nDeBruijn using multiplication (nNumber
559 // is all ones from topmost bit, thus nDeBruijn + (nDeBruijn *
560 // nNumber) => nDeBruijn * (nNumber+1) clears all those bits to
561 // zero, sets the next bit to one, and thus effectively shift-left
562 // nDeBruijn by lg2(nNumber+1). This generates a distinct 5bit
563 // sequence in the msb for each distinct position of the last
564 // leading 0 bit - that's the property of a de Bruijn number.
565 nNumber = nDeBruijn + ( nDeBruijn * nNumber );
567 // 5-bit window indexes the result
568 return ( nbits_table[nNumber >> 27] ) + nBonus;
571 /** Inaccurate cancellation for a fraction.
573 Clip both nominator and denominator to said number of bits. If
574 either of those already have equal or less number of bits used,
575 this method does nothing.
577 @param nSignificantBits denotes, how many significant binary
578 digits to maintain, in both nominator and denominator.
580 @example ReduceInaccurate(8) has an error <1% [1/2^(8-1)] - the
581 largest error occurs with the following pair of values:
583 binary 1000000011111111111111111111111b/1000000000000000000000000000000b
584 = 1082130431/1073741824
585 = approx. 1.007812499
587 A ReduceInaccurate(8) yields 1/1.
589 void Fraction::ReduceInaccurate( unsigned nSignificantBits )
591 if ( !nNumerator || !nDenominator )
592 return;
594 // Count with unsigned longs only
595 const bool bNeg = ( nNumerator < 0 );
596 unsigned long nMul = (unsigned long)( bNeg? -nNumerator: nNumerator );
597 unsigned long nDiv = (unsigned long)( nDenominator );
599 DBG_ASSERT(nSignificantBits<65, "More than 64 bit of significance is overkill!");
601 // How much bits can we lose?
602 const int nMulBitsToLose = Max( ( impl_NumberOfBits( nMul ) - int( nSignificantBits ) ), 0 );
603 const int nDivBitsToLose = Max( ( impl_NumberOfBits( nDiv ) - int( nSignificantBits ) ), 0 );
605 const int nToLose = Min( nMulBitsToLose, nDivBitsToLose );
607 // Remove the bits
608 nMul >>= nToLose;
609 nDiv >>= nToLose;
611 if ( !nMul || !nDiv )
613 // Return without reduction
614 DBG_ERROR( "Oops, we reduced too much..." );
615 return;
618 // Reduce
619 long n1 = GetGGT( nMul, nDiv );
620 if ( n1 != 1 )
622 nMul /= n1;
623 nDiv /= n1;
626 nNumerator = bNeg? -long( nMul ): long( nMul );
627 nDenominator = nDiv;
630 /*************************************************************************
632 |* Fraction::operator ==()
634 |* Beschreibung FRACT.SDW
635 |* Ersterstellung DV 20.09.90
636 |* Letzte Aenderung TH 19.08.92
638 *************************************************************************/
640 BOOL operator == ( const Fraction& rVal1, const Fraction& rVal2 )
642 if ( !rVal1.IsValid() || !rVal2.IsValid() )
643 return FALSE;
645 return rVal1.nNumerator == rVal2.nNumerator
646 && rVal1.nDenominator == rVal2.nDenominator;
649 /*************************************************************************
651 |* Fraction::operator <()
653 |* Beschreibung FRACT.SDW
654 |* Ersterstellung DV 20.09.90
655 |* Letzte Aenderung DV 21.12.92
657 *************************************************************************/
659 // Beide Operanden werden zunaechst auf ihre Gueltigkeit ueberprueft und
660 // anschliessend zur Sicherheit noch einmal gekuerzt. Um die Brueche
661 // (a/b) und (c/d) zu vergleichen, werden sie zunaechst auf einen
662 // gemeinsamen Nenner gebracht (b*d), um dann die beiden Zaehler (a*d)
663 // und (c*b) zu vergleichen. Das Ergebnis dieses Vergleichs wird
664 // zurueckgegeben.
666 BOOL operator < ( const Fraction& rVal1, const Fraction& rVal2 )
668 if ( !rVal1.IsValid() || !rVal2.IsValid() )
669 return FALSE;
671 BigInt nN( rVal1.nNumerator );
672 nN *= BigInt( rVal2.nDenominator );
673 BigInt nD( rVal1.nDenominator );
674 nD *= BigInt( rVal2.nNumerator );
676 return nN < nD;
679 /*************************************************************************
681 |* Fraction::operator >()
683 |* Beschreibung FRACT.SDW
684 |* Ersterstellung DV 20.09.90
685 |* Letzte Aenderung TH 19.08.92
687 *************************************************************************/
689 // Beide Operanden werden zunaechst auf ihre Gueltigkeit ueberprueft und
690 // anschliessend zur Sicherheit noch einmal gekuerzt. Um die Brueche
691 // (a/b) und (c/d) zu vergleichen, werden sie zunaechst auf einen
692 // gemeinsamen Nenner gebracht (b*d), um dann die beiden Zaehler (a*d)
693 // und (c*b) zu vergleichen. Das Ergebnis dieses Vergleichs wird
694 // zurueckgegeben.
696 BOOL operator > ( const Fraction& rVal1, const Fraction& rVal2 )
698 if ( !rVal1.IsValid() || !rVal2.IsValid() )
699 return FALSE;
701 BigInt nN( rVal1.nNumerator );
702 nN *= BigInt( rVal2.nDenominator );
703 BigInt nD( rVal1.nDenominator);
704 nD *= BigInt( rVal2.nNumerator );
706 return nN > nD;
709 /*************************************************************************
711 |* SvStream& operator>>( SvStream& rIStream, Fraction& rFract )
713 |* Beschreibung FRACT.SDW
714 |* Ersterstellung MM 08.01.96
715 |* Letzte Aenderung MM 08.01.96
717 *************************************************************************/
718 SvStream& operator >> ( SvStream& rIStream, Fraction& rFract )
720 rIStream >> rFract.nNumerator;
721 rIStream >> rFract.nDenominator;
722 return rIStream;
725 /*************************************************************************
727 |* SvStream& operator<<( SvStream& rIStream, Fraction& rFract )
729 |* Beschreibung FRACT.SDW
730 |* Ersterstellung MM 08.01.96
731 |* Letzte Aenderung MM 08.01.96
733 *************************************************************************/
734 SvStream& operator << ( SvStream& rOStream, const Fraction& rFract )
736 rOStream << rFract.nNumerator;
737 rOStream << rFract.nDenominator;
738 return rOStream;