public static int av_reduce(/*int *dst_num, int *dst_den,*/int[] num_den, long num, long den, long max) { AVRational a0 = new AVRational(0, 1); AVRational a1 = new AVRational(1, 0); int sign = ((num < 0) ^ (den < 0)) ? 1 : 0; long gcd = av_gcd(Math.Abs(num), Math.Abs(den)); if (gcd != 0) { num = Math.Abs(num) / gcd; den = Math.Abs(den) / gcd; } if (num <= max && den <= max) { a1 = new AVRational(num, den); den = 0; } while (den != 0) { /*uint64_t*/ long x = num / den; long next_den = num - den * x; long a2n = x * a1.num + a0.num; long a2d = x * a1.den + a0.den; if (a2n > max || a2d > max) { if (a1.num != 0) x = (max - a0.num) / a1.num; if (a1.den != 0) x = Math.Min(x, (max - a0.den) / a1.den); if (den * (2 * x * a1.den + a0.den) > num * a1.den) a1 = new AVRational(x * a1.num + a0.num, x * a1.den + a0.den); break; } a0 = a1; a1 = new AVRational(a2n, a2d); num = den; den = next_den; } //av_assert2(av_gcd(a1.num, a1.den) <= 1U); num_den[0] = ((sign != 0) ? -a1.num : a1.num); num_den[1] = a1.den; return (den == 0 ? 1 : 0); }
/** * Compare two rationals. * @param a first rational * @param b second rational * @return 0 if a==b, 1 if a>b, -1 if a<b, and INT_MIN if one of the * values is of the form 0/0 */ /*inline*/ public static int av_cmp_q(AVRational a, AVRational b) { long tmp = a.num * (long)b.den - b.num * (long)a.den; if (tmp != 0) return (int)(((tmp ^ a.den ^ b.den) >> 63) | 1); else if (b.den != 0 && a.den != 0) return 0; else if (a.num != 0 && b.num != 0) return (a.num >> 31) - (b.num >> 31); else return int.MinValue; }