2 // Tizen Web Device API
3 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
26 const double DOUBLE_ERROR_REPRESENTATION = static_cast<double>(0x7FFFFFFF);
27 } //anonymous namespace
29 Rational::Rational() :
35 Rational::Rational(ExifLong nom, ExifLong denom) :
41 Rational::Rational(const ExifRational& exif_rational) :
42 nominator(exif_rational.numerator),
43 denominator(exif_rational.denominator)
47 Rational Rational::createFromDouble(const double value, const long precision)
49 LOGD("Entered value:%f precision:%d", value, precision);
51 LOGW("Trying to create negative Rational: %f!", value);
55 if (value < 0.000000001) {
56 LOGD("Skipping calculation returning: Rational(0,1)");
67 m[0][0] = m[1][1] = 1;
68 m[0][1] = m[1][0] = 0;
70 //loop finding terms until denom gets too big
72 ai = static_cast<long>(x);
73 if(m[1][0] * ai + m[1][1] > precision) {
77 long t = m[0][0] * ai + m[0][1];
81 t = m[1][0] * ai + m[1][1];
85 if (x == static_cast<double>(ai)) {
86 break; // AF: division by zero
89 x = 1 / (x - static_cast<double>(ai));
90 if (x > DOUBLE_ERROR_REPRESENTATION) {
91 break; // AF: representation failure
95 // now remaining x is between 0 and 1/ai
96 // approx as either 0 or 1/m where m is max that will fit in precision
98 const long numerator0 = m[0][0];
99 const long denominator0 = m[1][0];
101 return Rational(numerator0, denominator0);
104 Rational Rational::createInvalid()
106 return Rational(0,0);
109 bool Rational::isValid() const
111 if (0 == denominator) {
119 double Rational::toDouble() const
125 return (double)nominator / (double)denominator;
128 Rational Rational::createFromExposureTimeString(const std::string& exp_time)
131 if (exp_time.length() == 0) {
132 return Rational::createInvalid(); //lets assume that empty string means 0,
133 //however exposure time = 0 is not valid value
136 std::string integer_part;
137 std::string fraction_part;
139 int first_space_at = -1;
140 int first_slash_at = -1;
142 for(size_t i=0; i < exp_time.size(); ++i) {
144 const char& cur = exp_time[i];
145 if (first_space_at < 0 && ' ' == cur) {
148 if (first_slash_at < 0 && '/' == cur) {
153 if (first_slash_at > 0) {
154 if (first_space_at > 0) {
155 integer_part = exp_time.substr(0,first_space_at);
156 fraction_part = exp_time.substr(first_space_at+1,
157 exp_time.size() - (first_space_at+1));
160 fraction_part = exp_time;
164 integer_part = exp_time;
167 LOGD("first_space_at: %d first_slash_at:%d int: [%s] , frac: [%s]",
168 first_space_at, first_slash_at, integer_part.c_str(), fraction_part.c_str());
170 long integer_value = 0;
172 long denominator = 1;
174 if (integer_part.length() > 0) {
175 integer_value = atol(integer_part.c_str());
178 if (fraction_part.length() > 0) {
179 if (sscanf(fraction_part.c_str(), "%ld/%ld", &nominator, &denominator) != 2) {
180 LOGD("Failed to parse nominator/denominator string: [%s]",
181 fraction_part.c_str());
182 return Rational::createInvalid();
186 nominator += denominator * integer_value;
187 LOGD("%d/%d -> %f", nominator, denominator, (float)nominator / denominator);
189 if (0 == nominator) {
190 //Exposure time = 0 is invalid value
191 return Rational::createInvalid();
194 return Rational(nominator, denominator);
197 std::string Rational::toString() const
199 std::stringstream ss;
200 ss << nominator << "/" << denominator;
204 std::string Rational::toExposureTimeString() const
207 if (!isValid() || 0 == nominator) {
208 return std::string();
211 std::string output_str;
213 if (nominator < denominator) {
214 output_str = toString();
216 else if (nominator % denominator == 0) {
217 std::stringstream ss;
218 ss << nominator / denominator;
219 output_str = ss.str();
222 ExifLong new_nominator = nominator % denominator;
223 ExifLong new_denominator = denominator;
224 ExifLong integer_value = nominator / denominator;
226 std::stringstream ss;
227 ss << integer_value << " ";
228 ss << new_nominator << "/" << new_denominator;
229 output_str = ss.str();