ALP User Documentation 0.7.0
Algebraic Programming User Documentation
Functions
Level-0 Primitives

A collection of functions that let GraphBLAS operators work on zero-dimensional containers, i.e., on scalars. More...

Functions

template<Descriptor descr = descriptors::no_operation, class OP , typename InputType1 , typename InputType2 , typename OutputType >
static enum RC apply (OutputType &out, const InputType1 &x, const InputType2 &y, const OP &op=OP(), const typename std::enable_if< grb::is_operator< OP >::value &&!grb::is_object< InputType1 >::value &&!grb::is_object< InputType2 >::value &&!grb::is_object< OutputType >::value, void >::type *=nullptr)
 Out-of-place application of the operator OP on two data elements. More...
 
template<Descriptor descr = descriptors::no_operation, class OP , typename InputType , typename IOType >
static RC foldl (IOType &x, const InputType &y, const OP &op=OP(), const typename std::enable_if< grb::is_operator< OP >::value &&!grb::is_object< InputType >::value &&!grb::is_object< IOType >::value, void >::type *=nullptr)
 Application of the operator OP on two data elements. More...
 
template<Descriptor descr = descriptors::no_operation, class OP , typename InputType , typename IOType >
static RC foldr (const InputType &x, IOType &y, const OP &op=OP(), const typename std::enable_if< grb::is_operator< OP >::value &&!grb::is_object< InputType >::value &&!grb::is_object< IOType >::value, void >::type *=nullptr)
 Application of the operator OP on two data elements. More...
 

Detailed Description

A collection of functions that let GraphBLAS operators work on zero-dimensional containers, i.e., on scalars.

The GraphBLAS uses opaque data types and defines several standard functions to operate on these data types. Examples types are grb::Vector and grb::Matrix, example functions are grb::dot and grb::vxm.

To input data into an opaque GraphBLAS type, each opaque type defines a member function build: grb::Vector::build() and grb::Matrix::build().

To extract data from opaque GraphBLAS types, each opaque type provides iterators that may be obtained via the STL standard begin and end functions:

Some GraphBLAS functions, however, reduce all elements in a GraphBLAS container into a single element of a given type. So for instance, grb::dot on two vectors of type grb::Vector<double> using the regular real semiring grb::Semiring<double> will store its output in a variable of type double.

When parametrising GraphBLAS functions in terms of arbitrary Semirings, Monoids, Operators, and object types, it is useful to have a way to apply the same operators on whatever type they make functions like grb::dot produce– that is, we require functions that enable the application of GraphBLAS operators on single elements.

This group of BLAS level 0 functions provides this functionality.

Function Documentation

◆ apply()

static enum RC grb::apply ( OutputType &  out,
const InputType1 &  x,
const InputType2 &  y,
const OP &  op = OP(),
const typename std::enable_if< grb::is_operator< OP >::value &&!grb::is_object< InputType1 >::value &&!grb::is_object< InputType2 >::value &&!grb::is_object< OutputType >::value, void >::type *  = nullptr 
)
static

Out-of-place application of the operator OP on two data elements.

The output data will be output to an existing memory location, overwriting any existing data.

Template Parameters
descrThe descriptor passed to this operator.
OPThe type of the oparator to apply.
InputType1The left-hand side input argument type.
InputType2The right-hand side input argument type.
OutputTypeThe output argument type.
Valid descriptors
  1. grb::descriptors::no_operation for default behaviour.
  2. grb::descriptors::no_casting when a call to this function should not automatically cast input arguments to operator input domain, and not automatically cast operator output to the output argument domain.

If InputType1 does not match the left-hand side input domain of OP, or if InputType2 does not match the right-hand side input domain of OP, or if OutputType does not match the output domain of OP while grb::descriptors::no_casting was set, then the code shall not compile.

Parameters
[in]xThe left-hand side input data.
[in]yThe right-hand side input data.
[out]outWhere to store the result of the operator.
[in]opThe operator to apply (optional).
Note
op is optional when the operator type OP is explicitly given. Thus there are two ways of calling this function:
  1. double a, b, c; grb::apply< grb::operators::add<double> >( a, b, c ); , or
  2. double a, b, c; grb::operators::add< double > addition_over_doubles; grb::apply( a, b, c, addition_over_doubles);
There should be no performance difference between the two ways of calling this function. For compatibility with other GraphBLAS implementations, the latter type of call is preferred.
Returns
grb::SUCCESS A call to this function never fails.
Performance semantics.
  1. This call comprises \( \Theta(1) \) work. The constant factor depends on the cost of evaluating the operator.
  2. This call takes \( \mathcal{O}(1) \) memory beyond the memory already used by the application when a call to this function is made.
  3. This call incurs at most \( \Theta(1) \) memory where the constant factor depends on the storage requirements of the arguments and the temporary storage required for evaluation of this operator.
Warning
The use of stateful operators, or even thus use of stateless operators that are not included in grb::operators, may cause this function to incur performance penalties beyond the worst case sketched above.
See also
foldr for applying an operator in-place (if allowed).
foldl for applying an operator in-place (if allowed).
grb::operators::internal::Operator for a discussion on when foldr and foldl successfully generate in-place code.

◆ foldl()

