Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/examples/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
CXX=g++-13

SOURCES += $(wildcard *.cpp)
TARGETS := $(patsubst %.cpp, %, $(SOURCES))

INCLUDE_FLAGS = -I../ -I../graphblas/platforms/sequential -I../interfaces/spec

CXXFLAGS = -std=c++2b -O3 $(INCLUDE_FLAGS)

all: $(TARGETS)

%: %.cpp
$(CXX) $(CXXFLAGS) -o $@ $^ $(CXXFLAGS)

clean:
rm -fv $(TARGETS)
35 changes: 35 additions & 0 deletions src/examples/ewise.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include <iostream>
#include <grb/grb.hpp>

//****************************************************************************
int main(int argc, char** argv) {
spec::matrix<int> a({10, 10});
spec::matrix<int> b({10, 10});
spec::matrix<int> c({10, 10});
spec::matrix<int> d({10, 10});

a[{2, 3}] = 12;
b[{2, 3}] = 12;

a[{1, 8}] = 7;
b[{1, 8}] = 4;

a[{7, 3}] = 2;
b[{4, 3}] = 2;

std::cout << "Matrix: a\n";
a.printInfo(std::cout);
std::cout << "Matrix: b\n";
b.printInfo(std::cout);

spec::ewise_intersection(c, a, b, spec::times{});

std::cerr << "Intersection (times) result: \n";
c.printInfo(std::cout);

spec::ewise_union(d, a, b, spec::plus{});

std::cerr << "Union (plus) result: \n";
d.printInfo(std::cout);
return 0;
}
25 changes: 25 additions & 0 deletions src/examples/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include <grb/grb.hpp>

int main(int argc, char** argv) {
spec::matrix<int> m({100, 100});

// Write to missing element.
m[{4, 4}] = 12;

// Access present element.
int v = m[{4, 4}];
std::cout << v << std::endl;

// Access missing element.
int g = m[{4, 3}];
std::cout << g << std::endl;

// Write to present element.
m[{4, 3}] = 12;

g = m[{4, 3}];
std::cout << g << std::endl;


return 0;
}
5 changes: 5 additions & 0 deletions src/interfaces/spec/grb/algorithms/algorithms.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once

// #include "multiply.hpp"
#include "ewise_intersection.hpp"
#include "ewise_union.hpp"
42 changes: 42 additions & 0 deletions src/interfaces/spec/grb/algorithms/ewise_intersection.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#pragma once

#include "../detail/detail.hpp"
#include "../util/util.hpp"
#include "../functional/functional.hpp"
#include "../matrix.hpp"
#include "../views/views.hpp"

namespace GRB_SPEC_NAMESPACE {

// NOTE: concepts are missing because `GRB_SPEC_NAMESPACE::matrix` does not
// satisfy iteration yet.
template <typename A,
typename B,
typename Combine,
typename C,
typename M = GRB_SPEC_NAMESPACE::full_matrix_mask<>,
typename Accumulate = GRB_SPEC_NAMESPACE::take_right<>
>
void ewise_intersection(C&& c, A&& a, B&& b,
Combine&& combine,
M&& mask = M{},
Accumulate&& acc = Accumulate{},
bool merge = false)
{
auto merge_enum = ((merge) ?
GBTL_NAMESPACE::OutputControlEnum::MERGE :
GBTL_NAMESPACE::OutputControlEnum::REPLACE);
if constexpr(std::is_same_v<M, GRB_SPEC_NAMESPACE::full_matrix_mask<>>)
{
GBTL_NAMESPACE::eWiseMult(c.backend_,
GBTL_NAMESPACE::NoMask(), acc,
combine, a.backend_, b.backend_, merge_enum);
} else
{
GBTL_NAMESPACE::eWiseMult(c.backend_,
mask.backend_, acc,
combine, a.backend_, b.backend_, merge_enum);
}
}

} // GRB_SPEC_NAMESPACE
42 changes: 42 additions & 0 deletions src/interfaces/spec/grb/algorithms/ewise_union.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#pragma once

#include "../detail/detail.hpp"
#include "../util/util.hpp"
#include "../functional/functional.hpp"
#include "../matrix.hpp"
#include "../views/views.hpp"

