Chris@49: // Copyright (C) 2011-2012 Ryan Curtin Chris@49: // Copyright (C) 2012 Conrad Sanderson Chris@49: // Chris@49: // This Source Code Form is subject to the terms of the Mozilla Public Chris@49: // License, v. 2.0. If a copy of the MPL was not distributed with this Chris@49: // file, You can obtain one at http://mozilla.org/MPL/2.0/. Chris@49: Chris@49: //! \addtogroup SpValProxy Chris@49: //! @{ Chris@49: Chris@49: //! SpValProxy implementation. Chris@49: template Chris@49: arma_inline Chris@49: SpValProxy::SpValProxy(uword in_row, uword in_col, T1& in_parent, eT* in_val_ptr) Chris@49: : row(in_row) Chris@49: , col(in_col) Chris@49: , val_ptr(in_val_ptr) Chris@49: , parent(in_parent) Chris@49: { Chris@49: // Nothing to do. Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_inline Chris@49: SpValProxy& Chris@49: SpValProxy::operator=(const SpValProxy& rhs) Chris@49: { Chris@49: return (*this).operator=(eT(rhs)); Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: template Chris@49: arma_inline Chris@49: SpValProxy& Chris@49: SpValProxy::operator=(const SpValProxy& rhs) Chris@49: { Chris@49: return (*this).operator=(eT(rhs)); Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_inline Chris@49: SpValProxy& Chris@49: SpValProxy::operator=(const eT rhs) Chris@49: { Chris@49: if (rhs != eT(0)) // A nonzero element is being assigned. Chris@49: { Chris@49: Chris@49: if (val_ptr) Chris@49: { Chris@49: // The value exists and merely needs to be updated. Chris@49: *val_ptr = rhs; Chris@49: } Chris@49: Chris@49: else Chris@49: { Chris@49: // The value is nonzero and must be added. Chris@49: val_ptr = &parent.add_element(row, col, rhs); Chris@49: } Chris@49: Chris@49: } Chris@49: else // A zero is being assigned.~ Chris@49: { Chris@49: Chris@49: if (val_ptr) Chris@49: { Chris@49: // The element exists, but we need to remove it, because it is being set to 0. Chris@49: parent.delete_element(row, col); Chris@49: val_ptr = NULL; Chris@49: } Chris@49: Chris@49: // If the element does not exist, we do not need to do anything at all. Chris@49: Chris@49: } Chris@49: Chris@49: return *this; Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_inline Chris@49: SpValProxy& Chris@49: SpValProxy::operator+=(const eT rhs) Chris@49: { Chris@49: if (val_ptr) Chris@49: { Chris@49: // The value already exists and merely needs to be updated. Chris@49: *val_ptr += rhs; Chris@49: check_zero(); Chris@49: } Chris@49: else Chris@49: { Chris@49: if (rhs != eT(0)) Chris@49: { Chris@49: // The value does not exist and must be added. Chris@49: val_ptr = &parent.add_element(row, col, rhs); Chris@49: } Chris@49: } Chris@49: Chris@49: return *this; Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_inline Chris@49: SpValProxy& Chris@49: SpValProxy::operator-=(const eT rhs) Chris@49: { Chris@49: if (val_ptr) Chris@49: { Chris@49: // The value already exists and merely needs to be updated. Chris@49: *val_ptr -= rhs; Chris@49: check_zero(); Chris@49: } Chris@49: else Chris@49: { Chris@49: if (rhs != eT(0)) Chris@49: { Chris@49: // The value does not exist and must be added. Chris@49: val_ptr = &parent.add_element(row, col, -rhs); Chris@49: } Chris@49: } Chris@49: Chris@49: return *this; Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_inline Chris@49: SpValProxy& Chris@49: SpValProxy::operator*=(const eT rhs) Chris@49: { Chris@49: if (rhs != eT(0)) Chris@49: { Chris@49: Chris@49: if (val_ptr) Chris@49: { Chris@49: // The value already exists and merely needs to be updated. Chris@49: *val_ptr *= rhs; Chris@49: check_zero(); Chris@49: } Chris@49: Chris@49: } Chris@49: else Chris@49: { Chris@49: Chris@49: if (val_ptr) Chris@49: { Chris@49: // Since we are multiplying by zero, the value can be deleted. Chris@49: parent.delete_element(row, col); Chris@49: val_ptr = NULL; Chris@49: } Chris@49: Chris@49: } Chris@49: Chris@49: return *this; Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_inline Chris@49: SpValProxy& Chris@49: SpValProxy::operator/=(const eT rhs) Chris@49: { Chris@49: if (rhs != eT(0)) // I hope this is true! Chris@49: { Chris@49: Chris@49: if (val_ptr) Chris@49: { Chris@49: *val_ptr /= rhs; Chris@49: check_zero(); Chris@49: } Chris@49: Chris@49: } Chris@49: else Chris@49: { Chris@49: Chris@49: if (val_ptr) Chris@49: { Chris@49: *val_ptr /= rhs; // That is where it gets ugly. Chris@49: // Now check if it's 0. Chris@49: if (*val_ptr == eT(0)) Chris@49: { Chris@49: parent.delete_element(row, col); Chris@49: val_ptr = NULL; Chris@49: } Chris@49: } Chris@49: Chris@49: else Chris@49: { Chris@49: eT val = eT(0) / rhs; // This may vary depending on type and implementation. Chris@49: Chris@49: if (val != eT(0)) Chris@49: { Chris@49: // Ok, now we have to add it. Chris@49: val_ptr = &parent.add_element(row, col, val); Chris@49: } Chris@49: Chris@49: } Chris@49: } Chris@49: Chris@49: return *this; Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_inline Chris@49: SpValProxy& Chris@49: SpValProxy::operator++() Chris@49: { Chris@49: if (val_ptr) Chris@49: { Chris@49: (*val_ptr) += eT(1); Chris@49: check_zero(); Chris@49: } Chris@49: Chris@49: else Chris@49: { Chris@49: val_ptr = &parent.add_element(row, col, eT(1)); Chris@49: } Chris@49: Chris@49: return *this; Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_inline Chris@49: SpValProxy& Chris@49: SpValProxy::operator--() Chris@49: { Chris@49: if (val_ptr) Chris@49: { Chris@49: (*val_ptr) -= eT(1); Chris@49: check_zero(); Chris@49: } Chris@49: Chris@49: else Chris@49: { Chris@49: val_ptr = &parent.add_element(row, col, eT(-1)); Chris@49: } Chris@49: Chris@49: return *this; Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_inline Chris@49: typename T1::elem_type Chris@49: SpValProxy::operator++(const int) Chris@49: { Chris@49: if (val_ptr) Chris@49: { Chris@49: (*val_ptr) += eT(1); Chris@49: check_zero(); Chris@49: } Chris@49: Chris@49: else Chris@49: { Chris@49: val_ptr = &parent.add_element(row, col, eT(1)); Chris@49: } Chris@49: Chris@49: if (val_ptr) // It may have changed to now be 0. Chris@49: { Chris@49: return *(val_ptr) - eT(1); Chris@49: } Chris@49: else Chris@49: { Chris@49: return eT(0); Chris@49: } Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_inline Chris@49: typename T1::elem_type Chris@49: SpValProxy::operator--(const int) Chris@49: { Chris@49: if (val_ptr) Chris@49: { Chris@49: (*val_ptr) -= eT(1); Chris@49: check_zero(); Chris@49: } Chris@49: Chris@49: else Chris@49: { Chris@49: val_ptr = &parent.add_element(row, col, eT(-1)); Chris@49: } Chris@49: Chris@49: if (val_ptr) // It may have changed to now be 0. Chris@49: { Chris@49: return *(val_ptr) + eT(1); Chris@49: } Chris@49: else Chris@49: { Chris@49: return eT(0); Chris@49: } Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_inline Chris@49: SpValProxy::operator eT() const Chris@49: { Chris@49: if (val_ptr) Chris@49: { Chris@49: return *val_ptr; Chris@49: } Chris@49: else Chris@49: { Chris@49: return eT(0); Chris@49: } Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_inline Chris@49: arma_hot Chris@49: void Chris@49: SpValProxy::check_zero() Chris@49: { Chris@49: if (*val_ptr == eT(0)) Chris@49: { Chris@49: parent.delete_element(row, col); Chris@49: val_ptr = NULL; Chris@49: } Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: //! @}