!standard A.5.4(4) 20-02-05 AI12-0362-1/01 !class Amendment 20-02-05 !status work item 20-02-05 !status received 19-11-12 !priority Low !difficulty Easy !subject Floor and other rounding attributes for fixed point types !summary Floor, Ceiling, and rounding attributes are supported for fixed point types. !problem There is a growing interest in fixed-point with the emergence of machine learning and GPUs. It is nice if an algorithm can be moved between fixed and float without signifiant re-engineering. However, the attributes Floor Ceiling, Rounding, Unbiased_Rounding, Machine_Rounding, and Truncation are missing for fixed point types. This forces unnecessary conversions to floating point types, which can themselves introduce rounding effects. !proposal (See Summary.) !wording A fixed point type *has integral values* if its Small value is an integral value or if a multiple of the Small value is an integral value. A generic formal type is defined to have integral values. Add after A.5.4(4): The following primitive function attributes are defined for any subtype S of a fixed point type T that has integral values: S'Ceiling S'Ceiling denotes a function with the following specification: function S'Ceiling (X : T) return T The function yields the value *Ceiling(X)*, that is, the smallest (most negative) integral value greater than or equal to X. If T is a generic formal type, S'Ceiling raises Program_Error if the actual subtype does not have integral values. S'Floor S'Floor denotes a function with the following specification: function S'Floor (X : T) return T The function yields the value *Floor(X)*, that is, the largest (most positive) integral value less than or equal to X. S'Rounding S'Rounding denotes a function with the following specification: function S'Rounding (X : T) return T The function yields the integral value nearest to X, rounding away from zero if X lies exactly halfway between two integers. S'Unbiased_Rounding S'Unbiased_Rounding denotes a function with the following specification: function S'Unbiased_Rounding (X : T) return T The function yields the integral value nearest to X, rounding toward the even integer if X lies exactly halfway between two integers. S'Machine_Rounding S'Machine_Rounding denotes a function with the following specification: function S'Machine_Rounding (X : T) return T The function yields the integral value nearest to X. If X lies exactly halfway between two integers, one of those integers is returned, but which of them is returned is unspecified. This function provides access to the rounding behavior which is most efficient on the target processor. AARM Discussion: We leave the rounding unspecified, so that users cannot depend on a particular rounding. This attribute is intended for use in cases where the particular rounding chosen is irrelevant. If there is a need to know which way values halfway between two integers are rounded, one of the other rounding attributes should be used. S'Truncation S'Truncation denotes a function with the following specification: function S'Truncation (X : T) return T The function yields the value Ceiling(X) when X is negative, and Floor(X) otherwise. [Editor's note: The following is not indented like the above; it applies to all of these attribute functions.] For all of these attributes, if T is a generic formal type, S'Floor raises Program_Error if the actual subtype does not have integral values. AARM To Be Honest: The check that the type of the prefix has integral values is considered a Legality Rule. AARM Reason: The rules here for generic formal types are classic assume-the-best rules for legality checking; the check is redone in the specification of the instance. We use a runtime check on the actual subtype to avoid assume-the-worst in generic bodies (which would mean the attributes could never be used in a generic body on a formal subtype). For implementations that expand generic bodies, it is always possible to provide a warning about the exception being raised. !discussion We only allow these attributes on types that have integral values in order to avoid nonsense results for types that cannot exactly represent integers. For instance, for a type defined: type Foobar is delta 0.7 range 0.0 .. 7.0 with Small => 0.7; Foobar'Floor(1.4) = 0.7 (as 0.7 is the nearest model number to 1.0). But these functions are defined to return "integral values", and it takes a strong imagination to see 0.7 as an integral value. Worse, in the worst case, this issue can destroy one of the primary purposes of the rounding attributes: to specify how a value gets rounded to an integer value. type Horrible is delta 2.5 range -10.0 .. 10.0 with Small => 2.5; Obj : Horrible := 2.5; A : Integer := Integer(Horrible'Floor(Obj)); The purpose of this expression is to ensure that 2.5 rounds down so that A = 2. But here, the result of Horrible'Floor(Obj) would be 2.5, meaning that the default rounding of the integer conversion would be used - which is defined by 4.6(33) as round away from zero. Thus A will be 3, even though the user carefully wrote the expression needed to prevent that. Note that if the Small is itself an integer, these attributes are identity functions, so these can be allowed. !ASIS No change is needed. !ACATS test ACATS B- and C-Tests are needed to check proper definition and operation of the attributes. !appendix From: Jean-Pierre Rosen Sent: Tuesday, November 12, 2019 2:59 AM The question came recently on fr.comp.lang.ada as to why there was no 'Floor attribute for fixed points... and I could not find any reason. Is it an omission, not enough value, possible candidate for 202X? **************************************************************** From: Tucker Taft Sent: Tuesday, November 12, 2019 7:50 AM I would agree with making the attributes as much as possible independent of whether a real type is fixed or float. There seems to be a growing interest in fixed-point with the emergence of machine learning and GPUs. It is nice if an algorithm can be moved between fixed and float without signifiant re-engineering. **************************************************************** From: Randy Brukardt Sent: Tuesday, November 12, 2019 3:10 PM One problem with defining Floor and Ceiling for fixed point is dealing with the corner case where some integral values cannot be represented in the fixed point type. We'd have to figure out how that works. There's two forms of this issue: type Tiny_Fixed is delta 0.125 range 0.0 .. 0.5 with Small => 0.125; Here, Ceiling of any Tiny_Fixed value would be out of range. Probably raising Constraint_Error is OK here. If the small is tiny enough, even the base type may not have an integer value other than 0.0. (The float version has this issue as well, and it doesn't seem to be defined what happens. Specifically, T'Ceiling(T'Base'Last) potentially is an issue if T'Base'Last is not an integer. Probably a To Be Honest is good enough for floats, since it doesn't happen in IEEE math.) One could have a similar probem for Floor with an appropriate range. The second case is the real problem: type Weird_Fixed is delta 0.7 range 0.0 .. 70.0 with Small => 0.7; What is Weird_Fixed'Floor(2.1)? Explain your answer. :-) Even though such a type is arguably a pathology, we need to have some sort of definition for it. (One possibility is to make 'Floor and 'Ceiling only available for Small values such that Small*N = 1.0 for some integer N. To avoid a contract model problem, they'd have to raise Program_Error in a generic if the Small is bad, even if illegal elsewhere.) I suspect this issue is why they're not defined, but since they're useful, it probably is worth working harder to define them rather than letting the existence of a pathology prevent that. **************************************************************** From: Tucker Taft Sent: Tuesday, November 12, 2019 3:20 PM Program_Error for deltas that are not divisible into 1.0 might be one choice. **************************************************************** From: Randy Brukardt Sent: Tuesday, November 12, 2019 3:29 PM That's what I said (Small, not Delta, though - Delta's are meaningless semantically), even if I couldn't figure out how to put it into English. **************************************************************** From: Jean-Pierre Rosen Sent: Tuesday, November 12, 2019 3:38 PM > The second case is the real problem: > > type Weird_Fixed is delta 0.7 range 0.0 .. 70.0 > with Small => 0.7; > > What is Weird_Fixed'Floor(2.1)? Explain your answer. :-) It's 2.1. The model should be that the floor is Universal_Integer, then converted back to the type. Simple to explain, works with every case. Interestingly enough, the OP suggested that 'Floor would return Universal_Integer instead of the original type. Another possibility, avoids many problems, but would not ease switching back and forth between fixed points and floating points. **************************************************************** From: Tucker Taft Sent: Tuesday, November 12, 2019 3:48 PM But the conversion from Univ Integer to a fixed point type is not fully defined if between two multiples of small, so we would need to define which one to choose. The whole idea is a bit weird if the result is not an integer when done, so I think an unconditional Program_Error might be a better result (which would generally be detected at compile-time except in shared-generic situations). **************************************************************** From: Jean-Pierre Rosen Sent: Thursday, December 5, 2019 4:11 AM I don't think that raising Program_Error for a simple mathematical operation is a good idea. Why should it be different from an explicit conversion? I am willing to write the AI if everybody agrees that it is worth a try. **************************************************************** From: Tucker Taft Sent: Thursday, December 5, 2019 9:17 AM Go for it! **************************************************************** From: Jean-Pierre Rosen Sent: Thursday, December 5, 2019 8:22 AM Here it is... !standard A.5.3 <19-12-05> AI12-000X-1/01 !class Amendment !status work item !status received !priority Medium !difficulty Easy !subject 'Floor and 'Ceiling for fixed point types. !summary The 'Floor and 'Ceiling attributes are defined for every fixed point type. !problem Floating point types have 'Floor and 'Ceiling attributes. These are useful functions for all real calculations, however they are not provided for fixed point types. In order to avoid unnecessary conversions to an intermediate floating point type, it would be useful to provide them for fixed point types. !proposal S'Floor denotes a function with the following specification: function S'Floor (X : T) return T The function yields the value Floor(X), i.e., the result of converting to S the largest (most positive) integral value less than or equal to X. S'Ceiling denotes a function with the following specification: function S'Ceiling (X : T) return T The function yields the value Ceiling(X), i.e., the result of converting to S the smallest (most negative) integral value greater than or equal to X. !wording !discussion There is a special difficulty for 'Floor and 'Ceiling on fixed points, since integer values are not necessarily model numbers of the type. Therefore, these attributes are defined as the result of the conversion of the (universal integer) value of the mathematical Floor and Ceiling to the fixed point type, following normal rules for conversion. Another option would be to raise an exception if the result cannot be represented as an integer value, but it would be presumably less user-friendly, since no other operation raises an exception when the result cannot be exactly represented. !ASIS No change is needed !ACATS test An ACATS C-Tests is needed to check the proper operation of the attributes. **************************************************************** From: Jean-Pierre Rosen Sent: Friday, December 6, 2019 8:04 PM > > But the conversion from Univ Integer to a fixed point type is not > > fully defined if between two multiples of small, so we would need to > > define which one to choose. The whole idea is a bit weird if the > > result is not an integer when done, so I think an unconditional > > Program_Error might be a better result (which would generally be > > detected at compile-time except in shared-generic situations). > I don't think that raising Program_Error for a simple mathematical > operation is a good idea. I agree. For types where it is possible, it should be illegal. For generic formal types (only), it needs to raise Program_Error to avoid contract problems. > Why should it be > different from an explicit conversion? Not quite sure what "explicit conversion" you are talking about. But for an Integer to fixed point conversion, the "contract" is that the result is the closest value to the operand. For the Floor and Ceiling attributes, the contract is that the result is the appropriate *Integer* value for the operand. If an integer value cannot be delivered in most cases, then the contract cannot be met for those cases, and the operation is misleading at best. If a multiple of the Small is not an integer, then the above is true, and the operation should not be allowed. My preference is for the operation to be illegal for non-formal types in that case, to avoid the possibility of someone failing to notice the problem until testing or worse, deployment. This case is likely the reason that these operations were not provided in the first place, but that seems like a baby with the bathwater situation (types for which this is a problem are quite unusual). > I am willing to write the AI if everybody agrees that it is worth a > try. I was going to do it next week, but I don't mind someone else doing work for me. :-) I'm not interested in a version that allows pathological results that violate the contract of the operation, however. **************************************************************** From: Jean-Pierre Rosen Sent: Saturday, December 7, 2019 1:02 AM >> Why should it be >> different from an explicit conversion? > Not quite sure what "explicit conversion" you are talking about. The explicit conversion of the universal integer representing the floor to the fixed point type. > But for an > Integer to fixed point conversion, the "contract" is that the result > is the closest value to the operand. For the Floor and Ceiling > attributes, the contract is that the result is the appropriate > *Integer* value for the operand. If an integer value cannot be > delivered in most cases, then the contract cannot be met for those > cases, and the operation is misleading at best. No, you miss Ada's (and Brown's) model of real arithmetic. A real value stands for a small interval, like an approximate number. Therefore it makes sense to return the value that represents an interval that includes the (mathematical) Floor/Ceiling, even if its associated model number is not integer. That behaviour is consistent with the model of arithmetic and avoids all exception and contract model problems. A note would certainly be welcome, though. This should not surprise the user more than the following example (extracted from one of my slides about real arithmetics): procedure Test_Fix is type Fix is delta 0.1 range -10.0 .. 10.0; X : Fix := 0.4; Y : Fix; begin Y := X + X + X; -- prints as 1.1 end Test_Fix; **************************************************************** From: Randy Brukardt Sent: Sunday, December 8, 2019 5:23 PM > >> Why should it be > >> different from an explicit conversion? > > Not quite sure what "explicit conversion" you are talking about. > The explicit conversion of the universal integer representing the > floor to the fixed point type. You can't directly write such a conversion in Ada for a non-static expression. Any conversion you can write has to include some explicit discrete type and that type brings the possibility of exceptions. > > But for an > > Integer to fixed point conversion, the "contract" is that the result > > is the closest value to the operand. For the Floor and Ceiling > > attributes, the contract is that the result is the appropriate > > *Integer* value for the operand. If an integer value cannot be > > delivered in most cases, then the contract cannot be met for those > > cases, and the operation is misleading at best. > No, you miss Ada's (and Brown's) model of real arithmetic. Not at all. > A real value stands for a small interval, like an approximate > number. Surely. But one of the reasons for using an integral value is that it avoids that nonsense; for all sane types, an integral value is a model number and thus the interval is just that exact value. > Therefore it makes sense to return the value that > represents an interval that includes the (mathematical) > Floor/Ceiling, even if its associated model number is not integer. No, that doesn't make sense. One of the important uses of attributes like 'Floor and 'Ceiling is to ensure that there is a unique value (*not* an interval) for the result. If you allow intervals from the result, then you are not getting that behavior. And you are bringing rounding effects into an operation that is intended to *eliminate* such effects. Fixed point 'Floor can be implemented with all integer operations so long as the scale factor (the inverse of the Small of the type) is an integer. Then 'Floor is (ignoring signs for the moment): Fixed'Floor(Expr) := Expr - (Expr mod Fixed'Scale); You can also implement 'Floor easily if the Small is an integer, in that case 'Floor is a no-op. Otherwise, through, the only sensible way to implement 'Floor would seem to be: Fixed (Some_Float'Floor (Some_Float(Expr) * Fixed'Small)) and that brings in the possibility of rounding errors and other nonsense. If someone really wants this latter expression, they can write it themselves and make all of the dangers obvious. It doesn't make sense to hide this mess behind an attribute that looks simple and accurate. These sorts of cases are rare, and I don't like the fact that we've thrown out the baby with the bathwater by not supporting this attribute in the common case where it makes sense and has a reasonable implementation. But forcing implementations to support a nonsense implementation which almost certainly is not going to give the result that the user wants is not helping anyone. Moreover, given the rare use of these things, it's likely that implementers would cut corners here and only use the bad implementation. (*I* surely would do that here; I don't care much about fixed point and don't have much customer usage.) I don't see any reason to make implementers spend effort on a bad implementation simply so that some rarely-used types can have attributes that doesn't even serve their intended purpose for such types. Let's have them spend all of their effort on a good implementation (only). > That behaviour is consistent with the model of arithmetic and > avoids all exception and contract model problems. A note > would certainly be welcome, though. > > This should not surprise the user more than the following > example (extracted from one of my slides about real arithmetics): > > procedure Test_Fix is > type Fix is delta 0.1 range -10.0 .. 10.0; > X : Fix := 0.4; > Y : Fix; > begin > Y := X + X + X; -- prints as 1.1 > end Test_Fix; This surprised me and I know the fixed point model. Eventually I realized that you had intentionally violated rule #1 of fixed point types -- *always* specify the small. Ada made a serious mistake by not making the Small = the Delta initially, and the only reasonable workaround to that is to always specify the Small so you get want you mean and not some nonsense like the above. I presume AdaControl has such a rule, and I doubt that there are any serious users of fixed point that don't follow it. Otherwise, *every* use of fixed point is a surprise. **************************************************************** From: Jean-Pierre Rosen Sent: Monday, December 9, 2019 10:04 AM > You can't directly write such a conversion in Ada for a non-static > expression. Any conversion you can write has to include some explicit > discrete type and that type brings the possibility of exceptions. Only in the case of an overflow, which is not what we are talking about. ... > Surely. But one of the reasons for using an integral value is that it > avoids that nonsense; for all sane types, an integral value is a model > number and thus the interval is just that exact value. I agree that a fixed point type where integer values are not model number may not be considered a "sane" type. But that's what we are talking about; otherwise, there is no problem. >> Therefore it makes sense to return the value that represents an >> interval that includes the (mathematical) Floor/Ceiling, even if its >> associated model number is not integer. > > No, that doesn't make sense. One of the important uses of attributes > like 'Floor and 'Ceiling is to ensure that there is a unique value > (*not* an interval) for the result. If you allow intervals from the result, > then you are not getting that behavior. And you are bringing rounding > effects into an operation that is intended to *eliminate* such effects. My proposal doesn't allow intervals: it requires the result of the conversion of the mathematical value to the fixed point type. I don't even think it is possible for the mathematical value to be exactly half way between two model numbers without being itself a model number. [proof needed]. (if 0.5 and 1.5 are model numbers, then certainly 1.0 is. 2.0 and 4.0 could be model numbers and not 3.0, but then there would be no model number whose floor is 3.0). > Fixed point 'Floor can be implemented with all integer operations so > long as the scale factor (the inverse of the Small of the type) is an > integer. Then 'Floor is (ignoring signs for the moment): > > Fixed'Floor(Expr) := Expr - (Expr mod Fixed'Scale); > > You can also implement 'Floor easily if the Small is an integer, in > that case 'Floor is a no-op. > > Otherwise, through, the only sensible way to implement 'Floor would > seem to > be: > > Fixed (Some_Float'Floor (Some_Float(Expr) * Fixed'Small)) > > and that brings in the possibility of rounding errors and other nonsense. You are talking here about implementation, which is a different issue. However, I don't see why it should be different from a conversion to an integer type, which has always been available. > If someone really wants this latter expression, they can write it > themselves and make all of the dangers obvious. It doesn't make sense > to hide this mess behind an attribute that looks simple and accurate. > > These sorts of cases are rare, and I don't like the fact that we've > thrown out the baby with the bathwater by not supporting this > attribute in the common case where it makes sense and has a reasonable > implementation. But forcing implementations to support a nonsense > implementation which almost certainly is not going to give the result > that the user wants is not helping anyone. Moreover, given the rare > use of these things, it's likely that implementers would cut corners here > and only use the bad implementation. > (*I* surely would do that here; I don't care much about fixed point > and don't have much customer usage.) Convert to some integer type, then convert back to the fixed point type (with some extra care to get the right integer). No need to use floats. ... >> This should not surprise the user more than the following example >> (extracted from one of my slides about real arithmetics): >> >> procedure Test_Fix is >> type Fix is delta 0.1 range -10.0 .. 10.0; >> X : Fix := 0.4; >> Y : Fix; >> begin >> Y := X + X + X; -- prints as 1.1 >> end Test_Fix; > > This surprised me and I know the fixed point model. Eventually I > realized that you had intentionally violated rule #1 of fixed point > types -- *always* specify the small. There are two views of fixed point types: some kind of integer type whose "step" happens to be different from 1, and the view of approximate numbers, which is what most physicists need. Your remark is correct only in the first case. A well behaved phycists would think (example above): Y = 1.2 +- 0.3 and of course, 1.1 is well within expected range. > Ada made a serious mistake by not making the Small = the Delta > initially, and the only reasonable workaround to that is to always > specify the Small so you get want you mean and not some nonsense like the > above. No nonsense, just a different use case. > I presume > AdaControl has such a rule, and I doubt that there are any serious > users of fixed point that don't follow it. check declarations (ordinary_fixed_type_no_small); > Otherwise, *every* use of fixed point is a surprise. ... until you are taught how it works (which is true of many things). **************************************************************** From: Randy Brukardt Sent: Monday, December 9, 2019 8:26 PM ... > > No, that doesn't make sense. One of the important uses of attributes > > like 'Floor and 'Ceiling is to ensure that there is a unique value > > (*not* an interval) for the result. If you allow intervals from the > > result, then you are not getting that behavior. And you are bringing rounding > > effects into an operation that is intended to *eliminate* such effects. > My proposal doesn't allow intervals: it requires the result of the > conversion of the mathematical value to the fixed point type. I don't > even think it is possible for the mathematical value to be exactly > half way between two model numbers without being itself a model > number. > [proof needed]. (if 0.5 and 1.5 are model numbers, then certainly 1.0 > is. 2.0 and 4.0 could be model numbers and not 3.0, but then there > would be no model number whose floor is 3.0). Huh? Now you are suggesting rounding (by the "halfway" stuff") in an attribute specifically designed to override any rounding with a specific answer. That doubles the nonsense! ... > > and that brings in the possibility of rounding errors and other nonsense. > You are talking here about implementation, which is a different issue. Not at all. The nonsense definition also leads to implementation expense. > However, I don't see why it should be different from a conversion to > an integer type, which has always been available. Conversion rounds, which is a very different operation. You can't use one to implement the other in general. Also, conversion also requires the use of floating point in general (or a runtime big-real library). Since that implementation has to be available as a fall-back, and no one can spend lots of time on a little-used feature, it becomes the primary implementation. After all, one has to handle types like: PI : constant := Ada.Numerics.PI; type Radian is delta PI/180.0 range -2*PI .. 2*PI with Small => PI/180.0; Even a simpler type like the Small => 0.7 that we were talking about can be problems to implement solely with integer math, as overflow is an ever-present problem. Only some cases can be implemented that way, and which ones depend on the Small and the range of the type. And there's at least 4 different patterns that might work, depending on those values. It's too expensive except for the most useful pattern. The integer conversions probably shouldn't have been available for these silly types, either, as they won't provide the intended results anyway. Probably too late for that (compatibility). ... > > Moreover, given the rare > > use of these things, it's likely that implementers would cut corners > > here and only use the bad implementation. > > (*I* surely would do that here; I don't care much about fixed point > > and don't have much customer usage.) > Convert to some integer type, then convert back to the fixed point > type (with some extra care to get the right integer). > No need to use floats. You have to use floats to convert to an integer in many of these cases (or a runtime big-real library). And a conversion rounds here, which is definitely not the Floor operation. For any of these types, converting to Integer will guarantee the wrong answer some of the time. ... > > This surprised me and I know the fixed point model. Eventually I > > realized that you had intentionally violated rule #1 of fixed point > > types -- *always* specify the small. > There are two views of fixed point types: some kind of integer type > whose "step" happens to be different from 1, and the view of > approximate numbers, which is what most physicists need. Your remark > is correct only in the first case. A well behaved phycists would think > (example above): > Y = 1.2 +- 0.3 > and of course, 1.1 is well within expected range. Since Ada real math is interval math, one has to analyze the intervals in order to know whether the error is really "+- 0.3". There's no way to know that for certain, in particular because Ada only requires the "close result set" for the results of operations on unusual small values. In any case, there are very few programmers who know enough to use proper error analysis on real math. Everyone one else "wings it" assuming usual mathematics. (For instance, the original SPARK did not use an interval math model, so it could "prove" all kinds of fallacies when it came to real math.) When that mathematics isn't followed, people are going to be confused. > > Ada made a serious mistake by not making the Small = the Delta > > initially, and the only reasonable workaround to that is to always > > specify the Small so you get want you mean and not some > nonsense like the above. > No nonsense, just a different use case. Even in the use case you are postulating, you don't get +- 0.3 as the error unless you specify the small. The actual error in each operation can be nearly as much as 2*Small, so you could get as much as +- 0.375. (Probably not in practice with these values and specific operations, but definitely with a mix of runtime values.) ... > > Otherwise, *every* use of fixed point is a surprise. > > > ... until you are taught how it works (which is true of many things). Sorry, human factors engineering does not rely on training to avoid surprise. (Boeing should have remembered that with the Max.) If something is designed in a way that means you don't get what you intend nearly all of the time, that is a surprise and it never goes away. I've seen examples like this for 30+ years, and I'm still surprised by them (I also remember that much about fixed point is a surprise, so I know to go back to first principles). I think that is the definition of a badly designed feature. We're getting off-topic here, and in any case, I don't think either of us is going to convince the other of anything. So it's probably getting close to time to close this discussion. This does reopen the question of whether we should be considering this idea for Ada 202x at all. It is well past our deadline for new ideas, and if we are going to take most people's new ideas and not consider them now (and that is certainly the case), we have to be very careful about adding in our own. Steve and I talked this over and thought that we could consider some very simple improvements so long as they have consensus. This one initially appeared in that category, but now that is looking less likely. Is it worth spending meeting time on an idea that isn't even supposed to be on our work list to solve this issue? **************************************************************** From: Jean-Pierre Rosen Sent: Tuesday, December 10, 2019 2:13 AM > We're getting off-topic here, and in any case, I don't think either of > us is going to convince the other of anything. So it's probably > getting close to time to close this discussion. Agreed > This does reopen the question of whether we should be considering this > idea for Ada 202x at all. It is well past our deadline for new ideas, > and if we are going to take most people's new ideas and not consider > them now (and that is certainly the case), we have to be very careful > about adding in our own. Steve and I talked this over and thought that > we could consider some very simple improvements so long as they have > consensus. This one initially appeared in that category, but now that > is looking less likely. Is it worth spending meeting time on an idea > that isn't even supposed to be on our work list to solve this issue? I propose to put it on the agenda, and then the group can vote it "stay alife" or "no action" (or anything else). **************************************************************** From: Arnaud Charlet Sent: Tuesday, December 10, 2019 2:49 AM > ... Is it worth spending meeting time on an idea > that isn't even supposed to be on our work list to solve this issue? No, I agree that it's not worth it and it's way too late for Ada 202x. ****************************************************************