number_impl.cpp

Go to the documentation of this file.
00001 #include <istream>
00002 #include <ostream>
00003 #include <sstream>
00004 
00005 #include "calc_error.hpp"
00006 #include "number_impl.hpp"
00007 
00008 number_impl::~number_impl()
00009 {}
00010 
00011 void number_impl::add_ref()
00012 {
00013   ++refcount_;
00014 }
00015 
00016 void number_impl::del_ref()
00017 {
00018   --refcount_;
00019   if (refcount_ == 0)
00020     delete this;
00021 }
00022 
00023 void number_impl::save(std::ostream& stream)
00024 const
00025 {
00026   do_save(stream);
00027 }
00028 
00029 number_impl* number_impl::read_library(std::istream& stream)
00030 {
00031   std::string type;
00032   if (not (stream >> type))
00033     throw calc_error("malformed library, missing number type");
00034 
00035   if (type == "void")
00036     return new number_void();
00037 
00038   if (type == "long") {
00039     long x;
00040     if (not (stream >> x))
00041       throw calc_error("malformed library, missing long value");
00042     return new number_long(x);
00043   }
00044 
00045   if (type == "double") {
00046     double x;
00047     if (not (stream >> x))
00048       throw calc_error("malformed library, missing double value");
00049     return new number_long(x);
00050   }
00051 
00052   throw calc_error("malformed library, unknown number type: " + type);
00053 }
00054 
00055 void number_impl::print(std::ostream& stream)
00056 const
00057 {
00058   stream << to_string();
00059 }
00060 
00061 std::string number_impl::to_string()
00062 const
00063 {
00064   return do_to_string();
00065 }
00066 
00067 number_impl* number_impl::promote(number_impl& rhs)
00068 const
00069 {
00070   return do_promote(rhs);
00071 }
00072 
00073 bool number_impl::equals(number_impl const& rhs)
00074 const
00075 {
00076   return do_equals(rhs);
00077 }
00078 
00079 bool number_impl::less(number_impl const& rhs)
00080 const
00081 {
00082   return do_less(rhs);
00083 }
00084 
00085 number_impl* number_impl::add(number_impl const& rhs)
00086 {
00087   return do_add(rhs);
00088 }
00089 
00090 number_impl* number_impl::subtract(number_impl const& rhs)
00091 {
00092   return do_subtract(rhs);
00093 }
00094 
00095 number_impl* number_impl::multiply(number_impl const& rhs)
00096 {
00097   return do_multiply(rhs);
00098 }
00099 
00100 number_impl* number_impl::divide(number_impl const& rhs)
00101 {
00102   return do_divide(rhs);
00103 }
00104 
00105 // Default is not to promote.
00106 // The return value from the promote_to_*() functions is either
00107 // a brand-new number_impl object, or this. In order to make the
00108 // reference counts balance, when returning this, bump the reference count.
00109 number_impl* number_impl::promote_to_void()
00110 {
00111   add_ref();
00112   return this;
00113 }
00114 
00115 number_impl* number_impl::promote_to_long()
00116 {
00117   add_ref();
00118   return this;
00119 }
00120 
00121 number_impl* number_impl::promote_to_rational()
00122 {
00123   add_ref();
00124   return this;
00125 }
00126 
00127 number_impl* number_impl::promote_to_double()
00128 {
00129   add_ref();
00130   return this;
00131 }
00132 
00133 
00134 
00135 std::string number_void::do_to_string()
00136 const
00137 {
00138   return std::string();
00139 }
00140 
00141 void number_void::do_save(std::ostream& stream)
00142 const
00143 {
00144   stream << "void ";
00145 }
00146 
00147 // void never equals anything, even another void
00148 bool number_void::do_equals(number_impl const&)
00149 const
00150 {
00151   return false;
00152 }
00153 
00154 // void is never less than anything
00155 bool number_void::do_less(number_impl const&)
00156 const
00157 {
00158   return false;
00159 }
00160 
00161 // void plus void equal void
00162 number_impl* number_void::do_add(number_impl const&)
00163 {
00164   add_ref();
00165   return this;
00166 }
00167 
00168 number_impl* number_void::do_subtract(number_impl const&)
00169 {
00170   add_ref();
00171   return this;
00172 }
00173 
00174 number_impl* number_void::do_multiply(number_impl const&)
00175 {
00176   add_ref();
00177   return this;
00178 }
00179 
00180 number_impl* number_void::do_divide(number_impl const&)
00181 {
00182   add_ref();
00183   return this;
00184 }
00185 
00186 number_impl* number_void::do_promote(number_impl& rhs)
00187 const
00188 {
00189   return rhs.promote_to_void();
00190 }
00191 
00192 
00193 
00194 std::string number_long::do_to_string()
00195 const
00196 {
00197   std::ostringstream stream;
00198   stream << value();
00199   return stream.str();
00200 }
00201 
00202 void number_long::do_save(std::ostream& stream)
00203 const
00204 {
00205   stream << "long " << value() << ' ';
00206 }
00207 
00208 bool number_long::do_equals(number_impl const& rhs)
00209 const
00210 {
00211   return value() == dynamic_cast<number_long const&>(rhs).value();
00212 }
00213 
00214 bool number_long::do_less(number_impl const& rhs)
00215 const
00216 {
00217   return value() < dynamic_cast<number_long const&>(rhs).value();
00218 }
00219 
00220 number_impl* number_long::do_add(number_impl const& rhs)
00221 {
00222   return new number_long(value_ + dynamic_cast<number_long const&>(rhs).value());
00223 }
00224 
00225 number_impl* number_long::do_subtract(number_impl const& rhs)
00226 {
00227   return new number_long(value_ - dynamic_cast<number_long const&>(rhs).value());
00228 }
00229 
00230 number_impl* number_long::do_multiply(number_impl const& rhs)
00231 {
00232   return new number_long(value_ * dynamic_cast<number_long const&>(rhs).value());
00233 }
00234 
00235 number_impl* number_long::do_divide(number_impl const& rhs)
00236 {
00237   long right = dynamic_cast<number_long const&>(rhs).value();
00238   if (right == 0)
00239     throw calc_error("division by zero");
00240   return new number_rational(value_, right);
00241 }
00242 
00243 number_impl* number_long::do_promote(number_impl& rhs)
00244 const
00245 {
00246   return rhs.promote_to_long();
00247 }
00248 
00249 number_impl* number_long::promote_to_void()
00250 {
00251   return new number_void();
00252 }
00253 
00254 number_impl* number_long::promote_to_rational()
00255 {
00256   return new number_rational(value());
00257 }
00258 
00259 number_impl* number_long::promote_to_double()
00260 {
00261   return new number_double(value());
00262 }
00263 
00264 
00265 std::string number_rational::do_to_string()
00266 const
00267 {
00268   std::ostringstream stream;
00269   stream << value();
00270   return stream.str();
00271 }
00272 
00273 void number_rational::do_save(std::ostream& stream)
00274 const
00275 {
00276   stream << "rational " << value() << ' ';
00277 }
00278 
00279 bool number_rational::do_equals(number_impl const& rhs)
00280 const
00281 {
00282   return value() == dynamic_cast<number_rational const&>(rhs).value();
00283 }
00284 
00285 bool number_rational::do_less(number_impl const& rhs)
00286 const
00287 {
00288   return value() < dynamic_cast<number_rational const&>(rhs).value();
00289 }
00290 
00291 number_impl* number_rational::do_add(number_impl const& rhs)
00292 {
00293   rational<long> result = value_ + dynamic_cast<number_rational const&>(rhs).value();
00294   if (result.denominator() == 1)
00295     return new number_long(result.numerator());
00296   else
00297     return new number_rational(result);
00298 }
00299 
00300 number_impl* number_rational::do_subtract(number_impl const& rhs)
00301 {
00302   rational<long> result = value_ - dynamic_cast<number_rational const&>(rhs).value();
00303   if (result.denominator() == 1)
00304     return new number_long(result.numerator());
00305   else
00306     return new number_rational(result);
00307 }
00308 
00309 number_impl* number_rational::do_multiply(number_impl const& rhs)
00310 {
00311   rational<long> result = value_ * dynamic_cast<number_rational const&>(rhs).value();
00312   if (result.denominator() == 1)
00313     return new number_long(result.numerator());
00314   else
00315     return new number_rational(result);
00316 }
00317 
00318 number_impl* number_rational::do_divide(number_impl const& rhs)
00319 {
00320   rational<long> right = dynamic_cast<number_rational const&>(rhs).value();
00321   if (right == 0L)
00322     throw calc_error("division by zero");
00323   rational<long> result = value_ / right;
00324   if (result.denominator() == 1)
00325     return new number_long(result.numerator());
00326   else
00327     return new number_rational(result);
00328 }
00329 
00330 number_impl* number_rational::do_promote(number_impl& rhs)
00331 const
00332 {
00333   return rhs.promote_to_rational();
00334 }
00335 
00336 number_impl* number_rational::promote_to_void()
00337 {
00338   return new number_void();
00339 }
00340 
00341 number_impl* number_rational::promote_to_double()
00342 {
00343   return new number_double(value().as<double>());
00344 }
00345 
00346 
00347 
00348 std::string number_double::do_to_string()
00349 const
00350 {
00351   std::ostringstream stream;
00352   stream << value();
00353   return stream.str();
00354 }
00355 
00356 void number_double::do_save(std::ostream& stream)
00357 const
00358 {
00359   stream << "double " << value() << ' ';
00360 }
00361 
00362 bool number_double::do_equals(number_impl const& rhs)
00363 const
00364 {
00365   return value() == dynamic_cast<number_double const&>(rhs).value();
00366 }
00367 
00368 bool number_double::do_less(number_impl const& rhs)
00369 const
00370 {
00371   return value() < dynamic_cast<number_double const&>(rhs).value();
00372 }
00373 
00374 number_impl* number_double::do_add(number_impl const& rhs)
00375 {
00376   return new number_double(value_ + dynamic_cast<number_double const&>(rhs).value());
00377 }
00378 
00379 number_impl* number_double::do_subtract(number_impl const& rhs)
00380 {
00381   return new number_double(value_ - dynamic_cast<number_double const&>(rhs).value());
00382 }
00383 
00384 number_impl* number_double::do_multiply(number_impl const& rhs)
00385 {
00386   return new number_double(value_ * dynamic_cast<number_double const&>(rhs).value());
00387 }
00388 
00389 number_impl* number_double::do_divide(number_impl const& rhs)
00390 {
00391   double right = dynamic_cast<number_double const&>(rhs).value();
00392   if (right == 0.0)
00393     throw calc_error("division by zero");
00394   return new number_double(value_ / right);
00395 }
00396 
00397 number_impl* number_double::do_promote(number_impl& rhs)
00398 const
00399 {
00400   return rhs.promote_to_double();
00401 }
00402 
00403 number_impl* number_double::promote_to_void()
00404 {
00405   return new number_void();
00406 }

Generated on Sun Nov 30 10:06:52 2008 for Calculator by  doxygen 1.5.3