static RC grb::foldl ( IOType &  x,
const InputType &  y,
const OP &  op = OP(),
const typename std::enable_if< grb::is_operator< OP >::value &&!grb::is_object< InputType >::value &&!grb::is_object< IOType >::value, void >::type *  = nullptr 
)
static

Application of the operator OP on two data elements.

The output data will overwrite the left-hand side input element.

In mathematical notation, this function calculates \( x \odot y \) and copies the result into x.

Template Parameters
descrThe descriptor passed to this operator.
OPThe type of the operator to apply.
IOTypeThe type of the left-hand side input element, which will be overwritten.
InputTypeThe type of the right-hand side input element. This element will be accessed read-only.
Valid descriptors
  1. grb::descriptors::no_operation for default behaviour.
  2. grb::descriptors::no_casting when a call to this function should not automatically cast input arguments to operator input domain, and not automatically cast operator output to the output argument domain.

If InputType does not match the right-hand side input domain (see grb::operators::internal::Operator::D2) corresponding to OP, then x will be temporarily cached and cast into D2. If IOType does not match the left-hand side input domain corresponding to OP, then y will be temporarily cached and cast into D1. If IOType does not match the output domain corresponding to OP, then the result of \( x \odot y \) will be temporarily cached before cast to IOType and written to y.

Parameters
[in,out]xOn function entry: the left-hand side input parameter. On function exit: the output of the operator.
[in]yThe right-hand side input parameter.
[in]opThe operator to apply (optional).
Returns
grb::SUCCESS A call to this function never fails.
Performance semantics.
  1. This call comprises \( \Theta(1) \) work. The constant factor depends on the cost of evaluating the operator.
  2. This call will not allocate any new dynamic memory.
  3. This call requires at most \( \mathit{sizeof}(D_1+D_2+D_3) \) bytes of temporary storage, plus any temporary requirements for evaluating op.
  4. This call incurs at most \( \mathit{sizeof}(D_1+D_2+D_3) + \mathit{sizeof}(\mathit{InputType}+2\mathit{IOType}) \) bytes of data movement, plus any data movement requirements for evaluating op.
Warning
The use of stateful operators, or even thus use of stateless operators that are not included in grb::operators, may cause this function to incur performance penalties beyond the worst case sketched above.
Note
For the standard stateless operators in grb::operators, there are no additional temporary storage requirements nor any additional data movement requirements than the ones mentioned above.
If OP is fold-left capable, the temporary storage and data movement requirements are less than reported above.
See also
foldr for a right-hand in-place version.
apply for an example of how to call this function without explicitly passing op.
grb::operators::internal Operator for a discussion on fold-right capable operators and on stateful operators.

◆ foldr()

static RC grb::foldr ( const InputType &  x,
IOType &  y,
const OP &  op = OP(),
const typename std::enable_if< grb::is_operator< OP >::value &&!grb::is_object< InputType >::value &&!grb::is_object< IOType >::value, void >::type *  = nullptr 
)
static

Application of the operator OP on two data elements.

The output data will overwrite the right-hand side input element.

In mathematical notation, this function calculates \( x \odot y \) and copies the result into y.

Template Parameters
descrThe descriptor passed to this operator.
OPThe type of the operator to apply.
InputTypeThe type of the left-hand side input element. This element will be accessed read-only.
IOTypeThe type of the right-hand side input element, which will be overwritten.
Valid descriptors
  1. grb::descriptors::no_operation for default behaviour.
  2. grb::descriptors::no_casting when a call to this function should not automatically cast input arguments to operator input domain, and not automatically cast operator output to the output argument domain.

If InputType does not match the left-hand side input domain (see grb::operators::internal::Operator::D1) corresponding to OP, then x will be temporarily cached and cast into D1. If IOType does not match the right-hand side input domain corresponding to OP, then y will be temporarily cached and cast into D2. If IOType does not match the output domain corresponding to OP, then the result of \( x \odot y \) will be temporarily cached before cast to IOType and written to y.

Parameters
[in]xThe left-hand side input parameter.
[in,out]yOn function entry: the right-hand side input parameter. On function exit: the output of the operator.
[in]opThe operator to apply (optional).
Returns
grb::SUCCESS A call to this function never fails.
Performance semantics.
  1. This call comprises \( \Theta(1) \) work. The constant factor depends on the cost of evaluating the operator.
  2. This call will not allocate any new dynamic memory.
  3. This call requires at most \( \mathit{sizeof}(D_1+D_2+D_3) \) bytes of temporary storage, plus any temporary requirements for evaluating op.
  4. This call incurs at most \( \mathit{sizeof}(D_1+D_2+D_3) + \mathit{sizeof}(\mathit{InputType}+2\mathit{IOType}) \) bytes of data movement, plus any data movement requirements for evaluating op.
Warning
The use of stateful operators, or even thus use of stateless operators that are not included in grb::operators, may cause this function to incur performance penalties beyond the worst case sketched above.
Note
For the standard stateless operators in grb::operators, there are no additional temporary storage requirements nor any additional data movement requirements than the ones mentioned above.
If OP is fold-right capable, the temporary storage and data movement requirements are less than reported above.
See also
foldl for a left-hand in-place version.
apply for an example of how to call this function without explicitly passing op.
grb::operators::internal Operator for a discussion on fold-right capable operators and on stateful operators.