- Main Page
- Classes
- Files

# 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 }