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 }