Graph Framework
Loading...
Searching...
No Matches
backend.hpp File Reference

Class signature to implement compute backends. More...

#include <algorithm>
#include <vector>
#include <cmath>
#include "special_functions.hpp"
#include "register.hpp"

Go to the source code of this file.

Classes

class  backend::buffer< T >
 Class representing a generic buffer. More...
 

Namespaces

namespace  backend
 Name space for backend buffers.
 

Macros

#define apply_op(op)
 Applies an operation over all elements in the buffer.
 
#define row_op(opp, oppeq)
 Applies an operator along a row.
 
#define col_op(opp, oppeq)
 Applies an operator along a column.
 
#define row_fn(fn)
 Applies a function along a row.
 
#define col_fn(fn)
 Applies a function along a column.
 
#define logic_is(op)
 Applies a logical is operator.
 
#define build_assoc_func(func)
 Applies an associative function.
 
#define build_assoc_op(op)
 Applies an associative operator.
 
#define build_non_assoc_op(op, opeq)
 Applies a non-associative operator.
 
#define build_assoc_func(func)
 Applies an associative function.
 
#define logic_op(op)
 Applies a logical operator.
 
#define branch_fn(fn)
 Applies a function with two operands.
 

Functions

template<jit::float_scalar T>
bool backend::operator== (const buffer< T > &a, const buffer< T > &b)
 Equal operation.
 
template<jit::float_scalar T>
buffer< T > backend::max (buffer< T > &a, buffer< T > &b)
 Max operation.
 
template<jit::float_scalar T>
buffer< T > backend::min (buffer< T > &a, buffer< T > &b)
 Min operation.
 
template<jit::float_scalar T>
buffer< T > backend::operator+ (buffer< T > &a, buffer< T > &b)
 Add operation.
 
template<jit::float_scalar T>
buffer< T > backend::operator- (buffer< T > &a, buffer< T > &b)
 Subtract operation.
 
template<jit::float_scalar T>
buffer< T > backend::operator* (buffer< T > &a, buffer< T > &b)
 Multiply operation.
 
template<jit::float_scalar T>
buffer< T > backend::operator/ (buffer< T > &a, buffer< T > &b)
 Divide operation.
 
template<std::floating_point T>
buffer< T > backend::hypot (buffer< T > &a, buffer< T > &b)
 hypot operation.
 
template<jit::float_scalar T>
buffer< T > backend::fma (buffer< T > &a, buffer< T > &b, buffer< T > &c)
 Fused multiply add operation.
 
template<std::floating_point T>
buffer< T > backend::operator% (buffer< T > &a, buffer< T > &b)
 Modulo operation.
 
template<jit::float_scalar T>
buffer< T > backend::operator== (buffer< T > &a, buffer< T > &b)
 Equal operation.
 
template<jit::float_scalar T>
buffer< T > backend::operator!= (buffer< T > &a, buffer< T > &b)
 Not equal operation.
 
template<std::floating_point T>
buffer< T > backend::operator> (buffer< T > &a, buffer< T > &b)
 Greater than operation.
 
template<std::floating_point T>
buffer< T > backend::operator< (buffer< T > &a, buffer< T > &b)
 Less than operation.
 
template<std::floating_point T>
buffer< T > backend::operator>= (buffer< T > &a, buffer< T > &b)
 Greater than equal operation.
 
template<std::floating_point T>
buffer< T > backend::operator<= (buffer< T > &a, buffer< T > &b)
 Less than equal operation.
 
template<std::floating_point T>
buffer< T > backend::operator&& (buffer< T > &a, buffer< T > &b)
 And operation.
 
template<std::floating_point T>
buffer< T > backend::operator|| (buffer< T > &a, buffer< T > &b)
 Or operation.
 
template<jit::float_scalar T>
buffer< T > backend::pow (buffer< T > &base, buffer< T > &exponent)
 Take the power.
 
template<jit::float_scalar T>
buffer< T > backend::atan (buffer< T > &x, buffer< T > &y)
 Take the inverse tangent.
 
template<std::floating_point T>
buffer< T > backend::copysign (buffer< T > &x, buffer< T > &y)
 Copy the sign of x and apply it to y.
 

Detailed Description

Class signature to implement compute backends.

Defined the function interfaces to access compute resources.

Macro Definition Documentation

◆ apply_op

#define apply_op (   op)
Value:
for (T &d : *this) { \
d = op(d); \
}

Applies an operation over all elements in the buffer.

