Why is there 'div()' in the standard lib

U

user923005

Does anybody know why div() was implemented?

It does seem a tempest in a teapot to get simultaneous div and mod
results, but I guess they wanted a portable way to do that and figured
that the library implementor would be able to do it faster than
average.

It turns out to be useful for things like time calculations (e.g.
convert a bushel of seconds into year/month/day/hour/min/sec).
 
R

Richard Heathfield

Joe Wright said:
Does anybody know why div() was implemented?

Those who have implemented their own arbitrary precision arithmetic library
will be particularly aware of the fact that performing a division gives
you a remainder for free. So if you need both the result of a division
*and* a remainder, instead of writing w = x / y; r = x % y; on at least
some machines you could have them both for the cost of only one... if only
you had the syntax for it. The div function provides that syntax. (Under
the hood, doubtless it will do something nastily machine-specific.)
 
P

Peter Nilsson

Joe Wright said:
Does anybody know why div() was implemented?

No, but other posts notwithstanding, it's worth noting that
the division and remainder returned by div need not be the
same as that returned by / and % under C89 (according to
the draft I have which may have changed).
 
S

Stephen Sprunk

Richard Heathfield said:
Joe Wright said:

Those who have implemented their own arbitrary precision
arithmetic library will be particularly aware of the fact that performing
a division gives you a remainder for free. So if you need both the
result of a division *and* a remainder, instead of writing w = x / y;
r = x % y; on at least some machines you could have them both for
the cost of only one... if only you had the syntax for it. The div
function provides that syntax. (Under the hood, doubtless it will do
something nastily machine-specific.)

Any decent compiler should be able to notice you're dividing and modding the
same value by the same other value and combine the expressions into one
operation at a lower level...

S
 
R

Richard Heathfield

Stephen Sprunk said:

Any decent compiler should be able to notice you're dividing and modding
the same value by the same other value and combine the expressions into
one operation at a lower level...

What constitutes a "decent compiler" has perhaps moved on somewhat from
whenever it was that div() was introduced.
 
C

CBFalconer

Joe said:
Does anybody know why div() was implemented?

Because it returns both the quotient and the remainder with one
relatively long division instruction.
 
C

CBFalconer

Stephen said:
Any decent compiler should be able to notice you're dividing and
modding the same value by the same other value and combine the
expressions into one operation at a lower level...

Why do people assume that such 'decent' compilers are always
available? Many machines operate with a minimal compiler, no
optimization, no this, no that. The code functions.
 
R

Richard Tobin

Any decent compiler should be able to notice you're dividing and
modding the same value by the same other value and combine the
expressions into one operation at a lower level...
[/QUOTE]
Why do people assume that such 'decent' compilers are always
available? Many machines operate with a minimal compiler, no
optimization, no this, no that. The code functions.

If you have a compiler with no optimisation, ensuring that you don't
do unnecessary divisions is likely to be the least of your problems.

-- Richard
 
E

Eric Sosman

Richard said:
Joe Wright said:


Those who have implemented their own arbitrary precision arithmetic library
will be particularly aware of the fact that performing a division gives
you a remainder for free. So if you need both the result of a division
*and* a remainder, instead of writing w = x / y; r = x % y; on at least
some machines you could have them both for the cost of only one... if only
you had the syntax for it. The div function provides that syntax. (Under
the hood, doubtless it will do something nastily machine-specific.)

Another reason is that the original ANSI C Standard gave
the implementation some freedom when negative numbers appeared
in divisions. For example, either of

-5 / 3 == -2, -5 % 3 == 1
or
-5 / 3 == -1, -5 % 3 == -2

was allowed. (Note that the two pieces of each pair agree:
3*(-2) + 1 == -5 in the first, and 3*(-1) + (-2) == -5 in
the second.) This implementation-specific variation could be
troublesome in some circumstances, so div() and ldiv() were
defined to produce results according to the second scheme, even
if the underlying machine's hardware used the first.

The 1999 edition of the Standard took away the freedom of
choice for / and %, requiring them to use the second method,
so that part of the reason for div() and ldiv() disappeared.
But it's still relevant for programs compiled under the older
rules -- in theory, anyhow, because the second scheme was
already the Law for other important programming languages, and
therefore most machines implemented the second scheme anyhow.
 
