!standard 3.5.9(2) 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. **************************************************************