Hi, I don’t understand the notion of error bound in fixed-point types. While I know the delta is different from the Small, I’ve always assumed that for my needs they were the same, because most of the time the compiler gives more precision than required.
But in the following I need a type with a precise size:
Do the computations in fixed point arithmetic and assume that the samples are 12 bits, where the first six bits represent numbers from −32 to 31 and the next six bits represent the fractions 0/63 to 64/64.
I found that “type Value is delta 0.02 range -32.0…31.0 with Size => 12;” gives exactly that, as confirmed by the compiler:
value’Value_Size use 12;
for value’Small use 1.02**(-6);
for value’Range use -2048.02**(-6) … 1984.0*2**(-6);
But… why 0.02 ? Is it possible to just precise the number of significant digits in binary digits, so as to stay close to the representation ? It seems a bit random to have to guess which delta would fit the representation wanted. It’s the opposite than what we do with record representation clauses.
And while we’re at it, would it be possible to define a modular fixed point type ? Meaning, a real based on unsigned integer arithmetic instead of a signed one ? I think of Degrees and angles in radians.
Edit: Yes I meant “0/64 toi 63/64”… sorry, copying from pdf sucks.
A fraction cannot be 64/64 = 1. Obviously. It is 0/64…63/64.
Indeed why? 1/64 = 0.015625. So
type Value is delta 0.015625 range -32.0..31.0;
Ah, but there is no guess. It is 1/64.
Fixed point is unreal. It is rational.
Degrees and angles can be negative, of course. You must distinguish absolute values and differences. Compare: Time and Duration. Location and Distance etc. If computations are involved you deal with differences rather than absolute values.
And yes you can have a shifted range:
type Byte is delta 0.125 range 0.0..32.0; -- Warning 32.0 is out of range
It actually means:
type Byte is delta 0.125 range 0.0..32.0 - 0.125;
And no, modular arithmetic is not supported because it makes no sense where fixed types are applied, e.g. engineering and financial computations (defined rounding).
package Precision is
Required_Delta : constant := 1.0 / 64.0;
type Value is delta Required_Delta range -32.0 .. 32.0 - Required_Delta with
Size => 12;
end Precision;
You can lazily let the compiler do the subtraction implicitly (not sure whether this is a GNAT-ism):
type Value is delta Required_Delta range -32.0 .. 32.0 with Size => 12;
leading to a warning:
gnatmake -c -u -f -gnatR2 precision.ads
gcc -c -gnatR2 precision.ads
precision.ads:5:09: warning: declared high bound of type "Value" is outside type range [enabled by default]
precision.ads:5:09: warning: high bound adjusted down by delta (RM 3.5.9(13)) [enabled by default]
Representation information for unit Precision (spec)
----------------------------------------------------
for Value'Object_Size use 16;
for Value'Value_Size use 12;
for Value'Alignment use 2;
for Value'Small use 1.0*2**(-6);
for Value'Range use -2048.0*2**(-6) .. 2047.0*2**(-6);
Oh I never thought of entering a fraction as the delta !!
delta 1.0/64.0 is so elegant, exactly what was asked. I never manipulated numeric types much.
I get what that warning means now. No guessing indeed !
As for a rounding, I get it, it’s not historically of much use. But in math fixed or floating point modular arithmetic can come very naturally in certain areas. Like everything to do with transcendental functions, sin & cosin. Hence my mention of angles, even though they do have signed uses as well.