Changes in libcfa/src/rational.cfa [5dc4c7e:fd54fef]
- File:
-
- 1 edited
-
libcfa/src/rational.cfa (modified) (10 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/rational.cfa
r5dc4c7e rfd54fef 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 20 16:30:06 202113 // Update Count : 1 9312 // Last Modified On : Sat Feb 8 17:56:36 2020 13 // Update Count : 187 14 14 // 15 15 … … 18 18 #include "stdlib.hfa" 19 19 20 forall( T | Arithmetic( T) ) {20 forall( RationalImpl | arithmetic( RationalImpl ) ) { 21 21 // helper routines 22 22 23 23 // Calculate greatest common denominator of two numbers, the first of which may be negative. Used to reduce 24 24 // rationals. alternative: https://en.wikipedia.org/wiki/Binary_GCD_algorithm 25 static T gcd( T a, Tb ) {25 static RationalImpl gcd( RationalImpl a, RationalImpl b ) { 26 26 for ( ;; ) { // Euclid's algorithm 27 Tr = a % b;28 if ( r == ( T){0} ) break;27 RationalImpl r = a % b; 28 if ( r == (RationalImpl){0} ) break; 29 29 a = b; 30 30 b = r; … … 33 33 } // gcd 34 34 35 static T simplify( T & n, T& d ) {36 if ( d == ( T){0} ) {35 static RationalImpl simplify( RationalImpl & n, RationalImpl & d ) { 36 if ( d == (RationalImpl){0} ) { 37 37 abort | "Invalid rational number construction: denominator cannot be equal to 0."; 38 38 } // exit 39 if ( d < ( T){0} ) { d = -d; n = -n; } // move sign to numerator39 if ( d < (RationalImpl){0} ) { d = -d; n = -n; } // move sign to numerator 40 40 return gcd( abs( n ), d ); // simplify 41 41 } // Rationalnumber::simplify … … 43 43 // constructors 44 44 45 void ?{}( Rational(T) & r, zero_t ) { 46 r{ (T){0}, (T){1} }; 47 } // rational 48 49 void ?{}( Rational(T) & r, one_t ) { 50 r{ (T){1}, (T){1} }; 51 } // rational 52 53 void ?{}( Rational(T) & r ) { 54 r{ (T){0}, (T){1} }; 55 } // rational 56 57 void ?{}( Rational(T) & r, T n ) { 58 r{ n, (T){1} }; 59 } // rational 60 61 void ?{}( Rational(T) & r, T n, T d ) { 62 T t = simplify( n, d ); // simplify 45 void ?{}( Rational(RationalImpl) & r ) { 46 r{ (RationalImpl){0}, (RationalImpl){1} }; 47 } // rational 48 49 void ?{}( Rational(RationalImpl) & r, RationalImpl n ) { 50 r{ n, (RationalImpl){1} }; 51 } // rational 52 53 void ?{}( Rational(RationalImpl) & r, RationalImpl n, RationalImpl d ) { 54 RationalImpl t = simplify( n, d ); // simplify 63 55 r.[numerator, denominator] = [n / t, d / t]; 64 56 } // rational 65 57 58 void ?{}( Rational(RationalImpl) & r, zero_t ) { 59 r{ (RationalImpl){0}, (RationalImpl){1} }; 60 } // rational 61 62 void ?{}( Rational(RationalImpl) & r, one_t ) { 63 r{ (RationalImpl){1}, (RationalImpl){1} }; 64 } // rational 65 66 66 // getter for numerator/denominator 67 67 68 T numerator( Rational(T) r ) {68 RationalImpl numerator( Rational(RationalImpl) r ) { 69 69 return r.numerator; 70 70 } // numerator 71 71 72 T denominator( Rational(T) r ) {72 RationalImpl denominator( Rational(RationalImpl) r ) { 73 73 return r.denominator; 74 74 } // denominator 75 75 76 [ T, T ] ?=?( & [ T, T ] dest, Rational(T) src ) {76 [ RationalImpl, RationalImpl ] ?=?( & [ RationalImpl, RationalImpl ] dest, Rational(RationalImpl) src ) { 77 77 return dest = src.[ numerator, denominator ]; 78 78 } // ?=? … … 80 80 // setter for numerator/denominator 81 81 82 T numerator( Rational(T) r, Tn ) {83 Tprev = r.numerator;84 Tt = gcd( abs( n ), r.denominator ); // simplify82 RationalImpl numerator( Rational(RationalImpl) r, RationalImpl n ) { 83 RationalImpl prev = r.numerator; 84 RationalImpl t = gcd( abs( n ), r.denominator ); // simplify 85 85 r.[numerator, denominator] = [n / t, r.denominator / t]; 86 86 return prev; 87 87 } // numerator 88 88 89 T denominator( Rational(T) r, Td ) {90 Tprev = r.denominator;91 Tt = simplify( r.numerator, d ); // simplify89 RationalImpl denominator( Rational(RationalImpl) r, RationalImpl d ) { 90 RationalImpl prev = r.denominator; 91 RationalImpl t = simplify( r.numerator, d ); // simplify 92 92 r.[numerator, denominator] = [r.numerator / t, d / t]; 93 93 return prev; … … 96 96 // comparison 97 97 98 int ?==?( Rational( T) l, Rational(T) r ) {98 int ?==?( Rational(RationalImpl) l, Rational(RationalImpl) r ) { 99 99 return l.numerator * r.denominator == l.denominator * r.numerator; 100 100 } // ?==? 101 101 102 int ?!=?( Rational( T) l, Rational(T) r ) {102 int ?!=?( Rational(RationalImpl) l, Rational(RationalImpl) r ) { 103 103 return ! ( l == r ); 104 104 } // ?!=? 105 105 106 int ?!=?( Rational(T) l, zero_t ) { 107 return ! ( l == (Rational(T)){ 0 } ); 108 } // ?!=? 109 110 int ?<?( Rational(T) l, Rational(T) r ) { 106 int ?<?( Rational(RationalImpl) l, Rational(RationalImpl) r ) { 111 107 return l.numerator * r.denominator < l.denominator * r.numerator; 112 108 } // ?<? 113 109 114 int ?<=?( Rational( T) l, Rational(T) r ) {110 int ?<=?( Rational(RationalImpl) l, Rational(RationalImpl) r ) { 115 111 return l.numerator * r.denominator <= l.denominator * r.numerator; 116 112 } // ?<=? 117 113 118 int ?>?( Rational( T) l, Rational(T) r ) {114 int ?>?( Rational(RationalImpl) l, Rational(RationalImpl) r ) { 119 115 return ! ( l <= r ); 120 116 } // ?>? 121 117 122 int ?>=?( Rational( T) l, Rational(T) r ) {118 int ?>=?( Rational(RationalImpl) l, Rational(RationalImpl) r ) { 123 119 return ! ( l < r ); 124 120 } // ?>=? … … 126 122 // arithmetic 127 123 128 Rational( T) +?( Rational(T) r ) {129 return (Rational( T)){ r.numerator, r.denominator };124 Rational(RationalImpl) +?( Rational(RationalImpl) r ) { 125 return (Rational(RationalImpl)){ r.numerator, r.denominator }; 130 126 } // +? 131 127 132 Rational( T) -?( Rational(T) r ) {133 return (Rational( T)){ -r.numerator, r.denominator };128 Rational(RationalImpl) -?( Rational(RationalImpl) r ) { 129 return (Rational(RationalImpl)){ -r.numerator, r.denominator }; 134 130 } // -? 135 131 136 Rational( T) ?+?( Rational(T) l, Rational(T) r ) {132 Rational(RationalImpl) ?+?( Rational(RationalImpl) l, Rational(RationalImpl) r ) { 137 133 if ( l.denominator == r.denominator ) { // special case 138 return (Rational( T)){ l.numerator + r.numerator, l.denominator };134 return (Rational(RationalImpl)){ l.numerator + r.numerator, l.denominator }; 139 135 } else { 140 return (Rational( T)){ l.numerator * r.denominator + l.denominator * r.numerator, l.denominator * r.denominator };136 return (Rational(RationalImpl)){ l.numerator * r.denominator + l.denominator * r.numerator, l.denominator * r.denominator }; 141 137 } // if 142 138 } // ?+? 143 139 144 Rational(T) ?+=?( Rational(T) & l, Rational(T) r ) { 145 l = l + r; 146 return l; 147 } // ?+? 148 149 Rational(T) ?+=?( Rational(T) & l, one_t ) { 150 l = l + (Rational(T)){ 1 }; 151 return l; 152 } // ?+? 153 154 Rational(T) ?-?( Rational(T) l, Rational(T) r ) { 140 Rational(RationalImpl) ?-?( Rational(RationalImpl) l, Rational(RationalImpl) r ) { 155 141 if ( l.denominator == r.denominator ) { // special case 156 return (Rational( T)){ l.numerator - r.numerator, l.denominator };142 return (Rational(RationalImpl)){ l.numerator - r.numerator, l.denominator }; 157 143 } else { 158 return (Rational( T)){ l.numerator * r.denominator - l.denominator * r.numerator, l.denominator * r.denominator };144 return (Rational(RationalImpl)){ l.numerator * r.denominator - l.denominator * r.numerator, l.denominator * r.denominator }; 159 145 } // if 160 146 } // ?-? 161 147 162 Rational(T) ?-=?( Rational(T) & l, Rational(T) r ) { 163 l = l - r; 164 return l; 165 } // ?-? 166 167 Rational(T) ?-=?( Rational(T) & l, one_t ) { 168 l = l - (Rational(T)){ 1 }; 169 return l; 170 } // ?-? 171 172 Rational(T) ?*?( Rational(T) l, Rational(T) r ) { 173 return (Rational(T)){ l.numerator * r.numerator, l.denominator * r.denominator }; 148 Rational(RationalImpl) ?*?( Rational(RationalImpl) l, Rational(RationalImpl) r ) { 149 return (Rational(RationalImpl)){ l.numerator * r.numerator, l.denominator * r.denominator }; 174 150 } // ?*? 175 151 176 Rational(T) ?*=?( Rational(T) & l, Rational(T) r ) { 177 return l = l * r; 178 } // ?*? 179 180 Rational(T) ?/?( Rational(T) l, Rational(T) r ) { 181 if ( r.numerator < (T){0} ) { 152 Rational(RationalImpl) ?/?( Rational(RationalImpl) l, Rational(RationalImpl) r ) { 153 if ( r.numerator < (RationalImpl){0} ) { 182 154 r.[numerator, denominator] = [-r.numerator, -r.denominator]; 183 155 } // if 184 return (Rational( T)){ l.numerator * r.denominator, l.denominator * r.numerator };156 return (Rational(RationalImpl)){ l.numerator * r.denominator, l.denominator * r.numerator }; 185 157 } // ?/? 186 158 187 Rational(T) ?/=?( Rational(T) & l, Rational(T) r ) {188 return l = l / r;189 } // ?/?190 191 159 // I/O 192 160 193 forall( istype & | istream( istype ) | { istype & ?|?( istype &, T& ); } )194 istype & ?|?( istype & is, Rational( T) & r ) {161 forall( istype & | istream( istype ) | { istype & ?|?( istype &, RationalImpl & ); } ) 162 istype & ?|?( istype & is, Rational(RationalImpl) & r ) { 195 163 is | r.numerator | r.denominator; 196 Tt = simplify( r.numerator, r.denominator );164 RationalImpl t = simplify( r.numerator, r.denominator ); 197 165 r.numerator /= t; 198 166 r.denominator /= t; … … 200 168 } // ?|? 201 169 202 forall( ostype & | ostream( ostype ) | { ostype & ?|?( ostype &, T); } ) {203 ostype & ?|?( ostype & os, Rational( T) r ) {170 forall( ostype & | ostream( ostype ) | { ostype & ?|?( ostype &, RationalImpl ); } ) { 171 ostype & ?|?( ostype & os, Rational(RationalImpl) r ) { 204 172 return os | r.numerator | '/' | r.denominator; 205 173 } // ?|? 206 174 207 void ?|?( ostype & os, Rational( T) r ) {175 void ?|?( ostype & os, Rational(RationalImpl) r ) { 208 176 (ostype &)(os | r); ends( os ); 209 177 } // ?|? … … 211 179 } // distribution 212 180 213 forall( T | Arithmetic( T ) | { T ?\?( T, unsigned long ); } ) { 214 Rational(T) ?\?( Rational(T) x, long int y ) { 215 if ( y < 0 ) { 216 return (Rational(T)){ x.denominator \ -y, x.numerator \ -y }; 217 } else { 218 return (Rational(T)){ x.numerator \ y, x.denominator \ y }; 219 } // if 220 } // ?\? 221 222 Rational(T) ?\=?( Rational(T) & x, long int y ) { 223 return x = x \ y; 224 } // ?\? 225 } // distribution 181 forall( RationalImpl | arithmetic( RationalImpl ) | { RationalImpl ?\?( RationalImpl, unsigned long ); } ) 182 Rational(RationalImpl) ?\?( Rational(RationalImpl) x, long int y ) { 183 if ( y < 0 ) { 184 return (Rational(RationalImpl)){ x.denominator \ -y, x.numerator \ -y }; 185 } else { 186 return (Rational(RationalImpl)){ x.numerator \ y, x.denominator \ y }; 187 } // if 188 } 226 189 227 190 // conversion 228 191 229 forall( T | Arithmetic( T ) | { double convert( T); } )230 double widen( Rational( T) r ) {192 forall( RationalImpl | arithmetic( RationalImpl ) | { double convert( RationalImpl ); } ) 193 double widen( Rational(RationalImpl) r ) { 231 194 return convert( r.numerator ) / convert( r.denominator ); 232 195 } // widen 233 196 234 forall( T | Arithmetic( T ) | { double convert( T ); Tconvert( double ); } )235 Rational( T) narrow( double f, Tmd ) {197 forall( RationalImpl | arithmetic( RationalImpl ) | { double convert( RationalImpl ); RationalImpl convert( double ); } ) 198 Rational(RationalImpl) narrow( double f, RationalImpl md ) { 236 199 // http://www.ics.uci.edu/~eppstein/numth/frap.c 237 if ( md <= ( T){1} ) { // maximum fractional digits too small?238 return (Rational( T)){ convert( f ), (T){1}}; // truncate fraction200 if ( md <= (RationalImpl){1} ) { // maximum fractional digits too small? 201 return (Rational(RationalImpl)){ convert( f ), (RationalImpl){1}}; // truncate fraction 239 202 } // if 240 203 241 204 // continued fraction coefficients 242 Tm00 = {1}, m11 = { 1 }, m01 = { 0 }, m10 = { 0 };243 Tai, t;205 RationalImpl m00 = {1}, m11 = { 1 }, m01 = { 0 }, m10 = { 0 }; 206 RationalImpl ai, t; 244 207 245 208 // find terms until denom gets too big … … 258 221 if ( f > (double)0x7FFFFFFF ) break; // representation failure 259 222 } // for 260 return (Rational( T)){ m00, m10 };223 return (Rational(RationalImpl)){ m00, m10 }; 261 224 } // narrow 262 225
Note:
See TracChangeset
for help on using the changeset viewer.