[net.lang.c] integer division in ANSI C

danny@sftig.UUCP (L.Rosler) (02/26/86)

There have been several thoughtful submissions on the subject
of integer division in C recently.  I think the ANSI X3J11
position should be introduced into the discussion.

This issue reveals the fundamental dichotomy in C -- between
the systems-programmers' language (replacing assembly language)
and the application-programmers' language (replacing FORTRAN or
Pascal, say).

System programmers really are not concerned about the behavior
when a negative number is involved.  Except perhaps for -1,
negative numbers are considered harmful in this arena.  The
goal of division is to get the positive quotient or positive
remainder as fast as the hardware can give it, and this will
always be hardware-independent.

Application programmers, on the other hand, ARE concerned about
portable division involving negative numbers, a need which C
does not address.  When this was discussed (at many Standards
meetings), the following positions emerged:

1.  Ignore the problem -- reliable application programs are
    not important.
2.  Force the compiler to generate code to produce portable
    semantics -- fast systems programs are not important.
3.  Enrich the language by adding semantics to the new
    ``signed'' keyword, which is at present redundant for
    int's.  This proposal would also have solved the problem
    of reliable semantics for right-shifting of negative
    int's.  It leads to 12 types of integers (``plain'',
    unsigned and signed; char, short, ``plain'' and long) and
    runs slightly afoul of the widening rules (signed char would
    widen to signed int, not ``plain'' int).  It was defeated at
    two successive meetings by a very narrow vote, and I have
    given up on it.
4.  Enrich the language by adding new operators (// and %%)
    to signify reliable signed division where desired.  (I
    tolerated this proposal until the // comment convention of
    C++ appeared.)
5.  Enrich the library by adding functions that do reliable
    signed division.  (Functions can be implemented as macros
    in ANSI C if appropriate, because their names are reserved.)
    The functions invented for this purpose are:
        typedef struct { int quot, rem; } idiv_t;
	idiv_t idiv(int numer, int denom);
    and
        typedef struct { long int quot, rem; } ldiv_t;
	ldiv_t ldiv(long int numer, long int denom);
    The semantics are those of FORTRAN:  The sign of the quotient
    and remainder are the same as the sign of the mathematical
    quotient.  The behavior on exceptions such as overflow or
    divide-by-zero is undefined, just like regular division.
    (Note that these are the only functions in the library that
    return structs.)

The functions were added last December, and could still be challenged.
Constructive comments on this "solution by committee" would be
appreciated, either on the Net or to me by e-mail.

Larry Rosler, AT&T
Editor, X3J11
ihnp4!attunix!lr, 201-522-5086

ka@hropus.UUCP (Kenneth Almquist) (03/02/86)

> This issue reveals the fundamental dichotomy in C -- between
> the systems-programmers' language and the application-programmers'
> language...

Yes.  I've never understood why anybody would *want* to do applications
programming in C, but then I've never understood why people want to use
Fortran and Cobol either...

The proposed functions will not fully solve the problem if C is used by
fallible programmers, but then only those of us who are perfect have
any business using a dangerous language like C anyway :-).  I would
suggest making the routines simpler to use by providing separate
routines for division and remainder, as this will encourage more people
to use them when necessary.  This would also mean that these routines
could be replaced with simple macros on machines that do division the
Fortran way (most of them).

It would also be nice to have a modulo function.  In my view, this
would be more useful than a remainder function.
				Kenneth Almquist
				ihnp4!houxm!hropus!ka	(official name)
				ihnp4!opus!ka		(shorter path)

seifert@hammer.UUCP (Snoopy) (03/04/86)

In article <695@sftig.UUCP> danny@sftig.UUCP (L.Rosler) writes:

>System programmers really are not concerned about the behavior
>when a negative number is involved.  Except perhaps for -1,
>negative numbers are considered harmful in this arena.  The
>goal of division is to get the positive quotient or positive
>remainder as fast as the hardware can give it, and this will
>always be hardware-independent.
>
>Application programmers, on the other hand, ARE concerned about
>portable division involving negative numbers, a need which C
>does not address.  When this was discussed (at many Standards
>meetings), the following positions emerged:
>
>1.  Ignore the problem -- reliable application programs are
>    not important.
>2.  Force the compiler to generate code to produce portable
>    semantics -- fast systems programs are not important.

[ various other options ]

How about:

case 1:
(unsigned) / (unsigned)  generates the positive quotient as fast as possible

case 2:
one or both are (signed) generates the correct signed quotient

The compiler knows whether the integers are (signed) or (unsigned)
at compile time, and can choose the appropriate code.

Seems like this would satisfy both camps.

Snoopy
tektronix!tekecs!doghouse.TEK!snoopy

franka@mmintl.UUCP (Frank Adams) (03/05/86)

In article <316@hropus.UUCP> ka@hropus.UUCP (Kenneth Almquist) writes:
[Concerning proposed ANSI divide funtion]
>I would
>suggest making the routines simpler to use by providing separate
>routines for division and remainder, as this will encourage more people
>to use them when necessary.  This would also mean that these routines
>could be replaced with simple macros on machines that do division the
>Fortran way (most of them).
>
>It would also be nice to have a modulo function.  In my view, this
>would be more useful than a remainder function.

Let me second both of these notions, especially the first.  It is relatively
rare to want both quotient and remainder.  Having to go through the extra
effort of pulling out the one desired is probably enough to keep most C
programmers from using the function unless they are on a machine where
they need it.

Frank Adams                           ihnp4!philabs!pwa-b!mmintl!franka
Multimate International    52 Oakland Ave North    E. Hartford, CT 06108

kwh@bentley.UUCP (KW Heuer) (03/07/86)

In article <1841@hammer.UUCP> hammer!seifert (Snoopy) writes:
>How about:
>(unsigned) / (unsigned)  generates the positive quotient as fast as possible
>one or both are (signed) generates the correct signed quotient

Won't work.  (unsigned)-1 denotes 65535 (assuming 16-bit ints for simplicity),
so (unsigned)-1 / 2 has to produce the answer 32767.  In order to generate the
correct result for the entire range of unsigned, the VAX compiler has to add
some stupid code (a function call on some compilers), so this can't be used as
the "fastest divide" datatype.

Here's a counterproposal.  Since _int_ has the range [-32768,32767] and
_unsigned_ is [0,65535], add a new datatype _positive_ (or _nonneg_ or
_nosign_) which has the range [0,32767], i.e. the intersection of _int_ and
_unsigned_.  Whenever it encounters an expression of this datatype, the
compiler can assume its sign bit is off and perform whatever optimization
it wants, i.e. use the fastest divide algorithm.  Similarly, ">>" could be
defined as arithmetic shift on _int_, logical shift on _unsigned_, and
fastest shift on _positive_.