1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
)
32 sal_uInt32 nShift
= 0;
33 while (((a
| b
) & 1) == 0)
54 sal_uInt32 nDiff
= a
- b
;
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
);
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
)
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: */