[comp.lang.c] ANSI C & Fortran 8x - Expand cpp to partially support generalized precision

dgh%dgh@Sun.COM (David Hough) (03/11/88)

I've previously proposed that Fortran 8x include the C preprocessor,
and that ANSI C support a limited interface to Fortran-77.
While thinking about Bob Corbett's comments about a related
Fortran 8x issue, generalized precision, a light flashed (fuse blowing?)
and the right thing to do seemed clear.  And unlike some of my
other comments, this one touches an issue dear to almost every
C programmer.  So here's what I'll propose to X3J11, modified
by the usual insightful reactions I expect you'll post:

Comment #26, Section 3.8.8 and  2.2.4.2: predefine  generalized precision macros

     The generalized precision proposal  in  Fortran  8x  is
complicated  and  controversial, yet responsive to a widely-
recognized need among  implementers  of  portable  numerical
software.   The  same need is most widely felt in the C com-
munity as a question like this: what is the  most  efficient
integral  type  that  contains  all integers in the range [-
99999,99999] ?

     Recommendation: To portably declare such types, add the
following predefined macros to 3.8.8:

     __int__(p) is evaluated to the name of  the  smal-
     lest  signed int type that contains all the signed
     p-digit  integers,   i.   e.   the   interval   [-
     (10**p)+1,10**p-1].

     __unsigned__(p) is evaluated to the  name  of  the
     smallest  unsigned  int type that contains all the
     p-digit unsigned  integers,  i.  e.  the  interval
     [0,10**p-1].

     __float__(p,r) is evaluated to  the  name  of  the
     smallest floating-point type that contains exactly
     all the p-digit signed integers,  i.  e.  all  the
     integers in the interval [-(10**p)+1,10**p-1], and
     contains 10**r and  10**-r  within  its  range  of
     positive model numbers.

     __INTEGER__(p) is evaluated to the Fortran name of
     the  type  corresponding  to    __int__(p,r),  or to
     INTEGER is no Fortran compiler is supported.

     __REAL__(p,r) is evaluated to the Fortran name  of
     the  type  corresponding  to   __float__(p,r), or to
     REAL if no Fortran compiler is supported.

     __COMPLEX__(p,r) is evaluated to the Fortran  name
     of   the   complex   type   whose  components  are
     __float__(p,r), or to COMPLEX if no  Fortran  com-
     piler is supported.

     All  the  precision-  and  range-dependent  macros
     fail, terminating compilation, if the precision or
     range requirements can't be met by  any  supported
     type.

     Recommendation:  In  order  that  the  C  pre-processor
itself  may  be  written  portably,  the  C run-time library
should provide certain corresponding string-valued functions
that  return the appropriate type for a particular implemen-
tation, or a null string on failure.  Add the  following  in
<float.h> to implement the corresponding cpp macros:

char * int__  (int p);
char * unsigned__  (int p);
char * float__  (int p; int r);
char * INTEGER__  (int p);
char * REAL__  (int p ; int r);
char * COMPLEX__  (int p ; int r);

David Hough

ARPA: dhough@sun.com
UUCP: {ucbvax,decvax,decwrl,seismo}!sun!dhough

swarbric@tramp.Colorado.EDU (Frank Swarbrick) (03/12/88)

I don't know if you'd take this into concideration, but Turbo C already
uses __int__() for a general interrupt.
(i.e. #define geninterrupt(i) __int__(i)  I have no idea why they have
this, but they do.)

Frank Swarbrick (and his cat)
swarbric@tramp.UUCP               swarbric@tramp.Colorado.EDU
...!{hao|nbires}!boulder!tramp!swarbric
"Welcome back my friends to the show that never ends..."

flaps@dgp.toronto.edu (Alan J Rosenthal) (03/12/88)

[In editing David Hough's article below, I have taken representative
 paragraphs.  -ajr]

In article <44981@sun.uucp> dgh%dgh@Sun.COM (David Hough) writes:
>Comment #26, Section 3.8.8 and 2.2.4.2: predefine generalized precision macros
>...
>__int__(p) is evaluated to the name of the smallest signed int type
>that contains all the signed p-digit integers, i. e. the interval
>[-(10**p)+1,10**p-1].
>...

Useable but not very useful.  Also not sufficiently well defined.  What
is its value for p > log10(LONG_MAX)?  Also, your macros are very
different from all other preprocessing macros in that they don't simply
substitute to a string (with possible replacements from the arguments).
Also also, nowhere else does the preprocessor know about names of types.

>__INTEGER__(p) is evaluated to the Fortran name of the type corresponding
>to __int__(p), or to INTEGER if no Fortran compiler is supported.
>...

Since no Fortran compiler is supported by the ANSI C standard, you
can just say "INTEGER".  The C standard does not mandate a separate
preprocessor, nor should it.  That would be the domain of a
Preprocessor Standard.  It seems like that is what you are proposing.
Perhaps you should write one, or get someone else to write one.

ajr
-- 
If you had eternal life, would you be able to say all the integers?

terry@wsccs.UUCP (terry) (03/20/88)

In article <4804@sigi.Colorado.EDU>, swarbric@tramp.Colorado.EDU (Frank Swarbrick) writes:
> I don't know if you'd take this into concideration, but Turbo C already
> uses __int__() for a general interrupt.
> (i.e. #define geninterrupt(i) __int__(i)  I have no idea why they have
> this, but they do.)

The response above was to an article suggesting __int__(999999) yeild the
smallest integer/char/long/etc. data type that could contain the value 999999,
and similar tricks, thus allowing you to declare only what you need to declare.

Not to be rude, but I don't think an interrupt routine on a severly localized
product based 1) on IBM DOS BIOS architecture, and 2) on 8086/80x86 calling
conventions based on register push order _should_ be considered.

The __int__(i) function is peculiar to Turbo C, which can not be demonstrated
to be K&R compatable as far as the book "The C Programming Language" has
defined pre-initialization of declared (non-external) global variables not
explicitly set to a value to have a value of 0.  Turbo C does not do this.
Neither does it correctly treat local non-initialized static variables.  It
is arguably not C. (I'll argue more, if you want :-}).

The function you talk about came as a result of the IBM-PC interrupt calling
sequence not being the same as the "normal" oprcedure calling sequence...
ie: PUSHing/POPing of registers on function entry/exit.  It is NOT standard
to any other C, and while it lets you do nifty things on DOS, such as
memory resident pink-pad replacements, it doesn't do a thing for UNIX/VMS
systems, which already have a standard method of catching catchable interrupts
called 'signal()'.  You can generate interrupts, too.

Nope, I think we can safley ignore Turbo C when considering standardization of
C across machines.

PS: Personally, I support the __<your_type_here>__(<sized object>) declarative
...it's pretty useless unless you are on a memory-limited machine, since you
might as well make it huge elsewhere if you can't remember what it should be.


| Terry Lambert           UUCP: ...{ decvax, ihnp4 }                          |
| @ Century Software          : ...utah-cs!uplherc!sp7040!obie!wsccs!terry    |
| SLC, Utah                                                                   |
|                   These opinions are not my companies, but if you find them |
|                   useful, send a $20.00 donation to Brisbane Australia...   |
| 'There are monkey boys in the facility.  Do not be alarmed; you are secure' |