update to set up make variables for compiling modules with libhrtime
[dyninst.git] / common / src / fraction.C
1 #include <iostream.h>
2 #include "common/h/fraction.h"
3 #include "common/h/int64iostream.h"
4
5
6 fraction::ostream_fmt fraction::curFmt = sparse;
7
8 /*
9 const fraction operator*(const fraction &a, const fraction &b) {
10   if(b.getNumer() < a.getMultOverflowPt()) {
11     return fraction(a.getNumer() * b.getNumer(), a.getDenom() * b.getDenom());
12   } else {
13     fraction c = a * b.getNumer();
14     c.setDenom(c.getDenom()*b.getDenom());
15     return c;
16   }
17 };
18 */
19
20 int64_t lcd(int64_t a, int64_t b) {
21   int64_t _gcd = gcd(a,b);
22   if(a > b) { a = a / _gcd; }
23   else      { b = b / _gcd; }
24   int64_t overflowPt = I64_MAX / b;
25   if(a > overflowPt) {  cerr << "lcd: overflow\n";  return -1; }
26   return a * b;
27 }
28
29 int64_t gcd(int64_t a, int64_t b) {
30   if (b == 0) return a;
31   return gcd(b, a % b);
32 }
33
34 // fraction + fraction
35 /*const fraction operator+(const fraction &a, const fraction &b) {
36   if(a.getDenom() == b.getDenom()) {
37     return fraction(a.getNumer() + b.getNumer(), a.getDenom());
38   } else {
39     int64_t ilcd = lcd(a.getDenom(), b.getDenom());
40     return fraction(a.getNumer()*ilcd + b.getNumer()*ilcd, a.getDenom()*ilcd);
41   }
42 }
43
44 // fraction - fraction
45 const fraction operator-(const fraction &a, const fraction &b) {
46   if(a.getDenom() == b.getDenom()) {
47     return fraction(a.getNumer() - b.getNumer(), a.getDenom());
48   } else {
49     int64_t ilcd = lcd(a.getDenom(), b.getDenom());
50     return fraction(a.getNumer()*ilcd - b.getNumer()*ilcd, a.getDenom()*ilcd);
51   }
52 }
53 */
54
55 const fraction operator*(const fraction &a, int64_t b) {
56   if(b < a.getInterimMultOverflowPt()) {
57     //   b < interimMultOverflowPt
58     return fraction(b * a.getNumer(), a.getDenom());
59   } else if(b <= a.getFinalMultOverflowPt()) {
60     //   interimMultOverflowPt <= b <= finalMultInterimPt
61     cerr << "fraction::operator*- an interim overflow has occurred\n";
62     return fraction(I64_MAX);
63   } else {  //  finalMultInterimPt < b
64     cerr << "fraction::operator*- a final overflow has occurred\n";
65     return fraction(I64_MAX);
66   }
67 }
68
69 int64_t fraction::multReturnInt64(int64_t b) const {
70   int64_t ret = 0;
71   if(b < getInterimMultOverflowPt()) {
72     //   b < interimMultOverflowPt
73     fraction fres(b * getNumer(), getDenom());
74     ret = fres.getI();
75   } else if(b <= getFinalMultOverflowPt()) {
76     //   interimMultOverflowPt <= b <= finalMultInterimPt
77     ret = multNoInterimOverflow(b);
78   } else {  //  finalMultInterimPt < b
79     cerr << "fraction::multReturnInt64- a final overflow has occurred\n";    
80     return I64_MAX;
81   }
82   return ret;
83 }
84
85 void fraction::calcOverflowPts() const {
86   if(getNumer() == 0) 
87     interimMultOverflowPt = I64_MAX;
88   else 
89     interimMultOverflowPt = I64_MAX / getNumer();
90   fraction recip;
91   recip.setRaw(getDenom(), getNumer());
92   if(recip.getDenom()==0 || recip.getD() > 1.0) 
93     finalMultOverflowPt = I64_MAX;
94   else
95     finalMultOverflowPt = recip.multNoInterimOverflow(I64_MAX);
96 }
97
98 // getFrSpec is a helper routine for the gt, lt operators
99 // n : numerator,   d: denominator
100 // ra: returns the numerator high 32 bits / denom (always positive)
101 // rb: returns the numerator low  32 bits / denom (always positive)
102 // rsign: -1 for negative, 1 for positive result
103 void getFrSpec(int64_t n, int64_t d, double *ra, double *rb, int *rsign) {
104   int sign = 1;
105   if(n < 0) { n = -n;  sign = -sign; }
106   if(d < 0) { d = -d;  sign = -sign; }
107   *rsign = sign;
108   int64_t upperI = n & I64_C(0xFFFFFFFF00000000);
109   *ra = static_cast<double>(upperI) / static_cast<double>(d);
110   int64_t lowerI = n & 0xFFFFFFFF;
111   *rb = static_cast<double>(lowerI) / static_cast<double>(d);
112 }
113
114 // the gcd of the denominators could easily grow beyond the int64 max
115 // so implement using doubles
116 bool operator>(const fraction &a, const fraction &b) {
117   double ax, ay;
118   int as;
119   getFrSpec(a.getNumer(), a.getDenom(), &ax, &ay, &as);
120   if(as == -1) { ax =- ax; ay =-ay; }
121
122   double bx, by;
123   int bs;
124   getFrSpec(b.getNumer(), b.getDenom(), &bx, &by, &bs);
125   if(bs == -1) { bx =- bx; by =-by; }
126   return (ax > bx || (ax == bx && ay > by));
127 }
128
129 bool operator<(const fraction &a, const fraction &b) {
130   double ax, ay;
131   int as;
132   getFrSpec(a.getNumer(), a.getDenom(), &ax, &ay, &as);
133   if(as == -1) { ax =- ax; ay =-ay; }
134
135   double bx, by;
136   int bs;
137   getFrSpec(b.getNumer(), b.getDenom(), &bx, &by, &bs);
138   if(bs == -1) { bx =- bx; by =-by; }
139   return (ax < bx || (ax == bx && ay < by));
140 }
141
142 bool operator>=(const fraction &a, const fraction &b) {
143   return ((a > b) || (a == b));
144 }
145
146 bool operator<=(const fraction &a, const fraction &b) {
147   return ((a < b) || (a == b));
148 }
149
150 ostream& operator<<(ostream&s, const fraction::ostream_fmt u) {
151   fraction::curFmt = u;
152   return s;
153 }
154
155 ostream& operator<<(ostream&s, const fraction &z) {
156   if(fraction::curFmt == fraction::sparse) {
157     s << "(" << z.getNumer() << "/" << z.getDenom() << ")";
158   } else { // fraction::verbose
159     s << "(" << z.getNumer() << "/" << z.getDenom() << " - interimOvflw:";
160     s << z.getInterimMultOverflowPt() << ", finalOvflw: " 
161       << z.getFinalMultOverflowPt();
162   }
163   return s;
164 }
165
166