Parameters
opThe operation to apply.

◆ branch_fn

#define branch_fn (   fn)
Value:
if (b.size() == 1) { \
const T right = b[0]; \
for (size_t i = 0, ie = a.size(); i < ie; i++) { \
a[i] = fn(a[i], right); \
} \
return a; \
} else if (a.size() == 1) { \
const T left = a[0]; \
for (size_t i = 0, ie = b.size(); i < ie; i++) { \
b[i] = fn(left, b[i]); \
} \
return b; \
} \
\
assert(a.size() == b.size() && \
"Left and right sizes are incompatible."); \
for (size_t i = 0, ie = a.size(); i < ie; i++) { \
a[i] = fn(a[i], b[i]); \
} \
return a;
constexpr T i
Convenience type for imaginary constant.
Definition node.hpp:1186

Applies a function with two operands.

Parameters
opThe operation to apply.

◆ build_assoc_func [1/2]

#define build_assoc_func (   func)
Value:
if (b.size() == 1) { \
const T right = b[0]; \
for (T &l : a) { \
l = func(std::real(l), \
std::real(right)); \
} \
return a; \
} else if (a.size() == 1) { \
const T left = a[0]; \
for (T &r : b) { \
r = func(std::real(r), \
std::real(left)); \
} \
return b; \
} \
\
assert(a.size() == b.size() && \
"Left and right sizes are incompatible."); \
for (size_t i = 0, ie = a.size(); i < ie; i++) { \
a[i] = func(std::real(a[i]), \
std::real(b[i])); \
} \
return a;

Applies an associative function.

Parameters
opThe operation to apply.
funcThe function to apply.

◆ build_assoc_func [2/2]

#define build_assoc_func (   func)
Value:
if (b.size() == 1) { \
const T right = b[0]; \
for (T &l : a) { \
l = func(l, right); \
} \
return a; \
} else if (a.size() == 1) { \
const T left = a[0]; \
for (T &r : b) { \
r = func(r, left); \
} \
return b; \
} \
\
assert(a.size() == b.size() && \
"Left and right sizes are incompatible."); \
for (size_t i = 0, ie = a.size(); i < ie; i++) { \
a[i] = func(a[i], b[i]); \
} \
return a;

Applies an associative function.

Parameters
opThe operation to apply.
funcThe function to apply.

◆ build_assoc_op

#define build_assoc_op (   op)
Value:
if (b.size() == 1) { \
const T right = b[0]; \
for (T &l : a) { \
l op right; \
} \
return a; \
} else if (a.size() == 1) { \
const T left = a[0]; \
for (T &r : b) { \
r op left; \
} \
return b; \
} \
\
assert(a.size() == b.size() && \
"Left and right sizes are incompatible."); \
for (size_t i = 0, ie = a.size(); i < ie; i++) { \
a[i] op b[i]; \
} \
return a;

Applies an associative operator.

Parameters
opThe operation to apply.

◆ build_non_assoc_op

#define build_non_assoc_op (   op,
  opeq 
)
Value:
if (b.size() == 1) { \
const T right = b[0]; \
for (T &l : a) { \
l opeq right; \
} \
return a; \
} else if (a.size() == 1) { \
const T left = a[0]; \
for (T &r : b) { \
r = left op r; \
} \
return b; \
} \
\
assert(a.size() == b.size() && \
"Left and right sizes are incompatible."); \
for (size_t i = 0, ie = a.size(); i < ie; i++) { \
a[i] opeq b[i]; \
} \
return a;

Applies a non-associative operator.

Parameters
opThe operation to apply.
opeqThe assign operation to apply.

◆ col_fn

#define col_fn (   fn)
Value:
if (size() > x.size()) { \
assert(size()%x.size() == 0 && \
"Vector operand size is not a multiple of matrix operand size"); \
\
const size_t num_columns = size()/x.size(); \
const size_t num_rows = x.size(); \
for (size_t i = 0; i < num_rows; i++) { \
for (size_t j = 0; j < num_columns; j++) { \
(*this)[i*num_columns + j] = fn((*this)[i*num_columns + j], x[j]); \
} \
} \
} else { \
assert(x.size()%size() == 0 && \
"Vector operand size is not a multiple of matrix operand size"); \
\
std::vector<T> m(x.size()); \
const size_t num_columns = x.size()/size(); \
const size_t num_rows = size(); \
for (size_t i = 0; i < num_rows; i++) { \
for (size_t j = 0; j < num_columns; j++) { \
m[i*num_columns + j] = fn((*this)[j], x[i*num_columns + j]); \
} \
} \
*this = m; \
}

