Calculator  Step 6
number_impl.cpp
Go to the documentation of this file.
1 #include <istream>
2 #include <ostream>
3 #include <sstream>
4 #include <utility>
5 
6 #include "calc_error.hpp"
7 #include "number_impl.hpp"
8 
10 {}
11 
12 void number_impl::save(std::ostream& stream)
13 const
14 {
15  do_save(stream);
16 }
17 
18 std::shared_ptr<number_impl> number_impl::read_library(std::istream& stream)
19 {
20  std::string type{};
21  if (not (stream >> type))
22  throw calc_error{"malformed library, missing number type"};
23 
24  if (type == "void")
25  return std::make_shared<number_void>();
26 
27  if (type == "long") {
28  long long x{};
29  if (not (stream >> x))
30  throw calc_error{"malformed library, missing long value"};
31  return std::make_shared<number_long>(x);
32  }
33 
34  if (type == "double") {
35  double x{};
36  if (not (stream >> x))
37  throw calc_error{"malformed library, missing double value"};
38  return std::make_shared<number_double>(x);
39  }
40 
41  throw calc_error{"malformed library, unknown number type: " + type};
42 }
43 
44 void number_impl::print(std::ostream& stream)
45 const
46 {
47  stream << to_string();
48 }
49 
51 const
52 {
53  return do_to_string();
54 }
55 
56 std::shared_ptr<number_impl> number_impl::promote(number_impl& rhs)
57 const
58 {
59  return do_promote(rhs);
60 }
61 
63 const
64 {
65  return do_equals(rhs);
66 }
67 
69 const
70 {
71  return do_less(rhs);
72 }
73 
74 std::shared_ptr<number_impl> number_impl::add(number_impl const& rhs)
75 {
76  return do_add(rhs);
77 }
78 
79 std::shared_ptr<number_impl> number_impl::subtract(number_impl const& rhs)
80 {
81  return do_subtract(rhs);
82 }
83 
84 std::shared_ptr<number_impl> number_impl::multiply(number_impl const& rhs)
85 {
86  return do_multiply(rhs);
87 }
88 
89 std::shared_ptr<number_impl> number_impl::divide(number_impl const& rhs)
90 {
91  return do_divide(rhs);
92 }
93 
94 // Default is not to promote.
95 // The return value from the promote_to_*() functions is either
96 // a brand-new number_impl object, or this.
97 std::shared_ptr<number_impl> number_impl::promote_to_void()
98 {
99  return shared_from_this();
100 }
101 
102 std::shared_ptr<number_impl> number_impl::promote_to_long()
103 {
104  return shared_from_this();
105 }
106 
107 std::shared_ptr<number_impl> number_impl::promote_to_rational()
108 {
109  return shared_from_this();
110 }
111 
112 std::shared_ptr<number_impl> number_impl::promote_to_double()
113 {
114  return shared_from_this();
115 }
116 
117 
118 
120 const
121 {
122  return std::string{};
123 }
124 
125 void number_void::do_save(std::ostream& stream)
126 const
127 {
128  stream << "void ";
129 }
130 
131 // void never equals anything, even another void
133 const
134 {
135  return false;
136 }
137 
138 // void is never less than anything
140 const
141 {
142  return false;
143 }
144 
145 // void plus void equal void
146 std::shared_ptr<number_impl> number_void::do_add(number_impl const&)
147 {
148  return shared_from_this();
149 }
150 
151 std::shared_ptr<number_impl> number_void::do_subtract(number_impl const&)
152 {
153  return shared_from_this();
154 }
155 
156 std::shared_ptr<number_impl> number_void::do_multiply(number_impl const&)
157 {
158  return shared_from_this();
159 }
160 
161 std::shared_ptr<number_impl> number_void::do_divide(number_impl const&)
162 {
163  return shared_from_this();
164 }
165 
166 std::shared_ptr<number_impl> number_void::do_promote(number_impl& rhs)
167 const
168 {
169  return rhs.promote_to_void();
170 }
171 
172 
173 
175 const
176 {
177  std::ostringstream stream{};
178  stream << value();
179  return stream.str();
180 }
181 
182 void number_long::do_save(std::ostream& stream)
183 const
184 {
185  stream << "long " << value() << ' ';
186 }
187 
189 const
190 {
191  return value() == dynamic_cast<number_long const&>(rhs).value();
192 }
193 
195 const
196 {
197  return value() < dynamic_cast<number_long const&>(rhs).value();
198 }
199 
200 std::shared_ptr<number_impl> number_long::do_add(number_impl const& rhs)
201 {
202  return std::make_shared<number_long>(value_ + dynamic_cast<number_long const&>(rhs).value());
203 }
204 
205 std::shared_ptr<number_impl> number_long::do_subtract(number_impl const& rhs)
206 {
207  return std::make_shared<number_long>(value_ - dynamic_cast<number_long const&>(rhs).value());
208 }
209 
210 std::shared_ptr<number_impl> number_long::do_multiply(number_impl const& rhs)
211 {
212  return std::make_shared<number_long>(value_ * dynamic_cast<number_long const&>(rhs).value());
213 }
214 
215 std::shared_ptr<number_impl> number_long::do_divide(number_impl const& rhs)
216 {
217  long long right = dynamic_cast<number_long const&>(rhs).value();
218  if (right == 0)
219  throw calc_error{"division by zero"};
220  return std::make_shared<number_rational>(value_, right);
221 }
222 
223 std::shared_ptr<number_impl> number_long::do_promote(number_impl& rhs)
224 const
225 {
226  return rhs.promote_to_long();
227 }
228 
229 std::shared_ptr<number_impl> number_long::promote_to_void()
230 {
231  return std::make_shared<number_void>();
232 }
233 
234 std::shared_ptr<number_impl> number_long::promote_to_rational()
235 {
236  return std::make_shared<number_rational>(value());
237 }
238 
239 std::shared_ptr<number_impl> number_long::promote_to_double()
240 {
241  return std::make_shared<number_double>(value());
242 }
243 
244 
246 const
247 {
248  std::ostringstream stream{};
249  stream << value();
250  return stream.str();
251 }
252 
253 void number_rational::do_save(std::ostream& stream)
254 const
255 {
256  stream << "rational " << value() << ' ';
257 }
258 
260 const
261 {
262  return value() == dynamic_cast<number_rational const&>(rhs).value();
263 }
264 
266 const
267 {
268  return value() < dynamic_cast<number_rational const&>(rhs).value();
269 }
270 
271 std::shared_ptr<number_impl> number_rational::do_add(number_impl const& rhs)
272 {
273  rational<long long> result{ value_ + dynamic_cast<number_rational const&>(rhs).value() };
274  if (result.denominator() == 1)
275  return std::make_shared<number_long>(result.numerator());
276  else
277  return std::make_shared<number_rational>(result);
278 }
279 
280 std::shared_ptr<number_impl> number_rational::do_subtract(number_impl const& rhs)
281 {
282  rational<long long> result{ value_ - dynamic_cast<number_rational const&>(rhs).value() };
283  if (result.denominator() == 1)
284  return std::make_shared<number_long>(result.numerator());
285  else
286  return std::make_shared<number_rational>(result);
287 }
288 
289 std::shared_ptr<number_impl> number_rational::do_multiply(number_impl const& rhs)
290 {
291  rational<long long> result{ value_ * dynamic_cast<number_rational const&>(rhs).value() };
292  if (result.denominator() == 1)
293  return std::make_shared<number_long>(result.numerator());
294  else
295  return std::make_shared<number_rational>(result);
296 }
297 
298 std::shared_ptr<number_impl> number_rational::do_divide(number_impl const& rhs)
299 {
300  rational<long long> right{ dynamic_cast<number_rational const&>(rhs).value() };
301  if (right.numerator() == 0)
302  throw calc_error{"division by zero"};
303  rational<long long> result = value_ / right;
304  if (result.denominator() == 1)
305  return std::make_shared<number_long>(result.numerator());
306  else
307  return std::make_shared<number_rational>(result);
308 }
309 
310 std::shared_ptr<number_impl> number_rational::do_promote(number_impl& rhs)
311 const
312 {
313  return rhs.promote_to_rational();
314 }
315 
316 std::shared_ptr<number_impl> number_rational::promote_to_void()
317 {
318  return std::make_shared<number_void>();
319 }
320 
321 std::shared_ptr<number_impl> number_rational::promote_to_double()
322 {
323  return std::make_shared<number_double>(static_cast<double>(value()));
324 }
325 
326 
327 
329 const
330 {
331  std::ostringstream stream{};
332  stream << value();
333  return stream.str();
334 }
335 
336 void number_double::do_save(std::ostream& stream)
337 const
338 {
339  stream << "double " << value() << ' ';
340 }
341 
343 const
344 {
345  return value() == dynamic_cast<number_double const&>(rhs).value();
346 }
347 
349 const
350 {
351  return value() < dynamic_cast<number_double const&>(rhs).value();
352 }
353 
354 std::shared_ptr<number_impl> number_double::do_add(number_impl const& rhs)
355 {
356  return std::make_shared<number_double>(value_ + dynamic_cast<number_double const&>(rhs).value());
357 }
358 
359 std::shared_ptr<number_impl> number_double::do_subtract(number_impl const& rhs)
360 {
361  return std::make_shared<number_double>(value_ - dynamic_cast<number_double const&>(rhs).value());
362 }
363 
364 std::shared_ptr<number_impl> number_double::do_multiply(number_impl const& rhs)
365 {
366  return std::make_shared<number_double>(value_ * dynamic_cast<number_double const&>(rhs).value());
367 }
368 
369 std::shared_ptr<number_impl> number_double::do_divide(number_impl const& rhs)
370 {
371  double right{ dynamic_cast<number_double const&>(rhs).value() };
372  if (right == 0.0)
373  throw calc_error{"division by zero"};
374  return std::make_shared<number_double>(value_ / right);
375 }
376 
377 std::shared_ptr<number_impl> number_double::do_promote(number_impl& rhs)
378 const
379 {
380  return rhs.promote_to_double();
381 }
382 
383 std::shared_ptr<number_impl> number_double::promote_to_void()
384 {
385  return std::make_shared<number_void>();
386 }
virtual bool do_less(number_impl const &rhs) const
virtual void do_save(std::ostream &stream) const
virtual void do_save(std::ostream &stream) const
virtual bool do_less(number_impl const &rhs) const =0
virtual std::shared_ptr< number_impl > do_multiply(number_impl const &rhs)
long long value() const
value_type denominator() const
Return the denominator.
Definition: rational.hpp:52
virtual std::shared_ptr< number_impl > do_multiply(number_impl const &rhs)
void save(std::ostream &stream) const
Definition: number_impl.cpp:12
virtual std::shared_ptr< number_impl > do_add(number_impl const &rhs)
value_type numerator() const
Return the numerator.
Definition: rational.hpp:50
virtual std::shared_ptr< number_impl > promote_to_double()
virtual std::shared_ptr< number_impl > do_subtract(number_impl const &rhs)=0
virtual std::shared_ptr< number_impl > do_add(number_impl const &rhs)
virtual std::shared_ptr< number_impl > promote_to_void()
bool less(number_impl const &rhs) const
Definition: number_impl.cpp:68
long long value_
std::shared_ptr< number_impl > promote(number_impl &rhs) const
Definition: number_impl.cpp:56
virtual std::shared_ptr< number_impl > do_subtract(number_impl const &rhs)
virtual bool do_less(number_impl const &rhs) const
virtual ~number_impl()
Definition: number_impl.cpp:9
virtual std::shared_ptr< number_impl > do_add(number_impl const &rhs)
virtual bool do_equals(number_impl const &rhs) const
virtual std::shared_ptr< number_impl > promote_to_double()
virtual std::shared_ptr< number_impl > do_subtract(number_impl const &rhs)
virtual std::shared_ptr< number_impl > do_divide(number_impl const &rhs)
void print(std::ostream &stream) const
Definition: number_impl.cpp:44
virtual std::shared_ptr< number_impl > promote_to_rational()
std::shared_ptr< number_impl > add(number_impl const &rhs)
Definition: number_impl.cpp:74
virtual void do_save(std::ostream &stream) const
virtual std::shared_ptr< number_impl > do_add(number_impl const &rhs)=0
virtual std::shared_ptr< number_impl > do_promote(number_impl &rhs) const
virtual void do_save(std::ostream &stream) const =0
virtual std::shared_ptr< number_impl > do_promote(number_impl &rhs) const =0
virtual bool do_less(number_impl const &rhs) const
std::shared_ptr< number_impl > subtract(number_impl const &rhs)
Definition: number_impl.cpp:79
virtual std::shared_ptr< number_impl > do_promote(number_impl &rhs) const
virtual std::shared_ptr< number_impl > do_divide(number_impl const &rhs)=0
virtual std::string do_to_string() const
virtual std::shared_ptr< number_impl > do_subtract(number_impl const &rhs)
rational< long long > value() const
virtual bool do_equals(number_impl const &rhs) const
virtual std::string do_to_string() const =0
static std::shared_ptr< number_impl > read_library(std::istream &stream)
Definition: number_impl.cpp:18
virtual std::shared_ptr< number_impl > promote_to_rational()
std::string to_string() const
Definition: number_impl.cpp:50
virtual std::string do_to_string() const
virtual std::shared_ptr< number_impl > do_multiply(number_impl const &rhs)
virtual std::shared_ptr< number_impl > do_multiply(number_impl const &rhs)=0
std::shared_ptr< number_impl > multiply(number_impl const &rhs)
Definition: number_impl.cpp:84
virtual bool do_equals(number_impl const &rhs) const
virtual std::shared_ptr< number_impl > promote_to_void()
Definition: number_impl.cpp:97
virtual std::shared_ptr< number_impl > do_divide(number_impl const &rhs)
virtual std::shared_ptr< number_impl > do_promote(number_impl &rhs) const
virtual std::shared_ptr< number_impl > promote_to_void()
virtual std::shared_ptr< number_impl > do_subtract(number_impl const &rhs)
virtual std::shared_ptr< number_impl > do_divide(number_impl const &rhs)
virtual std::string do_to_string() const
virtual void do_save(std::ostream &stream) const
virtual bool do_less(number_impl const &rhs) const
virtual std::shared_ptr< number_impl > promote_to_void()
virtual std::shared_ptr< number_impl > promote_to_long()
virtual bool do_equals(number_impl const &rhs) const
virtual bool do_equals(number_impl const &rhs) const =0
double value() const
virtual std::shared_ptr< number_impl > do_add(number_impl const &rhs)
virtual std::string do_to_string() const
virtual std::shared_ptr< number_impl > do_promote(number_impl &rhs) const
bool equals(number_impl const &rhs) const
Definition: number_impl.cpp:62
rational< long long > value_
std::shared_ptr< number_impl > divide(number_impl const &rhs)
Definition: number_impl.cpp:89
virtual std::shared_ptr< number_impl > promote_to_double()
virtual std::shared_ptr< number_impl > do_multiply(number_impl const &rhs)
virtual std::shared_ptr< number_impl > do_divide(number_impl const &rhs)