summaryrefslogtreecommitdiff
path: root/balance.h
diff options
context:
space:
mode:
Diffstat (limited to 'balance.h')
-rw-r--r--balance.h594
1 files changed, 594 insertions, 0 deletions
diff --git a/balance.h b/balance.h
new file mode 100644
index 00000000..3ecfd962
--- /dev/null
+++ b/balance.h
@@ -0,0 +1,594 @@
+#ifndef _BALANCE_H
+#define _BALANCE_H
+
+#include "ledger.h"
+
+namespace ledger {
+
+typedef std::map<const commodity_t *, amount_t> amounts_map;
+typedef std::pair<const commodity_t *, amount_t> amounts_pair;
+
+class balance_t
+{
+ public:
+ amounts_map amounts;
+
+ bool valid() const {
+ for (amounts_map::const_iterator i = amounts.begin();
+ i != amounts.end();
+ i++)
+ if (! (*i).second.valid())
+ return false;
+ return true;
+ }
+
+ // constructors
+ balance_t() {}
+ balance_t(const balance_t& bal) {
+ for (amounts_map::const_iterator i = bal.amounts.begin();
+ i != bal.amounts.end();
+ i++)
+ *this += (*i).second;
+ }
+ balance_t(const amount_t& amt) {
+ *this += amt;
+ }
+ balance_t(const int value) {
+ *this += amount_t(value);
+ }
+ balance_t(const unsigned int value) {
+ *this += amount_t(value);
+ }
+ balance_t(const double value) {
+ *this += amount_t(value);
+ }
+
+ // destructor
+ ~balance_t() {}
+
+ // assignment operator
+ balance_t& operator=(const balance_t& bal) {
+ amounts.clear();
+ for (amounts_map::const_iterator i = bal.amounts.begin();
+ i != bal.amounts.end();
+ i++)
+ *this += (*i).second;
+ return *this;
+ }
+ balance_t& operator=(const amount_t& amt) {
+ amounts.clear();
+ *this += amt;
+ return *this;
+ }
+ balance_t& operator=(const int value) {
+ amounts.clear();
+ *this += amount_t(value);
+ return *this;
+ }
+ balance_t& operator=(const unsigned int value) {
+ amounts.clear();
+ *this += amount_t(value);
+ return *this;
+ }
+ balance_t& operator=(const double value) {
+ amounts.clear();
+ *this += amount_t(value);
+ return *this;
+ }
+
+ // in-place arithmetic
+ balance_t& operator+=(const balance_t& bal) {
+ for (amounts_map::const_iterator i = bal.amounts.begin();
+ i != bal.amounts.end();
+ i++)
+ *this += (*i).second;
+ return *this;
+ }
+ balance_t& operator+=(const amount_t& amt) {
+ amounts_map::iterator i = amounts.find(amt.commodity);
+ if (i != amounts.end())
+ (*i).second += amt;
+ else if (amt)
+ amounts.insert(amounts_pair(amt.commodity, amt));
+ return *this;
+ }
+ balance_t& operator-=(const balance_t& bal) {
+ for (amounts_map::const_iterator i = bal.amounts.begin();
+ i != bal.amounts.end();
+ i++)
+ *this -= (*i).second;
+ return *this;
+ }
+ balance_t& operator-=(const amount_t& amt) {
+ amounts_map::iterator i = amounts.find(amt.commodity);
+ if (i != amounts.end())
+ (*i).second -= amt;
+ else if (amt)
+ amounts.insert(amounts_pair(amt.commodity, amt));
+ return *this;
+ }
+
+ // simple arithmetic
+ balance_t operator+(const balance_t& bal) const {
+ balance_t temp = *this;
+ temp += bal;
+ return temp;
+ }
+ balance_t operator+(const amount_t& amt) const {
+ balance_t temp = *this;
+ temp += amt;
+ return temp;
+ }
+ balance_t operator-(const balance_t& bal) const {
+ balance_t temp = *this;
+ temp -= bal;
+ return temp;
+ }
+ balance_t operator-(const amount_t& amt) const {
+ balance_t temp = *this;
+ temp -= amt;
+ return temp;
+ }
+
+ // multiplication and divide
+ balance_t& operator*=(const balance_t& bal) {
+ for (amounts_map::const_iterator i = bal.amounts.begin();
+ i != bal.amounts.end();
+ i++)
+ *this *= (*i).second;
+ return *this;
+ }
+ balance_t& operator*=(const amount_t& amt) {
+ // Multiplying by the null commodity causes all amounts to be
+ // increased by the same factor.
+ if (amt.commodity->symbol.empty()) {
+ for (amounts_map::iterator i = amounts.begin();
+ i != amounts.end();
+ i++)
+ (*i).second *= amt;
+ } else {
+ amounts_map::iterator i = amounts.find(amt.commodity);
+ if (i != amounts.end())
+ (*i).second *= amt;
+ }
+ return *this;
+ }
+
+ balance_t& operator/=(const balance_t& bal) {
+ for (amounts_map::const_iterator i = bal.amounts.begin();
+ i != bal.amounts.end();
+ i++)
+ *this /= (*i).second;
+ return *this;
+ }
+ balance_t& operator/=(const amount_t& amt) {
+ // Dividing by the null commodity causes all amounts to be
+ // increased by the same factor.
+ if (amt.commodity->symbol.empty()) {
+ for (amounts_map::iterator i = amounts.begin();
+ i != amounts.end();
+ i++)
+ (*i).second /= amt;
+ } else {
+ amounts_map::iterator i = amounts.find(amt.commodity);
+ if (i != amounts.end())
+ (*i).second /= amt;
+ }
+ return *this;
+ }
+
+ // multiplication and divide
+ balance_t operator*(const balance_t& bal) const {
+ balance_t temp = *this;
+ temp *= bal;
+ return temp;
+ }
+ balance_t operator*(const amount_t& amt) const {
+ balance_t temp = *this;
+ temp *= amt;
+ return temp;
+ }
+ balance_t operator/(const balance_t& bal) const {
+ balance_t temp = *this;
+ temp /= bal;
+ return temp;
+ }
+ balance_t operator/(const amount_t& amt) const {
+ balance_t temp = *this;
+ temp /= amt;
+ return temp;
+ }
+
+ // comparison
+ bool operator<(const balance_t& bal) const {
+ for (amounts_map::const_iterator i = bal.amounts.begin();
+ i != bal.amounts.end();
+ i++)
+ if (! (amount((*i).first) < (*i).second))
+ return false;
+
+ for (amounts_map::const_iterator i = amounts.begin();
+ i != amounts.end();
+ i++)
+ if (! ((*i).second < bal.amount((*i).first)))
+ return false;
+
+ return true;
+ }
+ bool operator<=(const balance_t& bal) const {
+ for (amounts_map::const_iterator i = bal.amounts.begin();
+ i != bal.amounts.end();
+ i++)
+ if (! (amount((*i).first) <= (*i).second))
+ return false;
+
+ for (amounts_map::const_iterator i = amounts.begin();
+ i != amounts.end();
+ i++)
+ if (! ((*i).second <= bal.amount((*i).first)))
+ return false;
+
+ return true;
+ }
+ bool operator<(const amount_t& amt) const {
+ return amount(amt.commodity) < amt;
+ }
+ bool operator<=(const amount_t& amt) const {
+ return amount(amt.commodity) <= amt;
+ }
+
+ bool operator>(const balance_t& bal) const {
+ for (amounts_map::const_iterator i = bal.amounts.begin();
+ i != bal.amounts.end();
+ i++)
+ if (! (amount((*i).first) > (*i).second))
+ return false;
+
+ for (amounts_map::const_iterator i = amounts.begin();
+ i != amounts.end();
+ i++)
+ if (! ((*i).second > bal.amount((*i).first)))
+ return false;
+
+ return true;
+ }
+ bool operator>=(const balance_t& bal) const {
+ for (amounts_map::const_iterator i = bal.amounts.begin();
+ i != bal.amounts.end();
+ i++)
+ if (! (amount((*i).first) >= (*i).second))
+ return false;
+
+ for (amounts_map::const_iterator i = amounts.begin();
+ i != amounts.end();
+ i++)
+ if (! ((*i).second >= bal.amount((*i).first)))
+ return false;
+
+ return true;
+ }
+ bool operator>(const amount_t& amt) const {
+ return amount(amt.commodity) > amt;
+ }
+ bool operator>=(const amount_t& amt) const {
+ return amount(amt.commodity) >= amt;
+ }
+
+ // unary negation
+ balance_t& negate() {
+ for (amounts_map::iterator i = amounts.begin();
+ i != amounts.end();
+ i++)
+ (*i).second.negate();
+ return *this;
+ }
+ balance_t negated() const {
+ balance_t temp = *this;
+ temp.negate();
+ return temp;
+ }
+ balance_t operator-() const {
+ return negated();
+ }
+
+ // test for non-zero (use ! for zero)
+ operator bool() const {
+ for (amounts_map::const_iterator i = amounts.begin();
+ i != amounts.end();
+ i++)
+ if ((*i).second)
+ return true;
+ return false;
+ }
+
+ amount_t amount(const commodity_t * commodity = NULL) const;
+#if 0
+ balance_t round() const;
+#endif
+ balance_t value(const std::time_t moment) const;
+
+ void write(std::ostream& out,
+ const int first_width,
+ const int latter_width = -1) const;
+};
+
+inline balance_t abs(const balance_t& bal) {
+ balance_t temp;
+ for (amounts_map::const_iterator i = bal.amounts.begin();
+ i != bal.amounts.end();
+ i++)
+ temp += abs((*i).second);
+ return temp;
+}
+
+#ifdef DEBUG
+inline std::ostream& operator<<(std::ostream& out, const balance_t& bal) {
+ bal.write(out, 12);
+ return out;
+}
+#endif
+
+
+class balance_pair_t
+{
+ public:
+ balance_t quantity;
+ balance_t cost;
+
+ bool valid() const {
+ return quantity.valid() && cost.valid();
+ }
+
+ // constructors
+ balance_pair_t() {}
+ balance_pair_t(const balance_pair_t& bal_pair)
+ : quantity(bal_pair.quantity), cost(bal_pair.cost) {}
+ balance_pair_t(const balance_t& _quantity, const balance_t& _cost)
+ : quantity(_quantity), cost(_cost) {}
+ balance_pair_t(const balance_t& _quantity)
+ : quantity(_quantity), cost(_quantity) {}
+ balance_pair_t(const amount_t& _quantity, const amount_t& _cost)
+ : quantity(_quantity), cost(_cost) {}
+ balance_pair_t(const amount_t& _quantity)
+ : quantity(_quantity), cost(_quantity) {}
+ balance_pair_t(const int value)
+ : quantity(value), cost(value) {}
+ balance_pair_t(const unsigned int value)
+ : quantity(value), cost(value) {}
+ balance_pair_t(const double value)
+ : quantity(value), cost(value) {}
+ balance_pair_t(const transaction_t& xact);
+
+ // destructor
+ ~balance_pair_t() {}
+
+ // assignment operator
+ balance_pair_t& operator=(const balance_pair_t& bal_pair) {
+ quantity = bal_pair.quantity;
+ cost = bal_pair.cost;
+ return *this;
+ }
+ balance_pair_t& operator=(const balance_t& bal) {
+ quantity = cost = bal;
+ return *this;
+ }
+ balance_pair_t& operator=(const amount_t& amt) {
+ quantity = cost = amt;
+ return *this;
+ }
+ balance_pair_t& operator=(const int value) {
+ quantity = cost = amount_t(value);
+ return *this;
+ }
+ balance_pair_t& operator=(const unsigned int value) {
+ quantity = cost = amount_t(value);
+ return *this;
+ }
+ balance_pair_t& operator=(const double value) {
+ quantity = cost = amount_t(value);
+ return *this;
+ }
+
+ // in-place arithmetic
+ balance_pair_t& operator+=(const balance_pair_t& bal_pair) {
+ quantity += bal_pair.quantity;
+ cost += bal_pair.cost;
+ return *this;
+ }
+ balance_pair_t& operator+=(const balance_t& bal) {
+ quantity += bal;
+ cost += bal;
+ return *this;
+ }
+ balance_pair_t& operator+=(const amount_t& amt) {
+ quantity += amt;
+ cost += amt;
+ return *this;
+ }
+ balance_pair_t& operator+=(const transaction_t& xact);
+
+ balance_pair_t& operator-=(const balance_pair_t& bal_pair) {
+ quantity -= bal_pair.quantity;
+ cost -= bal_pair.cost;
+ return *this;
+ }
+ balance_pair_t& operator-=(const balance_t& bal) {
+ quantity -= bal;
+ cost -= bal;
+ return *this;
+ }
+ balance_pair_t& operator-=(const amount_t& amt) {
+ quantity -= amt;
+ cost -= amt;
+ return *this;
+ }
+ balance_pair_t& operator-=(const transaction_t& xact);
+
+ // simple arithmetic
+ balance_pair_t operator+(const balance_pair_t& bal_pair) const {
+ balance_pair_t temp = *this;
+ temp += bal_pair;
+ return temp;
+ }
+ balance_pair_t operator+(const balance_t& bal) const {
+ balance_pair_t temp = *this;
+ temp += bal;
+ return temp;
+ }
+ balance_pair_t operator+(const amount_t& amt) const {
+ balance_pair_t temp = *this;
+ temp += amt;
+ return temp;
+ }
+
+ balance_pair_t operator-(const balance_pair_t& bal_pair) const {
+ balance_pair_t temp = *this;
+ temp -= bal_pair;
+ return temp;
+ }
+ balance_pair_t operator-(const balance_t& bal) const {
+ balance_pair_t temp = *this;
+ temp -= bal;
+ return temp;
+ }
+ balance_pair_t operator-(const amount_t& amt) const {
+ balance_pair_t temp = *this;
+ temp -= amt;
+ return temp;
+ }
+
+ // multiplication and division
+ balance_pair_t& operator*=(const balance_pair_t& bal_pair) {
+ quantity *= bal_pair.quantity;
+ cost *= bal_pair.quantity;
+ return *this;
+ }
+ balance_pair_t& operator*=(const balance_t& bal) {
+ quantity *= bal;
+ cost *= bal;
+ return *this;
+ }
+ balance_pair_t& operator*=(const amount_t& amt) {
+ quantity *= amt;
+ cost *= amt;
+ return *this;
+ }
+
+ balance_pair_t& operator/=(const balance_pair_t& bal_pair) {
+ quantity /= bal_pair.quantity;
+ cost /= bal_pair.quantity;
+ return *this;
+ }
+ balance_pair_t& operator/=(const balance_t& bal) {
+ quantity /= bal;
+ cost /= bal;
+ return *this;
+ }
+ balance_pair_t& operator/=(const amount_t& amt) {
+ quantity /= amt;
+ cost /= amt;
+ return *this;
+ }
+
+ balance_pair_t operator*(const balance_pair_t& bal_pair) const {
+ balance_pair_t temp = *this;
+ temp *= bal_pair;
+ return temp;
+ }
+ balance_pair_t operator*(const balance_t& bal) const {
+ balance_pair_t temp = *this;
+ temp *= bal;
+ return temp;
+ }
+ balance_pair_t operator*(const amount_t& amt) const {
+ balance_pair_t temp = *this;
+ temp *= amt;
+ return temp;
+ }
+
+ balance_pair_t operator/(const balance_pair_t& bal_pair) const {
+ balance_pair_t temp = *this;
+ temp /= bal_pair;
+ return temp;
+ }
+ balance_pair_t operator/(const balance_t& bal) const {
+ balance_pair_t temp = *this;
+ temp /= bal;
+ return temp;
+ }
+ balance_pair_t operator/(const amount_t& amt) const {
+ balance_pair_t temp = *this;
+ temp /= amt;
+ return temp;
+ }
+
+ // comparison
+ bool operator<(const balance_pair_t& bal_pair) const {
+ return quantity < bal_pair.quantity;
+ }
+ bool operator<(const balance_t& bal) const {
+ return quantity < bal;
+ }
+ bool operator<(const amount_t& amt) const {
+ return quantity < amt;
+ }
+ bool operator<=(const balance_pair_t& bal_pair) const {
+ return quantity <= bal_pair.quantity;
+ }
+ bool operator<=(const balance_t& bal) const {
+ return quantity <= bal;
+ }
+ bool operator<=(const amount_t& amt) const {
+ return quantity <= amt;
+ }
+
+ bool operator>(const balance_pair_t& bal_pair) const {
+ return quantity > bal_pair.quantity;
+ }
+ bool operator>(const balance_t& bal) const {
+ return quantity > bal;
+ }
+ bool operator>(const amount_t& amt) const {
+ return quantity > amt;
+ }
+ bool operator>=(const balance_pair_t& bal_pair) const {
+ return quantity >= bal_pair.quantity;
+ }
+ bool operator>=(const balance_t& bal) const {
+ return quantity >= bal;
+ }
+ bool operator>=(const amount_t& amt) const {
+ return quantity >= amt;
+ }
+
+ // unary negation
+ balance_pair_t& negate() {
+ quantity.negate();
+ cost.negate();
+ return *this;
+ }
+ balance_pair_t negated() const {
+ balance_pair_t temp = *this;
+ temp.negate();
+ return temp;
+ }
+ balance_pair_t operator-() const {
+ return negated();
+ }
+
+ // test for non-zero (use ! for zero)
+ operator bool() const {
+ return quantity;
+ }
+};
+
+inline balance_pair_t abs(const balance_pair_t& bal_pair) {
+ balance_pair_t temp;
+ temp.quantity = abs(bal_pair.quantity);
+ temp.cost = abs(bal_pair.cost);
+ return temp;
+}
+
+} // namespace ledger
+
+#endif // _BALANCE_H