|
Jaroslav |
203cc8 |
#include "toonz/cellpositionratio.h"
|
|
Jaroslav |
203cc8 |
|
|
Jaroslav |
203cc8 |
#include <stdexcept></stdexcept>
|
|
Jaroslav |
203cc8 |
#include <algorithm></algorithm>
|
|
Jaroslav |
203cc8 |
|
|
Jaroslav |
203cc8 |
// Euclid's algorithm
|
|
Jaroslav |
203cc8 |
int greatestCommonDivisor(int a, int b) {
|
|
Jaroslav |
203cc8 |
a = std::abs(a);
|
|
Jaroslav |
203cc8 |
b = std::abs(b);
|
|
Jaroslav |
203cc8 |
int c = std::max(a, b);
|
|
Jaroslav |
203cc8 |
int d = std::min(a, b);
|
|
Jaroslav |
203cc8 |
while (d) {
|
|
Jaroslav |
203cc8 |
int q = c / d;
|
|
Jaroslav |
203cc8 |
int r = c % d;
|
|
Jaroslav |
203cc8 |
c = d;
|
|
Jaroslav |
203cc8 |
d = r;
|
|
Jaroslav |
203cc8 |
}
|
|
Jaroslav |
203cc8 |
return c;
|
|
Jaroslav |
203cc8 |
}
|
|
Jaroslav |
203cc8 |
|
|
Jaroslav |
203cc8 |
int leastCommonMultiple(int a, int b) {
|
|
Jaroslav |
203cc8 |
return a * b / greatestCommonDivisor(a, b);
|
|
Jaroslav |
203cc8 |
}
|
|
Jaroslav |
203cc8 |
|
|
Jaroslav |
203cc8 |
void Ratio::normalize() {
|
|
Jaroslav |
203cc8 |
int gcd = greatestCommonDivisor(m_num, m_denom);
|
|
Jaroslav |
203cc8 |
if (m_denom < 0) gcd = -gcd;
|
|
Jaroslav |
203cc8 |
m_num /= gcd;
|
|
Jaroslav |
203cc8 |
m_denom /= gcd;
|
|
Jaroslav |
203cc8 |
}
|
|
Jaroslav |
203cc8 |
|
|
Jaroslav |
203cc8 |
Ratio Ratio::normalized() const {
|
|
Jaroslav |
203cc8 |
Ratio copy(*this);
|
|
Jaroslav |
203cc8 |
copy.normalize();
|
|
Jaroslav |
203cc8 |
return copy;
|
|
Jaroslav |
203cc8 |
}
|
|
Jaroslav |
203cc8 |
|
|
Jaroslav |
203cc8 |
Ratio::Ratio(int num, int denom) : m_num(num), m_denom(denom) {
|
|
Jaroslav |
203cc8 |
if (!denom) throw std::runtime_error("ratio with denominator == 0");
|
|
Jaroslav |
203cc8 |
normalize();
|
|
Jaroslav |
203cc8 |
}
|
|
Jaroslav |
203cc8 |
|
|
Jaroslav |
203cc8 |
Ratio operator*(const Ratio &a, const Ratio &b) {
|
|
Jaroslav |
203cc8 |
return Ratio(a.m_num * b.m_num, a.m_denom * b.m_denom);
|
|
Jaroslav |
203cc8 |
}
|
|
Jaroslav |
203cc8 |
Ratio operator/(const Ratio &a, const Ratio &b) {
|
|
Jaroslav |
203cc8 |
return Ratio(a.m_num * b.m_denom, a.m_denom * b.m_num);
|
|
Jaroslav |
203cc8 |
}
|
|
Jaroslav |
203cc8 |
|
|
Jaroslav |
203cc8 |
Ratio operator+(const Ratio &a, const Ratio &b) {
|
|
Jaroslav |
203cc8 |
int gcd = greatestCommonDivisor(a.m_denom, b.m_denom);
|
|
Jaroslav |
203cc8 |
int denom = a.m_denom * b.m_denom / gcd;
|
|
Jaroslav |
203cc8 |
int aMult = b.m_denom * gcd;
|
|
Jaroslav |
203cc8 |
int bMult = a.m_denom * gcd;
|
|
Jaroslav |
203cc8 |
return Ratio(a.m_num * aMult + b.m_num * bMult, denom);
|
|
Jaroslav |
203cc8 |
}
|
|
Jaroslav |
203cc8 |
|
|
Jaroslav |
203cc8 |
Ratio operator-(const Ratio &a, const Ratio &b) {
|
|
Jaroslav |
203cc8 |
int gcd = greatestCommonDivisor(a.m_denom, b.m_denom);
|
|
Jaroslav |
203cc8 |
int denom = a.m_denom * b.m_denom / gcd;
|
|
Jaroslav |
203cc8 |
int aMult = b.m_denom * gcd;
|
|
Jaroslav |
203cc8 |
int bMult = a.m_denom * gcd;
|
|
Jaroslav |
203cc8 |
return Ratio(a.m_num * aMult - b.m_num * bMult, denom);
|
|
Jaroslav |
203cc8 |
}
|
|
Jaroslav |
203cc8 |
|
|
Jaroslav |
203cc8 |
int operator*(const Ratio &a, int b) { return a.m_num * b / a.m_denom; }
|