S

Stephen Howe

Does anybody know why div() was implemented?

I like it and wish there was a udiv(), uldiv() and ulldiv()

Stephen Howe
 
J

Joe Wright

Eric said:
Another reason is that the original ANSI C Standard gave
the implementation some freedom when negative numbers appeared
in divisions. For example, either of

-5 / 3 == -2, -5 % 3 == 1
or
-5 / 3 == -1, -5 % 3 == -2

was allowed. (Note that the two pieces of each pair agree:
3*(-2) + 1 == -5 in the first, and 3*(-1) + (-2) == -5 in
the second.) This implementation-specific variation could be
troublesome in some circumstances, so div() and ldiv() were
defined to produce results according to the second scheme, even
if the underlying machine's hardware used the first.

The 1999 edition of the Standard took away the freedom of
choice for / and %, requiring them to use the second method,
so that part of the reason for div() and ldiv() disappeared.
But it's still relevant for programs compiled under the older
rules -- in theory, anyhow, because the second scheme was
already the Law for other important programming languages, and
therefore most machines implemented the second scheme anyhow.
On my kit (DJGPP circa 2002) I get..

num = 40, den = -3, quot -13, rem -1, d*q+r 38

from the div() function and..

num = 40, den = -3, quot -13, rem 1, d*q+r 40

when I do it myself. It would seem the div() version is simply wrong.
 
E

Eric Sosman

Joe said:
On my kit (DJGPP circa 2002) I get..

num = 40, den = -3, quot -13, rem -1, d*q+r 38

from the div() function and..

num = 40, den = -3, quot -13, rem 1, d*q+r 40

when I do it myself. It would seem the div() version is simply wrong.

It looks like DJGPP's div() has (had?) a bug. The quotient
is right (40/-3 = -13.333... -> -13), but the remainder is wrong.
 
C

Chris Torek


I recognize that comment.... :)

(I wrote that comment, and in fact, that entire file, except for
the Sun copyright at the top, which was not there in the original
BSD version, nor the two unnecessary and nonportable "#include"s.
Also, the "ident" was a static array initializer, not a "#pragma";
was inside a #ifndef lint; had slightly different text; and, of
course, the SCCSID key"words" were expanded when I checked it in
at Berkeley.)
 
P

Peter Nilsson

Now that I actually look at it in detail, I agree!

Chris Torek said:
I recognize that comment.... :)

You cater for rounding to -Inf (floored division), but
I honestly can't recall ever seeing that in a machine
instruction. [Perhaps ones that use floating point to
support integers?]

Is your interpretation of C89 that this is the only
other kind of rounding supported?

I always took the C89 (draft) as saying that division
involving one or more negative operands could result
in rounding up or down. That leads to 8 different forms
of division, if you exclude the possibility of mixed
runtime behaviour, i.e. sometimes round up, sometimes
round down.

In mathematics, I've certainly seen what I call
mathematical or modulo rounding wherein the remainder
is always positive, i.e. 0 <= |r| < |d|. But apart from
C89, I can't recall seeing an 'ordinary' computer
language that offered any direct support for it.

num den / zero -inf math
7 5 1.4 +1 r +2 +1 r +2 +1 r +2
7 -5 -1.4 -1 r +2 -2 r -3 -1 r +2
-7 5 -1.4 -1 r -2 -2 r +3 -2 r +3
-7 -5 1.4 1 r -2 +1 r -2 +2 r +3

I've certainly used and written maths applications that
offered the math form of rounding.
 
C

Chris Torek

Now that I actually look at it in detail, I agree!
You cater for rounding to -Inf (floored division), but
I honestly can't recall ever seeing that in a machine
instruction. [Perhaps ones that use floating point to
support integers?]

I recall Fortran allowing only two kinds of integer division:
round towards 0 (a la C99) and round towards -Inf (C89 and C99
both). As far as I know, this was because at least one machine
actually did the latter, but I have no idea which machine.
Is your interpretation of C89 that this is the only
other kind of rounding supported?

That was my impression, yes. Could be wrong. :) My C89 standard
is not handy (I think it is in a box but I have not seen it in
years now). C99 requires the truncation-towards-zero behavior,
which would simplify the implementation of div() quite a bit.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top