Could someone please help and tell me how to include IEEE mathematical functions in MSVC++6? I tried both and , but I still get these errors:
error C2065: 'ilogbf' : undeclared identifier
error C2065: 'scalbnf' : undeclared identifier
Edit 3: Hopefully this will be my final edit. I have come to realize that I haven't properly addressed this question at all. I am going to leave my answer in place as a cautionary tale, and because it may have some educational value. But I understand why I have zero upvotes, and in fact I am going to upvote Andy Ross' answer because I think his is much more relevant (although incomplete at least at the time of writing). It seems to me my mistake was to take the Man definitions I found for ilogbf() a little superficially. It's a function that takes the integer part of the log of a float, how hard can that be to implement ? It turns out what the function is really about is IEEE floating point representation, in particular the exponent (as opposed to the mantissa) part of that representation. I should definitely have realized that before attempting to answer the question! An interesting point to me is how a function can possibly find the exponent part of a float, as I thought a fundamental rule of C is that floats are promoted to doubles as part of a function call. But that's a whole separate discussion of course.
--- End of edit 3, start of cautionary tale ---
A little googling suggests these are defined in some flavors of Unix, but maybe are not in any Posix or ANSI standard and so not provided with the MSVC libraries. If the functions aren't in the library they won't be declared in math.h. Obviously if the compiler can't see declarations for these external symbols it won't be happy and you'll get errors like the ones you list.
The obvious work around is to create your own versions of these functions, using math functions that are provided. eg
#include <math.h>
int ilogbf( float f )
{
double d1 = (double)f;
double d2 = log(d1);
int ret = (int)d2;
return ret;
}
Edit: This isn't quite right. Apparently, this function should use log to the base 2, rather than natural logs, so that the returned value is actually a binary exponent. It should also take the absolute value of its parameter, so that it will work for negative numbers as well. I will work up an improved version, if you ask me in a comment, otherwise I'm tempted to leave that as an exercise for the reader :-)
The essence of my answer, i.e. that ANSI C doesn't require this function and that MSVC doesn't include it, is apparently correct.
Edit 2: Okay I've weakened and provided an improved version without being asked. Here it is;
#include <math.h>
int ilogbf( float f )
{
double d1 = (double)f;
if( d1 < 0 )
d1 = -d1;
double d2 = log(d1) / log(2); // log2(x) = ln(x)/ln(2)
int ret = (int)d2;
return ret;
}
These are C99 functions, not IEEE754-1985. Microsoft seems to have decided that their market doesn't care about C99 support, so they haven't bothered to provide them. This is a shame, but unless more of you (developers) complain, there's no reason to expect that the situation will change.
The brand new 754 standard, IEEE754-2008, requires these functions (Clause 5.3.3, "logBFormat operations"), but that version of the standard won't be widely adopted for several more years; even if it does reach wide adoption, Microsoft hasn't seen fit to provide these functions for the ten years they've been in C99 so why would they bother to provide them just because they're in the IEEE754 standard?
edit: note that scalb and logb are defined in the IEEE754-1985 Appendix "Recommended Functions and Predicates", but said appendix is explicitly "not a part of" said standard.
If you know you're on an IEEE system (and these days, you do), these functions aren't needed: just inspect the bits directly by unioning the double with a uint64_t. Presumably you're using these functions in the interest of efficiency in the first place (otherwise you'd be using more natural operations like log() or exp()), so spending a little effort on matching your code to the floating point representation is probably worthwhile.
Related
All C math functions seems to have an understandable name, but I can't find what the fdim acronym stands for.
(fdim computes the positive difference of it two floating-point inputs).
I searched the ISO-C working group's document archive, and noticed that most of the proposals for the floating-point enhancements to what would become C99 were contributed by Jim Thomas. Best I can tell, fdim was included in the draft new standard prior to 1996, and unfortunately the archive does not provide links to electronic copies for proposals from that time.
So I contacted Mr. Thomas directly via email and received a response, the relevant portion of which I quote here with his permission:
From: Jim Thomas
To: Norbert Juffa
Time: Sat 2/15/2020 8:42 AM
Subject: Re: Naming of, and rationale for, the fdim() function in ISO-C99
[...]
The C fdim function is the C versions for the Fortran DIM (positive difference) function. The C function, and its name, were intended for programmers porting code form Fortran to C.
This confirms the linkage with Fortran alluded to in comments. As for the name DIM itself, Ctx's answer addresses this as well as one could hope for in the case of a minor function that has been around for fifty years.
In comments below the question, Mark Dickinson pointed to the Fortran 66 standard, which on page 23 defined Fortran's DIM function as a₁ - Min (a₁, a₂). This provides further evidence that the name DIM is a contraction of DIfference and Minimum.
My guess is, that it is a composition from difference and max, because this is what the function does.
Pseudo-code
double fdim(x, y) {
float tmp = x - y; // 1st step: "di"fference
float result = fmax(tmp, 0); // 2nd step: "m"aximum
return result;
}
Same nomenclature for example with fma(a, b, c), which means "multiply" and "add" (a*b+c)
Edit:
The function indeed occurred even earlier in Fortran, where the function
DIM(number, number) is defined as
A function that returns the value of the first argument minus the minimum (MIN) of the two arguments.
so the function name is derived from difference and minimum here. See the F77 DIM manual
I can't find any good published first source for this. fdim first appeared in C99, and the C99 rationale (7.12.12) only mentions this:
The names for fmax, fmin and fdim have f prefixes to allow for
extension integer versions following the example of fabs and abs.
But we could already guess as much, the f stands for floating point.
Similarly, the last f in fdimf stands for float, and the last l in fdiml stands for long double. These prefix/postfix letters are commonly used in the standard libs.
Does the following code have defined beavior:
#include <stdio.h>
int main() {
int x;
if (scanf("%x", &x) == 1) {
printf("decimal: %d\n", x);
}
return 0;
}
clang compiles it without any warnings even with all warnings enabled, including -pedantic. The C Standard seems unambiguous about this:
C17 7.21.6.2 The fscanf function
...
... the result of the conversion is placed in the object pointed to by the first argument following the format argument that has not already received a conversion result. If this object does not have an appropriate type, or if the result of the conversion cannot be represented in the object, the behavior is undefined.
...
The conversion specifiers and their meanings are:
...
x Matches an optionally signed hexadecimal integer, whose format is the same as expected for the subject sequence of the strtoul function with the value 16 for the base argument. The corresponding argument shall be a pointer to unsigned integer.
On two's complement architectures, converting -1 with %x seems to work, but it would not on ancient sign/magnitude or ones complement systems.
Is there any provision to make this behavior defined or at least implementation defined?
This falls in the category of behaviors which quality implementations should support unless they document a good reason for doing otherwise, but which the Standard does not mandate. The authors of the Standard seem to have refrained from trying to list all such behaviors, and there are at least three good reasons for that:
Doing so would have made the Standard longer, and spending ink describing obvious behaviors that readers would expect anyway would distract from the places where the Standard needed to call readers' attention to things that they might not otherwise expect.
The authors of the Standard may not have wanted to preclude the possibility that an implementation might have a good reason for doing something unusual. I don't know whether that was a consideration in your particular case, but it could have been.
Consider, for example, a (likely theoretical) environment whose calling convention that requires passing information about argument types fed to variadic functions, and that supplies a scanf function that validates those argument types and squawks if int* is passed to a %X argument. The authors of the Standard were almost certainly not aware of any such environment [I doubt any ever existed], and thus would be in no position to weigh the benefits of using the environment's scanf routine versus the benefits of supporting the common behavior. Thus, it would make sense to leave such judgment up to people who would be in a better position to assess the costs and benefits of each approach.
It would be extremely difficult for the authors of the Standard to ensure that they exhaustively enumerated all such cases without missing any, and the more exhaustively they were to attempt to enumerate such cases, the more likely it would be that accidental omissions would be misconstrued as deliberate.
In practice, some compiler writers seem to regard most situations where the Standard fails to mandate the behavior of some action as an invitation to assume code will never attempt it, even if all implementations prior to the Standard had behaved consistently and it's unlikely there would ever be any good reason for an implementation to do otherwise. Consequently, using %X to read an int falls in the category of behaviors that will be reliable on implementations that make any effort to be compatible with common idioms, but could fail on implementations whose designers place a higher value on being able to process useless programs more efficiently, or on implementations that are designed to squawk when given programs that could be undermined by such implementations.
I have code that works mainly with single-precision floating point numbers. Calls to transcendental functions occur fairly often. Right now, I'm using sin(), cos(), sqrt(), etc--functions that accept and return double. When it's compiled for x87 only, I know there's no difference between single and double precision. I read in Agner Fog's optimization guide however that software versions of these function utilizing SSE instructions are faster for single-precision floating point numbers.
My question is whether the compiler would automatically use the faster function when it encounters something like:
float x = 1.23;
float y = sin(x);
Or does rounding rule preclude such an optimization?
It'd be easy enough to just do a search-and-replace and see whether there's any performance gain. Trouble is that I also need pointers to these functions. In MSVC, sinf(), cosf(), and friends are inline functions. Using them would therefore requires a bit of gymnastics. Before making the effort, I would like to know whether it's worthwhile.
Besides MSVC, I'm also targeting gcc.
There is really no need to have the cast when calling sin. In fact it would be counterproductive if you'd use the <tgmath.h> header that comes with C99. That provides you type generic macros that would chose the right function according to your argument, not for the target type unfortunately. So if you'd use that header (not sure if this is available for MS)
float x = 1.23;
float y = sin(x);
would automatically use sinf under the hood.
Why is it sensible for a language to allow implicit declarations of functions and typeless variables? I get that C is old, but allowing to omit declarations and default to int() (or int in case of variables) doesn't seem so sane to me, even back then.
So, why was it originally introduced? Was it ever really useful? Is it actually (still) used?
Note: I realise that modern compilers give you warnings (depending on which flags you pass them), and you can suppress this feature. That's not the question!
Example:
int main() {
static bar = 7; // defaults to "int bar"
return foo(bar); // defaults to a "int foo()"
}
int foo(int i) {
return i;
}
See Dennis Ritchie's "The Development of the C Language": http://web.archive.org/web/20080902003601/http://cm.bell-labs.com/who/dmr/chist.html
For instance,
In contrast to the pervasive syntax variation that occurred during the
creation of B, the core semantic content of BCPL—its type structure
and expression evaluation rules—remained intact. Both languages are
typeless, or rather have a single data type, the 'word', or 'cell', a
fixed-length bit pattern. Memory in these languages consists of a
linear array of such cells, and the meaning of the contents of a cell
depends on the operation applied. The + operator, for example, simply
adds its operands using the machine's integer add instruction, and the
other arithmetic operations are equally unconscious of the actual
meaning of their operands. Because memory is a linear array, it is
possible to interpret the value in a cell as an index in this array,
and BCPL supplies an operator for this purpose. In the original
language it was spelled rv, and later !, while B uses the unary *.
Thus, if p is a cell containing the index of (or address of, or
pointer to) another cell, *p refers to the contents of the pointed-to
cell, either as a value in an expression or as the target of an
assignment.
This typelessness persisted in C until the authors started porting it to machines with different word lengths:
The language changes during this period, especially around 1977, were largely focused on considerations of portability and type safety,
in an effort to cope with the problems we foresaw and observed in
moving a considerable body of code to the new Interdata platform. C at
that time still manifested strong signs of its typeless origins.
Pointers, for example, were barely distinguished from integral memory
indices in early language manuals or extant code; the similarity of
the arithmetic properties of character pointers and unsigned integers
made it hard to resist the temptation to identify them. The unsigned
types were added to make unsigned arithmetic available without
confusing it with pointer manipulation. Similarly, the early language
condoned assignments between integers and pointers, but this practice
began to be discouraged; a notation for type conversions (called
`casts' from the example of Algol 68) was invented to specify type
conversions more explicitly. Beguiled by the example of PL/I, early C
did not tie structure pointers firmly to the structures they pointed
to, and permitted programmers to write pointer->member almost without
regard to the type of pointer; such an expression was taken
uncritically as a reference to a region of memory designated by the
pointer, while the member name specified only an offset and a type.
Programming languages evolve as programming practices change. In modern C and the modern programming environment, where many programmers have never written assembly language, the notion that ints and pointers are interchangeable may seem nearly unfathomable and unjustifiable.
It's the usual story — hysterical raisins (aka 'historical reasons').
In the beginning, the big computers that C ran on (DEC PDP-11) had 64 KiB for data and code (later 64 KiB for each). There was a limit to how complex you could make the compiler and still have it run. Indeed, there was scepticism that you could write an O/S using a high-level language such as C, rather than needing to use assembler. So, there were size constraints. Also, we are talking a long time ago, in the early to mid 1970s. Computing in general was not as mature a discipline as it is now (and compilers specifically were much less well understood). Also, the languages from which C was derived (B and BCPL) were typeless. All these were factors.
The language has evolved since then (thank goodness). As has been extensively noted in comments and down-voted answers, in strict C99, implicit int for variables and implicit function declarations have both been made obsolete. However, most compilers still recognize the old syntax and permit its use, with more or less warnings, to retain backwards compatibility, so that old source code continues to compile and run as it always did. C89 largely standardized the language as it was, warts (gets()) and all. This was necessary to make the C89 standard acceptable.
There is still old code around using the old notations — I spend quite a lot of time working on an ancient code base (circa 1982 for the oldest parts) which still hasn't been fully converted to prototypes everywhere (and that annoys me intensely, but there's only so much one person can do on a code base with multiple millions of lines of code). Very little of it still has 'implicit int' for variables; there are too many places where functions are not declared before use, and a few places where the return type of a function is still implicitly int. If you don't have to work with such messes, be grateful to those who have gone before you.
Probably the best explanation for "why" comes from here:
Two ideas are most characteristic of C among languages of its class: the relationship between arrays and pointers, and the way in which declaration syntax mimics expression syntax. They are also among its most frequently criticized features, and often serve as stumbling blocks to the beginner. In both cases, historical accidents or mistakes have exacerbated their difficulty. The most important of these has been the tolerance of C compilers to errors in type. As should be clear from the history above, C evolved from typeless languages. It did not suddenly appear to its earliest users and developers as an entirely new language with its own rules; instead we continually had to adapt existing programs as the language developed, and make allowance for an existing body of code. (Later, the ANSI X3J11 committee standardizing C would face the same problem.)
Systems programming languages don't necessarily need types; you're mucking around with bytes and words, not floats and ints and structs and strings. The type system was grafted onto it in bits and pieces, rather than being part of the language from the very beginning. As C has moved from being primarily a systems programming language to a general-purpose programming language, it has become more rigorous in how it handles types. But, even though paradigms come and go, legacy code is forever. There's still a lot of code out there that relies on that implicit int, and the standards committee is reluctant to break anything that's working. That's why it took almost 30 years to get rid of it.
A long, long time ago, back in the K&R, pre-ANSI days, functions looked quite different than they do today.
add_numbers(x, y)
{
return x + y;
}
int ansi_add_numbers(int x, int y); // modern, ANSI C
When you call a function like add_numbers, there is an important difference in the calling conventions: all types are "promoted" when the function is called. So if you do this:
// no prototype for add_numbers
short x = 3;
short y = 5;
short z = add_numbers(x, y);
What happens is x is promoted to int, y is promoted to int, and the return type is assumed to be int by default. Likewise, if you pass a float it is promoted to double. These rules ensured that prototypes weren't necessary, as long as you got the right return type, and as long as you passed the right number and type of arguments.
Note that the syntax for prototypes is different:
// K&R style function
// number of parameters is UNKNOWN, but fixed
// return type is known (int is default)
add_numbers();
// ANSI style function
// number of parameters is known, types are fixed
// return type is known
int ansi_add_numbers(int x, int y);
A common practice back in the old days was to avoid header files for the most part, and just stick the prototypes directly in your code:
void *malloc();
char *buf = malloc(1024);
if (!buf) abort();
Header files are accepted as a necessary evil in C these days, but just as modern C derivatives (Java, C#, etc.) have gotten rid of header files, old-timers didn't really like using header files either.
Type safety
From what I understand about the old old days of pre-C, there wasn't always much of a static typing system. Everything was an int, including pointers. In this old language, the only point of function prototypes would be to catch arity errors.
So if we hypothesize that functions were added to the language first, and then a static type system was added later, this theory explains why prototypes are optional. This theory also explains why arrays decay to pointers when used as function arguments -- since in this proto-C, arrays were nothing more than pointers which get automatically initialized to point to some space on the stack. For example, something like the following may have been possible:
function()
{
auto x[7];
x += 1;
}
Citations
The Development of the C Language, Dennis M. Ritchie
On typelessness:
Both languages [B and BCPL] are typeless, or rather have a single data type, the 'word,' or 'cell,' a fixed-length bit pattern.
On the equivalence of integers and pointers:
Thus, if p is a cell containing the index of (or address of, or pointer to) another cell, *p refers to the contents of the pointed-to cell, either as a value in an expression or as the target of an assignment.
Evidence for the theory that prototypes were omitted due to size constraints:
During development, he continually struggled against memory limitations: each language addition inflated the compiler so it could barely fit, but each rewrite taking advantage of the feature reduced its size.
Some food for thought. (It's not an answer; we actually know the answer — it's permitted for backward compatibility.)
And people should look at COBOL code base or f66 libraries before saying why it's not cleaned up in 30 years or so!
gcc with its default does not spit out any warnings.
With -Wall and gcc -std=c99 do spit out the correct thing
main.c:2: warning: type defaults to ‘int’ in declaration of ‘bar’
main.c:3: warning: implicit declaration of function ‘foo’
The lint functionality built into modern gcc is showing its color.
Interestingly the modern clone of lint, the secure lint — I mean splint — gives only one warning by default.
main.c:3:10: Unrecognized identifier: foo
Identifier used in code has not been declared. (Use -unrecog to inhibit
warning)
The llvm C compiler clang which also has a static analyser built into it like gcc, spits out the two warnings by default.
main.c:2:10: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
static bar = 7; // defaults to "int bar"
~~~~~~ ^
main.c:3:10: warning: implicit declaration of function 'foo' is invalid in C99
[-Wimplicit-function-declaration]
return foo(bar); // defaults to a "int foo()"
^
People used to think we don't need backward compatibility for 80's stuff. All the code must be cleaned up or replaced. But it turns out it's not the case. A lot of production code stays in prehistoric non-standard times.
EDIT:
I didn't look through other answers before posting mine. I may have misunderstood the intention of the poster. But the thing is there was a time when you hand compiled your code, and use toggle to put the binary pattern in memory. They didn't need a "type system". Nor does the PDP machine in front of which Richie and Thompson posed like this :
Don't look at the beard, look at the "toggles", which I heard were used to bootstrap the machine.
And also look how they used to boot UNIX in this paper. It's from the Unix 7th edition manual.
http://wolfram.schneider.org/bsd/7thEdManVol2/setup/setup.html
The point of the matter is they didn't need so much software layer managing a machine with KB sized memory. Knuth's MIX has 4000 words. You don't need all these types to program a MIX computer. You can happily compare a integer with pointer in a machine like this.
I thought why they did this is quite self-evident. So I focused on how much is left to be cleaned up.
While researching how to do cross-platform printf() format strings in C (that is, taking into account the number of bits I expect each integer argument to printf() should be) I ran across this section of the Wikipedia article on printf(). The article discusses non-standard options that can be passed to printf() format strings, such as (what seems to be a Microsoft-specific extension):
printf("%I32d\n", my32bitInt);
It goes on to state that:
ISO C99 includes the inttypes.h header
file that includes a number of macros
for use in platform-independent printf
coding.
... and then lists a set of macros that can be found in said header. Looking at the header file, to use them I would have to write:
printf("%"PRId32"\n", my32bitInt);
My question is: am I missing something? Is this really the standard C99 way to do it? If so, why? (Though I'm not surprised that I have never seen code that uses the format strings this way, since it seems so cumbersome...)
The C Rationale seems to imply that <inttypes.h> is standardizing existing practice:
<inttypes.h> was derived from the header of the same name found on several existing 64-bit systems.
but the remainder of the text doesn't write about those macros, and I don't remember they were existing practice at the time.
What follows is just speculation, but educated by experience of how standardization committees work.
One advantage of the C99 macros over standardizing additional format specifier for printf (note that C99 also did add some) is that providing <inttypes.h> and <stdint.h> when you already have an implementation supporting the required features in an implementation specific way is just writing two files with adequate typedef and macros. That reduces the cost of making existing implementation conformant, reduces the risk of breaking existing programs which made use of the existing implementation specifics features (the standard way doesn't interfere) and facilitate the porting of conformant programs to implementation who don't have these headers (they can be provided by the program). Additionally, if the implementation specific ways already varied at the time, it doesn't favorize one implementation over another.
Correct, this is how the C99 standard says you should use them. If you want truly portablt code that is 100% standards-conformant to the letter, you should always print an int using "%d" and an int32_t using "%"PRId32.
Most people won't bother, though, since there are very few cases where failure to do so would matter. Unless you're porting your code to Win16 or DOS, you can assume that sizeof(int32_t) <= sizeof(int), so it's harmless to accidentally printf an int32_t as an int. Likewise, a long long is pretty much universally 64 bits (although it is not guaranteed to be so), so printing an int64_t as a long long (e.g. with a %llx specifier) is safe as well.
The types int_fast32_t, int_least32_t, et al are hardly ever used, so you can imagine that their corresponding format specifiers are used even more rarely.
You can always cast upwards and use %jd which is the intmax_t format specifier.
printf("%jd\n", (intmax_t)(-2));
I used intmax_t to show that any intXX_t can be used, but simply casting to long is much better for the int32_t case, then use %ld.
I can only speculate about why. I like AProgrammer's answer above, but there's one aspect overlooked: what are you going to add to printf as a format modifier? There are already two different ways that numbers are used in a printf format string (width and precision). Adding a third kind of number to say how many bits of precision are in the argument would be great, but where are you going to put it without confusing people? Unfortunatey one of the flaws in C is that printf was not designed to be extensible.
The macros are awful, but when you have to write code that is portable across 32-bit and 64-bit platforms, they are a godsend. Definitely saved my bacon.
I think the answer to your question why is either
Nobody could think of a better way to do it, or
The standards committee couldn't agree on anything they felt was clearly better.
Another possibility: backward compatibility. If you add more format specifiers to printf, or additional options, it is possible that a specifier in some pre-C99 code would have a format string interpreted differently.
With the C99 change, you're not changing the functionality of printf.