Bump version to 4.3-4
[LibreOffice.git] / writerfilter / source / resourcemodel / Fraction.cxx
blobba76985150a4110a410a2b0504bd2de22cd27129
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <resourcemodel/Fraction.hxx>
22 namespace writerfilter {
23 namespace resourcemodel {
25 // Stein's binary GCD for non-negative integers
26 // https://en.wikipedia.org/wiki/Binary_GCD_algorithm
27 static sal_uInt32 gcd(sal_uInt32 a, sal_uInt32 b)
29 if (a == 0 || b == 0)
30 return a | b;
32 sal_uInt32 nShift = 0;
33 while (((a | b) & 1) == 0)
35 a >>= 1;
36 b >>= 1;
37 ++nShift;
40 while ((a & 1) == 0)
41 a >>= 1;
45 while ((b & 1) == 0)
46 b >>= 1;
48 if (a < b)
50 b -= a;
52 else
54 sal_uInt32 nDiff = a - b;
55 a = b;
56 b = nDiff;
59 b >>= 1;
61 while (b != 0);
63 return a << nShift;
66 static sal_uInt32 lcm(sal_Int32 a, sal_Int32 b)
68 return abs(a * b) / gcd(abs(a), abs(b));
71 Fraction::Fraction(sal_Int32 nNumerator, sal_Int32 nDenominator)
73 init(nNumerator, nDenominator);
76 Fraction::~Fraction()
80 void Fraction::init(sal_Int32 nNumerator, sal_Int32 nDenominator)
82 // fdo#41068 pass non-negative numbers to gcd
83 sal_Int32 const nGCD = gcd(abs(nNumerator), abs(nDenominator));
85 // fdo#76803 do signed division
86 mnNumerator = nNumerator / nGCD;
87 mnDenominator = nDenominator / nGCD;
90 void Fraction::assign(const Fraction & rFraction)
92 init(rFraction.mnNumerator, rFraction.mnDenominator);
95 Fraction Fraction::inverse() const
97 return Fraction(mnDenominator, mnNumerator);
100 Fraction Fraction::operator + (const Fraction & rFraction) const
102 sal_uInt32 nLCM = lcm(mnDenominator, rFraction.mnDenominator);
104 return Fraction(mnNumerator * nLCM / mnDenominator + rFraction.mnNumerator * nLCM / rFraction.mnDenominator, nLCM);
107 Fraction Fraction::operator - (const Fraction & rFraction) const
109 sal_uInt32 nLCM = lcm(mnDenominator, rFraction.mnDenominator);
111 return Fraction(mnNumerator * nLCM / mnDenominator - rFraction.mnNumerator * nLCM / rFraction.mnDenominator, nLCM);
114 Fraction Fraction::operator * (const Fraction & rFraction) const
116 return Fraction(mnNumerator * rFraction.mnNumerator, mnDenominator * rFraction.mnDenominator);
119 Fraction Fraction::operator / (const Fraction & rFraction) const
121 return *this * rFraction.inverse();
124 Fraction Fraction::operator = (const Fraction & rFraction)
126 assign(rFraction);
128 return *this;
131 Fraction::operator sal_Int32() const
133 return mnNumerator / mnDenominator;
136 Fraction::operator float() const
138 return static_cast<float>(mnNumerator) / static_cast<float>(mnDenominator);
143 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */