comp.lang.ada
 help / color / mirror / Atom feed
From: "REH" <me@you.com>
Subject: Re: where exactly c++,c fail and Ada gets thru'
Date: Sat, 29 Apr 2006 14:08:18 GMT
Date: 2006-04-29T14:08:18+00:00	[thread overview]
Message-ID: <mrK4g.4748$Gg.3276@twister.nyroc.rr.com> (raw)
In-Reply-To: 1201812.r16X2gYOJE@linux1.krischik.com


"Martin Krischik" <krischik@users.sourceforge.net> wrote in message 
news:1201812.r16X2gYOJE@linux1.krischik.com...
> Now I do wonder if REH managed some template/boolean magic to get the same
> result on C++.
>

The simplistic answer is for each ranged type R, there is an intermediate 
type I.  I has the same properties as R, except it is allowed to "grow." 
That is, as the results of partial expressions become large, I chooses an 
integer type with a larger range (sadly, my technique will not work with 
floating point types).  If I is not able to find a type with a larger enough 
range, it is flagged has having the possibility of overflowing.  The math is 
basically done by partial specializing on whether overflow is possible.  The 
tricky part is determining whether an overflow can occur.  For this I took a 
page from my COBOL days.  If you performed an operation on two values and 
tried to shove it into a variable without enough digits, COBOL would warning 
you.  For example, multiplying two two-digit values and trying to assign it 
to anything less than a 4-digit variable can overflow.  Of course, it is 
trivial to determine this for every algebraic operator.  So, for each 
operation, we calculate the maximum number of digits needed for the result 
and try to use a type with that ranged.  The maximum digits is kept in I. 
This allows intermediate values to exceed the bounds of the ranged type 
(like doing the math using R'Base).  When a type I is assigned to type R, it 
is ranged check if necessary.  If the lower or upper bounds of I is within 
the bounds of R, that particular check is also removed.  This is all done at 
compile time.

 As an example, assume R is an unsigned type with a ranged of [0, 100].  The 
number of binary digits necessary to hold R is 7.  So, if x and y are 
variables of type R, then x * y needs at most 14 digits.  On any system, 
unsigned int can hold a 14-digit number.  No overflow can happen, so no 
check is done.  The result is of type I.  I is a class temple whose template 
parameters hold information needed at compile-time.  I "contains" type 
unsigned int, and 14 for the digits.  I also "knows" it's base type (R), so 
is able to keep types unique.  R can be instantiated with or without 
explicit construction (defines whether or not conversion to R requires an 
explicit cast), and with or without conversion operators (defines whether R 
can be implicitly converted to other types).  R can bound the largest type 
allowed in its calculations.  For example, assume we are on a system where 
int is 16 bits and long is 32 bits.  If we take the resulting value of type 
I above and do I * I, this needs a 28-digit type.  Normally, the resulting I 
type would use unsigned long.  R can be bounded to stop at 16-bits if, for 
some reason you do not want to use type long.  Thus, instead of growing, the 
new I would be flagged and the operation would be checked for overflow.

Now, you may ask why I didn't just define I with the resulting range of [0, 
1000].  The answer is that it would be a lot nastier because then I would 
also have to do overflow checking on the ranges at compile-time.  It would 
be really nasty for signed types because you cannot just do the operation 
and check for overflow.  Allowing a signed operation to overflow is 
undefined behavior.

The above technique works for both signed and unsigned types, and all three 
integer representations allowed by the C++ standard.  I'd like to enhance it 
to handle floating points, but I currently have no clue how that could be 
done.  I'll admit the templates are very, very complex, but for the most 
part the client software does not have to worry about it.  You can just use 
you would any other numerical type.  I don't recall having any issue with 
"error messages" while writing it.  Modern C++ compiler have gotten very 
good at giving more sane messages.  They have also gotten better at compile 
times.  My ranged type is not perfect, and there is no way to perfectly 
replicate what Ada can do, but as I said I cannot always use Ada.  I also 
realize that the class will never be able to remove as many checks as an Ada 
compiler, but it is much better than nothing.  The checks are very expensive 
since they are done in standard C++ (though one could sacrifice portability 
for speed if their compiler supported inline assembly).  On benchmarks I've 
run, the class can be very close to raw integers in terms of speed, where 
not eliminating any checks can cost 10x or more.  Of course this all depends 
on your system, compiler, etc., and the particular expressions (what the 
class can catch).  In particular, very complex expressions will saturate the 
range of the types available quickly and inhibit anymore optimizations. 
Breaking the expression up can help to alleviate this, but each time an I is 
assigned to an R, a range check may have to be done (those range checking is 
much, much more efficient than overflow checking).

REH









  reply	other threads:[~2006-04-29 14:08 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-04-24  4:19 where exactly c++,c fail and Ada gets thru' Ananth the Boss
2006-04-24  5:05 ` jimmaureenrogers
2006-04-24  7:45   ` Ananth the Boss
2006-04-24 19:17   ` Martin Krischik
2006-04-24 20:23   ` Simon Wright
2006-04-24 22:34     ` Keith Thompson
2006-04-24 22:33   ` Keith Thompson
2006-04-25  5:23     ` Jeffrey R. Carter
2006-04-26 17:48     ` Martin Krischik
2006-04-26 19:33       ` Keith Thompson
2006-04-26 15:10   ` Maciej Sobczak
2006-04-26 17:32     ` Martin Krischik
2006-04-27 10:07       ` Maciej Sobczak
2006-04-27 21:19         ` Keith Thompson
2006-04-28  7:00         ` Martin Krischik
2006-04-28 12:27           ` Maciej Sobczak
2006-04-29  7:03             ` Martin Krischik
2006-04-29 14:08               ` REH [this message]
2006-05-01 10:20                 ` Xcriber51
2006-05-01 13:55                   ` REH
2006-05-02  6:43               ` Maciej Sobczak
2006-04-27 16:48       ` REH
2006-04-28  7:49         ` Martin Krischik
2006-04-28 11:17           ` REH
2006-04-29  6:47             ` Martin Krischik
2006-04-24  8:13 ` Rod Chapman
2006-04-25  1:57 ` Steve
replies disabled

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