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
Campbell Barton e4aac6
static 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
Campbell Barton e4aac6
#if 0 /* UNUSED */
Jaroslav 203cc8
int leastCommonMultiple(int a, int b) {
Jaroslav 203cc8
  return a * b / greatestCommonDivisor(a, b);
Jaroslav 203cc8
}
Campbell Barton e4aac6
#endif
Jaroslav 203cc8
Jaroslav 203cc8
void Ratio::normalize() {
Campbell Barton e4aac6
  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; }