TEST(SparseArrayTest, InsertString) { SparseArray<string>* tDString = new SparseArray<string>(3, 3, "default"); tDString->insert(1, 2, "Sparse"); EXPECT_EQ("Sparse", tDString->access(1, 2)); delete tDString; }
SparseArray SparseMatrix::getColumn(unsigned i) const { SparseArray column; for (unsigned j=0; j<numRows(); ++j) { int pos = _row[j].findIndex(i); if (pos != -1) column.insert(j, _row[j].readValue(pos)); } return column; }
void SparseMatrix::setColumn(unsigned i, const SparseArray& col) { unsigned nnz = col.numNonZeros(); for (unsigned j=0; j<nnz; ++j) { int index = col.readIndex(j); double value = col.readValue(j); _row[index].setValue(i, value); } }
TEST(SparseArray, PrintInt) { SparseArray<int>* tdI = new SparseArray<int>(5, 5, 0); for (int i = 0; i < 5; i++) { tdI->insert(i, i, 4); } std::cout << "SparseArray Integer print" << std::endl; tdI->print(); delete tdI; }
TEST(SparseArrayTest, InsertInt) { SparseArray<int>* tDInt = new SparseArray<int>(3, 3, 0); for (int i=0; i < 3; i++) { tDInt->insert(i, i, 3); } EXPECT_EQ(3, tDInt->access(1, 1)); delete tDInt; }
TEST(SparseArrayRemove, RemoveString) { SparseArray<string>* tDString = new SparseArray<string>(10, 10, "default"); for (int i=0; i<10; i++) { tDString->insert(i, i, "HELLO"); } tDString->remove(7, 5); EXPECT_EQ("default", tDString->access(7, 5)); delete tDString; }
TEST(SparseArrayTest, InsertDouble) { SparseArray<double>* tDDouble = new SparseArray<double>(3, 3, 0.0); for (int i=0; i < 3; i++) { tDDouble->insert(i, i, 3.3); } EXPECT_EQ(3.3, tDDouble->access(1, 1)); delete tDDouble; }
TEST(SparseArray, PrintDouble) { SparseArray<double>* tdD = new SparseArray<double>(5, 5, 0.0); for (int i = 0; i < 5; i++) { tdD->insert(i, i, 2.9); } std::cout << "SparseArray Double print" << std::endl; tdD->print(); delete tdD; }
TEST(SparseArray, PrintString) { SparseArray<string>* tdS = new SparseArray<string>(5, 5, "default"); for (int i = 0; i < 5; i++) { tdS->insert(i, i, "Greg"); } std::cout << "SparseArray String print" << std::endl; tdS->print(); delete tdS; }
TEST(SparseArrayRemove, RemoveDouble) { SparseArray<double>* tDDouble = new SparseArray<double>(10, 10, 5.5); for (int i=0; i<10; i++) { tDDouble->insert(i, i, 7.7); } tDDouble->remove(7, 5); EXPECT_EQ(5.5, tDDouble->access(7, 5)); delete tDDouble; }
TEST(SparseArrayRemove, RemoveInt) { SparseArray<int>* tDInt = new SparseArray<int>(10, 10, 5); for (int i=0; i<10; i++) { tDInt->insert(i, i, 7); } tDInt->remove(7, 5); EXPECT_EQ(5, tDInt->access(7, 5)); delete tDInt; }
TEST(SparseArrayAccess, AccessString) { SparseArray<string>* tDString = new SparseArray<string>(12, 12, "9"); for (int i = 0; i < 10; i++) { for(int j = 0; j < 10; j++) { tDString->access(i, j); } } EXPECT_EQ("9", tDString->access(7, 7)); delete tDString; }
TEST(SparseArrayAccess, AccessDouble) { SparseArray<double>* tDDouble = new SparseArray<double>(11, 11, 8.8); for (int i = 0; i < 10; i++) { for(int j = 0; j < 10; j++) { tDDouble->access(i, j); } } EXPECT_EQ(8.8, tDDouble->access(7, 7)); delete tDDouble; }
TEST(SparseArrayAccess, AccessInt) { SparseArray<int>* tDInt = new SparseArray<int>(10, 10, 7); for (int i = 0; i < 10; i++) { for(int j = 0; j < 10; j++) { tDInt->access(i, j); } } EXPECT_EQ(7, tDInt->access(7, 7)); delete tDInt; }
SparseArray<T> sparseConvertStorageToStorage(const SparseArray<T> &in) { // Dummy function // TODO finish this function when support is required AF_ERROR("CPU Backend only supports Dense to CSR or COO", AF_ERR_NOT_SUPPORTED); in.eval(); SparseArray<T> dense = createEmptySparseArray<T>(in.dims(), (int)in.getNNZ(), dest); return dense; }
Array<T> sparseConvertStorageToDense(const SparseArray<T> &in_) { // MKL only has dns<->csr. // CSR <-> CSC is only supported if input is square if(stype == AF_STORAGE_CSC) AF_ERROR("CPU Backend only supports Dense to CSR or COO", AF_ERR_NOT_SUPPORTED); in_.eval(); Array<T> dense_ = createValueArray<T>(in_.dims(), scalar<T>(0)); dense_.eval(); auto func = [=] (Array<T> dense, const SparseArray<T> in) { // Read: https://software.intel.com/en-us/node/520848 // But job description is incorrect with regards to job[1] // 0 implies row major and 1 implies column major int j1 = 1, j2 = 0; const int job[] = {1, j1, j2, 2, (int)dense.elements(), 1}; const int M = dense.dims()[0]; const int N = dense.dims()[1]; int ldd = dense.strides()[1]; int info = 0; Array<T > values = in.getValues(); Array<int> rowIdx = in.getRowIdx(); Array<int> colIdx = in.getColIdx(); // Have to mess up all const correctness because MKL dnscsr function // is bidirectional and has input/output on all pointers dnscsr_func<T>()( job, &M, &N, reinterpret_cast<ptr_type<T>>(dense.get()), &ldd, reinterpret_cast<ptr_type<T>>(const_cast<T*>(values.get())), const_cast<int*>(colIdx.get()), const_cast<int*>(rowIdx.get()), &info); }; getQueue().enqueue(func, dense_, in_); if(stype == AF_STORAGE_CSR) return dense_; else AF_ERROR("CPU Backend only supports Dense to CSR or COO", AF_ERR_NOT_SUPPORTED); return dense_; }
Array<T> sparseConvertCOOToDense(const SparseArray<T> &in) { in.eval(); Array<T> dense = createValueArray<T>(in.dims(), scalar<T>(0)); dense.eval(); const Array<T> values = in.getValues(); const Array<int> rowIdx = in.getRowIdx(); const Array<int> colIdx = in.getColIdx(); getQueue().enqueue(kernel::coo2dense<T>, dense, values, rowIdx, colIdx); return dense; }
unsigned SparseMatrix::copyCCS(long*& colptr, long*& index, double*& value) const { unsigned N = numNonZeros(); colptr = (long int*) malloc((numColumns() + 1) * sizeof(long int)); index = (long int*) malloc(N * sizeof(long int)); value = (double*) malloc(N * sizeof(double)); colptr[0] = 0; for (unsigned i = 0; i < numColumns(); ++i) { SparseArray col = getColumn(i); int offset = col.numNonZeros(); col.copy( &(index[colptr[i]]), &(value[colptr[i]]) ); colptr[i+1] = colptr[i] + offset; } return N; }
TEST(sparseTest, getNumCols) { SparseArray<int>* i = new SparseArray<int>(5, 5, 0); SparseArray<double>* d = new SparseArray<int>(5, 10, 0); SparseArray<std::string>* s = new SparseArray<std::string>(5, 19, 0); i->insert(2, 2, 7); d->insert(4, 4, 3.145); s->insert(0, 0, "Hello"); EXPECT_EQ(5, i->getNumCols()); EXPECT_EQ(10, d->getNumCols()); EXPECT_EQ(19, s->getNumCols()); delete i; delete d; delete s; }
TEST(sparseTest, access) { SparseArray<int>* i = new SparseArray<int>(5, 5, 0); SparseArray<double>* d = new SparseArray<int>(5, 5, 0); SparseArray<std::string>* s = new SparseArray<std::string>(5, 5, "World"); i->insert(2, 2, 7); d->insert(4, 4, 3.145); s->insert(0, 0, "Hello"); EXPECT_EQ(7, i->access(2, 2)); EXPECT_EQ(3.145, d->access(4, 4)); EXPECT_EQ("World", s->access(2, 2)); delete i; delete d; delete s; }
TEST(Sparse, Print) { SparseArray<double>* newSparse = new SparseArray<double>(25,25,1.1); newSparse->insert(1,2,1.2); newSparse->insert(9,8,2.2); newSparse->insert(7,2,3.3); newSparse->insert(6,4,4.4); newSparse->insert(0,8,5.5); newSparse->insert(19,14,6.6); newSparse->insert(20,20,7.7); newSparse->insert(14,6,8.8); newSparse->insert(24,24,9.9); newSparse->print(); delete newSparse; }
double cosSim(const SparseArray& a, const SparseArray& b) { double ab = 0, a2 = 0, b2 = 0; auto i = a.begin(), j = b.begin(); while(i != a.end() || j != b.end()) { if(i == a.end()) { b2 += j->value * j->value; ++j; } else if(j == b.end()) { a2 += i->value * i->value; ++i; } else if((*i) < (*j)) { a2 += i->value * i->value; ++i; } else if((*j) < (*i)) { b2 += j->value * j->value; ++j; } else { a2 += i->value * i->value; b2 += j->value * j->value; ab += i->value * j->value; ++i; ++j; } } if(a2 == 0 || b2 == 0) { return 1.0; } else { //cout << "ab=" << ab << " a2=" << a2 << " b2=" << b2 << endl; return ab / sqrt(a2*b2); } }
TEST(sparseTest, print) { SparseArray<int>* i = new SparseArray<int>(5, 5, 0); SparseArray<double>* d = new SparseArray<int>(5, 5, 0); SparseArray<std::string>* s = new SparseArray<std::string>(5, 5, "o"); i->insert(2, 2, 7); d->insert(4, 4, 3.145); s->insert(0, 0, "Hello"); i->print(); std::cout << std::endl; d->print(); std::cout << std::endl; s->print(); delete i; delete d; delete s; }
Array<T> sparseConvertStorageToDense(const SparseArray<T> &in_) { in_.eval(); Array<T> dense_ = createValueArray<T>(in_.dims(), scalar<T>(0)); dense_.eval(); auto func = [=] (Array<T> dense, const SparseArray<T> in) { Array<T > values = in.getValues(); Array<int> rowIdx = in.getRowIdx(); Array<int> colIdx = in.getColIdx(); kernel::csr_dense<T>()(dense, values, rowIdx, colIdx); }; getQueue().enqueue(func, dense_, in_); if(stype == AF_STORAGE_CSR) return dense_; else AF_ERROR("CPU Backend only supports Dense to CSR or COO", AF_ERR_NOT_SUPPORTED); return dense_; }
/** * Read a topic vector file * The format of these files are such that each line is: * idx1 idx2 ... idxN ||| val1 val2 ... valN * Which represents a coordinate form sparse array * @param t Vector to write to * @param fname The file name to read from */ void readTopicFile(vector<SparseArray>& t, const char *fname) { cerr << "Reading " << fname << endl; int linesRead = 1; ifstream topic1file(fname,ifstream::in); if(topic1file.fail()) { cerr << "Failed to read " << fname << endl; return; } string line; while(getline(topic1file,line)) { stringstream ss(line); ss.exceptions(ifstream::failbit); if(linesRead % 10 == 0) { cerr << "."; } cerr.flush(); linesRead++; SparseArray arr; while(ss.peek() != '|') { SparseArrayElem e; ss >> e.idx; arr.push_back(e); while(ss.peek() == ' ') { ss.get(); } } while(ss.peek() == '|' || ss.peek() == ' ') { ss.get(); } unsigned vals = 0; for(auto it = arr.begin(); it != arr.end(); ++it) { if(++vals > arr.size()) { throw runtime_error("Index and value length differ (too many values)"); } ss >> it->value; } if(vals != arr.size()) { throw runtime_error("Index and value length differ (too few values)"); } sort(arr.begin(),arr.end()); t.push_back(arr); } cerr << "OK" << endl; }
TEST(SparseArrayCol, NumCol) { SparseArray<int>* tDInt = new SparseArray<int>(10, 10, 0); SparseArray<double>* tDDouble = new SparseArray<double>(11, 11, 0.0); SparseArray<string>* tDString = new SparseArray<string>(12, 12, "0"); EXPECT_EQ(10, tDInt->getNumCols()); delete tDInt; EXPECT_EQ(11, tDDouble->getNumCols()); delete tDDouble; EXPECT_EQ(12, tDString->getNumCols()); delete tDString; }
//test insert into sparse array of int, double, string TEST(Sparse, Insert) { SparseArray<int>* newInt= new SparseArray<int>(5,5,0); newInt->insert(0,0,5); EXPECT_EQ(5, newInt->access(0,0)); delete newInt; SparseArray<double>* newDouble = new SparseArray<double>(5,6,0.0); newDouble->insert(2,4,6.5); EXPECT_EQ(6.5, newDouble->access(2,4)); delete newDouble; SparseArray<std::string>* newString = new SparseArray<std::string>(7,8,"null"); newString->insert(4,3,"howdy"); EXPECT_EQ("howdy", newString->access(4,3)); delete newString; }
Test(sparseTest, remove) { SparseArray<int>* i = new SparseArray<int>(5, 5, 0); SparseArray<double>* d = new SparseArray<int>(5, 5, 0); SparseArray<std::string>* s = new SparseArray<std::string>(5, 5, "o"); i->insert(2, 2, 7); d->insert(4, 4, 3.145); s->insert(0, 0, "Hello"); i->insert(3, 3, 9); i->remove(2, 2); d->remove(4, 4); s->remove(0, 0); s->insert(0, 0, "y"); EXPECT_EQ(0, i->access(2, 2)); EXPECT_EQ(0, d->access(4, 4)); EXPECT_EQ("y", s->access(0, 0)); EXPECT_EQ(9, i->insert(3, 3)); delete i; delete d; delete s; }
TEST(Sparse, GetNumCols) { SparseArray<int>* newSparse = new SparseArray<int>(114,35,0); EXPECT_EQ(114, newSparse->getNumColumns()); delete newSparse; }
TEST(Sparse, GetNumRows) { SparseArray<int>* newSparse = new SparseArray<int>(7,8,0); EXPECT_EQ(8, newSparse->getNumRows()); delete newSparse; }