namespace GRB_SPEC_NAMESPACE {

// NOTE: concepts are missing because `GRB_SPEC_NAMESPACE::matrix` does not
// satisfy iteration yet.
template <typename A,
typename B,
typename Combine,
typename C,
typename M = GRB_SPEC_NAMESPACE::full_matrix_mask<>,
typename Accumulate = GRB_SPEC_NAMESPACE::take_right<>
>
void ewise_union(C&& c, A&& a, B&& b,
Combine&& combine,
M&& mask = M{},
Accumulate&& acc = Accumulate{},
bool merge = false)
{
auto merge_enum = ((merge) ?
GBTL_NAMESPACE::OutputControlEnum::MERGE :
GBTL_NAMESPACE::OutputControlEnum::REPLACE);
if constexpr(std::is_same_v<M, GRB_SPEC_NAMESPACE::full_matrix_mask<>>)
{
GBTL_NAMESPACE::eWiseAdd(c.backend_,
GBTL_NAMESPACE::NoMask(), acc,
combine, a.backend_, b.backend_, merge_enum);
} else
{
GBTL_NAMESPACE::eWiseAdd(c.backend_,
mask.backend_, acc,
combine, a.backend_, b.backend_, merge_enum);
}
}

} // GRB_SPEC_NAMESPACE
27 changes: 27 additions & 0 deletions src/interfaces/spec/grb/algorithms/multiply.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once

#include "../detail/detail.hpp"
#include "../util/util.hpp"
#include "../matrix.hpp"

namespace GRB_SPEC_NAMESPACE {

template <MatrixRange A,
MatrixRange B,
BinaryOperator<GRB_SPEC_NAMESPACE::matrix_scalar_t<A>, GRB_SPEC_NAMESPACE::matrix_scalar_t<B>> Combine = GRB_SPEC_NAMESPACE::multiplies<>,
BinaryOperator<GRB_SPEC_NAMESPACE::elementwise_return_type_t<A, B, Combine>,
GRB_SPEC_NAMESPACE::elementwise_return_type_t<A, B, Combine>,
GRB_SPEC_NAMESPACE::elementwise_return_type_t<A, B, Combine>> Reduce = GRB_SPEC_NAMESPACE::plus<>,
MaskMatrixRange M = GRB_SPEC_NAMESPACE::full_matrix_mask<>>
auto multiply(A&& a,
B&& b,
Reduce&& reduce = Reduce{},
Combine&& combine = Combine{},
M&& mask = GRB_SPEC_NAMESPACE::full_matrix_mask())
{
using T = GRB_SPEC_NAMESPACE::elementwise_return_type_t<A, B, Combine>;
matrix<T> c(a.shape()[0], b.shape()[1]);
multiply(c, a, b, reduce, combine, mask);
}

} // end GRB_SPEC_NAMESPACE
105 changes: 105 additions & 0 deletions src/interfaces/spec/grb/detail/concepts.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@

#pragma once

#include <ranges>

#include "matrix_traits.hpp"
#include "cpos.hpp"
#include "get.hpp"
#include "namespace_macros.hpp"

