OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimRationalNumber.cpp
Go to the documentation of this file.
1 //*******************************************************************
2 //
3 // License: See top level LICENSE.txt file.
4 //
5 // Author: Garrett Potts (gpotts@imagelinks.com)
6 //
7 //*******************************************************************
8 // $Id: ossimRationalNumber.cpp 11347 2007-07-23 13:01:59Z gpotts $
10 
11 // Normalisation
13 {
14  if (theDen == 0)
15  {
16  return;
17  }
18 
19  // Handle the case of zero separately, to avoid division by zero
20  if (theNum == 0)
21  {
22  theDen = 1;
23  return;
24  }
25 
27 
28  theNum /= g;
29  theDen /= g;
30 
31  // Ensure that the denominator is positive
32  if (theDen < 0)
33  {
34  theNum = -theNum;
35  theDen = -theDen;
36  }
37 }
38 
39 const ossimRationalNumber& ossimRationalNumber::assign(double value, long precision)
40 {
41  ossim_sint32 s = 1;
42  if(value <= 0.0)
43  {
44  s = -1;
45  value *= -1.0;
46  }
47  ossim_int32 integerPart = (ossim_int32)std::floor(value);
48  ossim_int32 decimalPart = (ossim_int32)((value - integerPart)*precision);
49  ossimRationalNumber temp(integerPart);
50  ossimRationalNumber temp2(decimalPart, precision);
51  temp2.normalize();
52  *this = (temp + temp2);
53  theNum *= s;
54  normalize();
55  return *this;
56 }
57 
59 {
60  // This calculation avoids overflow, and minimises the number of expensive
61  // calculations. Thanks to Nickolay Mladenov for this algorithm.
62  //
63  // Proof:
64  // We have to compute a/b + c/d, where gcd(a,b)=1 and gcd(b,c)=1.
65  // Let g = gcd(b,d), and b = b1*g, d=d1*g. Then gcd(b1,d1)=1
66  //
67  // The result is (a*d1 + c*b1) / (b1*d1*g).
68  // Now we have to normalize this ratio.
69  // Let's assume h | gcd((a*d1 + c*b1), (b1*d1*g)), and h > 1
70  // If h | b1 then gcd(h,d1)=1 and hence h|(a*d1+c*b1) => h|a.
71  // But since gcd(a,b1)=1 we have h=1.
72  // Similarly h|d1 leads to h=1.
73  // So we have that h | gcd((a*d1 + c*b1) , (b1*d1*g)) => h|g
74  // Finally we have gcd((a*d1 + c*b1), (b1*d1*g)) = gcd((a*d1 + c*b1), g)
75  // Which proves that instead of normalizing the result, it is better to
76  // divide num and den by gcd((a*d1 + c*b1), g)
77 
79  theDen /= g; // = b1 from the calculations above
80  theNum = theNum * (r.theDen / g) + r.theNum * theDen;
81  g = ossim::gcd(theNum, g);
82  theNum /= g;
83  theDen *= r.theDen/g;
84 
85  return *this;
86 }
87 
89 {
90  // This calculation avoids overflow, and minimises the number of expensive
91  // calculations. It corresponds exactly to the += case above
93  theDen /= g;
94  theNum = theNum * (r.theDen / g) - r.theNum * theDen;
95  g = ossim::gcd(theNum, g);
96  theNum /= g;
97  theDen *= r.theDen/g;
98 
99  return *this;
100 }
101 
103 {
104  // Avoid overflow and preserve normalization
105  ossim_int32 gcd1 = ossim::gcd(theNum, r.theDen);
106  ossim_int32 gcd2 = ossim::gcd(r.theNum, theDen);
107  theNum = (theNum/gcd1) * (r.theNum/gcd2);
108  theDen = (theDen/gcd2) * (r.theDen/gcd1);
109 
110  return *this;
111 }
112 
114 {
115  ossim_int32 zero(0);
116 
117  if (r.theNum == zero)
118  {
121 
122  return *this;
123  }
124  *this = (*this)*(ossimRationalNumber(r.theDen, r.theNum));
125 
126  return *this;
127 }
128 
129 // Mixed-mode operators
131 {
133 }
134 
136 {
138 }
139 
141 {
143 }
144 
146 {
148 }
149 
151 {
152  // This calculation avoids overflow, and minimises the number of expensive
153  // calculations. Thanks to Nickolay Mladenov for this algorithm.
154  //
155  // Proof:
156  // We have to compute a/b + c/d, where gcd(a,b)=1 and gcd(b,c)=1.
157  // Let g = gcd(b,d), and b = b1*g, d=d1*g. Then gcd(b1,d1)=1
158  //
159  // The result is (a*d1 + c*b1) / (b1*d1*g).
160  // Now we have to normalize this ratio.
161  // Let's assume h | gcd((a*d1 + c*b1), (b1*d1*g)), and h > 1
162  // If h | b1 then gcd(h,d1)=1 and hence h|(a*d1+c*b1) => h|a.
163  // But since gcd(a,b1)=1 we have h=1.
164  // Similarly h|d1 leads to h=1.
165  // So we have that h | gcd((a*d1 + c*b1) , (b1*d1*g)) => h|g
166  // Finally we have gcd((a*d1 + c*b1), (b1*d1*g)) = gcd((a*d1 + c*b1), g)
167  // Which proves that instead of normalizing the result, it is better to
168  // divide num and den by gcd((a*d1 + c*b1), g)
169 
171  ossim_int32 den = theDen;
172  ossim_int32 num = theNum;
173  den /= g; // = b1 from the calculations above
174  num = num * (r.theDen / g) + r.theNum * den;
175  g = ossim::gcd(num, g);
176  num /= g;
177  den *= r.theDen/g;
178 
179  return ossimRationalNumber(num, den);
180 }
181 
183 {
184  ossimRationalNumber result = *this;
185  // This calculation avoids overflow, and minimises the number of expensive
186  // calculations. It corresponds exactly to the += case above
187  ossim_int32 g = ossim::gcd(result.theDen, r.theDen);
188  result.theDen /= g;
189  result.theNum = result.theNum * (r.theDen / g) - r.theNum * result.theDen;
190  g = ossim::gcd(result.theNum, g);
191  result.theNum /= g;
192  result.theDen *= r.theDen/g;
193 
194  return result;
195 }
196 
198 {
199  ossimRationalNumber result = *this;
200  // Avoid overflow and preserve normalization
201  ossim_int32 gcd1 = ossim::gcd(result.theNum, r.theDen);
202  ossim_int32 gcd2 = ossim::gcd(r.theNum, result.theDen);
203  result.theNum = (result.theNum/gcd1) * (r.theNum/gcd2);
204  result.theDen = (result.theDen/gcd2) * (r.theDen/gcd1);
205 
206  return result;
207 }
208 
210 {
211  ossim_int32 zero(0);
212 
213  if (r.theNum == zero)
214  {
216  }
217 
218  return (*this)*(ossimRationalNumber(r.theDen, r.theNum));
219 }
const ossimRationalNumber & assign(ossim_int32 n, ossim_int32 d)
const ossimRationalNumber & operator+=(const ossimRationalNumber &r)
#define OSSIM_INT_NAN
ossimRationalNumber operator*(const ossimRationalNumber &r) const
const ossimRationalNumber & operator/=(const ossimRationalNumber &r)
signed int ossim_sint32
ossimRationalNumber operator+(const ossimRationalNumber &r) const
const ossimRationalNumber & operator-=(const ossimRationalNumber &r)
ossimRationalNumber operator-() const
ossimRationalNumber operator/(const ossimRationalNumber &r) const
int ossim_int32
IntType gcd(IntType n, IntType m)
Definition: ossimCommon.h:271
const ossimRationalNumber & operator*=(const ossimRationalNumber &r)