comp.lang.ada
 help / color / mirror / Atom feed
* Re: How I declare a 'mod' type within a record?
  1997-07-30  0:00 How I declare a 'mod' type within a record? Matthew Kennedy
@ 1997-07-30  0:00 ` Matthew Heaney
  1997-07-31  0:00 ` Robert Dewar
  1997-08-05  0:00 ` Mars Gralia
  2 siblings, 0 replies; 5+ messages in thread
From: Matthew Heaney @ 1997-07-30  0:00 UTC (permalink / raw)



In article <33DF3FD2.20D2@mail.connect.usq.edu.au>,
q9522772@mail.connect.usq.edu.au wrote:


>Also, I can see how this could be made into a generic package but what I
>need is multiple time-series of different sizes.
>
>with Text_IO; use  Text_IO;
>procedure Aging is
>
>   type Number is new Float;
>   type Buffer is array(Integer range <>) of Number;
>   type Time_Series(Size : Integer) is
>      record
>         History : Buffer(0..Size-1);
>         Head : mod Size;
>      end record;
>
>   X : Time_Series(3);
>begin
>   ...
>end Aging;

From one Matthew to another: No, you can't do this.  The modulus for the
type must be a static expression. 

The reason for this is so that the compiler knows how much space to
allocate for the type at compile time; this admits a more efficient
implementation.

All scalar types must have constraints that are determinable at compile
time, that's why there's a special syntax for first-named subtypes (they
are marked with the word "type" instead of "subtype").

Note that you can't use a discriminant for the range constraint of a
component that's a numeric type, for example

type RT (Max : Positive) is
   record
      C : Integer range 0 .. Max;  -- range constraint illegal
   end record;

is illegal.

Furthermore, even though you can use the discriminant as an index
constraint, you can't use the discriminant value in an expression for an
index constraint, ie

type RT (Size : Positive) is
   record
      B : Buffer (0 .. Size - 1);  -- index expression is illegal
   end record;

This is also illegal.

However, you can use the discriminant for an index constraint of an array
component:

type RT (Max : Positive) is
   record
      C : String (1 .. Max);
   end record;

is perfectly legal.

There is a time when you can use the discriminant as part of an expression,
and that's when the expression is used for the initial value of a
component:

type RT (Default : Integer) is
   record
      C : Integer := 10 * Default + 3; -- expression OK
   end record;

You can even pass the discrimint to a function that returns the value used
for an initial value of a component (you may have a more complex initial
value to calculate).

Note that staticness only applies to scalar types, because the compiler
picks the hardware types for objects at compile time.  But records and
arrays are very dynamic:

procedure P (N : Positive) is

   type Array_Type is array (Positive range 1 .. N) of Integer range 1 .. N;

   type Record_Type is
      record
         C : Array_Type;
         I : Integer;
         C2 : Array_Type;
      end record;

begin

At compile time, you don't know how big Array_type or Record_Type will be,
so there's much more freedom there compared to non-composite types.

You can't use generic formal parameters as the constraints in a type
declaration either, because formal paramters aren't static.  So you can't
do this

generic
   I : Integer;
package GP is

   type FT is digits I;

   type MT is mod I;

end;

This is illegal, because the digit constraint and modulus (is that the
correct term?) constraint must be static, and I is not a static expression.

But you can use it for subtype constraints, in the normal way:

generic
   I : Integer;
package GP is

   subtype IT is Integer range  0 .. I;

   type MT is mod 10;
   subtype MST is MT range 0 .. I;

   type AType is array (Positive range 1 .. I) of IT;

end;

All legal (I think - I haven't tried to compile, but you get the idea),
because subtype constraints don't have to be static.

Hope that helps,
Matt

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
<mailto:matthew_heaney@acm.org>
(818) 985-1271




^ permalink raw reply	[flat|nested] 5+ messages in thread

* How I declare a 'mod' type within a record?
@ 1997-07-30  0:00 Matthew Kennedy
  1997-07-30  0:00 ` Matthew Heaney
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Matthew Kennedy @ 1997-07-30  0:00 UTC (permalink / raw)



Hello all,

I'm trying to implement a time-series type to aid in defference equation
simulations. I would like to use a 'mod' type which would be an elegant
way of cycling around the buffer (which is just an array).

Here is my code example, if you could examine it, I would be very
grateful :)  The compiler (GNAT) has fits when it sees the anonymous mod
type declared within the record making use of 'Size' - which is the
record parameter.

Note, I can't declare 'mod Size' as a sepereate type outside
'time_series' because 'Size' must be part of 'time_series'.

Also, I can see how this could be made into a generic package but what I
need is multiple time-series of different sizes.

with Text_IO; use  Text_IO;
procedure Aging is

   type Number is new Float;
   type Buffer is array(Integer range <>) of Number;
   type Time_Series(Size : Integer) is
      record
         History : Buffer(0..Size-1);
         Head : mod Size;
      end record;

   X : Time_Series(3);
begin
   ...
end Aging;


Thank you,
Matthew

-- 
Matthew Kennedy
Student of Electronics Engineering
University of Southern Queensland, Australia
  "When will you realise your already there?" 
      - Marilyn Manson




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: How I declare a 'mod' type within a record?
  1997-07-30  0:00 How I declare a 'mod' type within a record? Matthew Kennedy
  1997-07-30  0:00 ` Matthew Heaney
@ 1997-07-31  0:00 ` Robert Dewar
  1997-08-05  0:00 ` Mars Gralia
  2 siblings, 0 replies; 5+ messages in thread
From: Robert Dewar @ 1997-07-31  0:00 UTC (permalink / raw)



Matthew says

<<Here is my code example, if you could examine it, I would be very
grateful :)  The compiler (GNAT) has fits when it sees the anonymous mod
type declared within the record making use of 'Size' - which is the
record parameter. >>

I am sure GNAT does not "have fits", but rather simply diagnoses your
obviously illegal code which bears no relation at all to legal Ada
syntax, with a clear message. I get:

     1. procedure Aging is
     2.
     3.    type Number is new Float;
     4.    type Buffer is array(Integer range <>) of Number;
     5.    type Time_Series(Size : Integer) is
     6.       record
     7.          History : Buffer(0..Size-1);
     8.          Head : mod Size;
                       |
        >>> subtype indication expected

     9.       end record;
    10.
    11.    X : Time_Series(3);
    12.
    13. begin
    14.    null;
    15. end;

And of course mod Size is not a subtype indication, or even close to one.

Modular types in Ada require that the modulus be a static expression.
This rule is quite clear in the reference manual. You need to study
modular types more carefully. When you do, you will see that they are
not particularly relevant to what you are trying to do here.

Records in Ada never allow anonymous types in any case, it is not clear
where you got the idea that they do, certainly you never saw any
examples like this. You might want to get a textbook with some clear
examples if reading the rules without examples is hard.





^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: How I declare a 'mod' type within a record?
  1997-07-30  0:00 How I declare a 'mod' type within a record? Matthew Kennedy
  1997-07-30  0:00 ` Matthew Heaney
  1997-07-31  0:00 ` Robert Dewar
@ 1997-08-05  0:00 ` Mars Gralia
  1997-08-05  0:00   ` John M. Mills
  2 siblings, 1 reply; 5+ messages in thread
From: Mars Gralia @ 1997-08-05  0:00 UTC (permalink / raw)



Matthew Kennedy wrote, on (apparently) 27-July:
> 
> Hello all,
> 
> I'm trying to implement a time-series type to aid in defference equation
> simulations. I would like to use a 'mod' type which would be an elegant
> way of cycling around the buffer (which is just an array).
(snip)
> Matthew Kennedy
> Student of Electronics Engineering
> University of Southern Queensland, Australia
>   "When will you realise your already there?"
>       - Marilyn Manson

a) I don't fully understand your specific application, but I have
   a good idea.  (I've done a bit of signal processing in my day.)
b) There is a data structure, often called a "ring" that will
   probably do what you need.  The primary references are:
   1) The theory: a text book, Grady Booch, "Software Components
      with Ada", Benjamin/Cummings Publishing, 1987, ISBN
      0-8053-0609-9.  (He also has a tape of code, but it you
      need to spend something like $500 (US) for it.)
   2) A package which seems to do the job is named on the page
      >  http://osiris.ipfw.indiana.edu/cs/cs260/labs/lab6.htm
   3) I hope to have an example for you tomorrow.

M Gralia, D.Sc.
mars.gralia@jhuapl.edu
Johns Hopkins University
Applied Physics Laboratory




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: How I declare a 'mod' type within a record?
  1997-08-05  0:00 ` Mars Gralia
@ 1997-08-05  0:00   ` John M. Mills
  0 siblings, 0 replies; 5+ messages in thread
From: John M. Mills @ 1997-08-05  0:00 UTC (permalink / raw)



Mars Gralia <mars.gralia@jhuapl.edu> writes:
[Mr. Gralia's comments elided without prejudice, as I don't have the original
post on hand. Please excuse me.]
>Matthew Kennedy wrote, on (apparently) 27-July:
>> I'm trying to implement a time-series type to aid in defference equation
>> simulations. I would like to use a 'mod' type which would be an elegant
>> way of cycling around the buffer (which is just an array).

You may want to consider a circularly linked list which tails back into its
own head and keep track of the current head.  I suppose that you might want
to link pointers forward and backward to quickly address terms at different
relative displacement.  You just keep stuffing newly acquired data at the
moving "head" as the list happily circles back on itself.  A little work
to construct the list (you can't simply "declare" it), then it runs itself.

I saw a comprensive example commonly called a "managed ring buffer" and
attributed to G.Booch.  Unfortunately I do not have a reference at hand.
Perhaps some other reader can direct you.

Otherwise you can certainly use "flat" arrays of your preferred type of
data record and a package to massage their "head" and "tail" pointers
(which are actually array subscripts), as well as to return indices at
different offsets, positive or negative.  The point is to provide a modular
manipulation package with which you manipulate the indices of arrays of
whatever data type you are using.  We did this by brute force in Ada83,
but it looks like a natural opportunity for OOD in Ada95. 

Sorry -- no code, but the linked-list is a common example, including
section 11.4 of Barnes _Programming in Ada_[83].  You want to return (warn)
appropriately when an excessive offset has been requested.  If you are just
"pushing" data and never "popping" it till it's overwritten, you probably
don't have many other errors to detect.

-- 
John M. Mills, Senior Research Engineer   --   john.m.mills@gtri.gatech.edu
   Georgia Tech Research Institute, Georgia Tech, Atlanta, GA 30332-0834
        Phone contacts: 404.894.0151 (voice), 404.894.6258 (FAX)
           "Lies, Damned Lies, Statistics, and Simulations."




^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~1997-08-05  0:00 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1997-07-30  0:00 How I declare a 'mod' type within a record? Matthew Kennedy
1997-07-30  0:00 ` Matthew Heaney
1997-07-31  0:00 ` Robert Dewar
1997-08-05  0:00 ` Mars Gralia
1997-08-05  0:00   ` John M. Mills

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox