Loading...
Searching...
No Matches
balance.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2003-2023, John Wiegley. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * - Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * - Neither the name of New Artisans LLC nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
49#pragma once
50
51#include "amount.h"
52
53namespace ledger {
54
55DECLARE_EXCEPTION(balance_error, std::runtime_error);
56
66 : public equality_comparable<balance_t,
67 equality_comparable<balance_t, amount_t,
68 equality_comparable<balance_t, double,
69 equality_comparable<balance_t, unsigned long,
70 equality_comparable<balance_t, long,
71 additive<balance_t,
72 additive<balance_t, amount_t,
73 additive<balance_t, double,
74 additive<balance_t, unsigned long,
75 additive<balance_t, long,
76 multiplicative<balance_t, amount_t,
77 multiplicative<balance_t, double,
78 multiplicative<balance_t, unsigned long,
79 multiplicative<balance_t, long> > > > > > > > > > > > > >
80{
81public:
82 typedef std::unordered_map<commodity_t *, amount_t> amounts_map;
83 typedef std::vector<const amount_t *> amounts_array;
84
86
109 }
111 if (amt.is_null())
113 _("Cannot initialize a balance from an uninitialized amount"));
114 if (! amt.is_realzero())
115 amounts.insert(amounts_map::value_type(&amt.commodity(), amt));
116 TRACE_CTOR(balance_t, "const amount_t&");
117 }
118 balance_t(const double val);
119 balance_t(const unsigned long val);
120 balance_t(const long val);
121
122 explicit balance_t(const string& val) {
124 amounts.insert(amounts_map::value_type(&temp.commodity(), temp));
125 TRACE_CTOR(balance_t, "const string&");
126 }
127 explicit balance_t(const char * val) {
129 amounts.insert(amounts_map::value_type(&temp.commodity(), temp));
130 TRACE_CTOR(balance_t, "const char *");
131 }
132
140
145 TRACE_CTOR(balance_t, "copy");
146 }
147
149 if (this != &bal)
150 amounts = bal.amounts;
151 return *this;
152 }
154 if (amt.is_null())
156 _("Cannot assign an uninitialized amount to a balance"));
157
158 amounts.clear();
159 if (! amt.is_realzero())
160 amounts.insert(amounts_map::value_type(&amt.commodity(), amt));
161
162 return *this;
163 }
164
165 balance_t& operator=(const string& str) {
166 return *this = balance_t(str);
167 }
168 balance_t& operator=(const char * str) {
169 return *this = balance_t(str);
170 }
171
187 bool operator==(const balance_t& bal) const {
188 return amounts == bal.amounts;
189 }
190 bool operator==(const amount_t& amt) const {
191 if (amt.is_null())
193 _("Cannot compare a balance to an uninitialized amount"));
194
195 if (amt.is_realzero())
196 return amounts.empty();
197 else
198 return amounts.size() == 1 && amounts.begin()->second == amt;
199 }
200
201 template <typename T>
202 bool operator==(const T& val) const {
203 return *this == amount_t(val);
204 }
205
213 balance_t& operator+=(const double val) {
214 return *this += amount_t(val);
215 }
216 balance_t& operator+=(const unsigned long val) {
217 return *this += amount_t(val);
218 }
219 balance_t& operator+=(const long val) {
220 return *this += amount_t(val);
221 }
222
225 balance_t& operator-=(const double val) {
226 return *this -= amount_t(val);
227 }
228 balance_t& operator-=(const unsigned long val) {
229 return *this -= amount_t(val);
230 }
231 balance_t& operator-=(const long val) {
232 return *this -= amount_t(val);
233 }
234
236 balance_t& operator*=(const double val) {
237 return *this *= amount_t(val);
238 }
239 balance_t& operator*=(const unsigned long val) {
240 return *this *= amount_t(val);
241 }
242 balance_t& operator*=(const long val) {
243 return *this *= amount_t(val);
244 }
245
247 balance_t& operator/=(const double val) {
248 return *this /= amount_t(val);
249 }
250 balance_t& operator/=(const unsigned long val) {
251 return *this /= amount_t(val);
252 }
253 balance_t& operator/=(const long val) {
254 return *this /= amount_t(val);
255 }
256
292 balance_t temp(*this);
293 temp.in_place_negate();
294 return temp;
295 }
297 foreach (amounts_map::value_type& pair, amounts)
298 pair.second.in_place_negate();
299 }
301 return negated();
302 }
303
304 balance_t abs() const {
306 foreach (const amounts_map::value_type& pair, amounts)
307 temp += pair.second.abs();
308 return temp;
309 }
310
312 balance_t temp(*this);
313 temp.in_place_round();
314 return temp;
315 }
317 foreach (amounts_map::value_type& pair, amounts)
318 pair.second.in_place_round();
319 }
320
322 balance_t temp(*this);
323 temp.in_place_roundto(places);
324 return temp;
325 }
326
328 foreach (amounts_map::value_type& pair, amounts)
329 pair.second.in_place_roundto(places);
330 }
331
333 balance_t temp(*this);
334 temp.in_place_truncate();
335 return temp;
336 }
338 foreach (amounts_map::value_type& pair, amounts)
339 pair.second.in_place_truncate();
340 }
341
343 balance_t temp(*this);
344 temp.in_place_floor();
345 return temp;
346 }
348 foreach (amounts_map::value_type& pair, amounts)
349 pair.second.in_place_floor();
350 }
351
353 balance_t temp(*this);
354 temp.in_place_ceiling();
355 return temp;
356 }
358 foreach (amounts_map::value_type& pair, amounts)
359 pair.second.in_place_ceiling();
360 }
361
362
364 balance_t temp(*this);
365 temp.in_place_unround();
366 return temp;
367 }
369 foreach (amounts_map::value_type& pair, amounts)
370 pair.second.in_place_unround();
371 }
372
374 balance_t temp(*this);
375 temp.in_place_reduce();
376 return temp;
377 }
379 // A temporary must be used here because reduction may cause
380 // multiple component amounts to collapse to the same commodity.
382 foreach (const amounts_map::value_type& pair, amounts)
383 temp += pair.second.reduced();
384 *this = temp;
385 }
386
388 balance_t temp(*this);
389 temp.in_place_unreduce();
390 return temp;
391 }
393 // A temporary must be used here because unreduction may cause
394 // multiple component amounts to collapse to the same commodity.
396 foreach (const amounts_map::value_type& pair, amounts)
397 temp += pair.second.unreduced();
398 *this = temp;
399 }
400
403 const commodity_t * in_terms_of = NULL) const;
404
423 operator bool() const {
424 return is_nonzero();
425 }
426
427 bool is_nonzero() const {
428 if (is_empty())
429 return false;
430
431 foreach (const amounts_map::value_type& pair, amounts)
432 if (pair.second.is_nonzero())
433 return true;
434 return false;
435 }
436
437 bool is_zero() const {
438 if (is_empty())
439 return true;
440
441 foreach (const amounts_map::value_type& pair, amounts)
442 if (! pair.second.is_zero())
443 return false;
444 return true;
445 }
446
447 bool is_realzero() const {
448 if (is_empty())
449 return true;
450
451 foreach (const amounts_map::value_type& pair, amounts)
452 if (! pair.second.is_realzero())
453 return false;
454 return true;
455 }
456
457 bool is_empty() const {
458 return amounts.size() == 0;
459 }
460 bool single_amount() const {
461 return amounts.size() == 1;
462 }
463
468 operator string() const {
469 return to_string();
470 }
471 string to_string() const {
472 std::ostringstream buf;
473 print(buf);
474 return buf.str();
475 }
476
478 if (is_empty())
479 throw_(balance_error, _("Cannot convert an empty balance to an amount"));
480 else if (amounts.size() == 1)
481 return amounts.begin()->second;
482 else
484 _("Cannot convert a balance with multiple commodities to an amount"));
485 return amount_t();
486 }
487
501 std::size_t commodity_count() const {
502 return amounts.size();
503 }
504
507
508 amounts_map::iterator find_by_name(const commodity_t& comm);
509 amounts_map::const_iterator find_by_name(const commodity_t& comm) const;
510
513 foreach (const amounts_map::value_type& pair, amounts)
514 temp += pair.second.number();
515 return temp;
516 }
517
525 balance_t strip_annotations(const keep_details_t& what_to_keep) const;
526
532
539 void map_sorted_amounts(function<void(const amount_t&)> fn) const;
540
562 void print(std::ostream& out,
563 const int first_width = -1,
564 const int latter_width = -1,
565 const uint_least8_t flags = AMOUNT_PRINT_NO_FLAGS) const;
566
578 void dump(std::ostream& out) const {
579 out << "BALANCE(";
580 bool first = true;
581 foreach (const amounts_map::value_type& pair, amounts) {
582 if (first)
583 first = false;
584 else
585 out << ", ";
586 pair.second.print(out);
587 }
588 out << ")";
589 }
590
591 bool valid() const {
592 foreach (const amounts_map::value_type& pair, amounts)
593 if (! pair.second.valid()) {
594 DEBUG("ledger.validate", "balance_t: ! pair.second.valid()");
595 return false;
596 }
597 return true;
598 }
599};
600
601inline std::ostream& operator<<(std::ostream& out, const balance_t& bal) {
602 bal.print(out, 12);
603 return out;
604}
605
606void put_balance(property_tree::ptree& pt, const balance_t& bal);
607
609
610} // namespace ledger
#define TRACE_DTOR(cls)
Definition utils.h:144
#define TRACE_CTOR(cls, args)
Definition utils.h:143
#define DEBUG(cat, msg)
Definition utils.h:327
Basic type for handling commoditized math: amount_t.
#define AMOUNT_PRINT_NO_FLAGS
An amount may be output to a stream using the ‘print’ method.
Definition amount.h:711
#define throw_(cls, msg)
Definition error.h:55
#define DECLARE_EXCEPTION(name, kind)
Definition error.h:88
balance_t average_lot_prices(const balance_t &bal)
void put_balance(property_tree::ptree &pt, const balance_t &bal)
std::string string
Definition utils.h:59
std::ostream & operator<<(std::ostream &out, const account_t &account)
T & downcast(U &object)
Definition utils.h:468
boost::posix_time::ptime datetime_t
Definition times.h:53
Encapsulate infinite-precision commoditized amounts.
Definition amount.h:96
A wrapper around amount_t allowing addition of multiple commodities.
Definition balance.h:80
void in_place_reduce()
Definition balance.h:378
balance_t & operator+=(const balance_t &bal)
Binary arithmetic operators.
void in_place_unround()
Definition balance.h:368
balance_t & operator*=(const unsigned long val)
Definition balance.h:239
void in_place_roundto(int places)
Definition balance.h:327
amounts_map amounts
Definition balance.h:85
balance_t & operator=(const string &str)
Definition balance.h:165
balance_t & operator/=(const long val)
Definition balance.h:253
bool single_amount() const
Definition balance.h:460
string to_string() const
Definition balance.h:471
balance_t unreduced() const
Definition balance.h:387
balance_t truncated() const
Definition balance.h:332
balance_t floored() const
Definition balance.h:342
balance_t & operator-=(const double val)
Definition balance.h:225
bool is_realzero() const
Definition balance.h:447
balance_t & operator=(const char *str)
Definition balance.h:168
optional< balance_t > value(const datetime_t &moment=datetime_t(), const commodity_t *in_terms_of=NULL) const
bool operator==(const balance_t &bal) const
Comparison operators.
Definition balance.h:187
balance_t & operator*=(const amount_t &amt)
balance_t reduced() const
Definition balance.h:373
void map_sorted_amounts(function< void(const amount_t &)> fn) const
Iteration primitives.
balance_t(const string &val)
Definition balance.h:122
balance_t & operator-=(const amount_t &amt)
balance_t & operator-=(const balance_t &bal)
balance_t(const amount_t &amt)
Definition balance.h:110
void in_place_round()
Definition balance.h:316
balance_t()
Constructors.
Definition balance.h:107
balance_t(const long val)
balance_t & operator+=(const amount_t &amt)
bool operator==(const amount_t &amt) const
Definition balance.h:190
void in_place_floor()
Definition balance.h:347
void in_place_ceiling()
Definition balance.h:357
balance_t & operator=(const amount_t &amt)
Definition balance.h:153
std::unordered_map< commodity_t *, amount_t > amounts_map
Definition balance.h:82
balance_t number() const
Definition balance.h:511
amount_t to_amount() const
Definition balance.h:477
balance_t(const balance_t &bal)
Assignment and copy operators.
Definition balance.h:144
balance_t(const char *val)
Definition balance.h:127
void in_place_unreduce()
Definition balance.h:392
bool is_zero() const
Definition balance.h:437
balance_t abs() const
Definition balance.h:304
void in_place_truncate()
Definition balance.h:337
balance_t(const double val)
balance_t operator-() const
Definition balance.h:300
balance_t unrounded() const
Definition balance.h:363
balance_t rounded() const
Definition balance.h:311
balance_t & operator*=(const long val)
Definition balance.h:242
balance_t & operator=(const balance_t &bal)
Definition balance.h:148
~balance_t()
Destructor.
Definition balance.h:137
balance_t & operator*=(const double val)
Definition balance.h:236
bool is_empty() const
Definition balance.h:457
balance_t roundto(int places) const
Definition balance.h:321
balance_t & operator/=(const double val)
Definition balance.h:247
balance_t & operator+=(const long val)
Definition balance.h:219
balance_t & operator-=(const long val)
Definition balance.h:231
void sorted_amounts(amounts_array &sorted) const
Given a balance, insert a commodity-wise sort of the amounts into the given amounts_array.
balance_t & operator+=(const unsigned long val)
Definition balance.h:216
balance_t negated() const
Unary arithmetic operators.
Definition balance.h:291
std::vector< const amount_t * > amounts_array
Definition balance.h:83
std::size_t commodity_count() const
Commodity-related methods.
Definition balance.h:501
bool operator==(const T &val) const
Definition balance.h:202
balance_t & operator-=(const unsigned long val)
Definition balance.h:228
amounts_map::const_iterator find_by_name(const commodity_t &comm) const
void print(std::ostream &out, const int first_width=-1, const int latter_width=-1, const uint_least8_t flags=0x00) const
Printing methods.
bool is_nonzero() const
Definition balance.h:427
balance_t strip_annotations(const keep_details_t &what_to_keep) const
Annotated commodity methods.
balance_t & operator/=(const amount_t &amt)
balance_t(const unsigned long val)
balance_t & operator+=(const double val)
Definition balance.h:213
optional< amount_t > commodity_amount(const optional< const commodity_t & > &commodity=none) const
amounts_map::iterator find_by_name(const commodity_t &comm)
bool valid() const
Definition balance.h:591
balance_t ceilinged() const
Definition balance.h:352
void in_place_negate()
Definition balance.h:296
balance_t & operator/=(const unsigned long val)
Definition balance.h:250
void dump(std::ostream &out) const
Debugging methods.
Definition balance.h:578