vspline 1.1.0
Generic C++11 Code for Uniform B-Splines
grok.cc
Go to the documentation of this file.
1/************************************************************************/
2/* */
3/* vspline - a set of generic tools for creation and evaluation */
4/* of uniform b-splines */
5/* */
6/* Copyright 2017 - 2023 by Kay F. Jahnke */
7/* */
8/* Permission is hereby granted, free of charge, to any person */
9/* obtaining a copy of this software and associated documentation */
10/* files (the "Software"), to deal in the Software without */
11/* restriction, including without limitation the rights to use, */
12/* copy, modify, merge, publish, distribute, sublicense, and/or */
13/* sell copies of the Software, and to permit persons to whom the */
14/* Software is furnished to do so, subject to the following */
15/* conditions: */
16/* */
17/* The above copyright notice and this permission notice shall be */
18/* included in all copies or substantial portions of the */
19/* Software. */
20/* */
21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
23/* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
24/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
25/* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
26/* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
27/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
28/* OTHER DEALINGS IN THE SOFTWARE. */
29/* */
30/************************************************************************/
31
32/// \file grok.cc
33///
34/// \brief demonstrates use of vspline::grok_type
35///
36/// 'grokking' functors is an extremely useful concept. It's applying
37/// 'type erasure' to functors, so that the resulting functor - the
38/// 'grokked' functor - behaves just like the 'grokkee' but hides the
39/// 'grokkee's' type. So what's the point? In functional composition,
40/// you build functors by combining several sub-functors. With rising
41/// complexity of the costruct, the type becomes quite unmamageably
42/// verbose, and every composite functor is unique, so it has to be
43/// handled as a template argument. On the other hand, all you want
44/// from the combined functor is to perform it's function on it's
45/// argument(s), no matter what the internal workings are, and you
46/// want to be able to 'slot in' different functors. With type
47/// erasure, this becomes much more straightforward: after grokking,
48/// the resulting functor is of vspline::grok_type, hiding the inner
49/// workings, and all grok_type objects with the same argument
50/// signature have *the same type*, so 'slotting in' becomes easy
51/// and the types are manageable. Nevertheless, the optimizer can
52/// 'look into' a grok_type and optimize the construct as if you'd
53/// not grokked it. std::function does just that: the template
54/// argument you pass (or which is inferred by ATD) just
55/// specifies return type and argument types, and the resulting
56/// object hides the inner workings. vspline::grok_type does not
57/// just 'grok' a 'normal' function, but instead it 'groks' a
58/// vspline::unary_functor, an object with an 'eval' function
59/// with overloads for scalar and SIMD arguments. It does that
60/// by using two std::functions internally, but most of the time
61/// you can remain unaware of how it's done - you simply use the
62/// factory function vspline::grok() and store the result in an
63/// 'auto' variable.
64
65#include <iostream>
66#include <vspline/vspline.h>
67
68/// grokkee_type is a vspline::unary_functor returning twice it's input
69
70template < size_t vsize >
72: public vspline::unary_functor < double , double , vsize >
73{
74 template < typename IN , typename OUT >
75 void eval ( const IN & in , OUT & out ) const
76 {
77 std::cout << "call to grokkee_type::eval, in = " << in ;
78 out = in + in ;
79 std::cout << ", out = " << out << std::endl ;
80 }
81} ;
82
83/// 'regular' function template doing the same
84
85template < typename T >
86void twice ( const T & in , T & out )
87{
88 std::cout << "call to twice, in = " << in ;
89 out = in + in ;
90 std::cout << ", out = " << out << std::endl ;
91}
92
93/// test 'groks' a grokkee_type object 'grokkee' as a vspline::grok_type
94/// and calls the resulting object, which behaves just as a grokkee_type.
95
96template < size_t vsize >
97void test()
98{
99 std::cout << "testing grok_type with vsize " << vsize << std::endl ;
100
102
103 grokkee_type<vsize> grokkee ;
104
105 grok_t gk ( grokkee ) ;
106
107 double x = 1.0 ;
108
109 std::cout << x << std::endl << " -> " << gk ( x ) << std::endl ;
110
111 typedef typename grok_t::in_v argtype ;
112
113 argtype xx = 1.0 ;
114
115 std::cout << xx << std::endl << " -> " << gk ( xx ) << std::endl ;
116}
117
118int main ( int argc , char * argv[] )
119{
120 test<1>() ;
121 test<4>() ;
122 test<8>() ;
123
124 // with vsize == 1, we can construct a grok_type with a single
125 // std::function:
126
128
129 typedef gk1_t::eval_type ev_t ;
130 ev_t ev = & twice<double> ;
131
133 std::cout << "calling grok_type with vsize 1" << std::endl ;
134 gk1 ( 1.23 ) ;
135
136 // with vsize greater than 1, we may pass another std::function
137 // for vectorized evaluation. If we omit it, it will be generated
138 // automatically, but then it won't use vector code.
139
141
142 typedef gk8_t::v_eval_type v_ev_t ;
143 typedef gk8_t::in_v v8_t ;
144
145 v_ev_t vev = & twice<v8_t> ;
146
149
150 typedef typename vspline::grok_type < double , double , 8 > :: in_v v_t ;
151 std::cout << "calling grok_type using vector code" << std::endl ;
152 gk8a ( v_t ( 1.23 ) ) ;
153 std::cout << "calling grok_type using broadcasting" << std::endl ;
154 gk8b ( v_t ( 1.23 ) ) ;
155}
@ vsize
Definition: eval.cc:96
int main(int argc, char *argv[])
Definition: grok.cc:118
void test()
test 'groks' a grokkee_type object 'grokkee' as a vspline::grok_type and calls the resulting object,...
Definition: grok.cc:97
void twice(const T &in, T &out)
'regular' function template doing the same
Definition: grok.cc:86
grokkee_type is a vspline::unary_functor returning twice it's input
Definition: grok.cc:73
void eval(const IN &in, OUT &out) const
Definition: grok.cc:75
class grok_type is a helper class wrapping a vspline::unary_functor so that it's type becomes opaque ...
class unary_functor provides a functor object which offers a system of types for concrete unary funct...
includes all headers from vspline (most of them indirectly)