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 #include <resourcemodel/Fraction.hxx>
25 
26 namespace writerfilter {
27 namespace resourcemodel {
28 
gcd(sal_uInt32 a,sal_uInt32 b)29 sal_uInt32 gcd(sal_uInt32 a, sal_uInt32 b)
30 {
31     if (a == 0 || b == 0)
32         return a | b;
33 
34     sal_uInt32 nShift = 0;
35     while (((a | b) & 1) == 0)
36     {
37         a >>= 1;
38         b >>= 1;
39         ++nShift;
40     }
41 
42     while ((a & 1) == 0)
43         a >>= 1;
44 
45     do
46     {
47         while ((b & 1) == 0)
48             b >>= 1;
49 
50         if (a < b)
51         {
52             b -= a;
53         }
54         else
55         {
56             sal_uInt32 nDiff = a - b;
57             a = b;
58             b = nDiff;
59         }
60 
61         b >>= 1;
62     }
63     while (b != 0);
64 
65     return a << nShift;
66 }
67 
lcm(sal_Int32 a,sal_Int32 b)68 sal_uInt32 lcm(sal_Int32 a, sal_Int32 b)
69 {
70     return abs(a * b) / gcd(abs(a), abs(b));
71 }
72 
Fraction(sal_Int32 nNumerator,sal_Int32 nDenominator)73 Fraction::Fraction(sal_Int32 nNumerator, sal_Int32 nDenominator)
74 {
75     init(nNumerator, nDenominator);
76 }
77 
Fraction(const Fraction & a,const Fraction & b)78 Fraction::Fraction(const Fraction & a, const Fraction & b)
79 {
80     init(a.mnNumerator * b.mnDenominator, a.mnDenominator * b.mnNumerator);
81 }
82 
~Fraction()83 Fraction::~Fraction()
84 {
85 }
86 
init(sal_Int32 nNumerator,sal_Int32 nDenominator)87 void Fraction::init(sal_Int32 nNumerator, sal_Int32 nDenominator)
88 {
89     sal_uInt32 nGCD = gcd(nNumerator, nDenominator);
90 
91     mnNumerator = nNumerator/ nGCD;
92     mnDenominator = nDenominator / nGCD;
93 }
94 
assign(const Fraction & rFraction)95 void Fraction::assign(const Fraction & rFraction)
96 {
97     init(rFraction.mnNumerator, rFraction.mnDenominator);
98 }
99 
inverse() const100 Fraction Fraction::inverse() const
101 {
102     return Fraction(mnDenominator, mnNumerator);
103 }
104 
operator +(const Fraction & rFraction) const105 Fraction Fraction::operator + (const Fraction & rFraction) const
106 {
107     sal_uInt32 nLCM = lcm(mnDenominator, rFraction.mnDenominator);
108 
109     return Fraction(mnNumerator * nLCM / mnDenominator + rFraction.mnNumerator * nLCM / rFraction.mnDenominator, nLCM);
110 }
111 
operator -(const Fraction & rFraction) const112 Fraction Fraction::operator - (const Fraction & rFraction) const
113 {
114     sal_uInt32 nLCM = lcm(mnDenominator, rFraction.mnDenominator);
115 
116     return Fraction(mnNumerator * nLCM / mnDenominator - rFraction.mnNumerator * nLCM / rFraction.mnDenominator, nLCM);
117 }
118 
operator *(const Fraction & rFraction) const119 Fraction Fraction::operator * (const Fraction & rFraction) const
120 {
121     return Fraction(mnNumerator * rFraction.mnNumerator, mnDenominator * rFraction.mnDenominator);
122 }
123 
operator /(const Fraction & rFraction) const124 Fraction Fraction::operator / (const Fraction & rFraction) const
125 {
126     return *this * rFraction.inverse();
127 }
128 
operator =(const Fraction & rFraction)129 Fraction Fraction::operator = (const Fraction & rFraction)
130 {
131     assign(rFraction);
132 
133     return *this;
134 }
135 
operator sal_Int32() const136 Fraction::operator sal_Int32() const
137 {
138     return mnNumerator / mnDenominator;
139 }
140 
141 Fraction::operator float() const
142 {
143     return static_cast<float>(mnNumerator) / static_cast<float>(mnDenominator);
144 }
145 
146 }}
147