* Re: Types with physical dimension [not found] <GRAHAM.94Sep27181841@canopus.clsi.com> @ 1994-09-28 17:36 ` William Brennan 1994-09-28 21:41 ` Tucker Taft 1 sibling, 0 replies; 26+ messages in thread From: William Brennan @ 1994-09-28 17:36 UTC (permalink / raw) In article <GRAHAM.94Sep27181841@canopus.clsi.com>, Paul Graham <graham@clsi.COM> wrote: > >One can model physical types in Ada by using private types, but this >involves writing a lot of operators. What do Ada programmers do to guard >against dimensional errors? > Ummm... I did it by using private types and writing a lot of operators. Yes, it's a bit unwieldy. But once it's done, it's done. Well, not really. If you want to create subtypes to have automatic constraint checking performed, you have to modify the package to add subtype definitions which I don't like too much. It would be best if the package remained totally stable, and subtypes could be added without surgery. Ada 9X may fix this with child units, but it doesn't do much for us living with Ada 83. If anyone wants to see an example of what I've got so far, please send me e-mail. These packages are still a work in progress, being done in my spare time. -- ---------------------------------------------------------------------------- === Team-Ada member === Bill Brennan brennan@panther.warm.inmet.com ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: Types with physical dimension [not found] <GRAHAM.94Sep27181841@canopus.clsi.com> 1994-09-28 17:36 ` Types with physical dimension William Brennan @ 1994-09-28 21:41 ` Tucker Taft 1994-09-29 4:11 ` Robert Dewar 1 sibling, 1 reply; 26+ messages in thread From: Tucker Taft @ 1994-09-28 21:41 UTC (permalink / raw) In article <GRAHAM.94Sep27181841@canopus.clsi.com>, Paul Graham <graham@clsi.COM> wrote: >While Ada's strong typing mechanism can catch errors like this: > > d : dollars; > f : francs; >... > d := d + f; -- error > >it does allow such nonsensical constructs as > > d := d * d; -- what does it mean to multiply dollars by dollars? > d := d ** 10; -- ?? > >VHDL provides physical types to model values with physical dimensions. A >VHDL physical type lacks certain predefined multiplication operations, lacks >exponentiation, and its division operation returns a universal_integer (or >root_integer in Ada 9x terminolgy). > ... >One can model physical types in Ada by using private types, but this >involves writing a lot of operators. What do Ada programmers do to guard >against dimensional errors? In Ada 9X, there is a new option. You can override the predefined operators of a numeric type with an abstract function. This flags any attempt to use the operation. For example, here we define 3 types and override their predefined multiplying and exponentiating operators with abstract versions: type Cm is digits 6; type Seconds is digits 6; type Cm_Per_Sec is digits 6; function "*"(Left, Right : Cm) return Cm is abstract; function "/"(Left, Right : Cm) return Cm is abstract; function "**"(Left : Cm; Right : Integer) return Cm is abstract; function "*"(Left, Right : Seconds) return Seconds is abstract; function "/"(Left, Right : Seconds) return Seconds is abstract; function "**"(Left : Seconds; Right : Integer) return Seconds is abstract; function "*"(Left, Right : Cm_Per_Sec) return Cm_Per_Sec is abstract; function "/"(Left, Right : Cm_Per_Sec) return Cm_Per_Sec is abstract; function "**"(Left : Cm_Per_Sec; Right : Integer) return Cm_Per_Sec is abstract; Then you can define the appropriate combinations: function "/"(Left : Cm; Right : Sec) return Cm_Per_Sec; function "*"(Left : Cm_Per_Sec; Right : Sec) return Cm; function "*"(Left : Sec; Right : Cm_Per_Sec) return Cm; You would probably want to put pragma Inline on these. You could actually define a generic to simplify this, so you wouldn't have to write the trivial bodies repeatedly: generic type Left_Type is digits <>; type Right_Type is digits <>; type Result_Type is digits <>; function Mul(Left : Left_Type; Right : Right_Type) return Result_Type; pragma Inline("*"); -- This means to inline calls on any instantiation function Mul(Left : Left_Type; Right : Right_Type) return Result_Type is begin return Result_Type(Left) * Result_Type(Right); -- Note that predefined operators "reemerge" in generics -- This is probably one of the few times where that is useful! end Mul; ... Ditto for a generic Div. Now you can just write: function "/" is new Div(Cm, Sec, Cm_Per_Sec); function "*" is new Mul(Cm_Per_Sec, Sec, Cm); function "*" is new Mul(Sec, Cm_Per_Sec, Cm); ... which is relatively painless. Of course it would be nice to have more direct support for units (given infinite resources, that is ;-), but at least with "abstract" and "generics" you can build your own consistency checks. >Paul >-- >Paul Graham graham@compass-da.com Compass Design Automation, Inc. >(speaking only for myself) "Cekoslovakyalilastiramadiklarimizdanmissiniz." S. Tucker Taft Ada 9X Mapping/Revision Team Intermetrics, Inc. Cambridge, MA 02138 P.S. "abstract" subprograms weren't invented for this purpose, but they seem to do the job fairly nicely. Note that any untagged type may have an "abstract" primitive subprogram. But if a tagged type has an "abstract" primitive, then it must itself be "abstract." -T ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: Types with physical dimension 1994-09-28 21:41 ` Tucker Taft @ 1994-09-29 4:11 ` Robert Dewar 1994-09-29 11:19 ` Peter Hermann 1994-09-29 13:37 ` Tucker Taft 0 siblings, 2 replies; 26+ messages in thread From: Robert Dewar @ 1994-09-29 4:11 UTC (permalink / raw) "Of course it would be nice to have more direct support for units" In the "of course" here likes a rather fundamental assumption which I question, namely that it is always desirable to have features at hand that do exactly what you want in the most convenient way. While that may seem locally optimal, I am afraid that following this inclination repeatedly leads to too much complexity in language design. Remember that a reader must be able to read the code, that means that a reader has to be able to pretty much understand the whole language since there is no restriction on what the writer can write. A big language is not so bad from the writer's point of view, since you only learn what you need, but from the reader's point of view, the complexity is much harder to handle. To me, the units case crosses the line. I think you can build this well enough in Ada, esp in Ada 9X with the abstract feature, and I think that (even given infinite resources :-) it would be a mistake to add an additional (inevitably somewhat complex) feature that would handle this more directly. ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: Types with physical dimension 1994-09-29 4:11 ` Robert Dewar @ 1994-09-29 11:19 ` Peter Hermann 1994-09-30 10:17 ` Dr John Stockton 1994-10-03 4:37 ` Robert Dewar 1994-09-29 13:37 ` Tucker Taft 1 sibling, 2 replies; 26+ messages in thread From: Peter Hermann @ 1994-09-29 11:19 UTC (permalink / raw) Robert Dewar (dewar@cs.nyu.edu) wrote: : "Of course it would be nice to have more direct support for units" : In the "of course" here likes a rather fundamental assumption which I : question, namely that it is always desirable to have features at hand : that do exactly what you want in the most convenient way. While that : may seem locally optimal, I am afraid that following this inclination : repeatedly leads to too much complexity in language design. Remember : that a reader must be able to read the code, that means that a reader : has to be able to pretty much understand the whole language since there : is no restriction on what the writer can write. A big language is not agreed. The reader would be "overloaded". but (see below) : so bad from the writer's point of view, since you only learn what you : need, but from the reader's point of view, the complexity is much : harder to handle. : To me, the units case crosses the line. I think you can build this well enough Because you are involved in compiler construction? ;-) :-) : in Ada, esp in Ada 9X with the abstract feature, and I think that (even : given infinite resources :-) it would be a mistake to add an additional : (inevitably somewhat complex) feature that would handle this more : directly. I don't see it necessarily as an add-on feature like another "rucksack". Ada has done a good job to prevent semantic errors. I think however, that for Ada2000+ there are still reserves which are not digged out in the abstraction process. I am feeling that there must be better methods which fit smoothly into a language concept. A good solution would bring another major step in the abstraction process. Today, we are able to prevent an expression like meter times meter giving meter. (you may substitute inch for meter :-) We may allow meter times meter giving an_area_type. The tools are here but certainly only rarely used. Did I tease your phantasy? The problem is with any language. We need some words to communicate but the optimal set is seldom reached. -- Peter Hermann Tel:+49-711-685-3611 Fax:3758 ph@csv.ica.uni-stuttgart.de Pfaffenwaldring 27, 70569 Stuttgart Uni Computeranwendungen Team Ada: "C'mon people let the world begin" (Paul McCartney) ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: Types with physical dimension 1994-09-29 11:19 ` Peter Hermann @ 1994-09-30 10:17 ` Dr John Stockton 1994-10-03 4:37 ` Robert Dewar 1 sibling, 0 replies; 26+ messages in thread From: Dr John Stockton @ 1994-09-30 10:17 UTC (permalink / raw) In article <36e7sf$19ql@info2.rus.uni-stuttgart.de> ucaa2385@iris3.csv.ica.uni-stuttgart.de (Peter Hermann) writes: >Robert Dewar (dewar@cs.nyu.edu) wrote: >: "Of course it would be nice to have more direct support for units" >Today, we are able to prevent an expression like >meter times meter giving meter. (you may substitute inch for meter :-) >We may allow meter times meter giving an_area_type. I missed the beginning of this. FYI, there was an article in European Journal of Physics earlier this decade AFAIR about a language, AMPERE?, which had types including physical dimensions for compile-time checking, and run-time limit (upper- & lower- bound) arithmetic. As a metrologist, I would find both very desirable, though I'd need "statistical" rather than "worst-case" arithmetic - and have implemented this to some extent in Borland Pascal. -- Regards, John Stockton. JRS@newton.npl.co.uk from off-site, or header address should now work. National Physical Laboratory, Teddington, Middlesex, TW11 0LW, UK Direct Phone +44 181-943 6087, Nearby Fax +44 181-943 7138 ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: Types with physical dimension 1994-09-29 11:19 ` Peter Hermann 1994-09-30 10:17 ` Dr John Stockton @ 1994-10-03 4:37 ` Robert Dewar 1 sibling, 0 replies; 26+ messages in thread From: Robert Dewar @ 1994-10-03 4:37 UTC (permalink / raw) Peter, your meters * meters not being allowed to give meters can be done in a perfectly straightforward manner using abstract subprograms in Ada 9X, why isn't that solution good enough for you? ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: Types with physical dimension 1994-09-29 4:11 ` Robert Dewar 1994-09-29 11:19 ` Peter Hermann @ 1994-09-29 13:37 ` Tucker Taft 1994-10-03 4:40 ` Robert Dewar 1 sibling, 1 reply; 26+ messages in thread From: Tucker Taft @ 1994-09-29 13:37 UTC (permalink / raw) In article <36deok$dce@gnat.cs.nyu.edu>, Robert Dewar <dewar@cs.nyu.edu> wrote: >"Of course it would be nice to have more direct support for units" That's cheating a bit (you must have a politician in the family) -- you left off my parenthetical comment and smiley "(given infinite resources, that is ;-)" >In the "of course" here likes a rather fundamental assumption which I >question, namely that it is always desirable to have features at hand >that do exactly what you want in the most convenient way. While that >may seem locally optimal, I am afraid that following this inclination >repeatedly leads to too much complexity in language design. > ... I completely agree with the above, and that is one reason why Ada 9X does *not* have direct support for units. You always have to weigh complexity versus benefits (some people's scales are sturdier than others ;-). I guess I should have "expanded" on my smiley a bit more... -Tucker Taft ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: Types with physical dimension 1994-09-29 13:37 ` Tucker Taft @ 1994-10-03 4:40 ` Robert Dewar 0 siblings, 0 replies; 26+ messages in thread From: Robert Dewar @ 1994-10-03 4:40 UTC (permalink / raw) Tuck takes me to task for not including the "given infinite resources :-) from his original message. But of course the point is that infinite resources for implementation are totally besides the point, I have no concern for implementors in this discussion, only for readers, and unless infinite resources also gives readers infinite brain power, it won't help :-) ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: Types with physical dimension
@ 1994-09-28 19:28 Paul Pukite
0 siblings, 0 replies; 26+ messages in thread
From: Paul Pukite @ 1994-09-28 19:28 UTC (permalink / raw)
To: graham
Paul Graham <graham@clsi.COM> wrote:
>One can model physical types in Ada by using private types, but this
>involves writing a lot of operators. What do Ada programmers do to guard
>against dimensional errors?
You don't necessarily need to invoke private types in Ada. By creating a
derived type like:
type Dollars is new INTEGER; -- Also can put in range constraints
you cannot multiply two dollar objects in another package unless you
specifically state that you want the "*" operator used. (Ada 9X reduces
the extra code required to "use" the "*".)
This guards against some of the dimensional errors as do the range
constraints, but I agree that VHDL physical types are rather neat.
--
Paul Pukite (pukite@daina.com)
DAINA Engineering 612/781-7600
4111 Central AVE NE, Suite 212
Minneapolis, MN 55421-2953
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: Types with physical dimension @ 1994-09-28 10:55 Simtel20 Transfer 1994-09-28 18:56 ` Mark A Biggar 1994-10-04 2:06 ` lmiller 0 siblings, 2 replies; 26+ messages in thread From: Simtel20 Transfer @ 1994-09-28 10:55 UTC (permalink / raw) Paul Grham writes: One can model physical types in Ada by using private types, but this involves writing a lot of operators. What do Ada programmers do to guard against dimensional errors? Paul -- Paul Graham graham@compass-da.com Compass Design Automation, Inc. The now renamed ABET (Ada Based Environment for Test) IEEE standard has an Ada package that defines _many_ physical types. If you need pointers let me know. p.s. It just occurred to e that maybe the SEI sghould consider putting references to it on their home page under programming languages. p.p.s. Its a shame they can't put the entire standard on-line but it is copyrighted by the IEEE (one of my favorite gripes is that such standards are not on-line). Now the IEEE may have changedd their policy. If so will someone please correct me. hope this helps. sam harbaugh HARBAUGH@ROO.FIT.EDU ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: Types with physical dimension 1994-09-28 10:55 Simtel20 Transfer @ 1994-09-28 18:56 ` Mark A Biggar 1994-10-04 2:06 ` lmiller 1 sibling, 0 replies; 26+ messages in thread From: Mark A Biggar @ 1994-09-28 18:56 UTC (permalink / raw) Another possibility is to use a discriminated type to keep track of dimensions like so: generic type Base is digits <>; package Units is type Unit(Length_DIM: Integer; Mass_DIM: Integer; Time_DIM: Integer) is private; function "*"(Left, Right: Unit) return Unit; function "*"(Left: Unit; Right: Base) return Unit; function "+"(Left, Right: Unit) return Unit; function "-"(X: Unit) return Unit; -- etc; subtype Length is Unit(1,0,0); subtype Area is Unit(2,0,0); subtype Mass is Unit(0,1,0); subtype Time is Unit(0,0,1); suntype Frequency is Unit(0,0,-1); subtype Energy is Unit(2,1,-2); -- etc; private type Unit(Length_DIM: Integer; Mass_DIM: Integer; Time_DIM: Integer) is record Value: Base; end record; end Units; package body Units is procedure Check_DIM(Left, Right: Unit) is begin if Left.Length_DIM \= Right.Length_DIM or else Left.Mass_DIM \= Right.Mass_DIM or else Left.Time_DIM \= Right.Time_DIM then raise CONSTRAINT_ERROR; end Check_DIM; function "*"(Left, Right: Unit) return Unit is begin return Unit'(Left.Length_DIM+Right.Length_DIM, Left.Mass_DIM+Right.Mass DIM, Left.Time_DIM+Right.Time_DIM, Left.Value * Right.Value); end "*"; function "+"(Left, RIght: Unit) return Unit is begin Check_DIM(Keft, Right); return UniL'(Left.Length_DIM, Left.Mass_DIM, Left.Time_DIM, Left.Value + Right.Value); end "+"; function "-"(X: Unit) is begin return Unit'(X.Length_DIM, X.Mass_DIM, X.Time_DIM, -X.Value); end "-"; -- etc; end Units; Yes I know that this requires runtime dimension checking, but you only have to use it until you are through debugging your code then you can replace the body with one that turns off all the checking. -- Mark Biggar mab@wdl.loral.com ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: Types with physical dimension 1994-09-28 10:55 Simtel20 Transfer 1994-09-28 18:56 ` Mark A Biggar @ 1994-10-04 2:06 ` lmiller 1 sibling, 0 replies; 26+ messages in thread From: lmiller @ 1994-10-04 2:06 UTC (permalink / raw) Stephe Leake at NASA GSFC (NBSSAL@stdvax.gsfc.nasa.gov) worked on something like this some years ago. I never worked with the packages produced but was told by Stephe that the huge number of types generated made for long compile times on good compilers and vast ugly deaths on poor ones. His final analysis: neat, but not quite worth the effort. For cartesian and other multi dimensional stuff I found creating types which reflected reality quite useful in pointing out errors at compile time. Overloading the operators then made for very readable expressions in code. type CART_AXES is (X, Y, Z); type POLAR_AXES is (Lat, Long, Radius); -- continue for all helpful coordinate systems... type CART_VECTORS is array (CART_AXES) of Float; type POLAR_VECTORS is array (POLAR_AXES) of Float; Then the compiler will always kick you in the shin if you try to add cart_vectors and Polar_Vectors without defining the proper operators. One can just imagine all of the opportunities C provides to make multitudes of mistakes related to this situation. ^ permalink raw reply [flat|nested] 26+ messages in thread
* Types with physical dimension @ 1994-09-27 22:18 Paul Graham 1994-09-28 13:59 ` Robert Dewar 1994-10-03 17:31 ` Stephen A. Leake 0 siblings, 2 replies; 26+ messages in thread From: Paul Graham @ 1994-09-27 22:18 UTC (permalink / raw) While Ada's strong typing mechanism can catch errors like this: d : dollars; f : francs; ... d := d + f; -- error it does allow such nonsensical constructs as d := d * d; -- what does it mean to multiply dollars by dollars? d := d ** 10; -- ?? VHDL provides physical types to model values with physical dimensions. A VHDL physical type lacks certain predefined multiplication operations, lacks exponentiation, and its division operation returns a universal_integer (or root_integer in Ada 9x terminolgy). An example of physical types: type length is range integer'low to integer'high units inches; feet = 12 inches; yards = 3 feet; end units; type area is range integer'low to integer'high units inches_2; feet_2 = 144 inches_2; yards_2 = 9 feet_2; end units; function "*"(x, y : length) return area is begin return length'pos(x) * length'pos(y) * inches_2; end; function "/"(x : area; y : length) return length is begin return area'pos(x) / length'pos(y) * inches; end; ... variable L : length; variable A : area; ... L := L * 2; -- legal L := L * L; -- illegal A := L * L; -- legal A := 2 inches * 2 inches; -- legal (= 4 inches_2) L := 4 feet_2 / 2 inches; -- legal (= 288 inches) (Please excuse any typos; I haven't simulated this.) One can model physical types in Ada by using private types, but this involves writing a lot of operators. What do Ada programmers do to guard against dimensional errors? Paul -- Paul Graham graham@compass-da.com Compass Design Automation, Inc. (speaking only for myself) "Cekoslovakyalilastiramadiklarimizdanmissiniz." ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: Types with physical dimension 1994-09-27 22:18 Paul Graham @ 1994-09-28 13:59 ` Robert Dewar 1994-09-30 2:06 ` R_Tim_Coslet 1994-10-03 17:31 ` Stephen A. Leake 1 sibling, 1 reply; 26+ messages in thread From: Robert Dewar @ 1994-09-28 13:59 UTC (permalink / raw) "What do Ada programmers do to guard against dimensional errors" Probably not much, because in practice, at least in my experience, such errors are rare, although they are an obvious target for theoretical discussions. Using private types is of course the appropriate way to do things in Ada 83. In Ada 9X, abstract operations can be used to eliminate unwanted operations. ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: Types with physical dimension 1994-09-28 13:59 ` Robert Dewar @ 1994-09-30 2:06 ` R_Tim_Coslet 0 siblings, 0 replies; 26+ messages in thread From: R_Tim_Coslet @ 1994-09-30 2:06 UTC (permalink / raw) >"What do Ada programmers do to guard against dimensional errors" > >Probably not much, because in practice, at least in my experience, such >errors are rare, although they are an obvious target for theoretical >discussions. When is 0 multiplied by 0 equal to 4 million? When a programmer dropped an equation from a data sheet directly into the code, without thinking that the equation used units of volts but the A/D converter supplying the numbers has some "arbitrary" unit scaling and is offset binary instead of twos complement. Example: 0V = 2048 A/D converter units. Therfore 0V * 0V = about 4 million. Admitedly not directly related to the current subject, but does illustrate a case of a problem with processing real world physical data without thinking the units and scaling thru... At least Ada reported constraint errors instead of just scrambling the result and giving a totally inexplicable wrong answer like Certain other languages would :-) R. Tim Coslet Usenet: R_Tim_Coslet@cup.portal.com technology, n. domesticated natural phenomena ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: Types with physical dimension 1994-09-27 22:18 Paul Graham 1994-09-28 13:59 ` Robert Dewar @ 1994-10-03 17:31 ` Stephen A. Leake 1994-10-04 11:51 ` Robert I. Eachus ` (2 more replies) 1 sibling, 3 replies; 26+ messages in thread From: Stephen A. Leake @ 1994-10-03 17:31 UTC (permalink / raw) In article <GRAHAM.94Sep27181841@canopus.clsi.COM> graham@clsi.COM (Paul Graham) writes: ... One can model physical types in Ada by using private types, but this involves writing a lot of operators. What do Ada programmers do to guard against dimensional errors? I run robots with Ada, so I deal with real dimensions all the time. Very early on, I started to write a package that enforced dimensionality; I defined METERS, METERS_PER_SECOND, etc. I quickly discovered that even simple equations need up to cubic dimensions, in all combinations of length, mass and time. Defining all these types and the associated operators was far too time-consuming to be worth it. So now I rely on code reviews and careful testing. The moral; strong typing is nice, but is no substitute for careful design and thorough testing. -- Stephen Leake, NASA Goddard Space Flight Center email: Stephen.Leake@gsfc.nasa.gov ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: Types with physical dimension 1994-10-03 17:31 ` Stephen A. Leake @ 1994-10-04 11:51 ` Robert I. Eachus 1994-10-04 19:45 ` Mark A Biggar 1994-10-12 3:43 ` Matt Kennel 1994-10-04 14:56 ` Robert Dewar 1994-10-05 8:38 ` Jean-Pierre Rosen 2 siblings, 2 replies; 26+ messages in thread From: Robert I. Eachus @ 1994-10-04 11:51 UTC (permalink / raw) In article <SAL714.94Oct3133110@rs710.gsfc.nasa.gov> sal714@rs710.gsfc.nasa.gov (Stephen A. Leake) writes: > I run robots with Ada, so I deal with real dimensions all the time. > Very early on, I started to write a package that enforced > dimensionality; I defined METERS, METERS_PER_SECOND, etc. I quickly > discovered that even simple equations need up to cubic dimensions, > in all combinations of length, mass and time. Defining all these > types and the associated operators was far too time-consuming to be > worth it. So now I rely on code reviews and careful testing. > The moral; strong typing is nice, but is no substitute for careful design > and thorough testing. Paul Hilfinger did a nice paper on using discriminants to check dimensionality. I don't have the paper in front of me but it works something like this: type Measure(Length,Mass,Time: Integer) is record Value: Float; end record; subtype Meters is Measure(1,0,0); subtype Kilograms is Measure(0,1,0); subtype Time is Measure(0,0,1); ...etc. Now you can define all the standard arithmetic operations on type Measure so that they keep the discriminants correct: function "*"(L,R: Measure) return Measure is begin return(L.Length+R.Length,L.Mass+R.Mass,L.Time+R.Time,L.Value*R.Value); end "*"; function "+"(L,R: Measure) return Measure is begin if L.Length /= R.Length or L.Mass /= R.Mass or L.Time /= R.Time then raise Constraint_Error; end if; return L.Value+R.Value; end "+"; In theory, if you use pragma INLINE, a good compiler should never store the discriminants and eliminate all the discriminant related code at compile time. In practice, when I used this technique, I had two versions of the specification of the types package, one with the discriminants and one which said "type Measure is Float;" and kept all the subtype declarations. I used the full package during unit test, and the streamlined package thereafter. The only problem I had was with square roots. I thought about changing the package to double all the dimensional values, so length would be (2,0,0), but I never did. -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is... ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: Types with physical dimension 1994-10-04 11:51 ` Robert I. Eachus @ 1994-10-04 19:45 ` Mark A Biggar [not found] ` <CxBBx8.7L@irvine.com> 1994-10-12 3:43 ` Matt Kennel 1 sibling, 1 reply; 26+ messages in thread From: Mark A Biggar @ 1994-10-04 19:45 UTC (permalink / raw) In article <EACHUS.94Oct4115107@spectre.mitre.org> eachus@spectre.mitre.org (Robert I. Eachus) writes: >In article <SAL714.94Oct3133110@rs710.gsfc.nasa.gov> sal714@rs710.gsfc.nasa.gov (Stephen A. Leake) writes: > > Very early on, I started to write a package that enforced > > dimensionality; I defined METERS, METERS_PER_SECOND, etc. I quickly > > discovered that even simple equations need up to cubic dimensions, > > in all combinations of length, mass and time. Defining all these > > types and the associated operators was far too time-consuming to be > > worth it. So now I rely on code reviews and careful testing. > > The moral; strong typing is nice, but is no substitute for careful design > > and thorough testing. > Paul Hilfinger did a nice paper on using discriminants to check >dimensionality. I don't have the paper in front of me but it works >something like this: > type Measure(Length,Mass,Time: Integer) is record > Value: Float; > end record; > subtype Meters is Measure(1,0,0); > subtype Kilograms is Measure(0,1,0); > subtype Time is Measure(0,0,1); > ...etc. > The only problem I had was with square roots. I thought about >changing the package to double all the dimensional values, so length >would be (2,0,0), but I never did. Unless you are doing some really wierd physics, the square root of a base dimension doesn't really make any sense. So just raise CONSTRAINT_ERROR whenever any of the dimensions is odd. -- Mark Biggar mab@wdl.loral.com ^ permalink raw reply [flat|nested] 26+ messages in thread
[parent not found: <CxBBx8.7L@irvine.com>]
* Re: Types with physical dimension [not found] ` <CxBBx8.7L@irvine.com> @ 1994-10-13 22:15 ` gamache 0 siblings, 0 replies; 26+ messages in thread From: gamache @ 1994-10-13 22:15 UTC (permalink / raw) In article <CxBBx8.7L@irvine.com>, adam@irvine.com (Adam Beneschan) writes: > mab@dst17.wdl.loral.com (Mark A Biggar) writes: > >> > Paul Hilfinger did a nice paper on using discriminants to check >> >dimensionality. I don't have the paper in front of me but it works >> >something like this: >> > type Measure(Length,Mass,Time: Integer) is record >> > Value: Float; >> > end record; >> > subtype Meters is Measure(1,0,0); >> > subtype Kilograms is Measure(0,1,0); >> > subtype Time is Measure(0,0,1); >> > ...etc. this part of the original post was snipped: >Now you can define all the standard arithmetic operations on type >Measure so that they keep the discriminant correct: > >function "+" (L,R : Measure) return Measure is >begin > if L.Length /= R.Length or L.Mass /= R.Mass or L.Time /= R.Time > then raise Constraint_Error; end if; > return L.Value + R.Value; >end "+"; I *really* liked this for a while after I saw it. For some scary reason, I guess I kept thinking about it in the back of my mind and now I'm not so sure. Couldn't I declare: Not_Kg : Measure(1,1,1); Not_Time : Measure(1,1,1); and then bypass all the protection this schema offers? Maybe use of membership tests in the if statement would help? But then again, I guess I never understood the *big deal* with units here anyway. Skipping to the chase scene: its my contention that most unit-related problems are systemic from engineers not wishing to declare the same units twice (or more). It's like, well we're building a couple 100K lines of code and I'm really gonna save by only defining Kilograms (or worse PI) once! My thinking is that if inside a given unit one is implementing D=R*T (distance = rate * time) then define all typesb as subtypes of a parent type that can be combined: subtype Feet is Float_32 range a..b; subtype Feet_per_Sec is Float_32 range c..d; subtype Sec is Float_32 range e..f; (assume float_32 is a 32-bit redefinition of a predefined type). Now variables can easily be combined in the necessary fashion WHILE AT LEAST INSURING VALID RANGE CONSTRAINTS ON THE INPUT DATA. In the example above one could envision either negative values (removable via a range constraint) or fractional values that may be nonesensical for certain inputs. Later in the application, some other object may need a type for seconds as well. In my experience often times these two objects never meet. So I say - define another type! In those interfacing situations between objects where there is commonality (in say the Seconds type) then I like the approach of a Time Package which provides needed operations (including conversion to float_32). Given the ability to build larger objects from small, isn't this the intent anyway? Just my 0.01 (two cents adjusted for inflation). ------------------------------------------------ with all_necessary_disclaimers; use 'em_2; ------------------------------------------------- ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: Types with physical dimension 1994-10-04 11:51 ` Robert I. Eachus 1994-10-04 19:45 ` Mark A Biggar @ 1994-10-12 3:43 ` Matt Kennel 1 sibling, 0 replies; 26+ messages in thread From: Matt Kennel @ 1994-10-12 3:43 UTC (permalink / raw) Robert I. Eachus (eachus@spectre.mitre.org) wrote: : In article <SAL714.94Oct3133110@rs710.gsfc.nasa.gov> sal714@rs710.gsfc.nasa.gov (Stephen A. Leake) writes: : > I run robots with Ada, so I deal with real dimensions all the time. : > Very early on, I started to write a package that enforced : > dimensionality; I defined METERS, METERS_PER_SECOND, etc. I quickly : > discovered that even simple equations need up to cubic dimensions, : > in all combinations of length, mass and time. Defining all these : > types and the associated operators was far too time-consuming to be : > worth it. So now I rely on code reviews and careful testing. : > The moral; strong typing is nice, but is no substitute for careful design : > and thorough testing. : Paul Hilfinger did a nice paper on using discriminants to check : dimensionality. I don't have the paper in front of me but it works : something like this: : type Measure(Length,Mass,Time: Integer) is record : Value: Float; : end record; : subtype Meters is Measure(1,0,0); : subtype Kilograms is Measure(0,1,0); : subtype Time is Measure(0,0,1); : ...etc. At one point I thought this was a good idea. Now my feeling is that you should have already non-dimensionalized your equations into systems of units specific for the problem. That way you get more understanding and "less number". Paradoxically, once you DON'T have physical units on your variables, it's easier to say whether something is "big" or "small". -- -Matt Kennel mbk@inls1.ucsd.edu -Institute for Nonlinear Science, University of California, San Diego -*** AD: Archive for nonlinear dynamics papers & programs: FTP to -*** lyapunov.ucsd.edu, username "anonymous". ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: Types with physical dimension 1994-10-03 17:31 ` Stephen A. Leake 1994-10-04 11:51 ` Robert I. Eachus @ 1994-10-04 14:56 ` Robert Dewar 1994-10-05 14:53 ` Bob Gilbert 1994-10-05 8:38 ` Jean-Pierre Rosen 2 siblings, 1 reply; 26+ messages in thread From: Robert Dewar @ 1994-10-04 14:56 UTC (permalink / raw) strong typing is like anything else, fine in moderation, but dangerous to health if overdoses are encountered. there is a common tendency in Ada programming to assume that since strong typing is a GOOD THING, it must make sense to use it as much as possible. This leads to programs which thousands of different integer types and conversions all over the place. For my taste that actually decreases reliability, since (a) it makes the code less readable (b) once you get in the habit of freely breaking type barriers by writing conversions, then the value of the type barriers is diminished. I much prefer a style in which different integer types are used only when it is very rare that the need for conversions will arise, or when the necessary conversions can be nicely abstracted. Similarly, if setting up an abstraction requires writing a huge amount of code, which might itself have errors, then the mere fact that you can use the abstraction neatly when you are done may not leave you ahead (this is an instance of the common behavior of spending your time building tools to increase your productivity, spending all your time on this is NOT a good idea :-) Obviously everyone knows that strong typing is helpful (says he after spending a frstrating half hour finding a bug in an idiotic little C program -- left the & off in a call to sscanf, resulting in unimaginable and hard to debug chaos). But that doesn't mean "the more strong typing tne better". Good software engineering is the art of choosing the right abstractions, and structures, and it is not the case that it is always preferable to raise the level of abstraction as far as possible -- it needs to be at just the right level. The units case is an interesting one. Sure there are are programming situations where providing some automatically type checked units checking makes sense, but there are also situations where the attempt to provide such checking is precisely abstraction overkill. It's a nice example that way, because it lies somewhere near the borderline, and you need the skill to make the right cut on this border. ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: Types with physical dimension 1994-10-04 14:56 ` Robert Dewar @ 1994-10-05 14:53 ` Bob Gilbert 0 siblings, 0 replies; 26+ messages in thread From: Bob Gilbert @ 1994-10-05 14:53 UTC (permalink / raw) In article km7@gnat.cs.nyu.edu, dewar@cs.nyu.edu (Robert Dewar) writes: ->strong typing is like anything else, fine in moderation, but dangerous to ->health if overdoses are encountered. -> ->there is a common tendency in Ada programming to assume that since strong ->typing is a GOOD THING, it must make sense to use it as much as possible. ->This leads to programs which thousands of different integer types and ->conversions all over the place. For my taste that actually decreases ->reliability, since {good stuff deleted} I can't agree more with this. I my work, I deal with mostly embedded processors with lots of interfaces to hardware. I have found that a very common mistake is to over-type, especially on input data from less than reliable sources. As an example, we had an interface with an IRIG time code generator which was supposed to generate a BCD format of the time. One of our programmers quickly set out to generate a BCD type to accomodate the input. Unfortunately, hardward does not always behave itself, and on occasion the time code generator would lock up and produce an output of all one's. Well needless to say we got constraint exceptions like crazy, and being a real-time system we could not tolerate the indeterminate nature of exceptions (besides software always has the burden of proving the hardware went south, and we needed to know what the illegal values being sent to us were in order to provide the necessary evidence). The solution was to just accept the BCD time value as an array of bytes, and then perform explicit conversion of this array to either a string value for output to a terminal, or a numeric value for use in internal computations. The explicit routines to perform the conversions would handle the case where illegal inputs were received without the use of exception handling. Anyway, I have found it very useful to never place constaints on input data from outside sources, and explicitly check the data for correctness. Now output data is a different matter. If I am generating something like gimbal commands where hardware could possibly be damaged if I output invalid or out of range values, then I definitely use strong typing to guarantee my output. Here getting the rare exception is usually much preferred, people get very upset when we software types break hardware. And of course the exception is rare since I (sould) have control of the data. I'm also usually very leery when constraint limits are placed on floats. I've seen too many instances where a programmer generated something like a float to represent a value from say 0..360 degrees on a circle and found that some intermediate result would take the value outside the range, or possibly rounding effects gave a value of 360.00000001, or the like. Many times it is easier to track down the error if you have the incorrect result rather than just an exception at the point where the value went out of the type range. -Bob ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: Types with physical dimension 1994-10-03 17:31 ` Stephen A. Leake 1994-10-04 11:51 ` Robert I. Eachus 1994-10-04 14:56 ` Robert Dewar @ 1994-10-05 8:38 ` Jean-Pierre Rosen 1994-10-05 10:35 ` Stephen J Bevan 1994-10-05 15:48 ` Norman H. Cohen 2 siblings, 2 replies; 26+ messages in thread From: Jean-Pierre Rosen @ 1994-10-05 8:38 UTC (permalink / raw) In article <SAL714.94Oct3133110@rs710.gsfc.nasa.gov>, sal714@rs710.gsfc.nasa.gov (Stephen A. Leake) writes: > I run robots with Ada, so I deal with real dimensions all the time. Very early > on, I started to write a package that enforced dimensionality; I defined > METERS, METERS_PER_SECOND, etc. I quickly discovered that even simple equations > need up to cubic dimensions, in all combinations of length, mass and time. > Defining all these types and the associated operators was far too > time-consuming to be worth it. So now I rely on code reviews and careful > testing. > > The moral; strong typing is nice, but is no substitute for careful design > and thorough testing. > There is another solution: run-time checking of dimensionality. You define a type like: type Physical is record Length : Dimension; Time : Dimension; Mass : Dimension; Charge : Dimension; Value : Float; end record; (Dimension being some Integer type). You redefine operators so that "+" and "-" operate only if the dimensions are the same (and raise Dimension_error otherwise), and "*" and "/" add (or subtract) dimensions. Note that if you are concerned about efficiency, you use this type for debugging, and then change it to: type Physical is new Float; for the working version (assuming a Value_of function to access the value). Alternatively, you can make the dimensions discriminants; this will improve safety and allow you to define nice subtypes like: subtype Meters is Physical(1, 0, 0, 0); but will make moving to plane Floats more difficult. Acknowledgements: I saw this idea in a paper long ago. As far as I recall, it was by N. Cohen. Norm, are you listening? ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: Types with physical dimension 1994-10-05 8:38 ` Jean-Pierre Rosen @ 1994-10-05 10:35 ` Stephen J Bevan 1994-10-05 13:17 ` Jean-Pierre Rosen 1994-10-05 15:48 ` Norman H. Cohen 1 sibling, 1 reply; 26+ messages in thread From: Stephen J Bevan @ 1994-10-05 10:35 UTC (permalink / raw) In article <36tole$j5e@cyclope.enst.fr> rosen@enst.fr (Jean-Pierre Rosen) writes: ... I saw this idea in a paper long ago. As far as I recall, it was by N. Cohen. Norm, are you listening? This sounds like the method discussed in [Hilfinger:acm:toplas:1988], I don't remember if Hilfinger referenced/acknowledged Norman though. For interested parties, I've also included some references to other work on adding dimensions to programming languages :- @article { Biedl:acm:sigplan:1977 , author= "Albrecht Biedl" , title= "An Extension of Programming Languages for Clerical Computation in Science and Engineering With Special Reference to PASCAL" , journal= acm:sigplan , volume= 12 , number= 4 , pages= "31--33" , month= apr , year= 1977 , checked= 19940516 , keywords= "Pascal, dimensional types" , sjb= "Proposes an extension to Pascal that allows dimensional information to be added to declarations." } @article { Karr:Lovemann:cacm:1978 , author= "Michael Kaar and Lovemann, III, David B." , title= "Incorporation of units into programming languages" , journal= cacm , volume= 21 , number= 5 , pages= "385--391" , month= may , year= 1978 , keywords= "dimensional types" , reffrom= Horning:pc:1978c , reffrom= Hilfinger:acm:toplas:1988 } @article { House:bcscj:1983 , author= "R. T. House" , title= "A proposal for an extended form of type checking of expressions" , journal= bcscj , volume= 26 , number= 4 , pages= "366--374" , month= nov , year= 1983 , cr= "8610-0116 (uncomplementary)" , cr= "8704-0276 (rebuttal+response)" , cr= "8705-0377 by Luca Cardelli - complementary" , keywords= "dimensional types" , sjb= "describes adding physical ``dimensions'' and ``units'' in a strongly typed language (Pascal in used)." , reffrom= Hilfinger:acm:toplas:1988 } @article { Gehani:spe:1985 , author= "N. H. Gehani" , title= "Ada's Derived Types and Units of Measure" , journal= spe , volume= 15 , year= 1985 , pages= "555--569" , keywords= "Ada, dimensional types" , reffrom= Dreiheller:Moerschbacher:Mohr:acm:sigplan:1986 , reffrom= Hilfinger:acm:toplas:1988 } @article { Manner:acm:sigplan:1986 , author= "R. M{\"a}nner" , title= "Strong Typing and Physical Units" , journal= acm:sigplan , volume= 21 , number= 3 , pages= "11--20" , month= mar , year= 1986 , keywords= "dimensional types" , reffrom= Dreiheller:Moerschbacher:Mohr:acm:sigplan:1986 } @article { Dreiheller:Moerschbacher:Mohr:acm:sigplan:1986 , author= "A. Dreiheller and M. Moerschbacher and B. Mohr" , title= "Programming Pascal with Physical Units" , journal= acm:sigplan , volume= 21 , number= 12 , pages= "114--123" , month= dec , year= 1986 , refs= 7 , checked= 19940617 , source= "Dept. Library" , keywords= "Pascal, dimensional types" , abstract= "In~\cite{Manner:acm:sigplan:1986} (SIGPLAN Notices 3/1986) M\"anner proposes an extension of Pascal permitting the use of physical units in programs. We discuss his issues in this paper and describe our own somewhat different approach. Our language extension PHYSCAL of Pascal not merely satisfies the requirements suggested by~\cite{Manner:acm:sigplan:1986}, but also supports predfined units (International Standard), thorough realisation of the concept of scale factors, input/output facilities for number with units. The new concepts are motivated, and the language description is given formally and by examples. Finally we discuss some details of the realised language implementation by a PHYSCAL-to-Pascal preprocessor in an UNIX environment." } @article { Jones:ddj:pp:1987 , author= "Do-While Jones" , title= "Dimensional Data Types" , journal= ddj:pp , volume= 12 , number= 127 , pages= "50--54" , month= may , year= 1987 , refs= 3 , checked= 19940513 , keywords= "Ada, dimensional types" , abstract= "Using dimensional units as data types can facilitate the writing of clearer, more easily maintained code. Do-While presents example programs in Ada." , xref= Ludquist:ddj:pp:1987 } @article { Hilfinger:acm:toplas:1988 , author= "Paul N. Hilfinger" , title= "An Ada Package for Dimensional Analysis" , journal= acm:toplas , volume= 10 , number= 2 , pages= "189--203" , month= apr , year= 1987 , refs= 8 , checked= 19940623 , source= "Dept. Library" , keywords= "dimensional analysis, language design, units, dimentional types" , abstract= "This paper illustrates the use of Ada's abstraction facilities -- notably, operator overloading and type parameterization -- to define an oft-requested feature: a way to attribute units of measure to variables and values. The definition given allows the programmer to specify units of measure for variables, constants, and parameters; checks uses of these entities for dimensional consistency; allows arithmetic between them, where legal; and provides scale conversions between commensurate units. It is not constrained to a particular system of measurement (such as the metric or English systems). Although the definition is in standard Ada and requires nothing special of the compiler, certain reasonable design choices in the compiler, discussed here at some length, can make its implementation particularly efficient." , sjb= "Proposes the use of a UNITS package which exports a QUANT type which encodes the various dimensions and which can be checked at runtime. Logically each variable/constant becomes a record with 5 integers representing the dimensions and a single float representing the scalar value. It is noted that With a naive compiler, this is very inefficient!" } ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: Types with physical dimension 1994-10-05 10:35 ` Stephen J Bevan @ 1994-10-05 13:17 ` Jean-Pierre Rosen 0 siblings, 0 replies; 26+ messages in thread From: Jean-Pierre Rosen @ 1994-10-05 13:17 UTC (permalink / raw) In article <BEVAN.94Oct5113509@lemur.cs.man.ac.uk>, bevan@cs.man.ac.uk (Stephen J Bevan) writes: > In article <36tole$j5e@cyclope.enst.fr> rosen@enst.fr (Jean-Pierre Rosen) writes: > ... I saw this idea in a paper long ago. As far as I recall, it was by > N. Cohen. Norm, are you listening? > > This sounds like the method discussed in [Hilfinger:acm:toplas:1988], > I don't remember if Hilfinger referenced/acknowledged Norman though. > For interested parties, I've also included some references to other > work on adding dimensions to programming languages :- My mistake - apologies to Paul Hilfinger ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: Types with physical dimension 1994-10-05 8:38 ` Jean-Pierre Rosen 1994-10-05 10:35 ` Stephen J Bevan @ 1994-10-05 15:48 ` Norman H. Cohen 1 sibling, 0 replies; 26+ messages in thread From: Norman H. Cohen @ 1994-10-05 15:48 UTC (permalink / raw) In article <36tole$j5e@cyclope.enst.fr>, rosen@enst.fr (Jean-Pierre Rosen) writes: |> Alternatively, you can make the dimensions discriminants; this will improve |> safety and allow you to define nice subtypes like: |> subtype Meters is Physical(1, 0, 0, 0); |> but will make moving to plane Floats more difficult. |> |> Acknowledgements: |> I saw this idea in a paper long ago. As far as I recall, it was by |> N. Cohen. Norm, are you listening? Yes, I'm listening. I wrote the paper under the pseudonym "Paul Hilfinger". :-) Here is the reference: Paul N. Hilfinger. An Ada package for dimensional analysis. ACM Transactions of Programming Languages and Systems 10, No. 2 (April 1988), 189-203 But seriously, folks, I disagree with Paul's approach. In the absence of heroic measures on the part of the compiler, besides imposing an added run-time overhead, it defers until run time the detection of errors that can be caught by static analysis. I've long felt that the best way to address this problem is at compile time, with a tool that takes a tabular specification of a system of units and generates a series of declarations declaring distinct types for distinct units, along with trivial subprogram bodies for overloaded versions of "*", "/", and "**". One complication in this approach is the need to define types for intermediate results that do not correspond to natural physical units. For example, the number of ergs spent in applying, over a distance of D centimeters, the amount of force required to accelerate a mass of M grams A centimeters per second per second is M*D*A. The intermediate result M*D is measured in gram centimeters, a physically meaningless unit. Had we written M*(D*A) instead, the intermediate result D*A would be measured in terms of centimeters squared over seconds squared, also physically meaningless. The tool must generate types for a reasonable number of such intermediate units of measure. There are an infinite number of possibilities--for example computing a mass by dividing mass to the fifth power by mass to the fourth power--that are not likely to arise in real expressions, but some rather strange-looking units like time to the power -2 ARE likely to arise. The trick is knowing where to draw the line so that a user of the automatically generated package will not be surprised by the illegality of a given expression. Another complication is scaling, when converting between different systems for measuring the same kind of quantity, such as the cm-g-sec (CGS) system and the m-kg-sec (MKS) system, or mixing units from different systems. One solution is to provide conversions only for a given kind of physical quantity--between kilograms and grams, or between meters and centimeters, for example, and to provide combining operators only within a given system. Thus you can't multiply kilograms times centimeters per second squared to obtain a force. You have to convert kilograms to grams and apply the CGS operators to obtain a result in dynes, or convert centimeters to meters and apply the MKS operators to obtain a result in newtons. If all these types are implemented as real types rather than private types, so that real literals can be used in expressions, then a conversion between, say, Dyne_Type and Newton_Type is automatically defined as a basic operation, but it does not have the right semantics. (It does not scale upon converting.) It is easy to write conversion functions that do the right thing, but there is no way to hide the automatically defined type conversions, which a programmer could easily be seduced into using by mistake. (The "is abstract" trick cannot be applied to type conversions.) -- Norman H. Cohen ncohen@watson.ibm.com ^ permalink raw reply [flat|nested] 26+ messages in thread
end of thread, other threads:[~1994-10-13 22:15 UTC | newest] Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- [not found] <GRAHAM.94Sep27181841@canopus.clsi.com> 1994-09-28 17:36 ` Types with physical dimension William Brennan 1994-09-28 21:41 ` Tucker Taft 1994-09-29 4:11 ` Robert Dewar 1994-09-29 11:19 ` Peter Hermann 1994-09-30 10:17 ` Dr John Stockton 1994-10-03 4:37 ` Robert Dewar 1994-09-29 13:37 ` Tucker Taft 1994-10-03 4:40 ` Robert Dewar 1994-09-28 19:28 Paul Pukite -- strict thread matches above, loose matches on Subject: below -- 1994-09-28 10:55 Simtel20 Transfer 1994-09-28 18:56 ` Mark A Biggar 1994-10-04 2:06 ` lmiller 1994-09-27 22:18 Paul Graham 1994-09-28 13:59 ` Robert Dewar 1994-09-30 2:06 ` R_Tim_Coslet 1994-10-03 17:31 ` Stephen A. Leake 1994-10-04 11:51 ` Robert I. Eachus 1994-10-04 19:45 ` Mark A Biggar [not found] ` <CxBBx8.7L@irvine.com> 1994-10-13 22:15 ` gamache 1994-10-12 3:43 ` Matt Kennel 1994-10-04 14:56 ` Robert Dewar 1994-10-05 14:53 ` Bob Gilbert 1994-10-05 8:38 ` Jean-Pierre Rosen 1994-10-05 10:35 ` Stephen J Bevan 1994-10-05 13:17 ` Jean-Pierre Rosen 1994-10-05 15:48 ` Norman H. Cohen
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox