9

Reading through the C specs I found this function:

double remquo(double x, double y, int *quo);
float remquof(float x, float y, int *quo);
long double remquol(long double x, long double y,
    int *quo);

The remquo functions compute the same remainder as the remainder functions. In the object pointed to by quo they store a value whose sign is the sign of x/y and whose magnitude is congruent modulo 2^n to the magnitude of the integral quotient of x/y, where n is an implementation-defined integer greater than or equal to 3.

The remquo functions return x REM y. If y is zero, the value stored in the object pointed to by quo is unspecified and whether a domain error occurs or the functions return zero is implementation defined.

I understand what it returns, it returns fmod(x, y), but I don't understand the whole quo part. Is it semantically equal to this?

*quo = (int) x/y;
*quo %= n; /* n implementation defined */

And my last question, for what could this function be useful?

orlp
  • 112,504
  • 36
  • 218
  • 315
  • see also http://www.kernel.org/doc/man-pages/online/pages/man3/remquo.3.html and http://sourceware.org/bugzilla/show_bug.cgi?id=4449 – Christoph Feb 19 '12 at 16:54
  • 1
    The usage was answered in [this question](http://stackoverflow.com/questions/11074865/stdremquo-purpose-and-usage) – phuclv Aug 12 '14 at 17:19
  • 1
    Also a note from [cppreference](http://en.cppreference.com/w/cpp/numeric/math/remquo): This function is useful when implementing periodic functions with the period exactly representable as a floating-point value: when calculating sin(πx) for a very large x, calling std::sin directly may result in a large error, but if the function argument is first reduced with std::remquo, the low-order bits of the quotient may be used to determine the sign and the octant of the result within the period, while the remainder may be used to calculate the value with high precision. – phuclv Aug 12 '14 at 17:20
  • 1
    Possible duplicate of [std::remquo purpose and usage?](https://stackoverflow.com/questions/11074865/stdremquo-purpose-and-usage) – underscore_d Apr 30 '19 at 19:10
  • @underscore_d 1. My question predates that question. 2. My question pertains to C, not C++. – orlp Apr 30 '19 at 20:05
  • @orlp I'd hoped not to need to explain these, but here we go. 1: I'm not aware that time matters when judging whether one thread better covers something than another. 2: That thread is not actually C++ specific at all except that the OP included an `std::` prefix, but the answer in C++ is inherited wholesale from C. – underscore_d May 01 '19 at 18:28

3 Answers3

9

A typical usage of remquo() is the reduction of trigonometry function arguments. The last 3 bits of the quotient would allow one to tell which semi-quadrant an angle resides in, after a reduction modulo Pi/4, and to convert the original trig call into another trig call over an angle within the [0,Pi/4) interval (the new trig function could be different). The latter is usually computed via a Pade approximation.

cruncher
  • 91
  • 1
  • 1
  • Yes, exactly. Well, except that it's within the [-pi/8,pi/8] interval, not [0,pi/4), which is much more useful, for subtle reasons. I just noted in a comment I made on @chux 's https://stackoverflow.com/questions/31502120/sin-and-cos-give-unexpected-results-for-well-known-angles#answer-31525208 "It's spooky how well remquo meets your needs here". But maybe not so spooky after all, since I'm now suspecting remquo's contract was written with precisely this application in mind. – Don Hatch May 13 '22 at 06:05
8

It seems pretty clear that remquo does not give the value of x / y. It only gives a few low bits of the quotient. Here's an example:

#define _ISOC99_SOURCE
#include <stdio.h>
#include <math.h>

int main()
{
    int quo;
    double res = remquo(88888.0, 3.0, &quo);
    printf("%f %d\n", res, quo);
    return 0;
}
$ 
$ cc -o rq rq.c
$ rq
1.000000 5

I get this same answer for OS X 10.8.2 (Xcode 4.6) and on a Linux system. The full quotient is 29629, and 5 is the low 3 bits thereof.

It's worth noting that the quotient can very easily be too large to be represented as an int. So really the best you can do is to give some low bits.

At any rate, this is not "language lawyerese." The specification is telling you something pretty specific.

Jeffrey Scofield
  • 65,646
  • 2
  • 72
  • 108
  • 2
    I must admit that you're right. The returned `quo` looks quite useless, though [this answer](http://lists.apple.com/archives/carbon-dev/2007/Dec/msg00354.html) explains its purpose a bit. – ugoren May 02 '13 at 07:12
  • @ugoren, updated link http://web.archive.org/web/20140115095533/http://lists.apple.com/archives/carbon-dev/2007/Dec/msg00354.html – alfC Aug 05 '19 at 07:16
4

EDIT: As Jeffrey Scofield said in his answer, the returned quotient really isn't x/y, but the low 3 bits (plus sign) of the quotient.

It's equivalent to (up to type differences):

quo = x/y;
rem = x%y;

Where rem is the return value, and quo is returned as an output parameter.
Its advantage over the above syntax is that it does just one division operation.

Community
  • 1
  • 1
ugoren
  • 16,023
  • 3
  • 35
  • 65
  • 1
    ugoren: what is this part about then? `and whose magnitude is congruent modulo 2^n to the magnitude of the integral quotient of x/y, where n is an implementation-defined integer greater than or equal to 3.` – orlp Feb 19 '12 at 14:32
  • 2
    That's programming language lawyer talk, which is quite hard to read. It basically means "equals x/y", but allowing for overflowing an integer. – ugoren Feb 19 '12 at 14:35
  • 1
    @ugoran: Since `2^3 == 8` I presume this is to allow this to work on implementations where `sizeof(int) == 1 byte`. But why didn't they force that `n == sizeof(int)`? – orlp Feb 19 '12 at 14:40
  • 2^3 would allow 4-bit integers (3+sign). I think the specification is intentionally loose, so it won't be difficult to implement on various platforms. I guess a reasonable implementation for 32-bit integers will give a correct quotient modulu 31. – ugoren Feb 19 '12 at 14:51
  • Ugh. I wish the C standard was a bit more strict so you actually know what you can get from calling a function. But thanks for your effort, I will accept your answer. – orlp Feb 19 '12 at 14:52
  • according to Intel's compiler guide, precision should indeed be 31 except on IA-64, where it's 24; for some reason, a simple test seems not to agree with that - either my compiler is broken, or I don't understand how remainder and quotient are computed... – Christoph Feb 19 '12 at 16:49
  • @nightcracker according to C standard, int is required to be at least 16 bits, char size is 1 byte and a byte has at least 8 bits. If sizeof(int) == 1 byte then CHAR_BIT should be larger than or equal to 16 – phuclv Aug 12 '14 at 10:30