Applies a function along a column.

Parameters
fnThe function to apply.

◆ col_op

#define col_op (   opp,
  oppeq 
)
Value:
if (size() > x.size()) { \
assert(size()%x.size() == 0 && \
"Vector operand size is not a multiple of matrix operand size"); \
\
const size_t num_columns = size()/x.size(); \
const size_t num_rows = x.size(); \
for (size_t i = 0; i < num_rows; i++) { \
for (size_t j = 0; j < num_columns; j++) { \
(*this)[i*num_columns + j] oppeq x[j]; \
} \
} \
} else { \
assert(x.size()%size() == 0 && \
"Vector operand size is not a multiple of matrix operand size"); \
\
std::vector<T> m(x.size()); \
const size_t num_columns = x.size()/size(); \
const size_t num_rows = size(); \
for (size_t i = 0; i < num_rows; i++) { \
for (size_t j = 0; j < num_columns; j++) { \
m[i*num_columns + j] = (*this)[j] opp x[i*num_columns + j]; \
} \
} \
*this = m; \
}

Applies an operator along a column.

Parameters
oppThe operation to apply.
oppeqThe assignment operator to apply.

◆ logic_is

#define logic_is (   op)
Value:
for (T &d : *this) { \
d = std::op(d); \
}

Applies a logical is operator.

Parameters
opThe operation to apply.

◆ logic_op

#define logic_op (   op)
Value:
if (b.size() == 1) { \
const T right = b[0]; \
for (size_t i = 0, ie = a.size(); i < ie; i++) { \
a[i] = static_cast<T> (a[i] op right); \
} \
return a; \
} else if (a.size() == 1) { \
const T left = a[0]; \
for (size_t i = 0, ie = b.size(); i < ie; i++) { \
b[i] = static_cast<T> (left op b[i]); \
} \
return b; \
} \
\
assert(a.size() == b.size() && \
"Left and right sizes are incompatible."); \
for (size_t i = 0, ie = a.size(); i < ie; i++) { \
a[i] = static_cast<T> (a[i] op b[i]); \
} \
return a;

Applies a logical operator.

Parameters
opThe operation to apply.

◆ row_fn

#define row_fn (   fn)
Value:
if (size() > x.size()) { \
assert(size()%x.size() == 0 && \
"Vector operand size is not a multiple of matrix operand size"); \
\
const size_t num_columns = size()/x.size(); \
const size_t num_rows = x.size(); \
for (size_t i = 0; i < num_rows; i++) { \
for (size_t j = 0; j < num_columns; j++) { \
(*this)[i*num_columns + j] = fn((*this)[i*num_columns + j], x[i]); \
} \
} \
} else { \
assert(x.size()%size() == 0 && \
"Vector operand size is not a multiple of matrix operand size"); \
\
std::vector<T> m(x.size()); \
const size_t num_columns = x.size()/size(); \
const size_t num_rows = size(); \
for (size_t i = 0; i < num_rows; i++) { \
for (size_t j = 0; j < num_columns; j++) { \
m[i*num_columns + j] = fn((*this)[i], x[i*num_columns + j]); \
} \
} \
*this = m; \
}

Applies a function along a row.

Parameters
fnThe function to apply.

◆ row_op

#define row_op (   opp,
  oppeq 
)
Value:
if (size() > x.size()) { \
assert(size()%x.size() == 0 && \
"Vector operand size is not a multiple of matrix operand size"); \
\
const size_t num_columns = size()/x.size(); \
const size_t num_rows = x.size(); \
for (size_t i = 0; i < num_rows; i++) { \
for (size_t j = 0; j < num_columns; j++) { \
(*this)[i*num_columns + j] oppeq x[i]; \
} \
} \
} else { \
assert(x.size()%size() == 0 && \
"Vector operand size is not a multiple of matrix operand size"); \
\
std::vector<T> m(x.size()); \
const size_t num_columns = x.size()/size(); \
const size_t num_rows = size(); \
for (size_t i = 0; i < num_rows; i++) { \
for (size_t j = 0; j < num_columns; j++) { \
m[i*num_columns + j] = (*this)[i] opp x[i*num_columns + j]; \
} \
} \
*this = m; \
}

Applies an operator along a row.

Parameters
oppThe operation to apply.
oppeqThe assignment operator to apply.