1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: fract.cxx,v $
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"
37 #include <tools/debug.hxx>
38 #include <tools/fract.hxx>
39 #include <tools/stream.hxx>
41 #include <tools/bigint.hxx>
43 /*************************************************************************
47 |* Beschreibung Berechnet den groessten gemeinsamen Teiler von
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
66 static long GetGGT( long nVal1
, long nVal2
)
71 if ( nVal1
<= 1 || nVal2
<= 1 )
74 while ( nVal1
!= nVal2
)
93 static void Reduce( BigInt
&rVal1
, BigInt
&rVal2
)
100 if ( nA
.IsOne() || nB
.IsOne() || nA
.IsZero() || nB
.IsZero() )
131 /*************************************************************************
133 |* Fraction::Fraction()
135 |* Beschreibung FRACT.SDW
136 |* Ersterstellung WP 07.03.97
139 *************************************************************************/
141 Fraction::Fraction( long nN1
, long nN2
, long nD1
, long nD2
)
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
; }
162 while ( nN
.bIsBig
|| nD
.bIsBig
)
172 // Kuerzen ueber Groesste Gemeinsame Teiler
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
)
200 if ( nDenominator
< 0 )
202 nDenominator
= -nDenominator
;
203 nNumerator
= -nNumerator
;
206 // Kuerzen ueber Groesste Gemeinsame Teiler
207 long n
= GetGGT( nNumerator
, nDenominator
);
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
228 Fraction::Fraction( double dVal
)
231 long nMAX
= LONG_MAX
/ 10;
233 if ( dVal
> LONG_MAX
|| dVal
< LONG_MIN
)
240 while ( Abs( (long)dVal
) < nMAX
&& nDen
< nMAX
)
245 nNumerator
= (long)dVal
;
248 // Kuerzen ueber Groesste Gemeinsame Teiler
249 long n
= GetGGT( nNumerator
, nDenominator
);
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
;
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() )
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
);
309 BigInt
nD( nDenominator
);
310 nD
*= BigInt( rVal
.nDenominator
);
314 if ( nN
.bIsBig
|| nD
.bIsBig
)
321 nNumerator
= (long)nN
,
322 nDenominator
= (long)nD
;
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() )
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
);
365 BigInt
nD( nDenominator
);
366 nD
*= BigInt( rVal
.nDenominator
);
370 if ( nN
.bIsBig
|| nD
.bIsBig
)
377 nNumerator
= (long)nN
,
378 nDenominator
= (long)nD
;
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() )
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
)
429 nNumerator
= (long)nN
,
430 nDenominator
= (long)nD
;
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
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
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() )
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
)
484 nNumerator
= (long)nN
,
485 nDenominator
= (long)nD
;
486 if ( nDenominator
< 0 )
488 nDenominator
= -nDenominator
;
489 nNumerator
= -nNumerator
;
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;
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 );
539 #if SAL_TYPES_SIZEOFLONG == 4
541 #elif SAL_TYPES_SIZEOFLONG == 8
542 nNum
|= ( nNum
>> 32 );
544 if ( nNum
& 0x80000000 )
546 nNumber
= sal_uInt32( nNum
>> 32 );
553 nNumber
= sal_uInt32( nNum
& 0xFFFFFFFF );
555 #error "Unknown size of long!"
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
)
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
);
611 if ( !nMul
|| !nDiv
)
613 // Return without reduction
614 DBG_ERROR( "Oops, we reduced too much..." );
619 long n1
= GetGGT( nMul
, nDiv
);
626 nNumerator
= bNeg
? -long( nMul
): long( nMul
);
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() )
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
666 BOOL
operator < ( const Fraction
& rVal1
, const Fraction
& rVal2
)
668 if ( !rVal1
.IsValid() || !rVal2
.IsValid() )
671 BigInt
nN( rVal1
.nNumerator
);
672 nN
*= BigInt( rVal2
.nDenominator
);
673 BigInt
nD( rVal1
.nDenominator
);
674 nD
*= BigInt( rVal2
.nNumerator
);
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
696 BOOL
operator > ( const Fraction
& rVal1
, const Fraction
& rVal2
)
698 if ( !rVal1
.IsValid() || !rVal2
.IsValid() )
701 BigInt
nN( rVal1
.nNumerator
);
702 nN
*= BigInt( rVal2
.nDenominator
);
703 BigInt
nD( rVal1
.nDenominator
);
704 nD
*= BigInt( rVal2
.nNumerator
);
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
;
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
;