comp.lang.ada
 help / color / mirror / Atom feed
* Re: Can you help with fixed-point arithmetic?
@ 1993-07-21  2:03 magnesium.club.cc.cmu.edu!news.sei.cmu.edu!ae
  0 siblings, 0 replies; 5+ messages in thread
From: magnesium.club.cc.cmu.edu!news.sei.cmu.edu!ae @ 1993-07-21  2:03 UTC (permalink / raw)


mfeldman@seas.gwu.edu (Michael Feldman) asks (in effect) why his
compiler reports that Constraint_Error will be raised from the statement
       27    TimeThen := TimeNow + 10 * Duration'(86400.0);

Consider in isolation
	10 * Duration'(86400.0)
This is a multiplication whose left operand is an integer and whose
right operand is of type Duration, and we find its semantics in
4.5.5(7), where we learn that its result type will be of type Duration.

The probable problem is that the result is too big for that type.
Although the LRM doesn't specify Duration's range (see C(19)), the usual
value is not much more than enough to store 24 hours.  (A larger range
is counter-productive, as it decreases the fineness.)  The range for
Duration in Meridian Ada on the Mac is
	-86400.0 .. 86400
I suspect it's the same on the PC.

Next question: how to get around the problem.  A way that at first seems
plausible is to declare a fixed-point type with a large enough range and
convert 86400.0 to that.  This won't work, though, since the '+' on line
27 wouldn't be defined.  (It's now the '+' exported by package
Calendar.)

If I were doing this and cared about dates only and not time, I would
ignore package Calendar and just represent dates as an integer offset
from some origin.  If you care about time, declare a record with such an
integer and a Duration field for time.  I'm sure you can think of other
ideas.

Cheers!

Art Evans
----------------------------------------------
Arthur Evans, Jr, PhD           Ada Consultant
461 Fairview Road
Pittsburgh PA  15238-1933
412-963-0839
ae@sei.cmu.edu

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

* Re: Can you help with fixed-point arithmetic?
@ 1993-07-21 12:29 magnesium.club.cc.cmu.edu!news.sei.cmu.edu!ae
  0 siblings, 0 replies; 5+ messages in thread
From: magnesium.club.cc.cmu.edu!news.sei.cmu.edu!ae @ 1993-07-21 12:29 UTC (permalink / raw)


mfeldman@seas.gwu.edu (Michael Feldman) asked about why his compiler
stated that Constraint_Error would be raised by this statement:
       27    TimeThen := TimeNow + 10 * Duration'(86400.0);

In an earlier message I explained, and I then proposed another way to
accomplish his goal of adding (in effect) days to a value of type
Calendar.Time.  Here's another approach to the latter problem.

Declare a function like this:
	function "+"(Left: in Calendar.Time; Days: in integer)
	    return Calendar.Time;
In the body, call Calendar.Split on Left, and add Days to the DAY
result.  While the result exceeds 365 (or 366 in leap years), subtract
365 (or 366) and add one to the year.  This needs some care; details are
left as an exercise for the student (or, in this case, the professor).
Then put it all back together with Calendar.Time_Of.

If you want to add both days and partial days, give this "+" a third
parameter of type Duration.  Again, detect the possible overflow and
propagate a carry into DAY.  Be careful -- there are subtleties in
detecting the overflow.  Consider
	if SECONDS + Increment > 86400.0 then
Your compiler is not incorrect if it lets Constraint_Error be raised in
evaluating the sum.  It's also not incorrect if it does the comparison
correctly, dealing with an intermediate result (the sum) outside the
range of type Duration.  In the worst case you may have to just do the
sum and detect the Constraint_Error.

If you put this function in a package My_Calendar, it can re-export the
needed parts of package Calendar, so your application would mention only
My_Calendar in a 'with' clause.

Cheers!

Art Evans
----------------------------------------------
Arthur Evans, Jr, PhD           Ada Consultant
461 Fairview Road
Pittsburgh PA  15238-1933
412-963-0839
ae@sei.cmu.edu

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

* Re: Can you help with fixed-point arithmetic?
@ 1993-07-21 16:38 Robert I. Eachus
  0 siblings, 0 replies; 5+ messages in thread
From: Robert I. Eachus @ 1993-07-21 16:38 UTC (permalink / raw)


    Art has explainded the reason for the CONSTRAINT_ERROR, now for
the solution(s).  The first is a pain, the second is non-portable, and
probably indicates a feature which can be added at low cost to Ada 9X.

    What you want to do is add days to times:

    with CALENDAR; use CALENDAR;
    ...
    function "+"(T: Time; Days: Integer) return Time is
      Y: Year_Number;
      M: Month_Number;
      D: Day_Number;
      S: Duration;
    begin
      Split(T,Y,M,D,S);
      -- do the arithmetic...
      return Time_Of(Y,M,D,S);
    end "+";

    -- the simpler solution is to peer into private parts.  SunAda:

    with Calendar;
    ...
    function "+"(T: Calendar.Time; Days: Integer) return Calendar.Time is
      type my_time is record -- lifted from calendar
           julian_day:    integer;    -- Julian Day Number
           sec:           duration;
      end record;
      function To_Mine is new UNCHECKED_CONVERSION(Time,My_Time);
      function To_Time is new UNCHECKED_CONVERSION(My_Time,Time);
      Input: To_Mine(T);
    begin
      Input.Julian_Day := Input.Julian_Day+Days;
      return To_Time(Input);
    end "+";

    In Ada_9X, it will be possible to extend Calendar with user
defined children, so the Unchecked conversions are unnecessary.
However, this particular function might make sense as an addition to
Calendar.



--

					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...

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

* Re: Can you help with fixed-point arithmetic?
@ 1993-07-21 18:13 Mark A Biggar
  0 siblings, 0 replies; 5+ messages in thread
From: Mark A Biggar @ 1993-07-21 18:13 UTC (permalink / raw)


In article <1993Jul21.082925.3193@sei.cmu.edu> ae@sei.cmu.edu (Arthur Evans) wr
ites:
>If you want to add both days and partial days, give this "+" a third
>parameter of type Duration.  Again, detect the possible overflow and
>propagate a carry into DAY.  Be careful -- there are subtleties in
>detecting the overflow.  Consider
>	if SECONDS + Increment > 86400.0 then
>Your compiler is not incorrect if it lets Constraint_Error be raised in
>evaluating the sum.  It's also not incorrect if it does the comparison
>correctly, dealing with an intermediate result (the sum) outside the
>range of type Duration.  In the worst case you may have to just do the
>sum and detect the Constraint_Error.

Sense, Increment is of type Duration (and probably positive as well) why
not just code the above condition as:

	if SECONDS > 86400.0 - Increment then

which correct detects the overflow and never raises Constraint_Error.
If Increment can be negitive, then you have to split the code into two cases
to handle the Carry vs Barrow cases after the call the Split anyway, so you
might as well use two different overflow tests.

It is almost alway possible to write an overflow test for addition in such
a way as to never raise Constraint_Error.  Dectecting overflow of multiplcation
is much more difficult.

--
Mark Biggar
mab@wdl.lroal.com

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

* Re: Can you help with fixed-point arithmetic?
@ 1993-07-21 22:19 Michael Feldman
  0 siblings, 0 replies; 5+ messages in thread
From: Michael Feldman @ 1993-07-21 22:19 UTC (permalink / raw)


In article <1993Jul20.220309.1563@sei.cmu.edu> ae@sei.cmu.edu (Arthur Evans) wr
ites:
>mfeldman@seas.gwu.edu (Michael Feldman) asks (in effect) why his
>compiler reports that Constraint_Error will be raised from the statement
>       27    TimeThen := TimeNow + 10 * Duration'(86400.0);
>
>Consider in isolation
>	10 * Duration'(86400.0)
>This is a multiplication whose left operand is an integer and whose
>right operand is of type Duration, and we find its semantics in
>4.5.5(7), where we learn that its result type will be of type Duration.
>
>The probable problem is that the result is too big for that type.
>Although the LRM doesn't specify Duration's range (see C(19)), the usual
>value is not much more than enough to store 24 hours.  (A larger range
>is counter-productive, as it decreases the fineness.)  The range for
>Duration in Meridian Ada on the Mac is
>	-86400.0 .. 86400
>I suspect it's the same on the PC.
>
>Next question: how to get around the problem.  A way that at first seems
>plausible is to declare a fixed-point type with a large enough range and
>convert 86400.0 to that.  This won't work, though, since the '+' on line
>27 wouldn't be defined.  (It's now the '+' exported by package
>Calendar.)
>
Yep, I got stung by forgetting that the LRM does not require a Duration 
range of more than a day. In any event, thanks to all of you who pointed
this out by e-mail and on the net. I'll find another way.

Actually, I'd decided to represent a date as a record containing year
and Julian date within year (1..365 or 1..366) but thought I could get
away with simpler date arithmetic by using built-in operations> I guess
my original design was OK after all.

Thanks!

Mike Feldman
------------------------------------------------------------------------
Michael B. Feldman -  co-chair, SIGAda Education Committee
Professor, Dept. of Electrical Engineering and Computer Science
The George Washington University -  Washington, DC 20052 USA
202-994-5253 (voice) - 202-994-0227 (fax) - mfeldman@seas.gwu.edu (Internet)
"We just changed our CONFIG.SYS, then pressed CTRL-ALT-DEL. It was easy."
-- Alexandre Giglavyi, director Lyceum of Information Technologies, Moscow.
------------------------------------------------------------------------

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

end of thread, other threads:[~1993-07-21 22:19 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1993-07-21 12:29 Can you help with fixed-point arithmetic? magnesium.club.cc.cmu.edu!news.sei.cmu.edu!ae
  -- strict thread matches above, loose matches on Subject: below --
1993-07-21 22:19 Michael Feldman
1993-07-21 18:13 Mark A Biggar
1993-07-21 16:38 Robert I. Eachus
1993-07-21  2:03 magnesium.club.cc.cmu.edu!news.sei.cmu.edu!ae

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