Changes in src/libcfa/rational.c [561f730:f621a148]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/libcfa/rational.c
r561f730 rf621a148 10 10 // Created On : Wed Apr 6 17:54:28 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun May 14 17:25:19201713 // Update Count : 13112 // Last Modified On : Thu Apr 27 17:05:06 2017 13 // Update Count : 51 14 14 // 15 15 … … 17 17 #include "fstream" 18 18 #include "stdlib" 19 #include "math" // floor 20 21 22 // constants 23 24 struct Rational 0 = {0, 1}; 25 struct Rational 1 = {1, 1}; 26 19 27 20 28 // helper routines … … 22 30 // Calculate greatest common denominator of two numbers, the first of which may be negative. Used to reduce rationals. 23 31 // alternative: https://en.wikipedia.org/wiki/Binary_GCD_algorithm 24 forall ( otype RationalImpl | arithmetic( RationalImpl ) )25 32 static RationalImpl gcd( RationalImpl a, RationalImpl b ) { 26 33 for ( ;; ) { // Euclid's algorithm 27 34 RationalImpl r = a % b; 28 if ( r == (RationalImpl){0}) break;35 if ( r == 0 ) break; 29 36 a = b; 30 37 b = r; … … 33 40 } // gcd 34 41 35 forall ( otype RationalImpl | arithmetic( RationalImpl ) ) 36 static RationalImpl simplify( RationalImpl * n, RationalImpl * d ) { 37 if ( *d == (RationalImpl){0} ) { 42 static RationalImpl simplify( RationalImpl *n, RationalImpl *d ) { 43 if ( *d == 0 ) { 38 44 serr | "Invalid rational number construction: denominator cannot be equal to 0." | endl; 39 45 exit( EXIT_FAILURE ); 40 46 } // exit 41 if ( *d < (RationalImpl){0} ) { *d = -*d; *n = -*n; }// move sign to numerator47 if ( *d < 0 ) { *d = -*d; *n = -*n; } // move sign to numerator 42 48 return gcd( abs( *n ), *d ); // simplify 43 49 } // Rationalnumber::simplify … … 46 52 // constructors 47 53 48 forall ( otype RationalImpl | arithmetic( RationalImpl ) ) 49 void ?{}( Rational(RationalImpl) * r ) { 50 r{ (RationalImpl){0}, (RationalImpl){1} }; 54 void ?{}( Rational * r ) { 55 r{ 0, 1 }; 51 56 } // rational 52 57 53 forall ( otype RationalImpl | arithmetic( RationalImpl ) ) 54 void ?{}( Rational(RationalImpl) * r, RationalImpl n ) { 55 r{ n, (RationalImpl){1} }; 58 void ?{}( Rational * r, RationalImpl n ) { 59 r{ n, 1 }; 56 60 } // rational 57 61 58 forall ( otype RationalImpl | arithmetic( RationalImpl ) ) 59 void ?{}( Rational(RationalImpl) * r, RationalImpl n, RationalImpl d ) { 62 void ?{}( Rational * r, RationalImpl n, RationalImpl d ) { 60 63 RationalImpl t = simplify( &n, &d ); // simplify 61 64 r->numerator = n / t; … … 66 69 // getter for numerator/denominator 67 70 68 forall ( otype RationalImpl | arithmetic( RationalImpl ) ) 69 RationalImpl numerator( Rational(RationalImpl) r ) { 71 RationalImpl numerator( Rational r ) { 70 72 return r.numerator; 71 73 } // numerator 72 74 73 forall ( otype RationalImpl | arithmetic( RationalImpl ) ) 74 RationalImpl denominator( Rational(RationalImpl) r ) { 75 RationalImpl denominator( Rational r ) { 75 76 return r.denominator; 76 77 } // denominator 77 78 78 forall ( otype RationalImpl | arithmetic( RationalImpl ) ) 79 [ RationalImpl, RationalImpl ] ?=?( * [ RationalImpl, RationalImpl ] dest, Rational(RationalImpl) src ) { 79 [ RationalImpl, RationalImpl ] ?=?( * [ RationalImpl, RationalImpl ] dest, Rational src ) { 80 80 return *dest = src.[ numerator, denominator ]; 81 81 } … … 83 83 // setter for numerator/denominator 84 84 85 forall ( otype RationalImpl | arithmetic( RationalImpl ) ) 86 RationalImpl numerator( Rational(RationalImpl) r, RationalImpl n ) { 85 RationalImpl numerator( Rational r, RationalImpl n ) { 87 86 RationalImpl prev = r.numerator; 88 87 RationalImpl t = gcd( abs( n ), r.denominator ); // simplify … … 92 91 } // numerator 93 92 94 forall ( otype RationalImpl | arithmetic( RationalImpl ) ) 95 RationalImpl denominator( Rational(RationalImpl) r, RationalImpl d ) { 93 RationalImpl denominator( Rational r, RationalImpl d ) { 96 94 RationalImpl prev = r.denominator; 97 95 RationalImpl t = simplify( &r.numerator, &d ); // simplify … … 104 102 // comparison 105 103 106 forall ( otype RationalImpl | arithmetic( RationalImpl ) ) 107 int ?==?( Rational(RationalImpl) l, Rational(RationalImpl) r ) { 104 int ?==?( Rational l, Rational r ) { 108 105 return l.numerator * r.denominator == l.denominator * r.numerator; 109 106 } // ?==? 110 107 111 forall ( otype RationalImpl | arithmetic( RationalImpl ) ) 112 int ?!=?( Rational(RationalImpl) l, Rational(RationalImpl) r ) { 108 int ?!=?( Rational l, Rational r ) { 113 109 return ! ( l == r ); 114 110 } // ?!=? 115 111 116 forall ( otype RationalImpl | arithmetic( RationalImpl ) ) 117 int ?<?( Rational(RationalImpl) l, Rational(RationalImpl) r ) { 112 int ?<?( Rational l, Rational r ) { 118 113 return l.numerator * r.denominator < l.denominator * r.numerator; 119 114 } // ?<? 120 115 121 forall ( otype RationalImpl | arithmetic( RationalImpl ) ) 122 int ?<=?( Rational(RationalImpl) l, Rational(RationalImpl) r ) { 123 return l.numerator * r.denominator <= l.denominator * r.numerator; 116 int ?<=?( Rational l, Rational r ) { 117 return l < r || l == r; 124 118 } // ?<=? 125 119 126 forall ( otype RationalImpl | arithmetic( RationalImpl ) ) 127 int ?>?( Rational(RationalImpl) l, Rational(RationalImpl) r ) { 120 int ?>?( Rational l, Rational r ) { 128 121 return ! ( l <= r ); 129 122 } // ?>? 130 123 131 forall ( otype RationalImpl | arithmetic( RationalImpl ) ) 132 int ?>=?( Rational(RationalImpl) l, Rational(RationalImpl) r ) { 124 int ?>=?( Rational l, Rational r ) { 133 125 return ! ( l < r ); 134 126 } // ?>=? … … 137 129 // arithmetic 138 130 139 forall ( otype RationalImpl | arithmetic( RationalImpl ) ) 140 Rational(RationalImpl) +?( Rational(RationalImpl) r ) { 141 Rational(RationalImpl) t = { r.numerator, r.denominator }; 142 return t; 143 } // +? 144 145 forall ( otype RationalImpl | arithmetic( RationalImpl ) ) 146 Rational(RationalImpl) -?( Rational(RationalImpl) r ) { 147 Rational(RationalImpl) t = { -r.numerator, r.denominator }; 131 Rational -?( Rational r ) { 132 Rational t = { -r.numerator, r.denominator }; 148 133 return t; 149 134 } // -? 150 135 151 forall ( otype RationalImpl | arithmetic( RationalImpl ) ) 152 Rational(RationalImpl) ?+?( Rational(RationalImpl) l, Rational(RationalImpl) r ) { 136 Rational ?+?( Rational l, Rational r ) { 153 137 if ( l.denominator == r.denominator ) { // special case 154 Rational (RationalImpl)t = { l.numerator + r.numerator, l.denominator };138 Rational t = { l.numerator + r.numerator, l.denominator }; 155 139 return t; 156 140 } else { 157 Rational (RationalImpl)t = { l.numerator * r.denominator + l.denominator * r.numerator, l.denominator * r.denominator };141 Rational t = { l.numerator * r.denominator + l.denominator * r.numerator, l.denominator * r.denominator }; 158 142 return t; 159 143 } // if 160 144 } // ?+? 161 145 162 forall ( otype RationalImpl | arithmetic( RationalImpl ) ) 163 Rational(RationalImpl) ?-?( Rational(RationalImpl) l, Rational(RationalImpl) r ) { 146 Rational ?-?( Rational l, Rational r ) { 164 147 if ( l.denominator == r.denominator ) { // special case 165 Rational (RationalImpl)t = { l.numerator - r.numerator, l.denominator };148 Rational t = { l.numerator - r.numerator, l.denominator }; 166 149 return t; 167 150 } else { 168 Rational (RationalImpl)t = { l.numerator * r.denominator - l.denominator * r.numerator, l.denominator * r.denominator };151 Rational t = { l.numerator * r.denominator - l.denominator * r.numerator, l.denominator * r.denominator }; 169 152 return t; 170 153 } // if 171 154 } // ?-? 172 155 173 forall ( otype RationalImpl | arithmetic( RationalImpl ) ) 174 Rational(RationalImpl) ?*?( Rational(RationalImpl) l, Rational(RationalImpl) r ) { 175 Rational(RationalImpl) t = { l.numerator * r.numerator, l.denominator * r.denominator }; 156 Rational ?*?( Rational l, Rational r ) { 157 Rational t = { l.numerator * r.numerator, l.denominator * r.denominator }; 176 158 return t; 177 159 } // ?*? 178 160 179 forall ( otype RationalImpl | arithmetic( RationalImpl ) ) 180 Rational(RationalImpl) ?/?( Rational(RationalImpl) l, Rational(RationalImpl) r ) { 181 if ( r.numerator < (RationalImpl){0} ) { 161 Rational ?/?( Rational l, Rational r ) { 162 if ( r.numerator < 0 ) { 182 163 r.numerator = -r.numerator; 183 164 r.denominator = -r.denominator; 184 165 } // if 185 Rational (RationalImpl)t = { l.numerator * r.denominator, l.denominator * r.numerator };166 Rational t = { l.numerator * r.denominator, l.denominator * r.numerator }; 186 167 return t; 187 168 } // ?/? … … 190 171 // conversion 191 172 192 // forall ( otype RationalImpl | arithmetic( RationalImpl ) ) 193 // double widen( Rational(RationalImpl) r ) { 194 // return (double)r.numerator / (double)r.denominator; 195 // } // widen 196 197 // // http://www.ics.uci.edu/~eppstein/numth/frap.c 198 // forall ( otype RationalImpl | arithmetic( RationalImpl ) ) 199 // Rational(RationalImpl) narrow( double f, RationalImpl md ) { 200 // if ( md <= 1 ) { // maximum fractional digits too small? 201 // return (Rational(RationalImpl)){ f, 1}; // truncate fraction 202 // } // if 203 204 // // continued fraction coefficients 205 // RationalImpl m00 = 1, m11 = 1, m01 = 0, m10 = 0; 206 // RationalImpl ai, t; 207 208 // // find terms until denom gets too big 209 // for ( ;; ) { 210 // ai = (RationalImpl)f; 211 // if ( ! (m10 * ai + m11 <= md) ) break; 212 // t = m00 * ai + m01; 213 // m01 = m00; 214 // m00 = t; 215 // t = m10 * ai + m11; 216 // m11 = m10; 217 // m10 = t; 218 // t = (double)ai; 219 // if ( f == t ) break; // prevent division by zero 220 // f = 1 / (f - (double)t); 221 // if ( f > (double)0x7FFFFFFF ) break; // representation failure 222 // } 223 // return (Rational(RationalImpl)){ m00, m10 }; 224 // } // narrow 173 double widen( Rational r ) { 174 return (double)r.numerator / (double)r.denominator; 175 } // widen 176 177 // http://www.ics.uci.edu/~eppstein/numth/frap.c 178 Rational narrow( double f, RationalImpl md ) { 179 if ( md <= 1 ) { // maximum fractional digits too small? 180 return (Rational){ f, 1}; // truncate fraction 181 } // if 182 183 // continued fraction coefficients 184 RationalImpl m00 = 1, m11 = 1, m01 = 0, m10 = 0; 185 RationalImpl ai, t; 186 187 // find terms until denom gets too big 188 for ( ;; ) { 189 ai = (RationalImpl)f; 190 if ( ! (m10 * ai + m11 <= md) ) break; 191 t = m00 * ai + m01; 192 m01 = m00; 193 m00 = t; 194 t = m10 * ai + m11; 195 m11 = m10; 196 m10 = t; 197 t = (double)ai; 198 if ( f == t ) break; // prevent division by zero 199 f = 1 / (f - t); 200 if ( f > (double)0x7FFFFFFF ) break; // representation failure 201 } 202 return (Rational){ m00, m10 }; 203 } // narrow 225 204 226 205 227 206 // I/O 228 207 229 forall ( otype RationalImpl | arithmetic( RationalImpl ) ) 230 forall( dtype istype | istream( istype ) | { istype * ?|?( istype *, RationalImpl * ); } ) 231 istype * ?|?( istype * is, Rational(RationalImpl) * r ) { 208 forall( dtype istype | istream( istype ) ) 209 istype * ?|?( istype *is, Rational *r ) { 232 210 RationalImpl t; 233 211 is | &(r->numerator) | &(r->denominator); … … 238 216 } // ?|? 239 217 240 forall ( otype RationalImpl | arithmetic( RationalImpl ) ) 241 forall( dtype ostype | ostream( ostype ) | { ostype * ?|?( ostype *, RationalImpl ); } ) 242 ostype * ?|?( ostype * os, Rational(RationalImpl ) r ) { 218 forall( dtype ostype | ostream( ostype ) ) 219 ostype * ?|?( ostype *os, Rational r ) { 243 220 return os | r.numerator | '/' | r.denominator; 244 221 } // ?|?
Note:
See TracChangeset
for help on using the changeset viewer.