On 05/11/11 21:43, Gabriel Dos Reis wrote:
On Sat, Nov 5, 2011 at 2:30 PM, David Brown
A C++ template class for "_Fract" support would be straightforward to write,
and could easily support the formats in N1169. But it would be very hard to
do so in a way that generates small and fast code without resorting to
inline assembly for targets that have hardware support for such features.
is this some sort of "here an outlanding statement and you would
have to prove a negative to prove me right" or do you have more
factual evidence to back your statement?
It is an estimation.
Some processors have particular instructions or mode flag settings that
let them handle fixed point data very efficiently, such as by doing
multiplication and shift at the same time, handling saturated
arithmetic, or using special "accumulator" registers for particular
features.
It is certainly /conceivable/ that gcc will generate such instructions
automatically, but I would be very surprised - and extremely impressed.
Take an example using a processor I know well, the AVR (it is an 8-bit
device, which is a little unusual for gcc). It has an instruction will
multiply two "1.7" signed 8-bit integers to get a single 1.15 signed
16-bit integer - basically combining an 8-bit x 8-bit to 16-bit multiply
with a left shift. So to do a "signed short _Fract" multiply, you have
a single instruction and discard the least significant byte.
Simulating the same operation in generic C would be something like :
int8_t multShortFract(int8_t a, int8_t b) {
int16_t c = (int16_t) a * b;
return (c >> 7);
}
Now, I have enormous respect for the gcc (and related libraries and
tools) developers, and I am regularly surprised by how smart the
compiler is. But using such features of the target requires specific code.
The advantage of using C's "signed short _Fract" here is that gcc /will/
use the optimal instruction in such cases (assuming, of course, that
support is added for the target in question). If it doesn't have such
support, it can do the calculation using something similar to the C
above - slower but correct.
As you say, it is possible that both could be supported - using a template
class to provide a generic solution, and using the C "_Fract" types for
specialized classes. The first step to that, however, is to allow the
standard C "_Fract" types to work in C++ as a gcc extension.
The same principle applies to the decimal types and extended float types
supported by C.
that is one possibility. However there is a difference between
restricted "extension" and full fledged extensions. I can see
how a restricted version would work in C++ as an extension, but
I doubt that is what you want. I can also see how unrestricted
extension (which you seemed to advocate) brings more headache
where a library solution is seamless.
I am not sure what you mean by a "restricted extension" and a "full
fledged extension". But I do appreciate that extensions cause issues
that libraries do not.
Keeping adding builtin type specifiers to a language is not a
sustainable and responsible way to grow a large language
for the real world. I appreciate we may disagree on that point.
It is always difficult for people to see all aspects of something like
this - and it is important to do so when figuring out what to implement.
That's what discussions like this are for!
Let me try to put forward the viewpoint of the embedded programmer,
since these are the people who would use such features. I fully
appreciate that other people see things differently, and that there are
often good reasons for doing something that seems wrong from my
viewpoint. And I also fully appreciate there is a very big difference
between agreeing that something is the best solution, and actual
implementation.
In embedded systems, C is often used for smaller systems, with bigger
systems using C++. There are also people who use C for big systems, and
those that use C++ for small systems. And lots of code is a mixture.
The key issue is that it is, quite frankly, a pain in the a** that C++
is not closer to a superset of C. Originally, C++ was a superset -
excluding a few points that can easily be avoided in well-written code.
These days, the two language standards have moved gradually further
away from each other. Obviously C++ is going to get features that C
does not - that's fair enough. But it is seldom that there is a good
reason for C++ not supporting the additions to C standards.
Some of the differences are just mind-boggling - C1x has got a
"_Static_assert" addition, while C++11 has "static_assert". They do the
same thing, but have a different keyword. Don't these people /talk/ to
each other? Do they make differences like this deliberately to annoy
people - both users and toolwriters?
gcc has always countered that to some extend, by allowing additional C
features to be used in C++. But even there there are limitations -
there are plenty of gcc extensions to C that are very useful, and for
some reason only work in C and not C++.
As a programmer, when I write portable code in C I want it to be valid
C++ as well. This gives the most flexibility, and the most efficient
use of my code. I don't want to have to re-write code to do the same
thing in each language, or to re-learn the differences.
So to make "_Fract" and "_Accum" really useful, I need to be able to use
it in C and C++ code, and know that the types are compatible across the
two languages, and that the generated code will be equally efficient.
Frankly, as a user I don't really care whether it is implemented by a
C++ library, a gcc extension, mind-numbing macros, or whatever. It is
absolutely fine if the details are hidden within a "stdfix.h" header
file. But what I /don't/ want to end up with is a type called "signed
short _Fract" in C and "_fract<8>" in C++, or being unable to pass data
between the languages, or having to have C++ call external C functions
just to get efficient implementations.
Sorry for the rant - it is not aimed at you or anyone involved in gcc,
David