source: src/libcfa/rational.c @ 0f35657

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsdeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newwith_gc
Last change on this file since 0f35657 was 6e4b913, checked in by Peter A. Buhr <pabuhr@…>, 8 years ago

allow 32-bit compilation of cfa-cpp, and 32-bit compilation of CFA programs (including CFA libraries)

  • Property mode set to 100644
File size: 5.1 KB
RevLine 
[53ba273]1//
2// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// rational.c --
8//
9// Author           : Peter A. Buhr
10// Created On       : Wed Apr  6 17:54:28 2016
11// Last Modified By : Peter A. Buhr
[6e4b913]12// Last Modified On : Sat Jul  9 11:18:04 2016
13// Update Count     : 40
[53ba273]14//
15
16#include "rational"
[3d9b5da]17#include "fstream"
18#include "stdlib"
[6e991d6]19#include "math"                                                                                 // floor
[53ba273]20
[630a82a]21
22// constants
23
[53ba273]24struct Rational 0 = {0, 1};
25struct Rational 1 = {1, 1};
26
27
[45161b4d]28// helper routines
[630a82a]29
30// Calculate greatest common denominator of two numbers, the first of which may be negative. Used to reduce rationals.
[45161b4d]31// alternative: https://en.wikipedia.org/wiki/Binary_GCD_algorithm
[630a82a]32static long int gcd( long int a, long int b ) {
[6e4b913]33        for ( ;; ) {                                                                            // Euclid's algorithm
[53ba273]34                long int r = a % b;
35          if ( r == 0 ) break;
36                a = b;
37                b = r;
[6e4b913]38        } // for
[53ba273]39        return b;
40} // gcd
41
[630a82a]42static long int simplify( long int *n, long int *d ) {
[6e4b913]43        if ( *d == 0 ) {
[53ba273]44                serr | "Invalid rational number construction: denominator cannot be equal to 0." | endl;
45                exit( EXIT_FAILURE );
[6e4b913]46        } // exit
47        if ( *d < 0 ) { *d = -*d; *n = -*n; }                           // move sign to numerator
48        return gcd( abs( *n ), *d );                                            // simplify
[53ba273]49} // Rationalnumber::simplify
50
[630a82a]51
52// constructors
53
[d1ab5331]54void ?{}( Rational * r ) {
[6e4b913]55        r{ 0, 1 };
[53ba273]56} // rational
57
[d1ab5331]58void ?{}( Rational * r, long int n ) {
[6e4b913]59        r{ n, 1 };
[53ba273]60} // rational
61
[d1ab5331]62void ?{}( Rational * r, long int n, long int d ) {
[6e4b913]63        long int t = simplify( &n, &d );                                        // simplify
64        r->numerator = n / t;
[d1ab5331]65        r->denominator = d / t;
[53ba273]66} // rational
67
[630a82a]68
69// getter/setter for numerator/denominator
70
[53ba273]71long int numerator( Rational r ) {
[6e4b913]72        return r.numerator;
[53ba273]73} // numerator
74
75long int numerator( Rational r, long int n ) {
[6e4b913]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;
[53ba273]81} // numerator
82
[630a82a]83long int denominator( Rational r ) {
[6e4b913]84        return r.denominator;
[630a82a]85} // denominator
86
[53ba273]87long int denominator( Rational r, long int d ) {
[6e4b913]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;
[53ba273]93} // denominator
94
[630a82a]95
96// comparison
97
[53ba273]98int ?==?( Rational l, Rational r ) {
[6e4b913]99        return l.numerator * r.denominator == l.denominator * r.numerator;
[53ba273]100} // ?==?
101
102int ?!=?( Rational l, Rational r ) {
[6e4b913]103        return ! ( l == r );
[53ba273]104} // ?!=?
105
106int ?<?( Rational l, Rational r ) {
[6e4b913]107        return l.numerator * r.denominator < l.denominator * r.numerator;
[53ba273]108} // ?<?
109
110int ?<=?( Rational l, Rational r ) {
[6e4b913]111        return l < r || l == r;
[53ba273]112} // ?<=?
113
114int ?>?( Rational l, Rational r ) {
[6e4b913]115        return ! ( l <= r );
[53ba273]116} // ?>?
117
118int ?>=?( Rational l, Rational r ) {
[6e4b913]119        return ! ( l < r );
[53ba273]120} // ?>=?
121
[630a82a]122
123// arithmetic
124
[53ba273]125Rational -?( Rational r ) {
126        Rational t = { -r.numerator, r.denominator };
[6e4b913]127        return t;
[53ba273]128} // -?
129
130Rational ?+?( Rational l, Rational r ) {
[6e4b913]131        if ( l.denominator == r.denominator ) {                         // special case
[53ba273]132                Rational t = { l.numerator + r.numerator, l.denominator };
133                return t;
[6e4b913]134        } else {
[53ba273]135                Rational t = { l.numerator * r.denominator + l.denominator * r.numerator, l.denominator * r.denominator };
136                return t;
[6e4b913]137        } // if
[53ba273]138} // ?+?
139
140Rational ?-?( Rational l, Rational r ) {
[6e4b913]141        if ( l.denominator == r.denominator ) {                         // special case
[53ba273]142                Rational t = { l.numerator - r.numerator, l.denominator };
143                return t;
[6e4b913]144        } else {
[53ba273]145                Rational t = { l.numerator * r.denominator - l.denominator * r.numerator, l.denominator * r.denominator };
146                return t;
[6e4b913]147        } // if
[53ba273]148} // ?-?
149
150Rational ?*?( Rational l, Rational r ) {
[6e4b913]151        Rational t = { l.numerator * r.numerator, l.denominator * r.denominator };
[53ba273]152        return t;
153} // ?*?
154
155Rational ?/?( Rational l, Rational r ) {
[6e4b913]156        if ( r.numerator < 0 ) {
[53ba273]157                r.numerator = -r.numerator;
158                r.denominator = -r.denominator;
159        } // if
160        Rational t = { l.numerator * r.denominator, l.denominator * r.numerator };
[6e4b913]161        return t;
[53ba273]162} // ?/?
163
[630a82a]164
165// conversion
166
[53ba273]167double widen( Rational r ) {
168        return (double)r.numerator / (double)r.denominator;
169} // widen
170
[6e4b913]171// http://www.ics.uci.edu/~eppstein/numth/frap.c
[53ba273]172Rational narrow( double f, long int md ) {
173        if ( md <= 1 ) {                                                                        // maximum fractional digits too small?
[d1ab5331]174                return (Rational){ f, 1};                                               // truncate fraction
[53ba273]175        } // if
176
177        // continued fraction coefficients
[6e4b913]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 };
[53ba273]197} // narrow
198
[630a82a]199
200// I/O
201
[3d9b5da]202forall( dtype istype | istream( istype ) )
203istype * ?|?( istype *is, Rational *r ) {
[53ba273]204        long int t;
[6e4b913]205        is | &(r->numerator) | &(r->denominator);
[53ba273]206        t = simplify( &(r->numerator), &(r->denominator) );
[6e4b913]207        r->numerator /= t;
208        r->denominator /= t;
209        return is;
[53ba273]210} // ?|?
211
[3d9b5da]212forall( dtype ostype | ostream( ostype ) )
213ostype * ?|?( ostype *os, Rational r ) {
[6e4b913]214        return os | r.numerator | '/' | r.denominator;
[53ba273]215} // ?|?
216
217// Local Variables: //
218// tab-width: 4 //
219// End: //
Note: See TracBrowser for help on using the repository browser.