#include "NTensor.hh" #include #include "Stopwatch.hh" #include #include using namespace cadabra; NTensor::NTensor(const std::vector& shape_, double val) : shape(shape_) { size_t len=1; for(auto dim: shape) len *= dim; values.resize(len); for(auto& v: values) v=val; } NTensor::NTensor(const std::vector& vals) : values(vals) { shape.push_back(values.size()); } NTensor::NTensor(double val) { values.push_back(val); shape.push_back(1); } NTensor::NTensor(const NTensor& other) { shape=other.shape; values=other.values; } NTensor NTensor::linspace(double from, double to, size_t steps) { NTensor res(std::vector({steps}), 0.0); assert(steps>1); for(size_t i=0; i& indices) const { if(indices.size()!=shape.size()) throw std::range_error("NTensor::at: number of indices != shape length."); size_t idx = 0; size_t stride=1; for(size_t p=indices.size(); p-- != 0; ) { if(indices[p]>=shape[p]) throw std::range_error("NTensor::at: index out of range."); idx += stride*indices[p]; stride *= shape[p]; } if(idx >= values.size()) throw std::range_error("NTensor::at: indices out of range."); return values[idx]; } double& NTensor::at(const std::vector& indices) { if(indices.size()!=shape.size()) throw std::range_error("NTensor::at: number of indices != shape length."); size_t idx = 0; size_t stride=1; for(size_t p=indices.size(); p-- != 0; ) { if(indices[p]>=shape[p]) throw std::range_error("NTensor::at: index out of range."); idx += stride*indices[p]; stride *= shape[p]; } if(idx >= values.size()) throw std::range_error("NTensor::at: indices out of range."); return values[idx]; } std::ostream& cadabra::operator<<(std::ostream &str, const NTensor &nt) { // For an {a,b} tensor, we display as a vector of size 'a', each // element of which is a vector of size 'b'. And so on. for(size_t p=0; p 2, 8, 24 mult *= nt.shape[p]; if((i+1)%mult == 0) str << "]"; } if(i+1 res_shape; res_shape.insert(res_shape.end(), a.shape.begin(), a.shape.end()); res_shape.insert(res_shape.end(), b.shape.begin(), b.shape.end()); NTensor res( res_shape, 0.0 ); for(size_t i=0; i new_shape, size_t pos) const { // for(auto s: new_shape) // std::cerr << s << ", "; // std::cerr << "\n" << pos << std::endl; assert( pos < new_shape.size() ); assert( shape.size()==1 ); assert( new_shape[pos]==shape[0] ); NTensor res(new_shape, 0.); size_t lower = 1, higher=1; for(size_t s=pos+1; s " << orig_i << std::endl; assert( orig_i < new_shape[pos] ); res.values[i] = values[orig_i]; } // sw.stop(); // std::cerr << "broadcast to " << res.values.size() << " took " << sw << std::endl; return res; }