#include "DataHandlerMapCPU.h" #include "DataHandlerCPU.h" namespace elsa { template DataHandlerMapCPU::DataHandlerMapCPU(DataHandlerCPU* dataOwner, data_t* data, index_t n) : _map(data, n), _dataOwner{dataOwner} { // sanity checks performed in getBlock() #pragma omp critical { // add self to list of Maps referring to the _dataOwner _dataOwner->_associatedMaps.push_front(this); _handle = _dataOwner->_associatedMaps.begin(); } } template DataHandlerMapCPU::DataHandlerMapCPU(const DataHandlerMapCPU& other) : _map{other._map}, _dataOwner{other._dataOwner} { #pragma omp critical { // add self to list of Maps referring to the _dataOwner _dataOwner->_associatedMaps.push_front(this); _handle = _dataOwner->_associatedMaps.begin(); } } template DataHandlerMapCPU::~DataHandlerMapCPU() { // remove self from list of Maps referring to the _dataOwner if (_dataOwner) { #pragma omp critical _dataOwner->_associatedMaps.erase(_handle); } } template index_t DataHandlerMapCPU::getSize() const { return static_cast(_map.size()); } template data_t& DataHandlerMapCPU::operator[](index_t index) { _dataOwner->detach(); return _map[index]; } template const data_t& DataHandlerMapCPU::operator[](index_t index) const { return _map[index]; } template data_t DataHandlerMapCPU::dot(const DataHandler& v) const { if (v.getSize() != getSize()) throw std::invalid_argument("DataHandlerMapCPU: dot product argument has wrong size"); // use Eigen if the other handler is CPU or Map, otherwise use the slow fallback version if (auto otherHandler = dynamic_cast*>(&v)) { return _map.dot(*otherHandler->_data); } else if (auto otherHandler = dynamic_cast(&v)) { return _map.dot(otherHandler->_map); } else { return this->slowDotProduct(v); } } template data_t DataHandlerMapCPU::squaredL2Norm() const { return _map.squaredNorm(); } template data_t DataHandlerMapCPU::l1Norm() const { return _map.array().abs().sum(); } template data_t DataHandlerMapCPU::lInfNorm() const { return _map.array().abs().maxCoeff(); } template data_t DataHandlerMapCPU::sum() const { return _map.sum(); } template std::unique_ptr> DataHandlerMapCPU::square() const { auto result = std::make_unique>(getSize(), false); *result->_data = _map.array().square(); return result; } template std::unique_ptr> DataHandlerMapCPU::sqrt() const { auto result = std::make_unique>(getSize(), false); *result->_data = _map.array().sqrt(); return result; } template std::unique_ptr> DataHandlerMapCPU::exp() const { auto result = std::make_unique>(getSize(), false); *result->_data = _map.array().exp(); return result; } template std::unique_ptr> DataHandlerMapCPU::log() const { auto result = std::make_unique>(getSize(), false); *result->_data = _map.array().log(); return result; } template DataHandler& DataHandlerMapCPU::operator+=(const DataHandler& v) { if (v.getSize() != getSize()) throw std::invalid_argument("DataHandler: addition argument has wrong size"); _dataOwner->detach(); // use Eigen if the other handler is CPU or Map, otherwise use the slow fallback version if (auto otherHandler = dynamic_cast*>(&v)) { _map += *otherHandler->_data; } else if (auto otherHandler = dynamic_cast(&v)) { _map += otherHandler->_map; } else { this->slowAddition(v); } return *this; } template DataHandler& DataHandlerMapCPU::operator-=(const DataHandler& v) { if (v.getSize() != getSize()) throw std::invalid_argument("DataHandler: subtraction argument has wrong size"); _dataOwner->detach(); // use Eigen if the other handler is CPU or Map, otherwise use the slow fallback version if (auto otherHandler = dynamic_cast*>(&v)) { _map -= *otherHandler->_data; } else if (auto otherHandler = dynamic_cast(&v)) { _map -= otherHandler->_map; } else { this->slowSubtraction(v); } return *this; } template DataHandler& DataHandlerMapCPU::operator*=(const DataHandler& v) { if (v.getSize() != getSize()) throw std::invalid_argument("DataHandler: multiplication argument has wrong size"); _dataOwner->detach(); // use Eigen if the other handler is CPU or Map, otherwise use the slow fallback version if (auto otherHandler = dynamic_cast*>(&v)) { _map.array() *= otherHandler->_data->array(); } else if (auto otherHandler = dynamic_cast(&v)) { _map.array() *= otherHandler->_map.array(); } else { this->slowMultiplication(v); } return *this; } template DataHandler& DataHandlerMapCPU::operator/=(const DataHandler& v) { if (v.getSize() != getSize()) throw std::invalid_argument("DataHandler: division argument has wrong size"); _dataOwner->detach(); // use Eigen if the other handler is CPU or Map, otherwise use the slow fallback version if (auto otherHandler = dynamic_cast*>(&v)) { _map.array() /= otherHandler->_data->array(); } else if (auto otherHandler = dynamic_cast(&v)) { _map.array() /= otherHandler->_map.array(); } else { this->slowDivision(v); } return *this; } template DataHandlerMapCPU& DataHandlerMapCPU:: operator=(const DataHandlerMapCPU& v) { if (v.getSize() != getSize()) throw std::invalid_argument("DataHandler: assignment argument has wrong size"); if (getSize() == _dataOwner->getSize() && v.getSize() == v._dataOwner->getSize()) { _dataOwner->attach(v._dataOwner->_data); } else { _dataOwner->detachWithUninitializedBlock(_map.data() - _dataOwner->_data->data(), getSize()); _map = v._map; } return *this; } template DataHandler& DataHandlerMapCPU::operator+=(data_t scalar) { _dataOwner->detach(); _map.array() += scalar; return *this; } template DataHandler& DataHandlerMapCPU::operator-=(data_t scalar) { _dataOwner->detach(); _map.array() -= scalar; return *this; } template DataHandler& DataHandlerMapCPU::operator*=(data_t scalar) { _dataOwner->detach(); _map.array() *= scalar; return *this; } template DataHandler& DataHandlerMapCPU::operator/=(data_t scalar) { _dataOwner->detach(); _map.array() /= scalar; return *this; } template DataHandler& DataHandlerMapCPU::operator=(data_t scalar) { _dataOwner->detach(); _map.setConstant(scalar); return *this; } template std::unique_ptr> DataHandlerMapCPU::getBlock(index_t startIndex, index_t numberOfElements) { if (startIndex >= getSize() || numberOfElements > getSize() - startIndex) throw std::invalid_argument("DataHandler: requested block out of bounds"); return std::unique_ptr>( new DataHandlerMapCPU{_dataOwner, _map.data() + startIndex, numberOfElements}); } template std::unique_ptr> DataHandlerMapCPU::getBlock(index_t startIndex, index_t numberOfElements) const { if (startIndex >= getSize() || numberOfElements > getSize() - startIndex) throw std::invalid_argument("DataHandler: requested block out of bounds"); // using a const_cast here is fine as long as the DataHandlers never expose the internal // Eigen objects auto mutableData = const_cast(_map.data() + startIndex); return std::unique_ptr>( new DataHandlerMapCPU{_dataOwner, mutableData, numberOfElements}); } template DataHandlerCPU* DataHandlerMapCPU::cloneImpl() const { if (getSize() == _dataOwner->getSize()) { return new DataHandlerCPU{*_dataOwner}; } else { return new DataHandlerCPU{_map}; } } template bool DataHandlerMapCPU::isEqual(const DataHandler& other) const { if (auto otherHandler = dynamic_cast(&other)) { if (_map.size() != otherHandler->_map.size()) return false; if (_map.data() != otherHandler->_map.data() && _map != otherHandler->_map) { return false; } return true; } else if (auto otherHandler = dynamic_cast*>(&other)) { if (_map.size() != otherHandler->_data->size()) return false; if (_map.data() != otherHandler->_data->data() && _map != *otherHandler->_data) return false; return true; } else return false; } template void DataHandlerMapCPU::assign(const DataHandler& other) { if (auto otherHandler = dynamic_cast(&other)) { if (getSize() == _dataOwner->getSize() && otherHandler->getSize() == otherHandler->_dataOwner->getSize()) { _dataOwner->attach(otherHandler->_dataOwner->_data); } else { _dataOwner->detachWithUninitializedBlock(_map.data() - _dataOwner->_data->data(), getSize()); _map = otherHandler->_map; } } else if (auto otherHandler = dynamic_cast*>(&other)) { if (getSize() == _dataOwner->getSize()) { _dataOwner->attach(otherHandler->_data); } else { _dataOwner->detachWithUninitializedBlock(_map.data() - _dataOwner->_data->data(), getSize()); _map = *otherHandler->_data; } } else this->slowAssign(other); } template void DataHandlerMapCPU::assign(DataHandler&& other) { assign(other); } // ------------------------------------------ // explicit template instantiation template class DataHandlerMapCPU; template class DataHandlerMapCPU>; template class DataHandlerMapCPU; template class DataHandlerMapCPU>; template class DataHandlerMapCPU; } // namespace elsa