-
Notifications
You must be signed in to change notification settings - Fork 5
ublas::apply Examples
-
Expression is any tensor-expression whose all terminal/leaf nodes are either tensors, vectors, or matrices. An attempt to put anything apart from these will likely fail a
static_assert
. -
Callable is callable(s) like
lambda
orstd::function
. Each callable must take only one argument by constant reference and return non-void type. Failing which raises astatic_assert
.
-
Implementing lazy casts We do not provide any such functionality but it would be nice and easy to implement using this utility. Consider this example :
auto expr = int_tensor1 + int_tensor2; auto lazy_cast = ublas::apply(expr, [](auto const & e){ return static_cast<char>(e); }); auto result = lazy_cast.eval(); // Okay result is a tensor of chars
-
Implementing Special Lazy Functions You can implement many great functions lazily using this utility. Consider this example :
auto expr = int_tensor1 + int_tensor2; auto lazy_sqrt = ublas::apply(expr, [](auto const & e){ return sqrt(e); }); auto result = lazy_sqrt.eval(); // Okay result is sqrt(tensor1 + tensor2); static_assert(std::is_same_v<typename result::value_type, double>); // Okay Passes, sqrt returns double.
-
Implementing Lazy Masking We have no such operator as masking or cliping tensors by values. It can be done in a efficient lazy way by this utility. Consider this Example :
auto tensor1 = tensor<int>{shape{50,50}, data}; // assume data is std::vector<int> of size 50*50; auto expr = ublas::apply(tensor1, [](auto const &e){ return e*(e > 45); }); // Sets a tensor element to 0 if its values is less than 45, otherwise no change. // This operator is sometimes called clipping / masking by value. tensor<int> ans{shape{50,50}}; expr.eval_to(ans); // ans now contains the results.
-
Cascaded Calls The callable to the utility can be cascaded in which case they are called one after the other. Consider this example where we take mod of real component of an imaginary tensor.
auto ten1 = tensor<std::complex<float>>{shape{5,6}}; auto expr = ublas::apply(ten1, [](auto const &e){ return std::real(e); }, [](auto const &e){ return abs(e); }); auto ans = expr.eval();
-
**SO MANY MORE, YOU DO IT AS YOU PLEASE **
The callable passed to the utility must be a valid and non-overloaded callable, it is because we store your callable as function pointer directly. Moreover when you pass any such callable the compiler will complain as to which overload to pass into the utility.
Consider this bad example :
auto expr = ublas::apply(old_expr, std::sqrt);
// Error : Which std::srqt()? It is overloaded
If you want to pass function and do not prefer the generic lambda syntax (recommended). Please consider wrapping your function into something that isn't overloaded.
Consider this example :
double my_sqrt(const int & ref){
return std::sqrt(ref);
}
// Wrapped the function into something non-overloaded
auto expr = ublas::apply(old_expr, my_sqrt);
// Okay, we know this my_sqrt
We both would like to thank our mentor Cem for his constant support and help in achieving our goals. We always find him helpful and he was always easy to reach for help or discussion regarding the work. We would also like to thank Google for the Google Summer of Code Programme, without which all these wouldn't be possible. Lastly, we express our gratitude to our parents for helping and providing us with all the indirect or direct needs for carrying out our work nicely in our homes.
- Home
- Project Proposal
- Milestones and Tasks
- Implementation
- Documentation
- Discussions
- Examples
- Experimental features
- Project Proposal
- Milestones and Tasks
- Implementation
- Documentation
- Discussions
- Example Code