!standard 3.5.9 09-10-28 AI05-0175-1/01
!class Amendment 09-10-28
!status work item 09-10-28
!status received 09-10-28
!priority Low
!difficulty Medium
!subject Cyclic fixed point types
!summary
Fixed point types that wrap around in a similar way to modular integer types
are introduced
!problem
Ada does not provide a simple way to model naturally occurring cyclic
quantities such as angles. Angles have the property of requiring absolute
accuracy rather than relative accuracy; an error of 0.01 degrees is just
as important at a bearing of 5 degrees as at 50 degrees. This implies that
floating types are not appropriate for angles. Moreover, wrap around at
a whole cycle must be modelled exactly.
At the moment, we can model angles as a modular integer type which solves
the accurate wrap around but then we have to look after the scaling
ourselves which means that programs are word length dependent and also
introduces the risk of errors in mapping from the problem domain (that
is getting the scaling wrong).
Or we can model angles as ordinary fixed point types but then we have to
look after the wrap around ourselves which is also prone to error and
can lose accuracy.
!proposal
Modular fixed point types are introduced using declarations of the form
type Bearing is delta 0.01 range 0.0 .. 360.0 mod 360.0;
This provides a type whose values range from 0.0 up to (but not
including) 360.0 with an accuracy of at least 0.01.
Appropriate operations are provided much as for ordinary fixed point
types. Addition and subtraction are only permitted between values of
the same type. The result is normalized by the addition or subtraction
of 360.0 to bring it into range.
(In hardware terms, it should happen automatically using unsigned
integer arithmetic.)
Multiplication and division by an integer are defined. Conversions to
other numeric types are performed in the usual way.
Abs and unary minus are not defined.
Another example might be
type Angle is delta 0.001 range -Pi .. +Pi mod 2*Pi;
An additional form of generic parameter is required thus
generic
type F is delta <> range <> mod <>;
Consider the general case
type F is delta D range L..R mod M;
Small is chosen so that the range L to R is mapped onto a suitable
unsigned word. The representations of L and R are identical.
Attributes Delta, Small, and Mod are available. Small cannot be set.
Similarly, First, Last and Range are available.
F'First gives L, F'Last gives R-Small. There is a static check that
Mod, L and R match appropriately.
!wording
!discussion
At first sight it might seem appropriate to use a syntax such as
type T is delta D mod M;
which merges the syntax of ordinary fixed point types and modular types.
Thus
type Bearing is delta 0.001 mod 360.0;
However, although a range of 0 degrees to 360 degrees is OK for many
applications such as navigation bearings. It is more helpful to use a
range such as -180 to +180 for angles used in geometrical constructions
and architecture.
Moreover, it seems reasonable to want the two ends of the range to be
represented in exactly the same way since they represent the same
physical entity. Indeed we want the range to map exactly onto a full
unsigned word with the two ends of the range (such as -180 and +180)
being represented in exactly the same way. Thus using a 16-bit word
the range from -180 to +180 would have
-180.0 -> 16#0000#
-90.0 -> 16#4000#
0.0 -> 16#8000#
45.0 -> 16#A000#
..90.0 -> 16#C000#
+180.0 -> 16#0000#
It thus seems more appropriate to use syntax which includes the range.
Moreover if we just give the range then it looks like an ordinary fixed
point type still so we had better give the mod thus
type T is delta D range L .. R mod M;
where the value of mod has to statically match the range. For example
type Signed_Degrees is delta 0.0001 range -180.0 .. 180.0 mod 360.0;
Perhaps the value after mod can be omitted. On the other hand perhaps
the range can be omitted if the lower bound is zero. But redundancy is a
good thing if they have to statically match.
The exact value of delta is pretty useless and is just given in order to
enable the compiler to choose an appropriate word length.
We would also be able to write
type Signed_Angle is delta D range -Pi..Pi mod 2*Pi;
The operations available would be much as expected. Addition and
subtraction are only permitted between values of the same type.
Multiplication and division by an integer are permitted as for ordinary
fixed point types. Should multiplication and division between values of
modular fixed types be permitted? Probably not. If you multiply an Angle
by an Angle then you have probably made a nasty mistake.
The operation abs could bring surprises. Thus if we have
type Curious is range -270.0 .. +90.0 mod 360.0;
C: Curious := -120.0;
D := abs C;
We might expect +120.0 but this wraps around to give -240.0 which is
nonsense. So abs is not permitted. Similarly unary minus.
Conversions to other numeric types would be permitted as usual.
The attributes Mod, Delta and Small are available. However, Small cannot
be set by a use clause since this could upset the automatic wrap around.
Mod is useful when using the trigonometric functions from
Ada.Numerics.Elementary_Functions thus
A: Signed_Angle;
...
X := Sin(Float(A), Angle'Mod);
Note that this works no matter whether Signed_Angle is defined in terms
of degrees, radians or cycles. The latter might be
type Cycle is range 0.0 .. 1.0 mod 1.0;
The attributes First and Last are defined. First returns L. Last does
not return R but R-Small. This prevents confusion which would occur since
Equality is permitted. Not sure about comparisons. It is clear that 45
degrees is greater than 40 degrees but not sure about -90 degrees and
+90 degrees.
For completeness, it is necessary to provide an additional form of generic
parameter thus
generic
type F is delta <> mod <>;
It does not seem fruitful to contemplate modular decimal types.
One problem with the above proposal is that on a binary machine a range
such as -180 to +180 does not permit the exact representation of 60
degrees which mathematically is a very important angle. Oh, maybe it
doesn't matter we cannot represent one-third accurately in any scheme.
!example
!corrigendum
!ACATS test
!appendix
From: John Barnes
Date: Friday, October 16, 2009
We had a meeting at the BSI recently and discussed a number of mostly
seemingly minor matters which had arisen and caused frustration in
practice (that is to real programmers working mostly in the aerospace
industries - your life could depend on them not making a mistake).
...
1 Cyclic fixed point. This is hardly minor but fixed point is used for
angles for navigation (aircraft bearing). The value of fixed point is
that it is accurate and meets the abstraction whereas the only cyclic
types we have are modular and to use them requires scaling once more.
So either we have to scale or we have to cope with wrap around at 360
degrees. Both provide opportunities for error.
There are, however, additional problems since the above works fine for
bearings and longitude but not for latitude. Thus adding 3 degrees to
88 degrees N does not give 91 degrees N but 89 degrees N with the
longitude changed by 180 degrees as well. So a package of operations
on latitude and longitude in fixed point might be a worthy addition.
Much as we added stuff on complex numbers last time.
...
****************************************************************
From: Tucker Taft
Date: Friday, 16 October 2009
Adding "mod 360.0" to the end of a fixed-point type for degrees would
seem to be reasonable syntax.
...
A latitude/longitude package sounds interesting, but we should try to
start from something that some project already finds useful. I could
easily see spending a lot of energy creating something that no one ever
uses.
****************************************************************
From: Jean-Pierre Rosen
Date: Friday, 16 October 2009
Getting farther than a trivial package that anyone can write in half an
hour would be incredibly difficult, since there are lots of geographical
referentials, and n**2 conversions. Latitude and longitude are well
defined, but altitude can be relative to the surface or the center of
the earth. You must then decide if you use a spheric or ellipsoidic
model of the earth, WGS84 or other. And this is just the surface of it...
****************************************************************
From: Bob Duff
Date: Sunday, 18 October 2009
Sounds like a very special-purpose feature. And a rather large change
(for example, as somebody else pointed out, it requires adding a couple
of new kinds of generic formal types).
I already hate modular types. I think if you want to do a "mod"
operation, you should write "mod" in your expressions. So adding a
new kind of modular type does not excite me. (I do understand that
you can get overflows, which is a pain.)
****************************************************************
From: Terry Frogatt
Date: Sunday, 18 October 2009
I've spent a lot of my working life in this area!
Angles are the one area where fixed-point is more logical than float.
Why on earth should we navigate more accurately at Heathrow near 0 deg
than at Apia in Samoa near 180 deg? (That's what happens with float).
I've landed at both, and Apia's runway is far narrower than Heathrow's.
But that's only a detail, the real problem is the wrap-round problem.
From as far back as the 1960/70s when I worked on the Jaguar flight
program on the Elliott 920M, to as recently as 2004 on the UK's Harrier
(a.k.a. USA's AV-8B) flight program on the AN/AYK14, angles were
represented in fixed-point, scaled so that wrap-round could be
implemented simply by ignoring the overflow. Thus, a heading of 355 deg
plus a wind drift of 10 deg gave a track of 5 deg.
And yes I can confirm that Ado's lack of cyclic fixed-point types is a
pain, although it might be a bit late in the day to be fixing it. When
BEE rewrote the Harrier program in Ada a lot of explicit wrap-round
code had to be added. (They also switched angles from fixed to float,
which they might not have done given a suitable cyclic fixed type).
If I declare an integer modular type such as "type degree is mod 360",
I guess their compiler has no choice but to generate wrap-round code (but
not for "type byte is mod 256"). But for fixed-point types, provided
"arbitrary" (non-power-of-2) scales are supported properly, the circle
of angles can be mapped onto the whole circle of underlying integers
with no wrap-round code. (Some folk call this mapping "BAMS").
Ideally I would like to be able to declare 4 cyclic fixed-point types
type signed_degrees from -180.0 to almost +180.0
type signed_radians from -pi to almost +pi
type unsigned_degrees from 0.0 to almost +360.0
type unsigned_radians from 0.0 to almost +2pi
followed by an "abs digits" clause to select accuracy-v-costs from the
available integer types, and I would like to be sure that all 4 mapped
onto the full integer circle without having to specify or know exactly
what the word-length was, or the value of the bottom bit (no more than
I do with float).
Thus the underlying bit pattern 1.1000000.... = -0.5 BAMS would
simultaneously represent -90, -pi/2, +270, or +3pi/2, in the 4 above
types. Providing all 4 types (per integer length) ensures that signed
& unsigned, and degrees & radians, don't get confused, whilst
conversions between them (which abound in the Harrier program) can be
encapsulated into suitably-named functions (which could be in-lined calls
to unchecked_conversion that generate no code). All 4 types have distinct
uses. The pilot's interface works in Degrees, whereas the navigation
internals work best in Radians, (remember that small-angle approximations
like sin(x)=x=tan(x) only work in radians, not BAMS, another source of
gotchas on the Harrier). Bearings are usually given Unsigned, 0 to 360,
whereas Longitudes are Signed, -180=west, +180=east. (And providing yet
more distinct types for Magnetic & True bearings would have avoided
several errors which weren't detected until after flight trials started).
As John has pointed out, Latitudes are different, -90=south, +90=north,
but I feel this is up to the programmer to sort out. In all the code I've
seen, Latitudes are scaled to range from -180 to +180 like Longitudes. If
an equation produces a Latitude outside -90 to +90 it is sometimes
appropriate to "reflect" it in the pole (+91 becomes +89) and take the
back-bearing of the Longitude (add or subtract 180), but sometimes it
can only have occurred due to rounding errors, so that the correct
action is to "saturate" it at the pole (just as you do if you find
yourself taking the arcsine of a number slightly outside -1 to +1 due
to rounding). I don't think that wrapping at -90 or +90 is ever the
right behaviour.
Hope this helps. Regards, Terry.
****************************************************************
From: Terry Froggat
Date: Monday, 19 October 2009
[This is part of an email conversation between Terry Froggatt and Bob Duff.]
Bob, this is in answer to your questions, but is NOT a request
for yet more changes, I do support the idea of Cyclic Fixed Types,
but sadly it is far too late to be of any help to me now. I'm a
"lapsed" member of the UK BSI panel. I was not at the meeting, so the
comments below are my own, and may not represent the panel's views.
Regards, Terry. www.tjfroggatt.plus.com
---
Terry Froggatt wrote:
Angles are the one area where fixed-point is more logical than float.
Bob Duff wrote
Well, not the _only_ area. Fixed point makes sense for money, and for time.
Terry's reply:
Yes fixed-point makes sense for money, but the reason is completely different.
For money, you want fractions which are exact (and not a power of 2).
Usually you want delta=small=1/100. You want "scaled integers".
When you are using fixed-point for mathematically "real" quantities
(either because you have no floating hardware, or because for angles
you want to exploit cyclic wrapround) there is no conceptual delta.
Ideally here you want "scaled fractions" defined by the value of their
most significant bit. (See Ada Letters Jan/Feb 1987 pp71-81?).
---
Terry Froggatt wrote:
Why on earth should we navigate more accurately at Heathrow near 0 deg
Bob Duff wrote:
Why "on earth" (roughly a sphere) indeed. ;-)
Terry's reply:
The pun was intended. Your point about "roughly" is valid, though.
For example, the formula for working out which way to turn, to pray
facing Mecca, is straightforward on a spherical earth. On an ellipsoid,
the real-time programmer has to choose between an iterative accurate
algorithm or a faster less accurate algorithm. And you may have to
convert between mapping datums too. There's a lot of interesting math
in navigation, but a lot of trade-offs too, so I don't really support
trying to provide a lat/long package as part of the Ada language.
---
Terry Froggatt wrote:
From as far back as the 1960/70s when I worked on the Jaguar flight program
on the Elliott 920M, to as recently as 2004 on the UK's Harrier (a.k.a. USA's
AV-8B) flight program on the AN/AYK14, angles were represented in fixed-point,
scaled so that wrap-round could be implemented simply by ignoring the overflow.
Thus, a heading of 355 deg plus a wind drift of 10 deg gave a track of 5 deg.
Bob Duff wrote:
Can you give some example Ada code? I'm not sure I understand what you mean.
Terry's reply:
-- The following types and functions provide a neat mechanism for
-- adding circular quantities scaled in BAMS, without raising an
-- exception at any point in the circle. For example
-- TRACK := Cyclic (HEADING + DRIFT);
type ANGLE_ADD is record LEFT, RIGHT: ANGLE; end record;
function "+" (LEFT, RIGHT: ANGLE) return ANGLE_ADD is begin
return (LEFT, RIGHT);
end "+";
function Cyclic (ITEM: ANGLE_ADD) return ANGLE is begin
if ITEM.LEFT >= 0.0 and then ITEM.RIGHT >= 0.0
and then ITEM.LEFT + ANGLE'FIRST + ITEM.RIGHT >= 0.0 then
return ITEM.LEFT + ANGLE'FIRST + ITEM.RIGHT + ANGLE'FIRST;
elsif ITEM.LEFT < 0.0 and then ITEM.RIGHT < 0.0
and then ITEM.LEFT - ANGLE'FIRST + ITEM.RIGHT < 0.0 then
return ITEM.LEFT - ANGLE'FIRST + ITEM.RIGHT - ANGLE'FIRST;
end if;
return ITEM.LEFT + ITEM.RIGHT;
end Cyclic;
The above code is for a SIGNED type ANGLE, say -180.0..(almost)+180.0.
(When I wrote this in 1999 to simulate fixed-point wrap-round in Ada,
I was deliberately making the Cyclics explicit and not compulsory,
otherwise I could have defined a cyclic "+" directly).
It would be nice if Ada let me write just TRACK := HEADING + DRIFT;
by providing a modular "+" with no risk of overflow or exceptions,
And then as a distinct issue, it would be nice if this mapped this
onto assembly code "read heading, add drift, write track" with no
need for any wrap-round code, which it does provided angles are
scaled so that the "sign" bit is worth +180deg for unsigned angles
or -180 for signed angles (and the next bit is worth +90 either way).
---
Terry Froggatt wrote:
And yes I can confirm that Ada's lack of cyclic fixed-point types is a pain,
although it might be a bit late in the day to be fixing it. When BAE rewrote
the Harrier program in Ada95 a lot of explicit wrap-round code had to be
added. (They also switched angles from fixed to float, which they might
not have done given a suitable cyclic fixed type).
Bob Duff wrote:
I don't understand that (the switch from fixed to float), because neither one
does any modular/wrap-around arithmetic.
Terry's reply:
Yes, neither currently provides wrap-round. If there had been cyclic
fixed types BAE might have mimicked the AN/AYK-14's fixed-point working
as being least risky. But forced to choose twixt the inefficient fixed-point
code I've given above, or using an (inefficient?) floating point subtype
(where you can use the base type to do the add and much simpler wrap) you
can understand why they opted for float. (It wasn't my decision anyway).
---
Terry Froggatt wrote:
...(Some folk call this mapping "BAMS").
Bob Duff wrote:
Sorry for my ignorance, but what's BAMS?
Terry's reply:
I was tempted to write "In some CIRCLES this mapping is called BAMS". ;-)
"Binary Angular Measurement System". I'd been using fixed-point angles
scaled in what I'd always assumed was the obvious way for many years
before I found out that it was called BAMS. It's certainly defined in
the documentation of the AV-8B, and in various on-line dictionaries.
I think there once was a mention in the Wikipedia article about
fixed-point number representations but it's not there now.
---
Terry Froggatt wrote:
Ideally I would like to be able to declare 4 cyclic fixed-point types
type signed_degrees from -180.0 to almost +180.0
type signed_radians from -pi to almost +pi
type unsigned_degrees from 0.0 to almost +360.0
type unsigned_radians from 0.0 to almost +2pi
followed by an "abs digits" clause to select accuracy-v-costs from the
available integer types, and I would like to be sure that all 4 mapped
onto the full integer circle without having to specify or know exactly what the
word-length was, or the value of the bottom bit (no more than I do with float).
Bob Duff wrote:
Makes sense to me, except I don't understand the reference to float.
Terry's reply:
I no more need to know the bottom-bit value for fixed than for float.
When I define a float type I say "digits N" meaning I want at least
this accuracy, maybe more (but not the best you have if it costs me more).
When I define a fixed type for a "real" quantity (NOT money!) the same
is true: I want a given range and minimal accuracy, but I don't really
want or need to know the delta or small. (Except that, when you've found
the smallest integer type that fits my range and accuracy, if there are
some spare bits, please use them for added accuracy, not inaccessible range).
I think someone once proposed the "abs digits" syntax to declare fixed types
where "delta" was OMITTED and to distinguish them from float types, because
float types have relative accuracy and fixed types have ABSolute accuracy.
But equally you could do this by putting the all-important range first
"type FIXED is range L..U digits N; -- Upper endpoint probably excluded".
Ada83 had "delta" to meet the money requirement, Ada95's decimal fixed
types do money better, but by then it was too late to change delta to
digits on the "real" fixed types, so it is far too late to sort it now.
****************************************************************
From John Barnes
Date: Monday, 26 October 2009 9:03 AM
!topic Cyclic fixed point
!reference Ada 2005 RM3.59(1)
!from John Barnes 09-10-26
!keywords angels bearings
!discussion
Some of us have been discussing the problems of using fixed point for angles.
The note below roughly summarizes my view as of this moment. I am indebted to
feedback from Terry Froggatt, Tucker Taft, Michael Pickett, Bob Duff,
Jean-Pierre Rosen and anyone else whom I have regrettably overlooked.
...
We had a meeting at the BSI recently and discussed a number of mostly
seemingly minor matters which had arisen and caused frustration in practice
(that is to real programmers working mostly in the aerospace industries - your
life could depend on them not making a mistake).
...
1 Cyclic fixed point. This is hardly minor but fixed point is used for angles
for navigation (aircraft bearing). The value of fixed point is that it is accurate
and meets the abstraction whereas the only cyclic types we have are modular and
to use them requires scaling once more. So either we have to scale or we have to
cope with wrap around at 360 degrees. Both provide opportunities for error.
There are, however, additional problems since the above works fine for bearings
and longitude but not for latitude. Thus adding 3 degrees to 88 degrees N does
not give 91 degrees N but 89 degrees N with the longitude changed by 180 degrees
as well. So a package of operations on latitude and longitude in fixed point
might be a worthy addition. Much as we added stuff on complex numbers last time.
...
At first sight it might seem appropriate to use a syntax such as
type T is delta D mod M;
which merges the syntax of ordinary fixed point types and modular types.
Thus
type Bearing is delta 0.001 mod 360.0;
However, although a range of 0 degrees to 360 degrees is OK for many applications
such as navigation bearings, it is more helpful to use a range such as -180 to +180
for angles used in geometrical constructions and architecture.
Moreover, it seems reasonable to want the two ends of the range to be represented in
exactly the same way since they represent the same physical entity. Indeed we want
the range to map exactly onto a full unsigned word with the two ends of the range
(such as -180 and +180) being represented in exactly the same way. Thus using a
16-bit word the range from -180 to +180 would have
-180.0 -> 16#0000#
-90.0 -> 16#4000#
0.0 -> 16#8000#
45.0 -> 16#A000#
90.0 -> 16#C000#
+180.0 -> 16#0000#
It thus seems more appropriate to use syntax which includes the range.
Moreover, if we just give the range then it looks like an ordinary fixed point
type still so we had better give the mod thus
type Signed_Degrees is delta 0.0001 range -180.0 .. 180.0 mod 360.0;
where the value of mod has to statically match the range.
Perhaps the value after mod can be omitted. On the other hand perhaps the
range can be omitted if the lower bound is zero. But redundancy is a good
thing if they have to statically match.
The exact value of delta is pretty useless and is just given in order to
enable the compiler to choose an appropriate word length.
We would also be able to write
type Signed_Angle is delta D range -Ada.Numerics.Pi..Ada.Numerics.Pi mod
2*Pi;
The operations available would be much as expected. Addition and subtraction
are only permitted between values of the same type. Multiplication and
division by an integer are permitted as for ordinary fixed point types.
Should multiplication and division between values of modular fixed types be
permitted? Probably not. If you multiply an Angle by an Angle then you have
probably made a nasty mistake.
The operation abs could bring surprise. Thus if we have
type Curious is range -270.0 .. +90.0 mod 360.0;
C: Curious := -120.0;
D := abs C;
We might expect +120.0 but this wraps around to give -240.0 which is
nonsense. So abs is not permitted.
Conversions to other numeric types would be permitted as usual.
The attributes Mod, Delta and Small are available. However, Small cannot be
set by a use clause since this could upset the automatic wrap around. Mod is
useful when using the trigonometric functions from
Ada.Numerics.Elementary_Functions thus
A: Signed_Angle;
...
X := Sin(Float(A), Angle'Mod);
Note that this works no matter whether Signed_Angle is defined in terms of
degrees, radians or cycles. The latter might be
type Cycle is range 0.0 .. 1.0 mod 1.0;
Equality is permitted. Not sure about comparisons. It is clear that 45
degrees is greater than 40 degrees but not sure about -90 degrees and +90
degrees.
For completeness, it is necessary to provide an additional form of generic
parameter thus
generic
type F is delta <> mod <>;
It does not seem fruitful to contemplate modular decimal types.
One problem with the above proposal is that on a binary machine a range such
as -180 to +180 does not permit the exact representation of 60 degrees which
mathematically is a very important angle. Oh, maybe it doesn't matter we
cannot represent one-third accurately in any scheme.
And the thought of writing a standard package for dealing with latitude and
longitude is just likely to lead to sleepless nights and no package.
Any thoughts anyone?
****************************************************************
From Bob Duff
Date: Monday, 26 October 2009 2009 9:41 AM
> !topic Cyclic fixed point
As I said before, I am not convinced that this feature is worth the trouble.
I'm mainly concerned about implementation cost.
> -180.0 -> 16#0000#
> -90.0 -> 16#4000#
> 0.0 -> 16#8000#
> 45.0 -> 16#A000#
> 90.0 -> 16#C000#
> +180.0 -> 16#0000#
Hmm... As a compiler writer, the above numbers look scary.
****************************************************************
From Randy Brukardt
Date: Monday, 26 October 2009 5:14 PM
Bob Duff writes:
> John Barnes wrote:
>
> > !topic Cyclic fixed point
>
> As I said before, I am not convinced that this feature is
> worth the trouble.
> I'm mainly concerned about implementation cost.
I agree with Bob.
> > -180.0 -> 16#0000#
> > -90.0 -> 16#4000#
> > 0.0 -> 16#8000#
> > 45.0 -> 16#A000#
> > 90.0 -> 16#C000#
> > +180.0 -> 16#0000#
>
> Hmm... As a compiler writer, the above numbers look scary.
They do to me, too. John might have missed the obvious problem: he has the
same representation for -180.0 and +180.0. That's going to make it really
hard to represent Bearing'First and Bearing'Last. I suppose one could define
the range such that the upper bound of the specified range isn't included in
the actual range (the real upper bound being Bearing'Last-Bearing'Small),
but that surely is going to complicate things. Especially as someone might
prefer that the lower bound is excluded rather than the upper (you would not
be allowed to write +180.0 in the scheme I suggested above - it's not in
range).
****************************************************************
From: John Barnes
Date: Monday, 26 October 2009 5:29 PM
Interesting point about First and Last. Maybe we don't need them. Maybe they
can be the same. Would it matter? Why would you want to use them? The
difficulty seems to me to lie with trying to pretend that they are
different. There is no difference physically between -180 degrees and +180
degrees (except in obscure bits of quantum mechanics but that's a
different application).
Terry Froggatt wanted the upper limit to be the given value minus Small.
Implementation looked rather easy to me at the code generation level.
****************************************************************
From: Randy Brukardt
Date: Monday, 26 October 2009 6:37 PM
John Barnes writes:
> Interesting point about First and Last. Maybe we don't need
> them. Maybe they can be the same. Would it matter? Why would
> you want to use them?
Well, the problem is that pretty much all of the semantics of scalar
subtypes in Ada is defined based on the range (or First .. Last) of the
subtype. And every scalar subtype has a range. I tried to eliminate that
requirement when I was working on discontiguous subtypes, and I completely
failed -- I ended up defining the range anyway.
You'd pretty much have to ban the use of any constraints with such a cyclic
type if you don't define the range. Along with the attributes 'First, 'Last,
'range. That could get pretty messy, and it would be totally inconsistent
with every other scalar type.
> The difficulty seems to me to lie with
> trying to pretend that they are different. There is no
> difference physically between -180 degrees and +180 degrees
> (except in obscure bits of quantum mechanics but that's a
> different application).
>
> Terry Froggatt wanted the upper limit to be the given value
> minus Small.
Right, that's the obvious answer. Fixed point already works that way and it
causes all kinds of problems writing the value of 'Last.
> Implementation looked rather easy to me at the code generation level.
Maybe if you know how to handle biased representations. If you don't
(Janus/Ada doesn't), it would appear that you'd have to add (at least) the
full generality of that. That's a *big* change to the code generation model.
****************************************************************
From: John Barnes
Date: Tuesday, 27 October 2009 2:54 AM
Randy Brukardt writes
>> Terry Froggatt wanted the upper limit to be the given value
>> minus Small.
>
> Right, that's the obvious answer. Fixed point already works that way
and it causes all kinds of problems writing the value of 'Last.
I don't think its the obvious answer. But maybe that is what one would have
to do.
It is a conundrum. Maybe one doesn't want constraints but it would seem nice
to be able to say to the pilot "steer East (90) with a tolerance of 2
degrees". Actually I don't suppose we really want Constraint_Error if he
veers slightly off course!
**************************************************************
From: Martin Dowie
Date: Tuesday, 27 October 2009 11:58 AM
FWIW...
Although the pilot (or any user of an avionic system) is presented with
degrees, it's very likely that value is converted before being 'used' by
the underlying software system. I've seen them converted into a
fixed-point range -1.0 .. 1.0-small; float range -180 .. 180; float
range -pi .. pi; float range -1.0 .. 1.0 and probably others.
I think getting a "System of Units" addition to the language would help
here more than trying to create a super-set solution to the curiosities
of deg/rad, az/el, u/v/w or lat/long. If there were a SoU feature to the
language I'm pretty sure that building lat/long et al packages on top
would be much simpler.
**************************************************************