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