Update copyright to LGPL on all files
[dyninst.git] / common / h / fraction.h
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32
33 #ifndef __FRACTION_H
34 #define __FRACTION_H
35
36 #include "common/h/std_namesp.h"
37 #include "common/h/Types.h"
38
39 #if defined(os_windows)
40                                         // exception SPECIFICATIONS aren't
41 #pragma warning( disable : 4290 )       // implemented yet on NT
42 #endif
43
44
45 class COMMON_EXPORT fraction {
46   mutable int64_t numer;
47   mutable int64_t denom;
48   // largest multiplicand until an interim overflow will occur, and need to 
49   // handle by different means
50   mutable int64_t interimMultOverflowPt;  
51   // largest multipland until a final overflow will occur, no way to handle
52   // because result value is just to large to handle with an int64_t
53   mutable int64_t   finalMultOverflowPt;
54  public:
55   typedef enum { sparse, verbose } ostream_fmt; 
56   static ostream_fmt curFmt;
57
58   fraction() : numer(0), denom(0), 
59     interimMultOverflowPt(0), finalMultOverflowPt(0)  { }
60   explicit fraction(int64_t n) : numer(n), denom(I64_C(1))  { 
61     calcOverflowPts();
62   }
63   explicit fraction(int64_t n, int64_t d) : numer(n), denom(d)  { 
64     calcOverflowPts();
65   }
66   // default copy constructor
67
68   // Selectors
69   int64_t getNumer() const {  return numer; }
70   int64_t getDenom() const {  return denom; }
71   // returns an integer representation of the fraction
72   int64_t getI() const {
73     return numer / denom;
74   }
75   // returns a double representation of the fraction
76   double  getD() const { return (double) numer / (double) denom; }
77   int64_t getInterimMultOverflowPt() const {  
78     return interimMultOverflowPt; 
79   }
80   int64_t   getFinalMultOverflowPt() const {  
81     return   finalMultOverflowPt; 
82   }
83
84 /* A fast specialized multiplication of a fraction and an int64
85    uses a special method that can keep from an interim overflow from occurring
86    precise in regards to the result (doesn't round, ie. rounds result down).
87    Returns int int64_t instead of a fraction, like the operator* does.
88    If a final overflow occurs, prints an error message and returns the
89    largest integer.
90 */
91   int64_t multReturnInt64(int64_t b) const;
92
93   fraction reciprocal() const {  
94     return fraction(denom, numer); 
95   }
96  private:
97   int64_t multNoInterimOverflow(int64_t b) const {
98     int64_t intdiv = b / getDenom();
99     int64_t decrem = b % getDenom();
100     return intdiv*getNumer() + decrem*getNumer()/getDenom();
101   }
102
103  public:
104   // Mutators
105   void setNumer(int64_t n) {
106     numer = n;
107     calcOverflowPts();
108   }
109   void setDenom(int64_t d) { 
110     denom = d; 
111     calcOverflowPts();
112   }
113  private:
114   void setRaw(int64_t n, int64_t d) {
115     numer = n;
116     denom = d;
117   }
118  public:
119   void set(int64_t n, int64_t d) { 
120     setRaw(n,d);
121     calcOverflowPts();
122   }
123   // This is const, because only modifying internal variables
124   void calcOverflowPts() const;
125
126   // A fraction is still logically unchanged when you reduce it, so consider
127   // it a constant operation  eg. this will work:
128   //   const fraction a(2,4);  a.reduce();
129   void reduce() const;
130 };
131
132
133 ostream& operator<<(ostream&s, const fraction::ostream_fmt u);
134 ostream& operator<<(ostream&s, const fraction &z);
135
136 /* If you want these, feel free to write them
137 const fraction &operator+(const fraction &a, const fraction &b); {
138 const fraction &operator-(const fraction &a, const fraction &b);
139 */
140
141 COMMON_EXPORT int64_t gcd(int64_t a, int64_t b);
142 COMMON_EXPORT int64_t lcd(int64_t a, int64_t b);
143
144 inline void fraction::reduce() const {
145   int64_t igcd = gcd(numer, denom);
146   numer = numer / igcd;
147   denom = denom / igcd;
148   calcOverflowPts();
149 }
150
151 // fraction * double
152 inline double operator*(const fraction &a, const double d) {
153   return d * a.getD();
154 }
155 // double   * fraction
156 inline double operator*(const double d, const fraction &a) {
157   return a * d;
158 }
159
160 // Upon an interim or final overflow, prints an error message and returns
161 // the largest fraction representable.
162 // fraction * int64_t
163 const fraction operator*(const fraction &a, int64_t b);
164 // int64_t  * fraction
165 inline const fraction operator*(int64_t a, const fraction &b) {
166   return b * a;
167 }
168
169 // fraction + fraction
170 //const fraction operator+(const fraction &a, const fraction &b);
171 // fraction - fraction
172 //const fraction operator-(const fraction &a, const fraction &b);
173
174 // fraction * fraction
175 /* Feel free to implement if needed:
176 const fraction operator*(const fraction &a, const fraction &b); 
177 */
178
179
180 inline const fraction operator/(const fraction &a, const fraction &b) {
181   return fraction(a.getNumer() * b.getDenom(), a.getDenom() * b.getNumer());
182 }
183
184 inline bool operator==(const fraction &a, const fraction &b) {
185   fraction ar = a;
186   ar.reduce();
187   fraction br = b;
188   br.reduce();
189   return ((ar.getNumer() == br.getNumer()) && (ar.getDenom() == br.getDenom()));
190 }
191 inline bool operator!=(const fraction &a, const fraction &b) {
192   fraction ar = a;
193   ar.reduce();
194   fraction br = b;
195   br.reduce();
196   return ((ar.getNumer() != br.getNumer()) || (ar.getDenom() != br.getDenom()));
197 }
198
199 // getFrSpec is a helper routine for the gt, lt operators
200 // n : numerator,   d: denominator
201 // ra: returns the numerator high 32 bits / denom (always positive)
202 // rb: returns the numerator low  32 bits / denom (always positive)
203 // rsign: -1 for negative, 1 for positive result
204 void getFrSpec(int64_t n, int64_t d, double *ra, double *rb, int *rsign);
205 bool operator>(const fraction &a, const fraction &b);
206 bool operator<(const fraction &a, const fraction &b);
207 bool operator>=(const fraction &a, const fraction &b);
208 bool operator<=(const fraction &a, const fraction &b);
209
210
211
212
213 #endif