Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/libcfa/rational.c

    r6e4b913 ra6151ba  
    1010// Created On       : Wed Apr  6 17:54:28 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul  9 11:18:04 2016
    13 // Update Count     : 40
     12// Last Modified On : Tue Jul  5 18:29:12 2016
     13// Update Count     : 26
    1414//
    1515
     
    3131// alternative: https://en.wikipedia.org/wiki/Binary_GCD_algorithm
    3232static long int gcd( long int a, long int b ) {
    33         for ( ;; ) {                                                                            // Euclid's algorithm
     33    for ( ;; ) {                                                                                // Euclid's algorithm
    3434                long int r = a % b;
    3535          if ( r == 0 ) break;
    3636                a = b;
    3737                b = r;
    38         } // for
     38    } // for
    3939        return b;
    4040} // gcd
    4141
    4242static long int simplify( long int *n, long int *d ) {
    43         if ( *d == 0 ) {
     43    if ( *d == 0 ) {
    4444                serr | "Invalid rational number construction: denominator cannot be equal to 0." | endl;
    4545                exit( EXIT_FAILURE );
    46         } // exit
    47         if ( *d < 0 ) { *d = -*d; *n = -*n; }                           // move sign to numerator
    48         return gcd( abs( *n ), *d );                                            // simplify
     46    } // exit
     47    if ( *d < 0 ) { *d = -*d; *n = -*n; }                               // move sign to numerator
     48    return gcd( abs( *n ), *d );                                                // simplify
    4949} // Rationalnumber::simplify
    5050
     
    5353
    5454void ?{}( Rational * r ) {
    55         r{ 0, 1 };
     55    r{ 0, 1 };
    5656} // rational
    5757
    5858void ?{}( Rational * r, long int n ) {
    59         r{ n, 1 };
     59    r{ n, 1 };
    6060} // rational
    6161
    6262void ?{}( Rational * r, long int n, long int d ) {
    63         long int t = simplify( &n, &d );                                        // simplify
    64         r->numerator = n / t;
     63    long int t = simplify( &n, &d );                                    // simplify
     64    r->numerator = n / t;
    6565        r->denominator = d / t;
    6666} // rational
     
    7070
    7171long int numerator( Rational r ) {
    72         return r.numerator;
     72    return r.numerator;
    7373} // numerator
    7474
    7575long int numerator( Rational r, long int n ) {
    76         long int prev = r.numerator;
    77         long int t = gcd( abs( n ), r.denominator );            // simplify
    78         r.numerator = n / t;
    79         r.denominator = r.denominator / t;
    80         return prev;
     76    long int prev = r.numerator;
     77    long int t = gcd( abs( n ), r.denominator );                // simplify
     78    r.numerator = n / t;
     79    r.denominator = r.denominator / t;
     80    return prev;
    8181} // numerator
    8282
    8383long int denominator( Rational r ) {
    84         return r.denominator;
     84    return r.denominator;
    8585} // denominator
    8686
    8787long int denominator( Rational r, long int d ) {
    88         long int prev = r.denominator;
    89         long int t = simplify( &r.numerator, &d );                      // simplify
    90         r.numerator = r.numerator / t;
    91         r.denominator = d / t;
    92         return prev;
     88    long int prev = r.denominator;
     89    long int t = simplify( &r.numerator, &d );                  // simplify
     90    r.numerator = r.numerator / t;
     91    r.denominator = d / t;
     92    return prev;
    9393} // denominator
    9494
     
    9797
    9898int ?==?( Rational l, Rational r ) {
    99         return l.numerator * r.denominator == l.denominator * r.numerator;
     99    return l.numerator * r.denominator == l.denominator * r.numerator;
    100100} // ?==?
    101101
    102102int ?!=?( Rational l, Rational r ) {
    103         return ! ( l == r );
     103    return ! ( l == r );
    104104} // ?!=?
    105105
    106106int ?<?( Rational l, Rational r ) {
    107         return l.numerator * r.denominator < l.denominator * r.numerator;
     107    return l.numerator * r.denominator < l.denominator * r.numerator;
    108108} // ?<?
    109109
    110110int ?<=?( Rational l, Rational r ) {
    111         return l < r || l == r;
     111    return l < r || l == r;
    112112} // ?<=?
    113113
    114114int ?>?( Rational l, Rational r ) {
    115         return ! ( l <= r );
     115    return ! ( l <= r );
    116116} // ?>?
    117117
    118118int ?>=?( Rational l, Rational r ) {
    119         return ! ( l < r );
     119    return ! ( l < r );
    120120} // ?>=?
    121121
     
    125125Rational -?( Rational r ) {
    126126        Rational t = { -r.numerator, r.denominator };
    127         return t;
     127    return t;
    128128} // -?
    129129
    130130Rational ?+?( Rational l, Rational r ) {
    131         if ( l.denominator == r.denominator ) {                         // special case
     131    if ( l.denominator == r.denominator ) {                             // special case
    132132                Rational t = { l.numerator + r.numerator, l.denominator };
    133133                return t;
    134         } else {
     134    } else {
    135135                Rational t = { l.numerator * r.denominator + l.denominator * r.numerator, l.denominator * r.denominator };
    136136                return t;
    137         } // if
     137    } // if
    138138} // ?+?
    139139
    140140Rational ?-?( Rational l, Rational r ) {
    141         if ( l.denominator == r.denominator ) {                         // special case
     141    if ( l.denominator == r.denominator ) {                             // special case
    142142                Rational t = { l.numerator - r.numerator, l.denominator };
    143143                return t;
    144         } else {
     144    } else {
    145145                Rational t = { l.numerator * r.denominator - l.denominator * r.numerator, l.denominator * r.denominator };
    146146                return t;
    147         } // if
     147    } // if
    148148} // ?-?
    149149
    150150Rational ?*?( Rational l, Rational r ) {
    151         Rational t = { l.numerator * r.numerator, l.denominator * r.denominator };
     151    Rational t = { l.numerator * r.numerator, l.denominator * r.denominator };
    152152        return t;
    153153} // ?*?
    154154
    155155Rational ?/?( Rational l, Rational r ) {
    156         if ( r.numerator < 0 ) {
     156    if ( r.numerator < 0 ) {
    157157                r.numerator = -r.numerator;
    158158                r.denominator = -r.denominator;
    159159        } // if
    160160        Rational t = { l.numerator * r.denominator, l.denominator * r.numerator };
    161         return t;
     161    return t;
    162162} // ?/?
    163163
     
    169169} // widen
    170170
    171 // http://www.ics.uci.edu/~eppstein/numth/frap.c
     171// https://rosettacode.org/wiki/Convert_decimal_number_to_rational#C
    172172Rational narrow( double f, long int md ) {
    173173        if ( md <= 1 ) {                                                                        // maximum fractional digits too small?
     
    176176
    177177        // continued fraction coefficients
    178         long int m00 = 1, m11 = 1, m01 = 0, m10 = 0;
    179         long int ai, t;
    180 
    181         // find terms until denom gets too big
    182         for ( ;; ) {
    183                 ai = (long int)f;
    184           if ( ! (m10 * ai + m11 <= md) ) break;
    185                 t = m00 * ai + m01;
    186                 m01 = m00;
    187                 m00 = t;
    188                 t = m10 * ai + m11;
    189                 m11 = m10;
    190                 m10 = t;
    191                 t = (double)ai;
    192           if ( f == t ) break;                                                          // prevent division by zero
    193                 f = 1 / (f - t);
    194           if ( f > (double)0x7FFFFFFF ) break;                          // representation failure
    195         }
    196         return (Rational){ m00, m10 };
     178        long int a, h[3] = { 0, 1, 0 }, k[3] = { 1, 0, 0 };
     179        long int x, d, n = 1;
     180        int i, neg = 0;
     181 
     182        if ( f < 0 ) { neg = 1; f = -f; }
     183        while ( f != floor( f ) ) { n <<= 1; f *= 2; }
     184        d = f;
     185 
     186        // continued fraction and check denominator each step
     187        for (i = 0; i < 64; i++) {
     188                a = n ? d / n : 0;
     189          if (i && !a) break;
     190                x = d; d = n; n = x % n;
     191                x = a;
     192                if (k[1] * a + k[0] >= md) {
     193                        x = (md - k[0]) / k[1];
     194                  if ( ! (x * 2 >= a || k[1] >= md) ) break;
     195                        i = 65;
     196                } // if
     197                h[2] = x * h[1] + h[0]; h[0] = h[1]; h[1] = h[2];
     198                k[2] = x * k[1] + k[0]; k[0] = k[1]; k[1] = k[2];
     199        } // for
     200        return (Rational){ neg ? -h[1] : h[1], k[1] };
    197201} // narrow
    198202
     
    203207istype * ?|?( istype *is, Rational *r ) {
    204208        long int t;
    205         is | &(r->numerator) | &(r->denominator);
     209    is | &(r->numerator) | &(r->denominator);
    206210        t = simplify( &(r->numerator), &(r->denominator) );
    207         r->numerator /= t;
    208         r->denominator /= t;
    209         return is;
     211    r->numerator /= t;
     212    r->denominator /= t;
     213    return is;
    210214} // ?|?
    211215
    212216forall( dtype ostype | ostream( ostype ) )
    213217ostype * ?|?( ostype *os, Rational r ) {
    214         return os | r.numerator | '/' | r.denominator;
     218    return os | r.numerator | '/' | r.denominator;
    215219} // ?|?
    216220
Note: See TracChangeset for help on using the changeset viewer.