Changeset 6e4b913 for src/libcfa/rational.c
- Timestamp:
- Jul 10, 2016, 4:35:32 PM (8 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, ctor, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, memory, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- 4e06c1e, c13d970
- Parents:
- 07bc165
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/libcfa/rational.c
r07bc165 r6e4b913 10 10 // Created On : Wed Apr 6 17:54:28 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Jul 5 18:29:12201613 // Update Count : 2612 // Last Modified On : Sat Jul 9 11:18:04 2016 13 // Update Count : 40 14 14 // 15 15 … … 31 31 // alternative: https://en.wikipedia.org/wiki/Binary_GCD_algorithm 32 32 static long int gcd( long int a, long int b ) { 33 33 for ( ;; ) { // Euclid's algorithm 34 34 long int r = a % b; 35 35 if ( r == 0 ) break; 36 36 a = b; 37 37 b = r; 38 38 } // for 39 39 return b; 40 40 } // gcd 41 41 42 42 static long int simplify( long int *n, long int *d ) { 43 43 if ( *d == 0 ) { 44 44 serr | "Invalid rational number construction: denominator cannot be equal to 0." | endl; 45 45 exit( EXIT_FAILURE ); 46 47 48 46 } // exit 47 if ( *d < 0 ) { *d = -*d; *n = -*n; } // move sign to numerator 48 return gcd( abs( *n ), *d ); // simplify 49 49 } // Rationalnumber::simplify 50 50 … … 53 53 54 54 void ?{}( Rational * r ) { 55 55 r{ 0, 1 }; 56 56 } // rational 57 57 58 58 void ?{}( Rational * r, long int n ) { 59 59 r{ n, 1 }; 60 60 } // rational 61 61 62 62 void ?{}( Rational * r, long int n, long int d ) { 63 64 63 long int t = simplify( &n, &d ); // simplify 64 r->numerator = n / t; 65 65 r->denominator = d / t; 66 66 } // rational … … 70 70 71 71 long int numerator( Rational r ) { 72 72 return r.numerator; 73 73 } // numerator 74 74 75 75 long int numerator( Rational r, long int n ) { 76 77 78 79 80 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; 81 81 } // numerator 82 82 83 83 long int denominator( Rational r ) { 84 84 return r.denominator; 85 85 } // denominator 86 86 87 87 long int denominator( Rational r, long int d ) { 88 89 90 91 92 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; 93 93 } // denominator 94 94 … … 97 97 98 98 int ?==?( Rational l, Rational r ) { 99 99 return l.numerator * r.denominator == l.denominator * r.numerator; 100 100 } // ?==? 101 101 102 102 int ?!=?( Rational l, Rational r ) { 103 103 return ! ( l == r ); 104 104 } // ?!=? 105 105 106 106 int ?<?( Rational l, Rational r ) { 107 107 return l.numerator * r.denominator < l.denominator * r.numerator; 108 108 } // ?<? 109 109 110 110 int ?<=?( Rational l, Rational r ) { 111 111 return l < r || l == r; 112 112 } // ?<=? 113 113 114 114 int ?>?( Rational l, Rational r ) { 115 115 return ! ( l <= r ); 116 116 } // ?>? 117 117 118 118 int ?>=?( Rational l, Rational r ) { 119 119 return ! ( l < r ); 120 120 } // ?>=? 121 121 … … 125 125 Rational -?( Rational r ) { 126 126 Rational t = { -r.numerator, r.denominator }; 127 127 return t; 128 128 } // -? 129 129 130 130 Rational ?+?( Rational l, Rational r ) { 131 131 if ( l.denominator == r.denominator ) { // special case 132 132 Rational t = { l.numerator + r.numerator, l.denominator }; 133 133 return t; 134 134 } else { 135 135 Rational t = { l.numerator * r.denominator + l.denominator * r.numerator, l.denominator * r.denominator }; 136 136 return t; 137 137 } // if 138 138 } // ?+? 139 139 140 140 Rational ?-?( Rational l, Rational r ) { 141 141 if ( l.denominator == r.denominator ) { // special case 142 142 Rational t = { l.numerator - r.numerator, l.denominator }; 143 143 return t; 144 144 } else { 145 145 Rational t = { l.numerator * r.denominator - l.denominator * r.numerator, l.denominator * r.denominator }; 146 146 return t; 147 147 } // if 148 148 } // ?-? 149 149 150 150 Rational ?*?( Rational l, Rational r ) { 151 151 Rational t = { l.numerator * r.numerator, l.denominator * r.denominator }; 152 152 return t; 153 153 } // ?*? 154 154 155 155 Rational ?/?( Rational l, Rational r ) { 156 156 if ( r.numerator < 0 ) { 157 157 r.numerator = -r.numerator; 158 158 r.denominator = -r.denominator; 159 159 } // if 160 160 Rational t = { l.numerator * r.denominator, l.denominator * r.numerator }; 161 161 return t; 162 162 } // ?/? 163 163 … … 169 169 } // widen 170 170 171 // http s://rosettacode.org/wiki/Convert_decimal_number_to_rational#C171 // http://www.ics.uci.edu/~eppstein/numth/frap.c 172 172 Rational narrow( double f, long int md ) { 173 173 if ( md <= 1 ) { // maximum fractional digits too small? … … 176 176 177 177 // continued fraction coefficients 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] }; 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 }; 201 197 } // narrow 202 198 … … 207 203 istype * ?|?( istype *is, Rational *r ) { 208 204 long int t; 209 205 is | &(r->numerator) | &(r->denominator); 210 206 t = simplify( &(r->numerator), &(r->denominator) ); 211 212 213 207 r->numerator /= t; 208 r->denominator /= t; 209 return is; 214 210 } // ?|? 215 211 216 212 forall( dtype ostype | ostream( ostype ) ) 217 213 ostype * ?|?( ostype *os, Rational r ) { 218 214 return os | r.numerator | '/' | r.denominator; 219 215 } // ?|? 220 216
Note: See TracChangeset
for help on using the changeset viewer.