1 /* -*- c++ -*- */
2 /*
3  * Copyright 2011,2013 Free Software Foundation, Inc.
4  *
5  * This file is part of GNU Radio
6  *
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  *
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 #include "transcendental_impl.h"
24 #include <gnuradio/io_signature.h>
25 #include <cmath>   //real math
26 #include <complex> //complex math
27 #include <map>
28 #include <stdexcept>
29 
30 namespace gr {
31 namespace blocks {
32 
33 /***********************************************************************
34  * work function creation and registration
35  **********************************************************************/
36 struct map_val_type {
37     work_fcn_type work_fcn;
38     size_t io_size;
39 };
40 typedef std::map<std::string, map_val_type> map_type;
41 
42 // construct map on first use idiom
get_map(void)43 static map_type& get_map(void)
44 {
45     static map_type map;
46     return map;
47 }
48 
49 // static initialization of this object registers a function
50 struct transcendental_registrant {
transcendental_registrantgr::blocks::transcendental_registrant51     transcendental_registrant(const std::string& key,
52                               const work_fcn_type& work_fcn,
53                               const size_t io_size)
54     {
55         map_val_type val;
56         val.work_fcn = work_fcn;
57         val.io_size = io_size;
58         get_map()[key] = val;
59     }
60 };
61 
62 // macro to create a work function and register it
63 #define REGISTER_FUNCTION(__fcn__, __type__, __key__)                 \
64     static int __key__##_work(int noutput_items,                      \
65                               gr_vector_const_void_star& input_items, \
66                               gr_vector_void_star& output_items)      \
67     {                                                                 \
68         const __type__* in = (const __type__*)input_items[0];         \
69         __type__* out = (__type__*)output_items[0];                   \
70         for (size_t i = 0; i < size_t(noutput_items); i++) {          \
71             out[i] = std::__fcn__(in[i]);                             \
72         }                                                             \
73         return noutput_items;                                         \
74     }                                                                 \
75     transcendental_registrant __key__##_registrant(                   \
76         #__key__, &__key__##_work, sizeof(__type__));
77 
78 // register work functions for real types
79 #define REGISTER_REAL_FUNCTIONS(__fcn__)               \
80     REGISTER_FUNCTION(__fcn__, float, __fcn__##_float) \
81     REGISTER_FUNCTION(__fcn__, double, __fcn__##_double)
82 
83 // register work functions for complex types
84 #define REGISTER_COMPLEX_FUNCTIONS(__fcn__)                                  \
85     REGISTER_FUNCTION(__fcn__, std::complex<float>, __fcn__##_complex_float) \
86     REGISTER_FUNCTION(__fcn__, std::complex<double>, __fcn__##_complex_double)
87 
88 // register both complex and real
89 #define REGISTER_FUNCTIONS(__fcn__)  \
90     REGISTER_REAL_FUNCTIONS(__fcn__) \
91     REGISTER_COMPLEX_FUNCTIONS(__fcn__)
92 
93 // create and register transcendental work functions
94 REGISTER_FUNCTIONS(cos)
REGISTER_FUNCTIONS(sin)95 REGISTER_FUNCTIONS(sin)
96 REGISTER_FUNCTIONS(tan)
97 REGISTER_REAL_FUNCTIONS(acos)
98 REGISTER_REAL_FUNCTIONS(asin)
99 REGISTER_REAL_FUNCTIONS(atan)
100 REGISTER_FUNCTIONS(cosh)
101 REGISTER_FUNCTIONS(sinh)
102 REGISTER_FUNCTIONS(tanh)
103 REGISTER_FUNCTIONS(exp)
104 REGISTER_FUNCTIONS(log)
105 REGISTER_FUNCTIONS(log10)
106 REGISTER_FUNCTIONS(sqrt)
107 
108 
109 transcendental::sptr transcendental::make(const std::string& name,
110                                           const std::string& type)
111 {
112     // search for an entry in the map
113     const std::string key = name + "_" + type;
114     const bool has_key = get_map().count(key) != 0;
115     if (!has_key)
116         throw std::runtime_error("could not find transcendental function for " + key);
117 
118     // make a new block with found work function
119     return gnuradio::get_initial_sptr(
120         new transcendental_impl(get_map()[key].work_fcn, get_map()[key].io_size));
121 }
122 
transcendental_impl(const work_fcn_type & work_fcn,const size_t io_size)123 transcendental_impl::transcendental_impl(const work_fcn_type& work_fcn,
124                                          const size_t io_size)
125     : sync_block("transcendental",
126                  io_signature::make(1, 1, io_size),
127                  io_signature::make(1, 1, io_size)),
128       _work_fcn(work_fcn)
129 {
130     // NOP
131 }
132 
~transcendental_impl()133 transcendental_impl::~transcendental_impl() {}
134 
work(int noutput_items,gr_vector_const_void_star & input_items,gr_vector_void_star & output_items)135 int transcendental_impl::work(int noutput_items,
136                               gr_vector_const_void_star& input_items,
137                               gr_vector_void_star& output_items)
138 {
139     return _work_fcn(noutput_items, input_items, output_items);
140 }
141 
142 } /* namespace blocks */
143 } /* namespace gr */
144