From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=unavailable autolearn_force=no version=3.4.4 Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!news.eternal-september.org!news.eternal-september.org!news.eternal-september.org!feeder.eternal-september.org!news.swapon.de!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail From: hreba Newsgroups: comp.lang.ada Subject: Re: integers of 1, 2, 4 bytes Date: Sun, 15 Jun 2014 18:25:14 -0300 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Trace: individual.net QV71wcLhzhpieSkOohBUJgHpTCrepTpsRAcFIxNaXxhslbvvNr Cancel-Lock: sha1:yHkg1yuNB4v3AuHhHmHJspRGwv4= User-Agent: Mozilla/5.0 (X11; Linux i686; rv:24.0) Gecko/20100101 Thunderbird/24.5.0 In-Reply-To: Xref: news.eternal-september.org comp.lang.ada:20333 Date: 2014-06-15T18:25:14-03:00 List-Id: On 06/15/2014 04:07 PM, Niklas Holsti wrote: > On 14-06-15 20:57 , hreba wrote: >> Hi, >> >> I want to translate some of my Oberon programs to Ada. > > That should be quite feasible. > >> So I need the Oberon types SHORTINT (1 byte), INTEGER (2 bytes) and >> LONGINT (4 bytes). A type BYTE (1 byte, values 0..255) would be useful >> too. In Oberon one uses CHAR for that. > > Ehm... why do you need exact equivalents to Oberon built-in types? Do > you intend to "write Oberon code in Ada", or do you intend to write in > "Ada style"? Ada style in choosing and defining types is to start from > what the type should represent (= the problem space), not to start from > how many bits it should use (= the solution space). > > Which aspects of the integer types are important to you? You should > think of at least these aspects: > > 1. The range of the values of the type. Ada allows more flexibility here > than Oberon, I believe. > > 2. The size in bits of each variable of the type. Is this really > important for you? Do your Oberon programs deal with hardware > interfaces, or call procedures from other languages (e.g. C) where one > must ensure matching parameter types and sizes? > > 3. Behaviour in case of computations that exceed the range of the type: > do you want silent wrap-around, or an exception? What happened in your > Oberon programs in such case, and do you want the same thing to happen > in the Ada version? (Sorry, I don't know how Oberon normally handles > overflow.) > > 4. Do you need "bitwise" operations on these integers, such as shifts, > rotates, and bitwise logical and/or/xor/not? > > As an example, if I need an integer type for which I know a range > (aspect 1) and I want an exception if I exceed the range (aspect 3) then > I would use the basic Ada form, > > type My_Int is .. ; > > and I would let the compiler choose whatever number of bits it finds > convenient. However, I would check that all intermediate values in my > calculations with My_Int also fit in the range - that is, I would choose > a range large enough to hold all intermediate computation values. > Otherwise, an overflow error could happen in the computations, even if > the final result is in the range. > > On the other hand, if I want silent wrap-around, I would use Ada's > "modular" integers. And if I want bitwise operations, I would choose a > suitable modular type from the library package Ada.Interfaces, which > defines shift and rotate operations. > >> The most obvious translation for INTEGER would be >> >> type INT is range -32768 .. 32767; >> >> (all platforms I have been working on use the two's complement). >> >> My Ada book says that range checks are applied to constrained subtypes >> (like that one) but not to unconstrained subtypes, but but overflow >> checks are applied nevertheless. So I came up with >> >> type Int16 is range -32768 .. 32767; >> for Int16'Size use 16; >> type INT is new Int16'Base; >> >> as a more efficient definition. > > Depends what you want; this type INT should signal overflow, but there > may be values that silently exceed the Int16 constraints. Is that what > you want? If I had some logical reason to use the range -32768..32767, I > would want to know if my program exceeds it. > > (For overflow checking, note that GNAT traditionally disables overflow > checks by default, and you must use the option -gnato to enable them.) > >> Now it seems the range specification doesn't matter any more and that I >> could equally write >> >> type Int16 is range -1 .. 1; >> for Int16'Size use 16; >> type INT is new Int16'Base; > > I don't think that the Size specification influences the compiler's > choice of Int16'Base, so the compiler could choose an 8-bit integer as > Int16'Base, and just not use the "extra" 8 bits that the Size > specification gives you. > >> Would you really define a 16 bit integer type this way? > > No, never. > >> And how about non-negative types? Would the following have the values >> 0 .. 255? >> >> type Nat8 is range 0..1; >> for Nat8'Size use 8; >> type BYTE is new Nat8'Base; > > No. Nat8 is an ordinary signed integer type, and therefore Nat8'Base has > a symmetric signed range (except for a possible extra most negative > number, -2**n in addition to -(2**n - 1). Nat8'Base could have the range > -128..127, for example. > > If you want unsigned integers, and the size matters to you, use a > modular type, perhaps one of those in Ada.Interfaces. > All I want is: 1. Same behaviour of translated program and original 2. Avoid unnecessary range checks. 1. Same behaviour I want do extend one of my programs and I want to switch from Oberon to Ada. So first of all I want to translate the existing part and I want it to behave as the original. So it would be Oberon style. In most cases the range doesn't matter really. One uses the default integer type (64 or 32 bits on PCs in C or 16 in Oberon) even in cases where the values don't exceed, let's say, 25. Then I want to extend the program using Ada _style_, not just language. And, during this process, and acquiring practice, revise the translated part. 2. Avoid unnecessary range checks. From what I read I had understood the following: Subtypes are always range checked, and in addition there are overflow checks. When my subtype boundaries are equal to the limits of the base type, one of the checks is redundant. I have nothing against checks and I don't have performance issues, I just wanted to avoid _unnecessary_ checks. Thanks for your explanations, it is much clearer now. -- Frank Hrebabetzky +55 / 48 / 3235 1106 Florianopolis, Brazil