Friday, March 11, 2016

Digest for comp.lang.c++@googlegroups.com - 10 updates in 3 topics

Paul <pepstein5@gmail.com>: Mar 11 03:56AM -0800

Suppose I want to sort a vector in reverse order, using std::greater. I use decltype because I don't want to explicitly state the type but I want to select the type of the first element.
 
The code snippet is below:
 
std::vector<int> v{1};
std::sort(v.begin(), v.end(), std::greater<decltype(v[0])>());
 
Why does this fail to compile? If v[0] is replaced by 5, it does compile. My thinking is that decltype(v[0]) means same type as v[0] which means same type as 1 which is int and that therefore std::sort(v.begin(),v.end(), std::greater<int>()); should be executed.
 
Where am I going wrong? What should be done in practice if the type of v[0] is not simply int but a very complex type, and I want to avoid repeating the name of the type? I suppose typedef is the solution, but I thought decltype was used to solve this type of problem, too.
 
Many thanks for your help.
 
Paul
Victor Bazarov <v.bazarov@comcast.invalid>: Mar 11 07:37AM -0500

On 3/11/2016 6:56 AM, Paul wrote:
 
> Why does this fail to compile? If v[0] is replaced by 5, it does compile. My thinking is that decltype(v[0]) means same type as v[0] which means same type as 1 which is int and that therefore std::sort(v.begin(),v.end(), std::greater<int>()); should be executed.
 
> Where am I going wrong? What should be done in practice if the type of v[0] is not simply int but a very complex type, and I want to avoid repeating the name of the type? I suppose typedef is the solution, but I thought decltype was used to solve this type of problem, too.
 
> Many thanks for your help.
 
It's possible that v[0] gives you not 'int', but 'int&', I'm too lazy to
check now. If you wanted to use 'v' and 'decltype' to supply 'int' to
instantiate 'greater', you could try
 
... std::greater<decltype(v)::value_type> ...
 
V
--
I do not respond to top-posted replies, please don't ask
Paul <pepstein5@gmail.com>: Mar 11 05:18AM -0800

On Friday, March 11, 2016 at 12:37:49 PM UTC, Victor Bazarov wrote:
> check now. If you wanted to use 'v' and 'decltype' to supply 'int' to
> instantiate 'greater', you could try
 
> ... std::greater<decltype(v)::value_type> ...
 
Yes, this works. Thanks.
 
Paul
Juha Nieminen <nospam@thanks.invalid>: Mar 11 07:31PM

> std::vector<int> v{1};
> std::sort(v.begin(), v.end(), std::greater<decltype(v[0])>());
 
I haven't tried, but this probably works:
 
std::greater<std::remove_reference_t<decltype(v[0])>>
 
Of course this is becoming needlessly verbose. Just use the vector's
value_type.
 
--- news://freenews.netfront.net/ - complaints: news@netfront.net ---
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Mar 11 11:00PM +0100

On 11.03.2016 12:56, Paul wrote:
 
> std::vector<int> v{1}; std::sort(v.begin(), v.end(),
> std::greater<decltype(v[0])>());
 
> Why does this fail to compile?
 
Sounds like a reference to me.
 
Why not try
 
decltype( +v[0] )
 
Disclaimer: I have not checked that.
 
Also there was something about double parenthesis.
 
They crammed too much into one thing, old g++ typeof was more practical.
 
 
Cheers!,
 
- Alf
woodbrian77@gmail.com: Mar 11 03:09PM -0800

On Friday, March 11, 2016 at 4:01:17 PM UTC-6, Alf P. Steinbach wrote:
 
> Sounds like a reference to me.
 
> Why not try
 
> decltype( +v[0] )
 
I think Victor's solution is clearer.
 
The syntax you suggest reminds me of Perl - cryptic.
 
Brian
Ebenezer Enterprises - If you can't join 'em, beat 'em.
http://webEbenezer.net
bitrex <bitrex@de.lete.earthlink.net>: Mar 11 11:49AM -0500

On 03/06/2016 09:25 AM, Alf P. Steinbach wrote:
> which gives O(f) ~= 2^n, which is rather ungood. Compared to O(n) for
> iterative, or (but lacking the precision implied by bignum ints) O(1)
> for using the golden ratio formula to compute the numbers directly.
 
The recursive Fibonacci algorithm's big O behavior is essentially due to
its shameless breaking of the first rule of algorithm design: never do
the same work twice.
bitrex <bitrex@de.lete.earthlink.net>: Mar 10 07:53PM -0500

Forgive me, my code-fu is a little rusty.
 
The ARM Cortex M4 (Teensy audio library) I'm writing some C++ code for
(for a personal project, I'm definitely not like, a professional) has a
simple fixed point math library the author put together. I can't seem to
find any references in the API to fixed point _unsigned_ multiply, however.
 
I have an unsigned 16 bit fractional part number (Q15?) in a uint16_t,
and I need to multiply another uint16_t with no fractional part by this
to scale it.
 
Apparently what I have available is a routine that multiples an int32_t
by an int16_t and stuffs the result in an int32_t. IIRC I should be able
to just treat the uint16_t as an int16_t and with twos complement it
should work out OK, right?
 
What would be the appropriate way to achieve what I need with what I have?
David Brown <david.brown@hesbynett.no>: Mar 11 09:25AM +0100

On 11/03/16 01:53, bitrex wrote:
> by an int16_t and stuffs the result in an int32_t. IIRC I should be able
> to just treat the uint16_t as an int16_t and with twos complement it
> should work out OK, right?
 
In practice that will probably work, but in theory it will not. In C,
signed and unsigned types have different overflow characteristics. It
is possible that you will hit undefined behaviour due to overflows for
some values. The compiler will probably generate code that will work as
expected anyway (since the cpu uses two's complement even though C does
not), but you should try to avoid the risk - weird things can happen if
the compiler uses inlining and constant propagation to pre-calculate
results.
 
> What would be the appropriate way to achieve what I need with what I have?
 
First, make sure you cast your operands to "unsigned int" before doing
the multiplication. That makes sure everything stays unsigned, there
are no overflows, and no risks of undefined behaviour. It is the
compiler's job to spot that it can do everything using using 16-bit
arithmetic instructions - your job is to make sure the C code is correct.
 
Secondly, you probably want saturation on overflow, rather than simply
taking the lowest 16 bits. If you multiply 0.25 (0x4000) by 5 (0x0005)
you want the result to be 0.999984741 (0xffff), not 0.25 (after
truncating 0x14000 to 0x4000).
 
uint16_t multQ_U(uint16_t q, uint16_t u) {
uint32_t x = (uint32_t) u * (uint32_t) q;
if (x <= 0xffff) return (uint16_t) x;
return 0xffff;
}
 
(That's for a UQ16, unsigned 16-bit format. If you have a 15-bit
unsigned format, the saturation will be at 0x7fff.)
 
An alternative option is to use <stdfix.h> and types such as "unsigned
fract". This lets the compiler do the work of getting the code correct,
but the resulting code can often be sub-optimal. In my quick tests, ARM
gcc 4.8 did a good job of some things like multiplying two "fract"
types, but quickly resorts to library calls for many other combinations.
It is also not supported in C++.
bitrex <bitrex@de.lete.earthlink.net>: Mar 11 08:40AM -0500

On 03/11/2016 03:25 AM, David Brown wrote:
> gcc 4.8 did a good job of some things like multiplying two "fract"
> types, but quickly resorts to library calls for many other combinations.
> It is also not supported in C++.
 
Thanks so much! This is an enormous help.
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: