// -*- Mode: C -*- // // Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // rational.c -- // // Author : Peter A. Buhr // Created On : Wed Apr 6 17:54:28 2016 // Last Modified By : Peter A. Buhr // Last Modified On : Thu Apr 7 17:28:03 2016 // Update Count : 12 // #include "rational" #include "fstream" #include "stdlib" extern "C" { #include // exit } // extern struct Rational 0 = {0, 1}; struct Rational 1 = {1, 1}; // Calculate the greatest common denominator of two numbers, the first of which may be negative. It is used to reduce // rationals. long int gcd( long int a, long int b ) { for ( ;; ) { // Euclid's algorithm long int r = a % b; if ( r == 0 ) break; a = b; b = r; } // for return b; } // gcd long int simplify( long int *n, long int *d ) { if ( *d == 0 ) { serr | "Invalid rational number construction: denominator cannot be equal to 0." | endl; exit( EXIT_FAILURE ); } // exit if ( *d < 0 ) { *d = -*d; *n = -*n; } // move sign to numerator return gcd( abs( *n ), *d ); // simplify } // Rationalnumber::simplify Rational rational() { // constructor // r = (Rational){ 0, 1 }; Rational t = { 0, 1 }; return t; } // rational Rational rational( long int n ) { // constructor // r = (Rational){ n, 1 }; Rational t = { n, 1 }; return t; } // rational Rational rational( long int n, long int d ) { // constructor long int t = simplify( &n, &d ); // simplify // r = (Rational){ n / t, d / t }; Rational t = { n / t, d / t }; return t; } // rational long int numerator( Rational r ) { return r.numerator; } // numerator long int numerator( Rational r, long int n ) { long int prev = r.numerator; long int t = gcd( abs( n ), r.denominator ); // simplify r.numerator = n / t; r.denominator = r.denominator / t; return prev; } // numerator long int denominator( Rational r, long int d ) { long int prev = r.denominator; long int t = simplify( &r.numerator, &d ); // simplify r.numerator = r.numerator / t; r.denominator = d / t; return prev; } // denominator int ?==?( Rational l, Rational r ) { return l.numerator * r.denominator == l.denominator * r.numerator; } // ?==? int ?!=?( Rational l, Rational r ) { return ! ( l == r ); } // ?!=? int ??( Rational l, Rational r ) { return ! ( l <= r ); } // ?>? int ?>=?( Rational l, Rational r ) { return ! ( l < r ); } // ?>=? Rational -?( Rational r ) { Rational t = { -r.numerator, r.denominator }; return t; } // -? Rational ?+?( Rational l, Rational r ) { if ( l.denominator == r.denominator ) { // special case Rational t = { l.numerator + r.numerator, l.denominator }; return t; } else { Rational t = { l.numerator * r.denominator + l.denominator * r.numerator, l.denominator * r.denominator }; return t; } // if } // ?+? Rational ?-?( Rational l, Rational r ) { if ( l.denominator == r.denominator ) { // special case Rational t = { l.numerator - r.numerator, l.denominator }; return t; } else { Rational t = { l.numerator * r.denominator - l.denominator * r.numerator, l.denominator * r.denominator }; return t; } // if } // ?-? Rational ?*?( Rational l, Rational r ) { Rational t = { l.numerator * r.numerator, l.denominator * r.denominator }; return t; } // ?*? Rational ?/?( Rational l, Rational r ) { if ( r.numerator < 0 ) { r.numerator = -r.numerator; r.denominator = -r.denominator; } // if Rational t = { l.numerator * r.denominator, l.denominator * r.numerator }; return t; } // ?/? double widen( Rational r ) { return (double)r.numerator / (double)r.denominator; } // widen // https://rosettacode.org/wiki/Convert_decimal_number_to_rational#C Rational narrow( double f, long int md ) { if ( md <= 1 ) { // maximum fractional digits too small? Rational t = rational( f, 1 ); // truncate fraction return t; } // if // continued fraction coefficients long int a, h[3] = { 0, 1, 0 }, k[3] = { 1, 0, 0 }; long int x, d, n = 1; int i, neg = 0; if ( f < 0 ) { neg = 1; f = -f; } while ( f != floor( f ) ) { n <<= 1; f *= 2; } d = f; // continued fraction and check denominator each step for (i = 0; i < 64; i++) { a = n ? d / n : 0; if (i && !a) break; x = d; d = n; n = x % n; x = a; if (k[1] * a + k[0] >= md) { x = (md - k[0]) / k[1]; if ( ! (x * 2 >= a || k[1] >= md) ) break; i = 65; } // if h[2] = x * h[1] + h[0]; h[0] = h[1]; h[1] = h[2]; k[2] = x * k[1] + k[0]; k[0] = k[1]; k[1] = k[2]; } // for Rational t = rational( neg ? -h[1] : h[1], k[1] ); return t; } // narrow forall( dtype istype | istream( istype ) ) istype * ?|?( istype *is, Rational *r ) { long int t; is | &(r->numerator) | &(r->denominator); t = simplify( &(r->numerator), &(r->denominator) ); r->numerator /= t; r->denominator /= t; return is; } // ?|? forall( dtype ostype | ostream( ostype ) ) ostype * ?|?( ostype *os, Rational r ) { return os | r.numerator | '/' | r.denominator; } // ?|? // Local Variables: // // tab-width: 4 // // End: //