namespace GRB_SPEC_NAMESPACE {

template <typename T, std::size_t I, typename U = GRB_SPEC_NAMESPACE::any>
concept TupleElementGettable = requires(T tuple) {
{GRB_SPEC_NAMESPACE::get<I>(tuple)} -> std::convertible_to<U>;
};

template <typename T, typename... Args>
concept TupleLike =
requires {
typename std::tuple_size<std::remove_cvref_t<T>>::type;
requires std::same_as<std::remove_cvref_t<decltype(std::tuple_size_v<std::remove_cvref_t<T>>)>, std::size_t>;
} &&
sizeof...(Args) == std::tuple_size_v<std::remove_cvref_t<T>> &&
[]<std::size_t... I>(std::index_sequence<I...>) {
return (TupleElementGettable<T, I, Args> && ...);
}(std::make_index_sequence<std::tuple_size_v<std::remove_cvref_t<T>>>());

template <typename Entry, typename T, typename I>
concept MatrixEntry = TupleLike<Entry, GRB_SPEC_NAMESPACE::any, GRB_SPEC_NAMESPACE::any> &&
requires(Entry entry) { {GRB_SPEC_NAMESPACE::get<0>(entry)} -> TupleLike<I, I>; } &&
requires(Entry entry) { {GRB_SPEC_NAMESPACE::get<1>(entry)} -> std::convertible_to<T>; };

template <typename Entry, typename T, typename I, typename U>
concept MutableMatrixEntry = MatrixEntry<Entry, T, I> &&
std::is_assignable_v<decltype(GRB_SPEC_NAMESPACE::get<1>(std::declval<Entry>())), U>;

template <typename M>
concept MatrixRange = std::ranges::sized_range<M> &&
requires(M matrix) {
typename container_traits<std::remove_cvref_t<M>>;
// typename GRB_SPEC_NAMESPACE::matrix_scalar_t<M>;
// typename GRB_SPEC_NAMESPACE::matrix_index_t<M>;
{std::declval<std::ranges::range_value_t<M>>()}
-> MatrixEntry<GRB_SPEC_NAMESPACE::matrix_scalar_t<M>,
GRB_SPEC_NAMESPACE::matrix_index_t<M>>;
{GRB_SPEC_NAMESPACE::shape(matrix)} -> TupleLike<GRB_SPEC_NAMESPACE::matrix_index_t<M>,
GRB_SPEC_NAMESPACE::matrix_index_t<M>>;
{GRB_SPEC_NAMESPACE::find(matrix, {GRB_SPEC_NAMESPACE::matrix_index_t<M>{}, GRB_SPEC_NAMESPACE::matrix_index_t<M>{}})} -> std::convertible_to<std::ranges::iterator_t<M>>;
};

template <typename M, typename T>
concept MutableMatrixRange = GRB_SPEC_NAMESPACE::MatrixRange<M> &&
GRB_SPEC_NAMESPACE::MutableMatrixEntry<std::ranges::range_reference_t<M>,
GRB_SPEC_NAMESPACE::matrix_scalar_t<M>,
GRB_SPEC_NAMESPACE::matrix_index_t<M>,
T> &&
requires(M matrix, T value) {
{GRB_SPEC_NAMESPACE::insert(matrix, {{GRB_SPEC_NAMESPACE::matrix_index_t<M>{}, GRB_SPEC_NAMESPACE::matrix_index_t<M>{}}, value})}
-> std::same_as<std::pair<std::ranges::iterator_t<M>, bool>>;
} &&
std::is_constructible_v<GRB_SPEC_NAMESPACE::matrix_scalar_t<M>, T>;

template <typename M>
concept MaskMatrixRange = MatrixRange<M> &&
std::is_convertible_v<GRB_SPEC_NAMESPACE::matrix_scalar_t<M>, bool>;

template <typename Entry, typename T, typename I>
concept VectorEntry = TupleLike<Entry, GRB_SPEC_NAMESPACE::any, GRB_SPEC_NAMESPACE::any> &&
requires(Entry entry) { {GRB_SPEC_NAMESPACE::get<0>(entry)} -> std::integral; } &&
requires(Entry entry) { {GRB_SPEC_NAMESPACE::get<1>(entry)} -> std::convertible_to<T>; };

template <typename Entry, typename T, typename I, typename U>
concept MutableVectorEntry = VectorEntry<Entry, T, I> &&
std::is_assignable_v<decltype(GRB_SPEC_NAMESPACE::get<1>(std::declval<Entry>())), U>;

template <typename V>
concept VectorRange = std::ranges::sized_range<V> &&
requires(V vector) {
typename GRB_SPEC_NAMESPACE::vector_scalar_t<V>;
typename GRB_SPEC_NAMESPACE::vector_index_t<V>;
{std::declval<std::ranges::range_value_t<V>>()}
-> VectorEntry<GRB_SPEC_NAMESPACE::vector_scalar_t<V>,
GRB_SPEC_NAMESPACE::vector_index_t<V>>;
{GRB_SPEC_NAMESPACE::shape(vector)} -> std::same_as<GRB_SPEC_NAMESPACE::vector_index_t<V>>;
{GRB_SPEC_NAMESPACE::find(vector, GRB_SPEC_NAMESPACE::vector_index_t<V>{})} -> std::convertible_to<std::ranges::iterator_t<V>>;
};

template <typename V, typename T>
concept MutableVectorRange = VectorRange<V> &&
MutableVectorEntry<std::ranges::range_reference_t<V>,
GRB_SPEC_NAMESPACE::vector_scalar_t<V>,
GRB_SPEC_NAMESPACE::vector_index_t<V>,
T> &&
requires(V vector, T value) {
{GRB_SPEC_NAMESPACE::insert(vector, {GRB_SPEC_NAMESPACE::vector_index_t<V>{}, GRB_SPEC_NAMESPACE::vector_scalar_t<V>{}})}
-> std::same_as<std::pair<std::ranges::iterator_t<V>, bool>>;
} &&
std::is_constructible_v<GRB_SPEC_NAMESPACE::vector_scalar_t<V>, T>;

template <typename M>
concept MaskVectorRange = VectorRange<M> &&
std::is_convertible_v<GRB_SPEC_NAMESPACE::vector_scalar_t<M>, bool>;

} // end GRB_SPEC_NAMESPACE
Loading