1///////////////////////////////////////////////////////////////////////////
2//
3// Copyright (c) 2006, Industrial Light & Magic, a division of Lucas
4// Digital Ltd. LLC
5//
6// All rights reserved.
7//
8// Redistribution and use in source and binary forms, with or without
9// modification, are permitted provided that the following conditions are
10// met:
11// *       Redistributions of source code must retain the above copyright
12// notice, this list of conditions and the following disclaimer.
13// *       Redistributions in binary form must reproduce the above
14// copyright notice, this list of conditions and the following disclaimer
15// in the documentation and/or other materials provided with the
16// distribution.
17// *       Neither the name of Industrial Light & Magic nor the names of
18// its contributors may be used to endorse or promote products derived
19// from this software without specific prior written permission.
20//
21// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32//
33///////////////////////////////////////////////////////////////////////////
34
35//-----------------------------------------------------------------------------
36//
37//	Rational numbers
38//
39//	The double-to-Rational conversion code below
40//	was contributed to OpenEXR by Greg Ward.
41//
42//-----------------------------------------------------------------------------
43
44#include <ImfRational.h>
45#include <cmath>
46
47using namespace std;
48
49namespace Imf {
50namespace {
51
52double
53frac (double x, double e)
54{
55    return x - floor (x + e);
56}
57
58
59double
60square (double x)
61{
62    return x * x;
63}
64
65
66double
67denom (double x, double e)
68{
69    if (e > frac (x, e))
70    {
71        return 1;
72    }
73    else
74    {
75	double r = frac (1 / x, e);
76
77        if (e > r)
78        {
79            return floor (1 / x + e);
80        }
81        else
82        {
83            return denom (frac (1 / r, e), e / square (x * r)) +
84                   floor (1 / x + e) * denom (frac (1 / x, e), e / square (x));
85        }
86    }
87}
88
89} // namespace
90
91
92Rational::Rational (double x)
93{
94    int sign;
95
96    if (x >= 0)
97    {
98	sign = 1;	// positive
99    }
100    else if (x < 0)
101    {
102	sign = -1;	// negative
103	x = -x;
104    }
105    else
106    {
107	n = 0;		// NaN
108	d = 0;
109	return;
110    }
111
112    if (x >= (1U << 31) - 0.5)
113    {
114	n = sign;	// infinity
115	d = 0;
116	return;
117    }
118
119    double e = (x < 1? 1: x) / (1U << 30);
120    d = (unsigned int) denom (x, e);
121    n = sign * (int) floor (x * d + 0.5);
122}
123
124
125} // namespace Imf
126