I'm making a simple function to calculate the difference between two inputs. Just for convenience really. Something to refer to in personal header files.
I wish to input either:
two integers : output one integer
two doubles : output one double
I've tried searching online for some kind of global input declaration but can't find it.
I prefer not to have two functions, just one simple one.
Example code headers:
int diff(int a, int b);
double diff(double a, double b);
Thanks for the help!
No, this is called overloading and it's not a feature C has. You are best off creating distinct functions to handle this.
You can do it with all sorts of C wizardry (you can just about do anything with enough C wizardry), but the resulting code may be so ugly as to be unmaintainable :-)
For example, C11 introduced generic selections, with the _Generic primary expression, and this allows you to call different functions based on the input argument type. It actually does a little more than that, but that's the aspect you're interested in, based on your question.
For example, let's say you define two functions thus:
int diffi (int a, int b) { return a - b; }
double diffd (double a, double b) { return a - b; }
Normally, you would have to decide which to call based on what your input types were. The C11 generic selection feature allows you to do this:
#define diff(a,b) \
_Generic((a), \
double: diffd, \
int: diffi, \
default: diffX \
)(a,b)
And what this does is basically, on finding the macro diff(x,y) in the source code:
determine the type of the expression (a), without evaluating it;
inject into the source stream the token matching that type (or default if no match found);
inject into the source stream the (a,b) text at the end.
So, if your source file contains the lines:
x = diff (1, 2);
y = diff (1.0, 2);
this will be translated into:
x = diffi (1 , 2);
y = diffd (1.0, 2);
giving you your effective overloading.
Now that's a moderately easy case since it relies on only the first argument type - you'll see a hole there if you try to do:
z = diff (1, 2.0);
in that the type of the first argument is an int so you'll get:
z = diffi (1, 2.0);
which won't be what you actually want to do. This is where the complexities come in since you have to cover four possibilities: {int/int, int/double, double/int, double/double} and it gets more complex based on the number of arguments and the possible types for each argument.
That full case of yours, however, can be done with judicious use of defaults and nested generic selections, something like:
#define diff(a,b) \
_Generic((a), \
double: diffd, \
default: _Generic((b), \
double: diffd, \
default: diffi \
) \
)(a,b)
and this can be read as:
if the type of a is double, use diffd;
otherwise, if the type of b is double, use diffd;
otherwise, use diffi.
don't forget to inject the arguments as well.
The following complete program (compiled with clang 3.0) shows this feature in action:
#include <stdio.h>
int diffi (int a, int b) {
printf ("diffi %d %d", a, b);
return a - b;
}
double diffd (double a, double b) {
printf ("diffd %f %f", a, b);
return a - b;
}
#define diff(a,b) \
_Generic((a), \
double: diffd, \
default: _Generic((b), \
double: diffd, \
default: diffi \
) \
)(a,b)
int main (void) {
int i; double d;
i = diff (1 , 2 ); printf (" --> %d\n", i);
d = diff (1.0, 2 ); printf (" --> %f\n", d);
d = diff (1 , 2.0); printf (" --> %f\n", d);
d = diff (1.0, 2.0); printf (" --> %f\n", d);
return 0;
}
The output of that program is:
diffi 1 2 --> -1
diffd 1.000000 2.000000 --> -1.000000
diffd 1.000000 2.000000 --> -1.000000
diffd 1.000000 2.000000 --> -1.000000
showing that the correct function is being called for the four possibilities.
And, in fact, as rici points out in a comment, you can rely on the promotion rules of C, where adding a double and int (in any order) gives you a double while adding two int variables gives you an int:
#define diff(a,b) _Generic((a+b), double:diffd, default:diffi)(a,b)
Function overloading is not available in C.
Some possible workarounds
Use two functions with different names for ex: diff_i and diff_d
(Recommended)
Use varargs (not recommended) This will make code difficult to maintain with time.
Use _Generic
An IEEE754 double has more than 32bits of precision, so just write the double version and let automatic conversion take care of the rest.
Of course if you're using a system where sizeof(int)>4 or a char has more than 8 bits, it may be best to write variants for each type, and adopt some kind of Hungarian-naming-convension for them. You could then write, maybe:
int diffi(int, int);
double diffd(double, double);
ssize_t diffz(size_t, size_t);
etc. Essentially, this is manually name-mangling, the same technique the C++ compiler uses to generate distinct symbolic-names for the object-file's export table.
Related
The question is about the (good) old printf function.
The length sub-specifier "l" is documented in the table named "specifiers" in:
https://www.cplusplus.com/reference/cstdio/printf/
The cell for the explenation for the combination of the length sub-specifier “l“ with the specifiers "f F e E g G a A" is left blanck. Does this mean, that for example "%le" behaves always like "%e"?
I tried hard to find an example where I get a difference between the "%le"-output and the "%e"-output … without any success. Can it be, that "%le" and "%e" produce generally the same output in the printf-context? I am using the Visual Studio Version 16.11.5 with the MSC-Version 19.29.30136 (MSC_FULL_VER is “192930136“). Here is my code:
#include <iostream>
//to get the MSC-compiler version
#define XSTR(x) STR(x)
#define STR(x) #x
#pragma message("_MSC_FULL_VER:")
#pragma message(XSTR(_MSC_FULL_VER))
int main()
{
double d = 1.123456789123456789123456789;
long double ld = static_cast<long double>(d);
printf("%.20e\n" , d);
printf("%.20le\n", d);
printf("%.20le\n", ld);
printf("%.20e\n" , ld);
return 0;
}
And here is the corresponding output:
1.12345678912345681155e+00
1.12345678912345681155e+00
1.12345678912345681155e+00
1.12345678912345681155e+00
The 2018 C standard says in clause 7.21.6.1, paragraph 7, for l:
… has no effect on a following a, A, e, E, f, F, g, or G conversion specifier.
(Text elided to the “…” used above specifies the effects of l on other specifiers.)
As already pointed out by Eric Postpischil, the length specifier l has no effect for the specifiers f F e E g G a A. Use the length specifier L for printing long double.
Note that some compilers (e.g. MSVC) will treat long double as if it is double.
The following code will generate different output if the compiler supports higher precession for long double:
#include <stdio.h>
int main()
{
double d = 1.123456789123456789123456789;
long double ld = 1.123456789123456789123456789L;
printf("Double: %.20e\n", d);
printf("Long Double: %.20Le\n", ld);
printf("Size of double: %lu\n", sizeof(double));
printf("Size of long double: %lu\n", sizeof(long double));
}
Output with clang 13.0.0 is the following:
Double: 1.12345678912345681155e+00
Long Double: 1.12345678912345678911e+00
Size of double: 8
Size of long double: 16
I'm trying to understand something about sin and sinf from math.h.
I understand that their types differ: the former takes and returns doubles, and the latter takes and returns floats.
However, GCC still compiles my code if I call sin with float arguments:
#include <stdio.h>
#include <math.h>
#define PI 3.14159265
int main ()
{
float x, result;
x = 135 / 180 * PI;
result = sin (x);
printf ("The sin of (x=%f) is %f\n", x, result);
return 0;
}
By default, all compiles just fine (even with -Wall, -std=c99 and -Wpedantic; I need to work with C99). GCC won't complain about me passing floats to sin. If I enable -Wconversion then GCC tells me:
warning: conversion to ‘float’ from ‘double’ may alter its value [-Wfloat-conversion]
result = sin (x);
^~~
So my question is: is there a float input for which using sin, like above, and (implicitly) casting the result back to float, will result in a value that is different from that obtained using sinf?
This program finds three examples on my machine:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i;
float f, f1, f2;
for(i = 0; i < 10000; i++) {
f = (float)rand() / RAND_MAX;
float f1 = sinf(f);
float f2 = sin(f);
if(f1 != f2) printf("jackpot: %.8f %.8f %.8f\n", f, f1, f2);
}
}
I got:
jackpot: 0.98704159 0.83439910 0.83439904
jackpot: 0.78605396 0.70757037 0.70757031
jackpot: 0.78636044 0.70778692 0.70778686
This will find all the float input values in the range 0.0 to 2 * M_PI where (float)sin(input) != sinf(input):
#include <stdio.h>
#include <math.h>
#include <float.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
int main(void)
{
for (float in = 0.0; in < 2 * M_PI; in = nextafterf(in, FLT_MAX)) {
float sin_result = (float)sin(in);
float sinf_result = sinf(in);
if (sin_result != sinf_result) {
printf("sin(%.*g) = %.*g, sinf(%.*g) = %.*g\n",
FLT_DECIMAL_DIG, in, FLT_DECIMAL_DIG, sin_result,
FLT_DECIMAL_DIG, in, FLT_DECIMAL_DIG, sinf_result);
}
}
return 0;
}
There are 1020963 such inputs on my amd64 Linux system with glibc 2.32.
float precision is approximately 6 significant figures decimal, while double is good for about 15. (It is approximate because they are binary floating point values not decimal floating point).
As such for example: a double value 1.23456789 will become 1.23456xxx as a float where xxx are unlikely to be 789 in this case.
Clearly not all (in fact very few) double values are exactly representable by float, so will change value when down-converted.
So for:
double a = 1.23456789 ;
float b = a ;
printf( "double: %.10f\n", a ) ;
printf( "float: %.10f\n", b ) ;
The result in my test was:
double: 1.2345678900
float: 1.2345678806
As you can see the float in fact retained 9 significant figures in this case, but it is by no means guaranteed for all possible values.
In your test you have limited the number of instances of mismatch because of the limited and finite range of rand() and also because f itself is float. Consider:
int main()
{
unsigned mismatch_count = 0 ;
unsigned iterations = 0 ;
for( double f = 0; f < 6.28318530718; f += 0.000001)
{
float f1 = sinf(f);
float f2 = sin(f);
iterations++ ;
if(f1 != f2)
{
mismatch_count++ ;
}
}
printf("%f%%\n", (double)mismatch_count/iterations* 100.0);}
In my test about 55% of comparisons mismatched. Changing f to float, the mismatches reduced to 1.3%.
So in your test, you see few mismatches because of the constraints of your method of generating f and its type. In the general case the issue is much more obvious.
In some cases you might see no mismatches - an implementation may simply implement sinf() using sin() with explicit casts. The compiler warning is for the general case of implicitly casting a double to a float without reference to any operations performed prior to the conversion.
However, GCC still compiles my code if I call sin with float arguments:
Yes, this is because they are implicitly converted to double (because sin() requires a float), and back to float (because sin() returns a double) on entering and exiting from the sinf() function. See below why it is better to use sinf() in this case, instead of having only one function.
You have included math.h which has prototypes for both function calls:
double sin(double);
float sinf(float);
And so, the compiler knows that to use sin() it is necessary a conversion from float to double so it compiles a conversion before calling, and also compiles a conversion from double to float in the result from sin().
In case you have not #include <math.h> and you ignored the compiler warning telling you are calling a function sin() with no prototype, the compiler should have also converted first the float to double (because on nonspecified argument types this is how it mus proceed) and pass the double data to the function (which is assumed to return an int in this case, that will provoke a serious Undefined Behaviour)
In case you have used the sinf() function (with the proper prototype), and passed a float, then no conversion should be compiled, the float is passed as such with no type conversion, and the returned value is assigned to a float variable, also with no conversion. So everything goes fine with no conversion, this makes the fastest code.
In case you have used the sinf() function (with no prototype), and passed a float, this float would be converted to a double and passed as such to sinf(), resulting in undefined behaviour. In case somehow sinf() returned properly, an int result (that could have something to do with the calculation or not, as per UB) would be converted into float type (should this be possible) and assigned to the result value.
In the case mentioned above, in case you are operating on floats, it is better to use sinf() as it takes less to execute (it has less iterations to do, as less precision is required in them) and the two conversions (from float to double and back from double to float) have not to be compiled in, in the binary code output by the compiler.
There are some systems where computations on float are an order of magnitude faster than computations on double. The primary purpose of sinf is to allow trigonometric calculations to be performed efficiently on such systems in cases where the lower precision of float would be adequate to satisfy application needs. Converting a value to float, calling sin, and converting the result to float would always yield a value that either matched that of sinf or was more accurate(*), and on some implementations that would in fact be the most efficient way of implementing sinf. On some other systems, however, such an approach would be more than an order of magnitude slower than using a purpose-designed function to evaluate the sine of a float.
(*) Note that for arguments outside the range +/- π/2, the most mathematically accurate way of computing sin(x) for an exact specified value of x might not be the most accurate way of computing what the calling code wants to know. If an application computes sinf(angle * (2.0f * 3.14159265f)), when angle is 0.5, having the function (double)3.1415926535897932385-(float)3.14159265f may be more "mathematically accurate" than having it return sin(angle-(2.0f*3.14159265f)), but the latter would more accurately represent the sine of the angle the code was actually interested in.
Using the complex number type of the C99 standard, how does one assign the real and imaginary parts of a variable individually? I found the GNU extension __real__ and __imag__ will do it, as in the following example program. But this isn't portable or standard. How can one do this portably?
#include <stdio.h>
#include <stdlib.h>
#include <complex.h>
int
main()
{
complex double z;
__real__ z = 3.0;
__imag__ z = 2.0;
fprintf(stderr, "z = %f + i %f\n", creal(z), cimag(z));
return 0;
}
C 2018 6.2.5 13 implies we can treat complex number as an array of two elements:
Each complex type has the same representation and alignment requirements as an array type containing exactly two elements of the corresponding real type; the first element is equal to the real part, and the second element to the imaginary part, of the complex number.
This is crude wording, at odds with the explicitly stated aliasing rules in 6.5 7, but the standard is imperfect, and footnotes 41 and 49, about integers and pointers, suggest such statements about representation and alignment are supposed to allow some use of one view of the object for another in spite of the rules in 6.5 7. If so, we can define macros:
#define Re(x) (_Generic((x), \
complex float : ((float *) &(x)), \
complex double : ((double *) &(x)), \
complex long double : ((long double *) &(x)))[0])
#define Im(x) (_Generic((x), \
complex float : ((float *) &(x)), \
complex double : ((double *) &(x)), \
complex long double : ((long double *) &(x)))[1])
after which Re(x) and Im(x), when given a complex object, produce an lvalue for the real or imaginary part. So we can assign them:
Re(x) = 3;
Im(x) = 4;
How can one do this portably?
It's just... addition:
z = 3.0;
z += I * 2.0;
You could first zero the imaginary part, if you want to:
z = creal(z) + I * 2.0;
how does one assign the real and imaginary parts of a variable
individually?
// assign real
z = new_value + I * cimag(z);
// assign imaginary
z = creal(z) + I * new_value;
One could prefer _Imaginary_I or CMPLXF macros over I.
I found another possible solution. The code below assumes that complex double is bit-equivalent to double[2] (which I think is correct but would appreciate a verification!). I think the solution below may be more efficient since it doesn't involve an extra addition operation for each assignment (as does KamilCuk's solution).
If anyone can verify this is will be portable to all platforms, I would appreciate it.
#include <stdio.h>
#include <stdlib.h>
#include <complex.h>
#define SET_REAL(z, x) ( *((double *) &(z)) = (x) )
#define SET_IMAG(z, x) ( *(((double *) &(z)) + 1) = (x) )
int
main()
{
complex double z;
SET_REAL(z, 3.0);
SET_IMAG(z, 2.0);
fprintf(stderr, "z = %f + i %f\n", creal(z), cimag(z));
return 0;
}
I need to write a macro that would count bits in odd positions (in ANSI C). For example, in 1010 the count of such bits is 2 while in 0101 the count is 0.
This is the macro I came up with:
#include <stdio.h>
#define BIT_IN_BYTE 8
#define size(x,t) { \
int i, sum = 0; \
for(i = 0; x; x >>= 1) { \
if( (x & 1) && (i % 2) != 0) { \
sum++; \
} \
i++; \
} \
t = sum; \
} \
int main() {
int b = 44444, result;
size(b, result);
printf("count = %d\n", result);
return 0;
}
I have 2 questions really: whether I could've written the macro in a way that it wouldn't need two arguments in its signature and more importantly if there's a relatively simple way to extend the macro onto float and double types.
As in the comments to your question, using a macro here really is not good practice. You should really use a function instead - inline or otherwise.
Since you're apparently forced to use a macro in your case for reasons outside of your control, here are some relevant points to your example:
You can use sizeof to get the number of bytes in whatever type you pass in your x parameter. This will potentially allow you to generalize the macros to different types (you mention float and double) that have different sizes.
Since the macro does not do type checking, if you have something that works for int in a generic way - probably using bit-wise operations - you'll have a fighting chance of making it work for other types. I again note, however, that the lack of type safety is a reason to avoid macros in many cases.
As noted in a comment on your question, your current approach destroys the value in whatever you pass as parameter x. That's likely undesired and unnecessary.
You would only be able to avoid passing the second parameter if you can rewrite this such that is evaluates to a number. I'm not motivated to figure out exactly how to do that for this contrived example or if it is actually possible.
How can I work with complex numbers in C? I see there is a complex.h header file, but it doesn't give me much information about how to use it. How to access real and imaginary parts in an efficient way? Is there native functions to get module and phase?
This code will help you, and it's fairly self-explanatory:
#include <stdio.h> /* Standard Library of Input and Output */
#include <complex.h> /* Standard Library of Complex Numbers */
int main() {
double complex z1 = 1.0 + 3.0 * I;
double complex z2 = 1.0 - 4.0 * I;
printf("Working with complex numbers:\n\v");
printf("Starting values: Z1 = %.2f + %.2fi\tZ2 = %.2f %+.2fi\n", creal(z1), cimag(z1), creal(z2), cimag(z2));
double complex sum = z1 + z2;
printf("The sum: Z1 + Z2 = %.2f %+.2fi\n", creal(sum), cimag(sum));
double complex difference = z1 - z2;
printf("The difference: Z1 - Z2 = %.2f %+.2fi\n", creal(difference), cimag(difference));
double complex product = z1 * z2;
printf("The product: Z1 x Z2 = %.2f %+.2fi\n", creal(product), cimag(product));
double complex quotient = z1 / z2;
printf("The quotient: Z1 / Z2 = %.2f %+.2fi\n", creal(quotient), cimag(quotient));
double complex conjugate = conj(z1);
printf("The conjugate of Z1 = %.2f %+.2fi\n", creal(conjugate), cimag(conjugate));
return 0;
}
with:
creal(z1): get the real part (for float crealf(z1), for long double creall(z1))
cimag(z1): get the imaginary part (for float cimagf(z1), for long double cimagl(z1))
Another important point to remember when working with complex numbers is that functions like cos(), exp() and sqrt() must be replaced with their complex forms, e.g. ccos(), cexp(), csqrt().
Complex types are in the C language since C99 standard (-std=c99 option of GCC). Some compilers may implement complex types even in more earlier modes, but this is non-standard and non-portable extension (e.g. IBM XL, GCC, may be intel,... ).
You can start from http://en.wikipedia.org/wiki/Complex.h - it gives a description of functions from complex.h
This manual http://pubs.opengroup.org/onlinepubs/009604499/basedefs/complex.h.html also gives some info about macros.
To declare a complex variable, use
double _Complex a; // use c* functions without suffix
or
float _Complex b; // use c*f functions - with f suffix
long double _Complex c; // use c*l functions - with l suffix
To give a value into complex, use _Complex_I macro from complex.h:
float _Complex d = 2.0f + 2.0f*_Complex_I;
(actually there can be some problems here with (0,-0i) numbers and NaNs in single half of complex)
Module is cabs(a)/cabsl(c)/cabsf(b); Real part is creal(a), Imaginary is cimag(a). carg(a) is for complex argument.
To directly access (read/write) real an imag part you may use this unportable GCC-extension:
__real__ a = 1.4;
__imag__ a = 2.0;
float b = __real__ a;
For convenience, one may include tgmath.h library for the type generate macros. It creates the same function name as the double version for all type of variable. For example, For example, it defines a sqrt() macro that expands to the sqrtf() , sqrt() , or sqrtl() function, depending on the type of argument provided.
So one don't need to remember the corresponding function name for different type of variables!
#include <stdio.h>
#include <tgmath.h>//for the type generate macros.
#include <complex.h>//for easier declare complex variables and complex unit I
int main(void)
{
double complex z1=1./4.*M_PI+1./4.*M_PI*I;//M_PI is just pi=3.1415...
double complex z2, z3, z4, z5;
z2=exp(z1);
z3=sin(z1);
z4=sqrt(z1);
z5=log(z1);
printf("exp(z1)=%lf + %lf I\n", creal(z2),cimag(z2));
printf("sin(z1)=%lf + %lf I\n", creal(z3),cimag(z3));
printf("sqrt(z1)=%lf + %lf I\n", creal(z4),cimag(z4));
printf("log(z1)=%lf + %lf I\n", creal(z5),cimag(z5));
return 0;
}
The notion of complex numbers was introduced in mathematics, from the need of calculating negative quadratic roots. Complex number concept was taken by a variety of engineering fields.
Today that complex numbers are widely used in advanced engineering domains such as physics, electronics, mechanics, astronomy, etc...
Real and imaginary part, of a negative square root example:
#include <stdio.h>
#include <complex.h>
int main()
{
int negNum;
printf("Calculate negative square roots:\n"
"Enter negative number:");
scanf("%d", &negNum);
double complex negSqrt = csqrt(negNum);
double pReal = creal(negSqrt);
double pImag = cimag(negSqrt);
printf("\nReal part %f, imaginary part %f"
", for negative square root.(%d)",
pReal, pImag, negNum);
return 0;
}
To extract the real part of a complex-valued expression z, use the notation as __real__ z.
Similarly, use __imag__ attribute on the z to extract the imaginary part.
For example;
__complex__ float z;
float r;
float i;
r = __real__ z;
i = __imag__ z;
r is the real part of the complex number "z"
i is the imaginary part of the complex number "z"