fraction.C

Go to the documentation of this file.
00001 /*
00002  * See the dyninst/COPYRIGHT file for copyright information.
00003  * 
00004  * We provide the Paradyn Tools (below described as "Paradyn")
00005  * on an AS IS basis, and do not warrant its validity or performance.
00006  * We reserve the right to update, modify, or discontinue this
00007  * software at any time.  We shall have no obligation to supply such
00008  * updates or modifications or any other form of support to you.
00009  * 
00010  * By your use of Paradyn, you understand and agree that we (or any
00011  * other person or entity with proprietary rights in Paradyn) are
00012  * under no obligation to provide either maintenance services,
00013  * update services, notices of latent defects, or correction of
00014  * defects for Paradyn.
00015  * 
00016  * This library is free software; you can redistribute it and/or
00017  * modify it under the terms of the GNU Lesser General Public
00018  * License as published by the Free Software Foundation; either
00019  * version 2.1 of the License, or (at your option) any later version.
00020  * 
00021  * This library is distributed in the hope that it will be useful,
00022  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00024  * Lesser General Public License for more details.
00025  * 
00026  * You should have received a copy of the GNU Lesser General Public
00027  * License along with this library; if not, write to the Free Software
00028  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00029  */
00030 
00031 #include "common/h/fraction.h"
00032 #include "common/h/int64iostream.h"
00033 
00034 fraction::ostream_fmt fraction::curFmt = sparse;
00035 
00036 /*
00037 const fraction operator*(const fraction &a, const fraction &b) {
00038   if(b.getNumer() < a.getMultOverflowPt()) {
00039     return fraction(a.getNumer() * b.getNumer(), a.getDenom() * b.getDenom());
00040   } else {
00041     fraction c = a * b.getNumer();
00042     c.setDenom(c.getDenom()*b.getDenom());
00043     return c;
00044   }
00045 };
00046 */
00047 
00048 int64_t lcd(int64_t a, int64_t b) {
00049   int64_t _gcd = gcd(a,b);
00050   if(a > b) { a = a / _gcd; }
00051   else      { b = b / _gcd; }
00052   int64_t overflowPt = I64_MAX / b;
00053   if(a > overflowPt) {  cerr << "lcd: overflow\n";  return -1; }
00054   return a * b;
00055 }
00056 
00057 int64_t gcd(int64_t a, int64_t b) {
00058   if (b == 0) return a;
00059   return gcd(b, a % b);
00060 }
00061 
00062 // fraction + fraction
00063 /*const fraction operator+(const fraction &a, const fraction &b) {
00064   if(a.getDenom() == b.getDenom()) {
00065     return fraction(a.getNumer() + b.getNumer(), a.getDenom());
00066   } else {
00067     int64_t ilcd = lcd(a.getDenom(), b.getDenom());
00068     return fraction(a.getNumer()*ilcd + b.getNumer()*ilcd, a.getDenom()*ilcd);
00069   }
00070 }
00071 
00072 // fraction - fraction
00073 const fraction operator-(const fraction &a, const fraction &b) {
00074   if(a.getDenom() == b.getDenom()) {
00075     return fraction(a.getNumer() - b.getNumer(), a.getDenom());
00076   } else {
00077     int64_t ilcd = lcd(a.getDenom(), b.getDenom());
00078     return fraction(a.getNumer()*ilcd - b.getNumer()*ilcd, a.getDenom()*ilcd);
00079   }
00080 }
00081 */
00082 
00083 const fraction operator*(const fraction &a, int64_t b) {
00084   if(b < a.getInterimMultOverflowPt()) {
00085     //   b < interimMultOverflowPt
00086     return fraction(b * a.getNumer(), a.getDenom());
00087   } else if(b <= a.getFinalMultOverflowPt()) {
00088     //   interimMultOverflowPt <= b <= finalMultInterimPt
00089     cerr << "fraction::operator*- an interim overflow has occurred\n";
00090     return fraction(I64_MAX);
00091   } else {  //  finalMultInterimPt < b
00092     cerr << "fraction::operator*- a final overflow has occurred\n";
00093     return fraction(I64_MAX);
00094   }
00095 }
00096 
00097 int64_t fraction::multReturnInt64(int64_t b) const {
00098   int64_t ret = 0;
00099   if(b < getInterimMultOverflowPt()) {
00100     //   b < interimMultOverflowPt
00101     fraction fres(b * getNumer(), getDenom());
00102     ret = fres.getI();
00103   } else if(b <= getFinalMultOverflowPt()) {
00104     //   interimMultOverflowPt <= b <= finalMultInterimPt
00105     ret = multNoInterimOverflow(b);
00106   } else {  //  finalMultInterimPt < b
00107     cerr << "fraction::multReturnInt64- a final overflow has occurred\n";    
00108     return I64_MAX;
00109   }
00110   return ret;
00111 }
00112 
00113 void fraction::calcOverflowPts() const {
00114   if(getNumer() == 0) 
00115     interimMultOverflowPt = I64_MAX;
00116   else 
00117     interimMultOverflowPt = I64_MAX / getNumer();
00118   fraction recip;
00119   recip.setRaw(getDenom(), getNumer());
00120   if(recip.getDenom()==0 || recip.getD() > 1.0) 
00121     finalMultOverflowPt = I64_MAX;
00122   else
00123     finalMultOverflowPt = recip.multNoInterimOverflow(I64_MAX);
00124 }
00125 
00126 // getFrSpec is a helper routine for the gt, lt operators
00127 // n : numerator,   d: denominator
00128 // ra: returns the numerator high 32 bits / denom (always positive)
00129 // rb: returns the numerator low  32 bits / denom (always positive)
00130 // rsign: -1 for negative, 1 for positive result
00131 void getFrSpec(int64_t n, int64_t d, double *ra, double *rb, int *rsign) {
00132   int sign = 1;
00133   if(n < 0) { n = -n;  sign = -sign; }
00134   if(d < 0) { d = -d;  sign = -sign; }
00135   *rsign = sign;
00136   int64_t upperI = n & I64_C(0xFFFFFFFF00000000);
00137   *ra = static_cast<double>(upperI) / static_cast<double>(d);
00138   int64_t lowerI = n & 0xFFFFFFFF;
00139   *rb = static_cast<double>(lowerI) / static_cast<double>(d);
00140 }
00141 
00142 // the gcd of the denominators could easily grow beyond the int64 max
00143 // so implement using doubles
00144 bool operator>(const fraction &a, const fraction &b) {
00145   double ax, ay;
00146   int as;
00147   getFrSpec(a.getNumer(), a.getDenom(), &ax, &ay, &as);
00148   if(as == -1) { ax =- ax; ay =-ay; }
00149 
00150   double bx, by;
00151   int bs;
00152   getFrSpec(b.getNumer(), b.getDenom(), &bx, &by, &bs);
00153   if(bs == -1) { bx =- bx; by =-by; }
00154   return (ax > bx || (ax == bx && ay > by));
00155 }
00156 
00157 bool operator<(const fraction &a, const fraction &b) {
00158   double ax, ay;
00159   int as;
00160   getFrSpec(a.getNumer(), a.getDenom(), &ax, &ay, &as);
00161   if(as == -1) { ax =- ax; ay =-ay; }
00162 
00163   double bx, by;
00164   int bs;
00165   getFrSpec(b.getNumer(), b.getDenom(), &bx, &by, &bs);
00166   if(bs == -1) { bx =- bx; by =-by; }
00167   return (ax < bx || (ax == bx && ay < by));
00168 }
00169 
00170 bool operator>=(const fraction &a, const fraction &b) {
00171   return ((a > b) || (a == b));
00172 }
00173 
00174 bool operator<=(const fraction &a, const fraction &b) {
00175   return ((a < b) || (a == b));
00176 }
00177 
00178 ostream& operator<<(ostream&s, const fraction::ostream_fmt u) {
00179   fraction::curFmt = u;
00180   return s;
00181 }
00182 
00183 ostream& operator<<(ostream&s, const fraction &z) {
00184   if(fraction::curFmt == fraction::sparse) {
00185     s << "(" << z.getNumer() << "/" << z.getDenom() << ")";
00186   } else { // fraction::verbose
00187     s << "(" << z.getNumer() << "/" << z.getDenom() << " - interimOvflw:";
00188     s << z.getInterimMultOverflowPt() << ", finalOvflw: " 
00189       << z.getFinalMultOverflowPt();
00190   }
00191   return s;
00192 }
00193 
00194 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 12 Jul 2013 for SymtabAPI by  doxygen 1.6.1