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