samng Posted September 2, 2013 Report Posted September 2, 2013 Hi sc_fixed type looks ahead to the type of the destination variable to pick the right action for quatisation and overflow handling: sc_fixed<6,6> a = 13; sc_fixed<5,5,SC_RND> b = a>>1; a become 7. But using sc_fixed in a template class like: template <class T, int N> class Vector { T m_array[N]; Vector operator>> (const unisgned int m) const { Vector tmp; for (int i=0; i<N; i++) tmp.m_array = m_array>>m; } }; ..... Vector <sc_fixed<6,6>,1 > a; Vector <sc_fixed<5,5,SC_RND>,1 > b = a >> 1; a[0] is now 6 not 7, because the return type of operator >> is still Vector<sc_fixed<6,6>,1 >. Is there anyway to write the template class/operator that can see the type of b so that sc_fixed rounding behaviour can preserved? Thanks Sam Quote
Philipp A Hartmann Posted September 2, 2013 Report Posted September 2, 2013 Sam, sc_fixed type looks ahead to the type of the destination variable to pick the right action for quatisation and overflow handling: That's not fully correct. In C++, you can't (directly) consider the return-type of a function (e.g: for overloading) to adapt the behaviour. You need to resort to intermediate values instead. In case of sc_fix(ed)/sc_fxnum, this intermediate value is sc_fxval, a variable-precision fixed-point value. Objects of this type always carry the required amount of bits during run-time and the assignment to another finite-precision type (sc_fxnum et.al.) handles the quantisation and overflow. Is there anyway to write the template class/operator that can see the type of b so that sc_fixed rounding behaviour can preserved? AFAICS, you want to build a container class template for arithmetic types that provides element-wise operators. In order to deal with such intermediate values, there are several options depending on the level of generality you need to achieve and the constraints on the C++ language features, you can rely on. Disclaimer: The following snippets are fully untested. Simplest solution: Return a Vector<sc_fxval> instead (and provide an appropriate assignment operator/conversion constructor): Vector<sc_fxval,N> operator>> (unsigned m) const { Vector<sc_fxval,N> tmp; for (int i=0; i<N; i++) tmp.m_array[i] = m_array[i]>>m; return tmp; } Of course, this will limit the use of this shift operator in your Vector template to classes, where the result of the shift operator on the elements can be reasonably converted to sc_fxval. As a second option, you can use C++11's decltype and new function declaration syntax: auto operator>> (unsigned m) const -> Vector< decltype(T() >> m), N > { typedef decltype( T() >> m ) return_type; Vector<return_type,N> tmp; for (int i=0; i<N; i++) tmp.m_array[i] = m_array[i]>>m; return tmp; } This should work correctly for arbitrary shift operators and return an array of shift results.Since your compiler may not support these shiny new features of C++11, you can use a traits class with (partial) specialisation: template< typename T > struct vector_element_traits; // partial specialisation for sc_fixed template< int WordLength, int IntegerWordLength, sc_o_mode Overflow, sc_q_mode Quantization > struct vector_element_traits< sc_fixed<WordLength, IntegerWordLength, Overflow, Quantization > > { typedef sc_fxval right_shift_result; }; // ... Vector<typename vector_element_traits<T>::right_shift_result,N> operator>> (unsigned m) const { Vector<typename vector_element_traits<T>::right_shift_result,N> > tmp; for (int i=0; i<N; i++) tmp.m_array[i] = m_array[i]>>m; return tmp; } Last but not least, you can defer the evaluation of the element-wise operator by using expression templates to the implementation of the assignment operator of the vector. But this may be a bit too advanced for tonight. ;-) Greetings from Oldenburg, Philipp maehne and apfitch 2 Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.