00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00132 #ifndef frac_INCLUDED
00133 #define frac_INCLUDED
00134
00135 extern "C" {
00136 #ifndef defs_INCLUDED
00137 #include "defs.h"
00138 #endif
00139 #ifndef ERRORS_INCLUDED
00140 #include "errors.h"
00141 #endif
00142 }
00143
00144
00145
00146
00147
00148
00149 #define FRAC_ETY mINT32
00150 #define FRAC_ITY mINT64
00151
00152 #ifdef Is_True_On
00153
00154 #define FRAC_MAX 1000000
00155 #else
00156
00157 #define FRAC_MAX INT32_MAX
00158 #endif
00159
00160 class FRAC {
00161 public:
00162 static BOOL Exception;
00163
00164 FRAC() {_n = 0; _d = 1;}
00165 FRAC(FRAC_ETY n) : _n(_checksz(n)), _d(1) {}
00166 FRAC(FRAC_ETY n, FRAC_ETY d) : _n(n), _d(d) {_reduce();}
00167 FRAC(const FRAC& f) : _n(f._n), _d(f._d) {}
00168
00169
00170 FRAC_ETY N() const {return _n;}
00171 FRAC_ETY D() const {return _d;}
00172
00173 FRAC& operator =(const FRAC& f) {_n = f._n; _d = f._d; return *this;}
00174
00175 BOOL operator ==(FRAC f) const
00176 {return _n == f._n && _d == f._d;}
00177 BOOL operator !=(FRAC f) const
00178 {return _n != f._n || _d != f._d;}
00179 BOOL operator <(FRAC f) const
00180 {return FRAC_ITY(_n)*f._d < FRAC_ITY(f._n)*_d;}
00181 BOOL operator <=(FRAC f) const
00182 {return FRAC_ITY(_n)*f._d <= FRAC_ITY(f._n)*_d;}
00183 BOOL operator >(FRAC f) const
00184 {return FRAC_ITY(_n)*f._d > FRAC_ITY(f._n)*_d;}
00185 BOOL operator >=(FRAC f) const
00186 {return FRAC_ITY(_n)*f._d >= FRAC_ITY(f._n)*_d;}
00187
00188 FRAC_ETY Integer() const
00189 {FmtAssert(_d == 1, ("int(%d/%d)", _n, _d)); return _n;}
00190 double Real() const
00191 {return (double(_n))/_d;}
00192
00193 FRAC operator +(FRAC f) const;
00194 FRAC& operator +=(FRAC f) {return (*this) = (*this) + f;}
00195 FRAC operator -(FRAC f) const;
00196 FRAC& operator -=(FRAC f) {return (*this) = (*this) - f;}
00197 FRAC operator *(FRAC f) const;
00198 FRAC& operator *=(FRAC f) {return (*this) = (*this) * f;}
00199 FRAC operator /(FRAC f) const;
00200 FRAC& operator /=(FRAC f) {return (*this) = (*this) / f;}
00201 FRAC operator -() const {return FRAC(-_n, _d, 0);}
00202
00203 FRAC Abs() const {return FRAC(_n < 0 ? -_n : _n, _d, 0);}
00204 friend FRAC Abs(FRAC f) {return f.Abs();}
00205
00206 void Print(FILE* f) const;
00207 char* Print(char* f) const;
00208
00209 private:
00210
00211 FRAC(FRAC_ITY n, FRAC_ITY d) {_reduce(n, d);}
00212 FRAC(FRAC_ETY n, FRAC_ETY d, INT32) : _n(n), _d(d) {}
00213
00214
00215
00216
00217 void _reduce() {
00218 if (_d == 1)
00219 _n = _checksz(_n);
00220 else if (_n == 0) {
00221 _d = 1;
00222 }
00223 else if (_n == 1 || _n == -1) {
00224 _n = _d < 0 ? -_n : _n;
00225 _d = _checksz(_d < 0 ? -_d : _d);
00226 }
00227 else if (_d == -1) {
00228 _n = _checksz(-_n);
00229 _d = -_d;
00230 }
00231 else
00232 _reduce2();
00233 }
00234
00235
00236 void _reduce(FRAC_ITY n, FRAC_ITY d) {
00237 if (d == 1) {
00238 _n = _checksz(n);
00239 _d = 1;
00240 }
00241 else if (n == 0) {
00242 _n = 0;
00243 _d = 1;
00244 }
00245 else if (n == 1 || n == -1) {
00246 _n = d < 0 ? FRAC_ETY(-n) : FRAC_ETY(n);
00247 _d = _checksz(d < 0 ? -d : d);
00248 }
00249 else if (d == -1) {
00250 _n = _checksz(-n);
00251 _d = 1;
00252 }
00253 else
00254 _reduce2(n, d);
00255 }
00256
00257
00258
00259
00260 void _reduce2();
00261 void _reduce2(FRAC_ITY n, FRAC_ITY d);
00262
00263
00264
00265 static FRAC_ETY _checksz(FRAC_ETY x) {
00266 if (!_sz_ok(x)) {
00267 if (Exception == FALSE) {
00268 DevWarn("FRAC component too big: %d", x);
00269 Exception = TRUE;
00270 }
00271 x = MIN(x, FRAC_MAX);
00272 x = MAX(x, -FRAC_MAX);
00273 }
00274 return x;
00275 }
00276 static FRAC_ETY _checksz(FRAC_ITY x) {
00277 if (!_sz_ok(x)) {
00278 if (Exception == FALSE) {
00279 DevWarn("FRAC component too big: %lld", x);
00280 Exception = TRUE;
00281 }
00282 x = MIN(x, FRAC_MAX);
00283 x = MAX(x, -FRAC_MAX);
00284 }
00285 return FRAC_ETY(x);
00286 }
00287 static FRAC _checksz(FRAC_ETY n, FRAC_ETY d) {
00288 FRAC f;
00289 if (!_sz_ok(n) || !_sz_ok(d)) {
00290 if (Exception == FALSE) {
00291 DevWarn("FRAC component too big: %d/%d", n, d);
00292 Exception = TRUE;
00293 }
00294 f._n = d == 0 ? 1 : n/d;
00295 f._d = 1;
00296 }
00297 else {
00298 f._n = n;
00299 f._d = d;
00300 }
00301 return f;
00302 }
00303 static FRAC _checksz(FRAC_ITY n, FRAC_ITY d) {
00304 FRAC f;
00305 if (!_sz_ok(n) || !_sz_ok(d)) {
00306 if (Exception == FALSE) {
00307 DevWarn("FRAC component too big: %lld/%lld", n, d);
00308 Exception = TRUE;
00309 }
00310 f._n = d == 0 ? 1 : n/d;
00311 f._d = 1;
00312 }
00313 else {
00314 f._n = n;
00315 f._d = d;
00316 }
00317 return f;
00318 }
00319
00320
00321 static BOOL _sz_ok(FRAC_ITY x) {
00322 return (x <= FRAC_MAX && x >= -FRAC_MAX);
00323 }
00324 static BOOL _sz_ok(FRAC_ITY n, FRAC_ITY d) {
00325 return _sz_ok(n) && _sz_ok(d);
00326 }
00327 static BOOL _sz_ok(FRAC_ETY x) {
00328 return (x <= FRAC_MAX && x >= -FRAC_MAX);
00329 }
00330 static BOOL _sz_ok(FRAC_ETY n, FRAC_ETY d) {
00331 return _sz_ok(n) && _sz_ok(d);
00332 }
00333
00334 FRAC_ETY _n;
00335 FRAC_ETY _d;
00336 };
00337 #endif