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