Please read without prejudice!
What would you think of the following: we all know about various bitsizes Integer and Cardinal types.
What I've seen was a "customized" real type. Imagine you have to store lots of data for GSM-encoding, or some similar measurement purpose. Lots of bits are wasted, as they don't correspond to accurate digits of measurement. I.e. on a weather station that has only an occassional link to a satellite.
For example, let's suppose we have lots of data that that we could express as reals in 16-bit precision, and all fit between -0.5 and 0.5 (for example, but standard can be defined in different way):
type MyReal = Real attribute (Exponent = 0, Mantissa = 16);
GSMReal = Real attribute (Exponent = 8, Mantissa = 8);
The latter could represent a number with same range like IEEE single precision float, just with only 2 accurate digits.
or even
TEMPReal = Real attribute (ExponentRange = 0..15, Mantisa = 4);
for keeping the temperature in one byte from range of 0.0625 K to 30720 K (where precision is not that much important as the value on the logarithmic scale ...)
The compiler could use hardware floating point when it's faster than emulation with less bits of precision, then round/truncate when storing back into memory/variable.
This is just a tip, not a real syntax or semantics proposal.
Mirsad
Mirsad Todorovac wrote:
Please read without prejudice!
What would you think of the following: we all know about various bitsizes Integer and Cardinal types.
What I've seen was a "customized" real type. Imagine you have to store lots of data for GSM-encoding, or some similar measurement purpose. Lots of bits are wasted, as they don't correspond to accurate digits of measurement. I.e. on a weather station that has only an occassional link to a satellite.
For example, let's suppose we have lots of data that that we could express as reals in 16-bit precision, and all fit between -0.5 and 0.5 (for example, but standard can be defined in different way):
type MyReal = Real attribute (Exponent = 0, Mantissa = 16);
GSMReal = Real attribute (Exponent = 8, Mantissa = 8);
The latter could represent a number with same range like IEEE single precision float, just with only 2 accurate digits.
or even TEMPReal = Real attribute (ExponentRange = 0..15, Mantisa = 4);
for keeping the temperature in one byte from range of 0.0625 K to 30720 K (where precision is not that much important as the value on the logarithmic scale ...)
The compiler could use hardware floating point when it's faster than emulation with less bits of precision, then round/truncate when storing back into memory/variable.
This is just a tip, not a real syntax or semantics proposal.
Something like this was suggested, referring to the Fortran feature `SELECTED_REAL_KIND'. I don't know Fortran, though, so I don't know exactly how it works.
Anyway, as you're certainly aware, the main problem is to implement all this (whereas the syntax, e.g. as using attributes, should be no big problem). Basically, you need a complete software floating point emulation with arbitrary precision/range of which parts have to be in the compiler, other parts can be done in the RTS, and the interfaces between them have to be defined and implemented.
Then don't underestimate the (implicit, I suppose) conversions required between those and standard real types (and even from integer). If I think of the plans for various string types, that's a main issue there.
This also raises the issue how to handle real constants. To avoid loss of precision, they might have to be kept in such a format in the compiler (which means that you need two versions of this emulation, one at compile-time, one at run-time).
The same is true if you want compile-time optimizations, but they will probably require even more work since the existing optimizations for real types will probably have to be copied or in part rewritten for the new types.
If you want to handle them in I/O, you also need a new mechanism(*).
Now, an alternative would be to use GMP types. They're a little different since they can determine the precision at runtime. This is more flexible, but requires dynamic memory allocation, which is also more overhead (so they're suitable when you need big precision, not for those examples above where you want reduced precision and storage requirements).
Another disadvantage of them is that they require routine calls. It is possible to wrap some of them into user-defined operators, but it only goes so far. I did that in http://gnu-pascal.de/contrib/frank/gmpop.inc, but it has some limitations. (There's a longish comment in the file that describes the details.) The main problem is that they need explicit initialization and finalization routine calls, and GPC doesn't yet support those. (It's a planned feature, but especially for finalizers not exactly trivial, but I may do it sometime ...)
Another idea, for your first example, would be to use a fixed-point representation (indeed, I'd recommend that since it would probably be the cheapest (at runtime) solution). Just use a 16 bit integer and do the operations on it with appropriate scaling.
In fact, you can also use operators for this (their implementation is mostly as boring as in gmpop.inc, but without the problems of initialization/finalization). If you wrap the integer in a record (or an array of size 1), you can prevent it from being accidentally used as an integer value. This way, I think, only conversions from integer or real to the fixed point type will need an explicit function call, and I/O needs to be dealt with(*), anything else (including comparisons) will work with operators.
Of course, something like this can also be done with any user-space implemented floating point emulation (perhaps using schemata for the varying exponent/mantissa size, though you have the overhead of the discriminants being stored in the schemata). It might be interesting to see how far one gets this way. One limitation will, also here, be the lack of automatic conversions. (This refers to the recent discussion of "type-cast" operators or something like this which is another can of worms I think ...)
(*) There was another idea to allow for user-defined I/O operators for arbitrary types, something like this:
operator Write (var f: Text; a: MyType); [...]
Which would allow:
var Foo: MyType;
begin WriteLn ('Hello ', Foo, 42) end.
This might actually not be too difficult to implement ...
Bottom line: I think the suggested feature would be a *major* effort to implement. I'm not sure if we should add it to the compiler (it's already so complex) if a user-space solution, even perhaps with some small drawbacks, is possible ...
Frank
A 15:36 01/07/03 +0200, Mirsad Todorovac a écrit :
Please read without prejudice!
What would you think of the following: we all know about various bitsizes Integer and Cardinal types.
What I've seen was a "customized" real type. Imagine you have to store lots of data for GSM-encoding, or some similar measurement purpose. Lots of bits are wasted, as they don't correspond to accurate digits of measurement. I.e. on a weather station that has only an occassional link to a satellite.
For example, let's suppose we have lots of data that that we could express as reals in 16-bit precision, and all fit between -0.5 and 0.5 (for example, but standard can be defined in different way):
type MyReal = Real attribute (Exponent = 0, Mantissa = 16);
GSMReal = Real attribute (Exponent = 8, Mantissa = 8);
The latter could represent a number with same range like IEEE single precision float, just with only 2 accurate digits.
or even TEMPReal = Real attribute (ExponentRange = 0..15, Mantisa = 4);
for keeping the temperature in one byte from range of 0.0625 K to 30720 K (where precision is not that much important as the value on the logarithmic scale ...)
The compiler could use hardware floating point when it's faster than emulation with less bits of precision, then round/truncate when storing back into memory/variable.
This is just a tip, not a real syntax or semantics proposal.
This would be very much hardware-dependant.
Almost the same result can be obtained in practice with two assembly-level conversion function, one from private format to ordinary single precision real, the other for conversion in the other way. Jean-Pierre Vial
On Tue, 1 Jul 2003, Jean-Pierre Vial wrote:
A 15:36 01/07/03 +0200, Mirsad Todorovac a écrit :
Please read without prejudice!
What would you think of the following: we all know about various bitsizes Integer and Cardinal types.
[ snip ]
In the meanwhile gcc-3.3.1 is due out in a few days; there's enough stuff on the "to do" lists to keep Frank busy for the next six months. Unless it's really important I'd like to suggest not adding any new features to the "to do" list for a while.
my 2 cents, Russ
On Tue, 1 Jul 2003, Russell Whitaker wrote:
On Tue, 1 Jul 2003, Jean-Pierre Vial wrote:
A 15:36 01/07/03 +0200, Mirsad Todorovac a écrit :
Please read without prejudice!
What would you think of the following: we all know about various bitsizes Integer and Cardinal types.
[ snip ]
In the meanwhile gcc-3.3.1 is due out in a few days; there's enough stuff on the "to do" lists to keep Frank busy for the next six months. Unless it's really important I'd like to suggest not adding any new features to the "to do" list for a while.
my 2 cents, Russ
Thanks, Russ, for mentioning this. (I hope gcc-3.3's DFA scheduler will improve code optimization, if nothing else, so it'll be worthwhile to adapt GPC to work with it ...)
Anyway, I propose we put thing of this sort on a WISH-LIST, w priorities, so we'd don't forget about it and propose it again.
IMHO this parametrized reals might be a good idea, yet GPC should worry only about loads from/stores into Reals with this new precision, all arithmetic would inevitably have to be done in standard single/double/long double floats, since back-end is simply not ready for Reals of this type at present, and may even never be.
The latter means GPC would be heavied with tons of possibly obfuscated code.
Being able to store Reals in space-saving format when excess precision is not needed wouldn't hurt OTOH, and I propose we put this on not TO-DO, but on the WISH-LIST.
(* IMHO GCC back-end is fundamentally behind some already marketed processors on having 128-bit or even 256-bit Integers, Cardinals or Reals. *)
My $0.02 :-)
Mirsad
Mirsad Todorovac wrote:
Anyway, I propose we put thing of this sort on a WISH-LIST, w priorities, so we'd don't forget about it and propose it again.
Many items on the to-do list are "wishes", and the mentioned `SELECTED_REAL_KIND' is already there. (Though it may refer to a feature to choose between the available standard real types according to some parameters -- as I said, I don't know it exactly.)
But while we're at it, we might as well think about if, how, and how far something can/should be implemented at all before we put it on the list, so the wish list remains (or perhaps gets ;-) a little more realistic.
IMHO this parametrized reals might be a good idea, yet GPC should worry only about loads from/stores into Reals with this new precision, all arithmetic would inevitably have to be done in standard single/double/long double floats,
This would simplify things quite a bit, but it would leave it somewhat unclear (to the programmer) how much of the declared precision is actually used. (Naively, when declaring a real with a precision of 256 bits, I'd expect it to have that precision, not artihmetic done with 64 or so bits of precision.)
Also, I more and more tend to "do it in Pascal code" whenever it has no big disadvantages. So my questions are:
- Do you really see the need for such *parametrized* types? (As opposed to a few particular types for specific needs, such as your GSM example. Those could be implemented individually, though with a bit of code duplication, but also probably more efficiently, since dealing with fixed sizes of exponent and mantissa should make for faster code than variable sizes.)
- How big are the disadvantages of a Pascal-based solution really? As I said in my previous mail, it might not be more than explicit conversions in assignments. If that's really all, I'm not convinced that the extra effort in the compiler is worth it.
In fact, I might rather consider such "type-cast" operators as mentioned. They would be a more general concept, and perhaps even easier to implement (since the actual conversions can be kept to Pascal code this way).
If we agree on this, I'd rather only put the more general solution on the to-do list (which happens to be there already), so perhaps future contributors who read the list won't waste their time on a feature that was already rejected.
So in fact I suggest you try to write a Pascal unit for such a type that you see a need for, with all those operators etc., and find out what can't be done currently.
Frank
On Wed, Jul 02, 2003 at 10:14:22PM +0200, Frank Heckenbach wrote:
Mirsad Todorovac wrote:
Anyway, I propose we put thing of this sort on a WISH-LIST, w priorities, so we'd don't forget about it and propose it again.
Many items on the to-do list are "wishes", and the mentioned `SELECTED_REAL_KIND' is already there. (Though it may refer to a feature to choose between the available standard real types according to some parameters -- as I said, I don't know it exactly.)
I don't know much about Fortran either, but I'm afraid that "KIND" has the meaning you put in parenthesis, not a handcrafted user-defined type. See `info g77', for example.
Emil
On Thu, 3 Jul 2003, Emil Jerabek wrote:
On Wed, Jul 02, 2003 at 10:14:22PM +0200, Frank Heckenbach wrote:
Mirsad Todorovac wrote:
Anyway, I propose we put thing of this sort on a WISH-LIST, w priorities, so we'd don't forget about it and propose it again.
Many items on the to-do list are "wishes", and the mentioned `SELECTED_REAL_KIND' is already there. (Though it may refer to a feature to choose between the available standard real types according to some parameters -- as I said, I don't know it exactly.)
I don't know much about Fortran either, but I'm afraid that "KIND" has the meaning you put in parenthesis, not a handcrafted user-defined type. See `info g77', for example.
Err, well, it's not a "handcrafted user-defined" type, it's actually meant to be IEEE-form floating point number, it's just that exponent and mantissa size is customizable.
I.e. like Integer attribute (Size = 42), likewise you'd have Real (ExponentSize = 22, MantissaSize = 42), depending on the fact you need more in maximum range, or more in maximum precision to be stored in variable ...
When possible, arithmetic would be done in hardware precision, if that is greater or equal than type's own precision, otherwise it would be done by emulation. This is inefficient to select at runtime, or have both types of code; hence the idea that compiler is armed itself with it -- just like it can do Integer attribute (Size = 1..64).
We might chose to limit ExponentSize and MantissaSize attributes for Real just like Size attribute is limited for Integer, Word and Cardinal to maximum that harware can accomplish.
In Pascal unit (probably schemata) implementation, we just might not have to limit anything OTOH. But the price is lost efficiency. (Just like with sets: to test one bit (a IN setA), we have to construct entire function call.)
Emil?
Mirsad
On Thu, Jul 03, 2003 at 02:16:18PM +0200, Mirsad Todorovac wrote:
On Thu, 3 Jul 2003, Emil Jerabek wrote:
On Wed, Jul 02, 2003 at 10:14:22PM +0200, Frank Heckenbach wrote:
Mirsad Todorovac wrote:
Anyway, I propose we put thing of this sort on a WISH-LIST, w priorities, so we'd don't forget about it and propose it again.
Many items on the to-do list are "wishes", and the mentioned `SELECTED_REAL_KIND' is already there. (Though it may refer to a feature to choose between the available standard real types according to some parameters -- as I said, I don't know it exactly.)
I don't know much about Fortran either, but I'm afraid that "KIND" has the meaning you put in parenthesis, not a handcrafted user-defined type. See `info g77', for example.
Err, well, it's not a "handcrafted user-defined" type, it's actually meant to be IEEE-form floating point number, it's just that exponent and mantissa size is customizable.
I doubt that there is such a thing as IEEE float with customizable sizes, AFAIK IEEE 754 specifies both the general layout _and_ exponent and mantissa sizes for its types. Anyway, this is just playing with words, it doesn't matter whether it's called "customizable" or "user-defined".
What I was trying to say is that the "SELECTED_REAL_KIND" entry on the TODO list is something different from these customizable real types, thus a new entry would be appropriate for your proposal. (In Fortran "REAL(KIND=N)", the number N has nothing to do with the size of the type, it is just an (almost) arbitrary index chosen by the implementation to select from the set of available _built-in_ types.)
Emil
On Thu, 3 Jul 2003, Emil Jerabek wrote:
On Thu, Jul 03, 2003 at 02:16:18PM +0200, Mirsad Todorovac wrote:
On Thu, 3 Jul 2003, Emil Jerabek wrote:
On Wed, Jul 02, 2003 at 10:14:22PM +0200, Frank Heckenbach wrote:
Mirsad Todorovac wrote:
Anyway, I propose we put thing of this sort on a WISH-LIST, w priorities, so we'd don't forget about it and propose it again.
Many items on the to-do list are "wishes", and the mentioned `SELECTED_REAL_KIND' is already there. (Though it may refer to a feature to choose between the available standard real types according to some parameters -- as I said, I don't know it exactly.)
I don't know much about Fortran either, but I'm afraid that "KIND" has the meaning you put in parenthesis, not a handcrafted user-defined type. See `info g77', for example.
Err, well, it's not a "handcrafted user-defined" type, it's actually meant to be IEEE-form floating point number, it's just that exponent and mantissa size is customizable.
I doubt that there is such a thing as IEEE float with customizable sizes, AFAIK IEEE 754 specifies both the general layout _and_ exponent and mantissa sizes for its types. Anyway, this is just playing with words, it doesn't matter whether it's called "customizable" or "user-defined".
What I had in mind is the number with exact IEEE layout and semantics, except for the difference in the number of exponent/mantissa (significand) bits. In this sense, "customizable" may be when you add extra 32 bits for mantissa precission, not changing anything else; while user-defined might be something that doesn't resemlbe IEEE 754 layout even distantly, if one can imagine such a thing.
What I was trying to say is that the "SELECTED_REAL_KIND" entry on the TODO list is something different from these customizable real types, thus a new entry would be appropriate for your proposal. (In Fortran "REAL(KIND=N)", the number N has nothing to do with the size of the type, it is just an (almost) arbitrary index chosen by the implementation to select from the set of available _built-in_ types.)
I looked at that, and it appears that this (KIND=..) has the same meaning as "long" or "long long" in C ...
To be realistic, Frank has made it very clear so far that excess precision doesn't make much sense if i.e. Sin(x) is calculated in (only) double precision, and depends on the quality of implementation in system's C library -- otherwise we're depending on GNU GMP lib or something like that. Or, we'd have to instantiate compiled math library for every given (Exponent, mantissa) combination and requested range/precision.
So, having all this limitations in mind customized Reals could serve for the same purpose as customized Integers - yet we'd better estimate cost/benefit in this case. If it's month of compiler writter's work, then it's expensive; and Frank is right when he says as much as possible should be done on user level.
The only problem lies in (lack of) automatic promotions/conversions/interoperability with other types.
Mirsad
Mirsad Todorovac a écrit:
The only problem lies in (lack of) automatic promotions/conversions/interoperability with other types.
I have a smilar problem with complex type. Since gpc does not implement LongComplex types, I use the CEPHES library which contains (in C) all needed functions, and make interface with the attached import unit. The only drawback is that this LongComplex type has nothing to do with Complex, or Real and LongReal. So to avoid conflicts I need to give different names to functions like Re, Im and also sin (-> csin) which have meaning both in Real and Complex types etc. Otherwise it works perfectly when everything is done only in LongComplex.
In fact there is nothing in Pascal to say in a program that two types are somewhat related, by giving rules for automatic conversion. Any such concept is then implemented manually inside the compiler, e.g. by saying that you can assign an integer to a real, but cannot do the reverse. With C++ objects one can give such rules in constructors, by defining several constructors which differ by the types of their arguments. But this is valid only in objects, which are heavy structures. So we begin to imagine a new language.
Maurice
Maurice Lombardi wrote:
I have a smilar problem with complex type. Since gpc does not implement LongComplex types, I use the CEPHES library which contains (in C) all needed functions, and make interface with the attached import unit.
LongComplex is also such a beast. I've thought about adding it (and possibly ShortComplex, though I don't know if there's a real need for it), but so far I've shyed away because of the complexities ;-) involved.
One reason for adding it would be consistence, since we have Real, LongReal and Complex already, so I might accept it for this reason ...
This is, provided the backend handles LongComplex sufficiently (for the basic arithmetics). I haven't checked this. According to the documentation, I think it should (also complex integers, but that's yet another story ...).
OTOH, it might be worth considering if it's possible to move the whole complex numbers out of the compiler. (Of course, provided we have user-defined conversions, here Real -> Complex.) Even if the basic operations would have to be written as operators, this might not have to be less efficient than done by the backend (provided we have inlines in GPIs ...). And cases such as Real * Complex (which are currently poorly optimized) could be improved just by supplying a respective operator.
With C++ objects one can give such rules in constructors, by defining several constructors which differ by the types of their arguments. But this is valid only in objects, which are heavy structures. So we begin to imagine a new language.
That it's valid only for objects in C++ doesn't mean that it would have to be so in Pascal. (But as I said in the other mail, it's complicated, anyway.)
Frank
I am getting an error "incompatible types in assignment" on Inc(CSPtr(c))
It seems the cast of the pointer inside the Inc procedure is confusing it. What is especially weird is that the case does not even change the type because!
{$x+} program testpas8;
type U8 = Cardinal attribute ( size = 8); U8Ptr = ^U8; CSPtr = U8Ptr;
var c: CSPtr; begin Inc(CSPtr(c)); end.
Note that the CSPtr type is required - changing the use to U8Ptr removes the problem.
Thanks, Peter.
Peter N Lewis wrote:
I am getting an error "incompatible types in assignment" on Inc(CSPtr(c))
Note that the CSPtr type is required - changing the use to U8Ptr removes the problem.
Fixed. (peter3.pas)
Frank
On Fri, 4 Jul 2003, Peter N Lewis wrote:
I am getting an error "incompatible types in assignment" on Inc(CSPtr(c))
It seems the cast of the pointer inside the Inc procedure is confusing it. What is especially weird is that the case does not even change the type because!
{$x+} program testpas8;
type U8 = Cardinal attribute ( size = 8); U8Ptr = ^U8; CSPtr = U8Ptr;
var c: CSPtr;
Since c is a pointer where does it point?
begin Inc(CSPtr(c)); end.
If you increment c just where does it point?
Russ
var c: CSPtr;
Since c is a pointer where does it point?
begin Inc(CSPtr(c)); end.
If you increment c just where does it point?
It's just an example, a minimal example that generates the error to make it as easy as possible to find the cause. The actual code was in a C String to PString routine and did indeed assign the variable a value first.
CodeWarrior actually would detect this and give a warning "possible use before assignment" which is very nice. CodeWarrior also detects unused parameters in procedures/functions (with an {$unused( whatever )} construct to silence the warning). These are both useful warnings, so consider it a feature request for the todo list (or wish list or whatever) if it's not already there.
Thanks for the quick fix!
Enjoy, Peter.
Peter N Lewis a écrit:
var
c: CSPtr;
Since c is a pointer where does it point?
begin Inc(CSPtr(c)); end.
If you increment c just where does it point?
It's just an example, a minimal example that generates the error to make it as easy as possible to find the cause. The actual code was in a C String to PString routine and did indeed assign the variable a value first.
CodeWarrior actually would detect this and give a warning "possible use before assignment" which is very nice. CodeWarrior also detects unused parameters in procedures/functions (with an {$unused( whatever )} construct to silence the warning). These are both useful warnings, so consider it a feature request for the todo list (or wish list or whatever) if it's not already there.
use -Wall
Maurice
At 9:47 AM +0200 5/7/03, Maurice Lombardi wrote:
Peter N Lewis a écrit:
CodeWarrior actually would detect this and give a warning "possible use before assignment" which is very nice. CodeWarrior also detects unused parameters in procedures/functions (with an {$unused( whatever )} construct to silence the warning). These are both useful warnings, so consider it a feature request for the todo list (or wish list or whatever) if it's not already there.
use -Wall
Does not do anything for me:
program testpas9;
procedure test( a, b: Integer ); begin WriteLn( a ); end;
var i: Integer; begin Inc(i); WriteLn( i ); test( i, i * 2 ); end.
gpc -Wall -o testpas9 testpas9.pas
generates no warnings about the unused b nor any warning about the used before defined i.
Enjoy, Peter.
-- http://www.interarchy.com/ http://documentation.interarchy.com/
Hi!
On Sat, Jul 05, 2003 at 07:27:58PM +0800, Peter N Lewis wrote:
use -Wall
Does not do anything for me:
[...]
gpc -Wall -o testpas9 testpas9.pas
Same for me. Looks like a bug?
program Foo; var i: Integer; begin WriteLn (i) end.
gpc -W -Wall -O3 foo.pas (Documentation about -Wall says, you may have to switch on optimization). gives no warnings :-(
Eike
Peter N Lewis a écrit:
At 9:47 AM +0200 5/7/03, Maurice Lombardi wrote:
Peter N Lewis a écrit:
CodeWarrior actually would detect this and give a warning "possible use before assignment" which is very nice. CodeWarrior also detects unused parameters in procedures/functions (with an {$unused( whatever )} construct to silence the warning). These are both useful warnings, so consider it a feature request for the todo list (or wish list or whatever) if it's not already there.
use -Wall
Does not do anything for me:
program testpas9;
procedure test( a, b: Integer ); begin WriteLn( a ); end;
var i: Integer; begin Inc(i); WriteLn( i ); test( i, i * 2 ); end.
gpc -Wall -o testpas9 testpas9.pas
generates no warnings about the unused b nor any warning about the used before defined i.
with -W -Wall I obtain:
testpas9.pas:3: warning: unused parameter `b'
but nothing about i (so -Wall does not imply -W). I am baffled because I use by default -W -Wall (-Wno-identifier-case) and I receive in other programs lots of messages like:
warning: `foo' might be used uninitialized in this function
Well after some experimentation it seems that the latter works only in functions and procedures, not at the main level. Modifying your program as:
program testpas10;
procedure test( a, b: Integer ); var j: integer; begin WriteLn( a, j); end;
var i: Integer; begin Inc( i ); WriteLn( i ); test( i, i * 2 ); end.
I obtain with -W -Wall
testpas9.pas: In procedure `test': testpas9.pas:3: warning: unused parameter `b' testpas9.pas:5: warning: `j' might be used uninitialized in this function testpas9.pas: In main program: testpas9.pas:5: warning: `j' might be used uninitialized in this function
(not `i' in the last message).
I see no reason for that behavior: bug?
Maurice
Maurice Lombardi wrote:
program testpas10;
procedure test( a, b: Integer ); var j: integer; begin WriteLn( a, j); end;
var i: Integer; begin Inc( i ); WriteLn( i ); test( i, i * 2 ); end.
I obtain with -W -Wall
testpas9.pas: In procedure `test': testpas9.pas:3: warning: unused parameter `b' testpas9.pas:5: warning: `j' might be used uninitialized in this function testpas9.pas: In main program: testpas9.pas:5: warning: `j' might be used uninitialized in this function
(not `i' in the last message).
I see no reason for that behavior: bug?
That's a limitation of the backend. It recognizes such problems when analyzing variable usage when optimizing (therefore this warning appears only with `-O'), and it does so only on a per-routine basis.
You can get the warning by declaring `i' in the statement part of the main program (GPC extension), so it becomes really local.
Alternatively, we could (internally) make all global declarations local to the main program. However, this would mean that, e.g. all global variables would be allocated on the stack and all global routines, when used as procedural parameters/variables, would be called through trampolines. Given the stack size limitations and trampoline bugs on some systems, I don't think that would be useful.
Frank
Maurice Lombardi wrote:
with -W -Wall I obtain:
testpas9.pas:3: warning: unused parameter `b'
but nothing about i (so -Wall does not imply -W).
In the current change notes of gcc-3.4, I read:
"The -W warning option has been renamed to -Wextra, which is more easily understood. The older spelling will be retained for backwards compatibility."
Regards,
Adriaan van Os
On Sat, 5 Jul 2003, Peter N Lewis wrote:
var c: CSPtr;
Since c is a pointer where does it point?
begin Inc(CSPtr(c)); end.
If you increment c just where does it point?
It's just an example, a minimal example that generates the error to make it as easy as possible to find the cause. The actual code was in a C String to PString routine and did indeed assign the variable a value first.
A class I took some 20+ years age touched on pointers in pascal and the "proposed standard": given " Var A: ^x; B: ^x;" then A & B are considered to be different types. If the standard in this area has not been changed from the proposed standard then it appears to me that "incompatable types" for the example program is correct.
But then, I've been wrong before.
Russ
Russell Whitaker wrote:
On Sat, 5 Jul 2003, Peter N Lewis wrote:
var c: CSPtr;
Since c is a pointer where does it point?
begin Inc(CSPtr(c)); end.
If you increment c just where does it point?
It's just an example, a minimal example that generates the error to make it as easy as possible to find the cause. The actual code was in a C String to PString routine and did indeed assign the variable a value first.
A class I took some 20+ years age touched on pointers in pascal and the "proposed standard": given " Var A: ^x; B: ^x;" then A & B are considered to be different types. If the standard in this area has not been changed from the proposed standard then it appears to me that "incompatable types" for the example program is correct.
AFAIK, the standard hasn't changed, but that's not relevant here. In Peter's test program there are no two distinct pointers -- the whole program contains only one `^'. (Besides, pointer arithmetics are non-standard, anyway.)
Frank
IEEE defines only two real formats with 32 and 64 bits. These are implemented in the backend. There is absolutely no need to implement further IEEE- analogue formats with different bitnumbers.
It would be dangerous to give programmers the possibility to change the number of bits in the exponent and mantissa (even if everything is correctly implemented!). Would you immediately see, that real numbers with 8 bits in the exponent and more than 256 bits in the mantissa would loose precision for example when calculating a cos?
The mathematical challenges of an IEEE-like number with i.e. 15-bit-exponents and 93-bit-mantissae are immense especially when considering the problems of nonnormalized numbers AND the result is absolutly not worth the labours put into! The problem of correctly calculating elementary functions (sin..) has to be solved too!
What people really need is an arithmetic with more precision and that already exists in several versions including freeware (see gmp)
Frank Braun
Date sent: Thu, 3 Jul 2003 18:21:16 +0200 (CEST) From: Mirsad Todorovac mtodorov@alu.hr To: jerabek@math.cas.cz Copies to: gpc@gnu.de Subject: Re: Real with attributes (...)
On Thu, 3 Jul 2003, Emil Jerabek wrote:
On Thu, Jul 03, 2003 at 02:16:18PM +0200, Mirsad Todorovac wrote:
On Thu, 3 Jul 2003, Emil Jerabek wrote:
On Wed, Jul 02, 2003 at 10:14:22PM +0200, Frank Heckenbach wrote:
Mirsad Todorovac wrote:
Anyway, I propose we put thing of this sort on a WISH-LIST, w priorities, so we'd don't forget about it and propose it again.
Many items on the to-do list are "wishes", and the mentioned `SELECTED_REAL_KIND' is already there. (Though it may refer to a feature to choose between the available standard real types according to some parameters -- as I said, I don't know it exactly.)
I don't know much about Fortran either, but I'm afraid that "KIND" has the meaning you put in parenthesis, not a handcrafted user-defined type. See `info g77', for example.
Err, well, it's not a "handcrafted user-defined" type, it's actually meant to be IEEE-form floating point number, it's just that exponent and mantissa size is customizable.
I doubt that there is such a thing as IEEE float with customizable sizes, AFAIK IEEE 754 specifies both the general layout _and_ exponent and mantissa sizes for its types. Anyway, this is just playing with words, it doesn't matter whether it's called "customizable" or "user-defined".
What I had in mind is the number with exact IEEE layout and semantics, except for the difference in the number of exponent/mantissa (significand) bits. In this sense, "customizable" may be when you add extra 32 bits for mantissa precission, not changing anything else; while user-defined might be something that doesn't resemlbe IEEE 754 layout even distantly, if one can imagine such a thing.
What I was trying to say is that the "SELECTED_REAL_KIND" entry on the TODO list is something different from these customizable real types, thus a new entry would be appropriate for your proposal. (In Fortran "REAL(KIND=N)", the number N has nothing to do with the size of the type, it is just an (almost) arbitrary index chosen by the implementation to select from the set of available _built-in_ types.)
I looked at that, and it appears that this (KIND=..) has the same meaning as "long" or "long long" in C ...
To be realistic, Frank has made it very clear so far that excess precision doesn't make much sense if i.e. Sin(x) is calculated in (only) double precision, and depends on the quality of implementation in system's C library -- otherwise we're depending on GNU GMP lib or something like that. Or, we'd have to instantiate compiled math library for every given (Exponent, mantissa) combination and requested range/precision.
So, having all this limitations in mind customized Reals could serve for the same purpose as customized Integers - yet we'd better estimate cost/benefit in this case. If it's month of compiler writter's work, then it's expensive; and Frank is right when he says as much as possible should be done on user level.
The only problem lies in (lack of) automatic promotions/conversions/interoperability with other types.
Mirsad
-- "I have a dream!" -- Martin Luther King Jr.
Frank Braun Rechenzentrum Universitaetsstrasse 31 D-93053 Regensburg Germany
Tel.: +49-941-943-4891
email: frank.braun@rz.uni-regensburg.de
On Fri, 4 Jul 2003, Frank Thomas Braun wrote:
IEEE defines only two real formats with 32 and 64 bits. These are implemented in the backend. There is absolutely no need to implement further IEEE- analogue formats with different bitnumbers.
It would be dangerous to give programmers the possibility to change the number of bits in the exponent and mantissa (even if everything is correctly implemented!).
With all due respect, please let me quote an article on floating-point:
"Computer owner derive scant benefit from advantageous harware features they have paid for since these are practically inaccessible through commercially dominant compilers and computer languages."
"The improved capabilities are features of IEEE Standard 754 for Binary Floating-Point Arithmetic mistakenly deemed arcane, as if intended for only a few specialists"
(John von Neumann Lecture on Baleful Effect of Computer Languages and Benchmarks upon Applied Mathematics, Physics and Chemistry, presented by Prof. W. Kahan, 45th Annual Meeting of SIAM, July 1997, URL: http://cch.loria.fr/documentation/IEEE754/wkahan/SIAMjvnl.ps
Would you immediately see, that real numbers with 8 bits in the exponent and more than 256 bits in the mantissa would loose precision for example when calculating a cos?
Of course, if we do not recompile math library in given precision, or have such an implementation that could suffer variable precisions.
The mathematical challenges of an IEEE-like number with i.e. 15-bit-exponents and 93-bit-mantissae are immense especially when considering the problems of nonnormalized numbers AND the result is absolutly not worth the labours put into! The problem of correctly calculating elementary functions (sin..) has to be solved too!
Of course.
What people really need is an arithmetic with more precision and that already exists in several versions including freeware (see gmp)
Certainly. Yet please note how for example a version of M$ CC started to map long double calculations into simple 64-bit double, throwing 16 bits of precision customers have paid for not into recycle bin, but into /dev/null ...
IMVHO we should not limit programmer by language this much, we should offer both variants (extended precision and saving of memory for special purposes)
New epsilon for given p precision bits and ß = 2 is easily detemined (http://cch.loria.fr/documentation/IEEE754/ACM/goldberg.pdf), while about sin(), cos(9 etc. it isn't quite certain how things go on about it even with standard C libm math, we're depending on provider ...
I'm certain that GPC team is able to do the task correctly, to the last theoretically achievable bit of precision, it's only the matter whether it is worthwhile the effort. If Frank's idea of typecast operators is achivable, it might be a more general solution, and this way probably a better one ...
Mirsad Todorovac
Frank Braun
Mirsad Todorovac wrote:
What people really need is an arithmetic with more precision and that already exists in several versions including freeware (see gmp)
Certainly. Yet please note how for example a version of M$ CC started to map long double calculations into simple 64-bit double, throwing 16 bits of precision customers have paid for not into recycle bin, but into /dev/null ...
With all due criticism of Microsoft, I don't quite agree. AFAIK, the "official" formats of IA32 floating point are 32 and 64 bits, while the 80 bits format was meant as an internal format, to be used for temporary results. So I think it's valid for a language to not offer it to the programmer (though GCC/GPC and BP do, which is also valid :-), in particular if one wants to avoid "surprises" (rounding errors strike with full force in the 80 bits type because there's no extra precision, whereas a results stored in 64 bits and computed in 80 bits (which the processor always does if a temporary result isn't stored in shorter form) are more accurate). I don't know if that what their reason -- but then, I'm not even sure if `long double' is a standard C type ...
I'm certain that GPC team is able to do the task correctly, to the last theoretically achievable bit of precision, it's only the matter whether it is worthwhile the effort.
Well, I think this would be an issue for the GCC (backend) and library (libm) teams, not so much for us.
If Frank's idea of typecast operators is achivable, it might be a more general solution, and this way probably a better one ...
Yes, this might be the way to go (but don't expect it too soon, since it's really not trivial). Then it's an issue for us and some Pascal programmer ...
Frank
I'm not sure if this is a bug, but the error you get when two symbols have the same name is rather obscure:
zany:~/unix/c/testpas% gpc -W -Wall testpas10.pas /var/tmp//ccWdBBvY.s:36:FATAL:Symbol _SAME already defined.
Example:
program testpas10;
procedure test( a: Integer ); attribute( name = 'SAME' ); begin WriteLn( a ); end;
procedure test2( a: Integer ); attribute( name = 'SAME' ); begin WriteLn( a ); end;
begin end.
I would expect a more sensible error.
Enjoy, Peter.
Peter N Lewis wrote:
I'm not sure if this is a bug, but the error you get when two symbols have the same name is rather obscure:
zany:~/unix/c/testpas% gpc -W -Wall testpas10.pas /var/tmp//ccWdBBvY.s:36:FATAL:Symbol _SAME already defined.
Example:
program testpas10;
procedure test( a: Integer ); attribute( name = 'SAME' ); begin WriteLn( a ); end;
procedure test2( a: Integer ); attribute( name = 'SAME' ); begin WriteLn( a ); end;
begin end.
I would expect a more sensible error.
Well, you're (explicitly!) producing a link-time problem, so you should expect an error from the linker, not the compiler, I'd say.
IOW, when using explicit linker names, I think it's the programmer's responsibility to ensure they are used correctly (i.e., match when referred to in different places, and don't conflict).
Frank
I'm certain that GPC team is able to do the task correctly, to the last theoretically achievable bit of precision, it's only the matter whether it is worthwhile the effort. If Frank's idea of typecast operators is
<cough cough> I suspect that the correct language to implement arbitrary-precision floating point numbers in is C++, with heavily templated floating point types... Generic algorithms could be written and specialized for hardware facilities...
OK, I'm not volunteering to do this today; it's just a thought.
achivable, it might be a more general solution, and this way probably a better one ...
Mirsad Todorovac
Mirsad Todorovac wrote:
To be realistic, Frank has made it very clear so far that excess precision doesn't make much sense if i.e. Sin(x) is calculated in (only) double precision, and depends on the quality of implementation in system's C library -- otherwise we're depending on GNU GMP lib or something like that.
I think if you want excess precision, you either have to implement it all yourself (including Sin and all), or switch to GMP completely (which, as I mentioned, is not exactly saving memory). Converting to GMP just for an operation seems clusmy and inefficient. But if you use GMP types for high precision, self-made types (memory saving) for very low precision plus the standard types, then it really becomes a nightmare I guess ...
Or, we'd have to instantiate compiled math library for every given (Exponent, mantissa) combination and requested range/precision.
So, having all this limitations in mind customized Reals could serve for the same purpose as customized Integers -
And while we're at it, I'm not even sure if these are worth the effort. They can be useful for backward-compatibility with some fixed-layout bit-formats, but I don't use them much otherwise (with the exception of things like size = 8, 16 or 32 which basically does the same as SELECTED_REAL_KIND, or even things like uint32_t in C, i.e. just chooses one of the available types).
yet we'd better estimate cost/benefit in this case. If it's month of compiler writter's work, then it's expensive; and Frank is right when he says as much as possible should be done on user level.
If you really want to do it all in the compiler, then a month might be short actually.
In Pascal unit (probably schemata) implementation, we just might not have to limit anything OTOH. But the price is lost efficiency. (Just like with sets: to test one bit (a IN setA), we have to construct entire function call.)
The solution I prefer is to store routine bodies in GPI files so they can be inlined. That's non-trivial currently, but it's a more general solution, so in the end it will be better than a special hand-crafted set implementation in the compiler(*), a special hand-crafted customized real implementation in the compiler, etc.
(*) which GPC once had, but Juki who wrote it left the compiler team, and nobody else understood the code or was able to fix the bugs, so we switched back to a Pascal based solution.
But while we're at it, we might as well think about if, how, and how far something can/should be implemented at all before we put it on the list, so the wish list remains (or perhaps gets ;-) a little more realistic.
IMHO strivings should be 100x of what we can achieve, and what is planned only 10x that much ;-)
I wasn't so much talking about what we can achieve (the list might already contain more than that), but what we should actually try to put in the compiler. I don't want to repeat myself too often, but I really prefer powerful and general mechanisms in the compiler (such as GPI inlines, user-defined conversions) rather than a lot of complex special-case features which will inevitable increase the complexity and decrease the maintainability of the code considerably.
So generally (this also applies for other features that may be discussed in the future), I'd like to raise the question, how much of it does *really* have to be in the compiler, and how much can be done on the Pascal side.
In fact, in ideal world all the hassle over standard arithmetic with modifications of standard types would have been taken care of by the back-end.
Now this might be an argument for putting this in the compiler, if the backend was able to do better optimizations on it. (The same applies, BTW, to strings and sets; we currently have a few problems since we convert them to backend-representable expressions, often RTS calls, rather early, so it's hard to optimize them later.)
If that's your goal, well, you'll have to talk to the backend-people, anyway, and convince them. If you succeed, we can, of course, add the necessary interfaces in the frontend, but frankly I doubt it.
I don't knwo what ar the experiences with the implementation of Cardinal, Word and Integer bitfields;
I don't know very much either, since most of it is done in the backend. Only packed arrays are handled in the frontend (since the backend doesn't support them yet), and that's evil enough. We have 64 lines for reading them (build_pascal_packed_array_ref), 100 lines for writing them (within build_modify_expr), various special cases for `BitSizeOf', I/O and other things, and two fundamental problems (initializers don't work and the current implementation fails badly on some platforms), both of which can perhaps be solved with quite a bit of extra code. Bottom line: Doing this in the frontend is a bad idea. I really hope the backend will be able to handle this in the future (currently it supports bitfields with constant offsets as in packed records, and generalizing it to variable offsets should be easier than the mess we have to do in the frontend).
Of course, it would be very clumsy to instantiate all the arithmetic separatelly for each new manitissa or exponent size, now matter how standard the calculation routines may be. And worse, the resulting arithmetic could be slower than that generated by promotion to nearest higher precision standard IEEE float.
I can't tell. I'd have to know more details about the hand-written arithmetic on the one side, and the (also hand-written) conversions on the other side. Since the latter are two operations (plus the IEEE operation), I suppose it may be faster perhaps only for more complex operations like trigonometrics if they use specially optimized hardware ...
I'd be very encouraged if it's not rejected that easily, and for good. Perhaps in 5 years it would be 50 lines in the front-end to implement it, at little cost of programming and debugging.
If the backend does all the real work (see above), we might be able to get by with 50 lines. But already the basic declarations in the compiler, plus syntax and such "administrative" stuff might exceed that.
So in fact I suggest you try to write a Pascal unit for such a type that you see a need for, with all those operators etc., and find out what can't be done currently.
OK; then I'll add it to my TODO list. It appears at first glance that authomatic promotions are the first thing that is missing -- compiler might never know that new defined type is even a numeric, let alone real ...
Yes, the automatic conversions seem to be the main problem. That's true whether full customized reals will be implemented in the compiler, or only user-defined conversions. (There are many places that check, e.g. if some value is numeric, and they'd all have to be changed to take possible user-defined conversions into account, possibly several ones in a row. Not to mention possible ambiguities ...)
Frank
On Wed, 2 Jul 2003, Frank Heckenbach wrote:
Mirsad Todorovac wrote:
Anyway, I propose we put thing of this sort on a WISH-LIST, w priorities, so we'd don't forget about it and propose it again.
Many items on the to-do list are "wishes", and the mentioned `SELECTED_REAL_KIND' is already there. (Though it may refer to a feature to choose between the available standard real types according to some parameters -- as I said, I don't know it exactly.)
But while we're at it, we might as well think about if, how, and how far something can/should be implemented at all before we put it on the list, so the wish list remains (or perhaps gets ;-) a little more realistic.
IMHO strivings should be 100x of what we can achieve, and what is planned only 10x that much ;-)
IMHO this parametrized reals might be a good idea, yet GPC should worry only about loads from/stores into Reals with this new precision, all arithmetic would inevitably have to be done in standard single/double/long double floats,
This would simplify things quite a bit, but it would leave it somewhat unclear (to the programmer) how much of the declared precision is actually used. (Naively, when declaring a real with a precision of 256 bits, I'd expect it to have that precision, not artihmetic done with 64 or so bits of precision.)
Certainly, if so is defined, yet of course one should be aware of the performance penalty for extra precision. Even if not, it could be defined that parametrized Real's precision will not be allowed to be greater than what hardware supports {just like Word attribute (Size = 1..64), even though cardinals of 128 or more bits are very imaginable and could easily find application - i.e. in astronomy}.
Also, I more and more tend to "do it in Pascal code" whenever it has no big disadvantages. So my questions are:
- Do you really see the need for such *parametrized* types? (As opposed to a few particular types for specific needs, such as your GSM example. Those could be implemented individually, though with a bit of code duplication, but also probably more efficiently, since dealing with fixed sizes of exponent and mantissa should make for faster code than variable sizes.)
At the time programmers were using FORTRAN just because it had reals with greater precision and few mathematical libraries written in it -- in fact, it may still be so ...
But I understand the *legitimate* concern not to over-burden the compiler that already isn't what you'd want it to be with extra heavy stuff.
In fact, in ideal world all the hassle over standard arithmetic with modifications of standard types would have been taken care of by the back-end. IRW, front-end should do much more of the total work.
I don't knwo what ar the experiences with the implementation of Cardinal, Word and Integer bitfields; before telling anything specific on implementation of similar functionality with Reals.
Sadly, I've had to convince myself that back-end is an untamed beast (with RotateLeft/RotateRight implementation e.g.), and how it doesn't always do the right thing -- and how it's not very educated about bitfields.
At the level of definition, parametrized Reals arithmetic doesn't seem to complex to write, as long as we stick to modification of IEEE floats. Add, mul, and sqrt are rather trivial; and everything else can be derived from it.
Of course, it would be very clumsy to instantiate all the arithmetic separatelly for each new manitissa or exponent size, now matter how standard the calculation routines may be. And worse, the resulting arithmetic could be slower than that generated by promotion to nearest higher precision standard IEEE float.
- How big are the disadvantages of a Pascal-based solution really? As I said in my previous mail, it might not be more than explicit conversions in assignments. If that's really all, I'm not convinced that the extra effort in the compiler is worth it.
With clever tricks and using some hacks it could be done in rather efficient manner, probably. The only issue is *elegance*, the same way as I declare
var mybitfield : Integer attribute (Size = 2);
and later have almost no worry, i use it as the normal Integer type, and I enjoy the benefit of all automatic conversions Integer type already has, all the functions defined on Integer etc. If I had mybitfield as unit, I'd probably have to call conversion routines myself, but I'm not this familiar with GNU Pascal.
In fact, I might rather consider such "type-cast" operators as mentioned. They would be a more general concept, and perhaps even easier to implement (since the actual conversions can be kept to Pascal code this way).
Interesting.
If we agree on this, I'd rather only put the more general solution on the to-do list (which happens to be there already), so perhaps future contributors who read the list won't waste their time on a feature that was already rejected.
I'd be very encouraged if it's not rejected that easily, and for good. Perhaps in 5 years it would be 50 lines in the front-end to implement it, at little cost of programming and debugging.
So in fact I suggest you try to write a Pascal unit for such a type that you see a need for, with all those operators etc., and find out what can't be done currently.
OK; then I'll add it to my TODO list. It appears at first glance that authomatic promotions are the first thing that is missing -- compiler might never know that new defined type is even a numeric, let alone real ...
Mirsad