I have a lengthy numeric integration scheme written in C. I'd like to test my algorithm in floating point precision. Is there a way to tell gcc to demote every occurrence of double to float in the entire program?
You can't safely do this without modifying your source code, but that shouldn't be terribly difficult to do.
Using the preprocessor to force the keyword double in your program to be treated as float is a bad idea; it will make your program difficult to read, and if you happen to use long double anywhere it would be treated as long float, which is a syntax error.
As stix's answer suggests, you can add a typedef, either at the top of your program (if it's a single source file) or in some header that's #includeed by all the relevant source files:
typedef double real; /* or pick a different name */
Then go through your source code and change each occurrence of double to real. (Be careful about doing a blind global search-and-replace.)
Make sure that the program still compiles, runs, and behaves the same way after this change. Then you can change the typedef to:
typedef float real;
and recompile to use float rather than double.
It's not quite that simple, though. If you're using functions declared in <math.h>, you'll want to use the right function for whatever floating-point type you're using; for example, sqrt() is for double, sqrtf() is for float, and sqrtl() is for long double.
If your compiler supports it, you might use the <tgmath.h> header, which defines type-generic macros corresponding to the math functions from <math.h>. If you use <tgmath.h>, then sqrt(x) will resolve to call the correct square root function depending on the type of the argument.
typedef double float;
Before any doubles that you want to replace should work, however be warned it may confuse some external libraries.
In the future, the best approach is to define your own float type:
#ifdef USE_FLOATS
typedef float MyFloatType;
#else
typedef double MyFloatType;
#endif
Or use templates, which has the added benefit of allowing you to change the code at runtime to use one or the other.
Related
Consider a library that defines in a header file
struct Proj {
struct Depth {
static constexpr unsigned Width = 10u;
static constexpr unsigned Height = 10u;
};
struct Video {
static constexpr unsigned Width = 10u;
static constexpr unsigned Height = 10u;
};
};
The library gets compiled, and I'm now developing an application that links against this library. I thought for a long time it was some kind of visibility problem, but even after adding B_EXPORT (standard visibility stuff from CMake) everywhere with no change, I finally found the problem.
template <class Projection>
struct SomeApplication {
SomeApplication() {
unsigned height = std::max(// or std::max<unsigned>
Projection::Depth::Height,
Projection::Video::Height
);
}
};
I can't even reproduce the problem with a small dummy library / sample application. But using std::max in the application causes the link error, whereas if I just do it myself
unsigned height = Projection::Depth::Height;
if (height < Projection::Video::Height)
height = Projection::Video::Height;
Everything works out. AKA there don't appear to be any specific issues with the visibility in terms of just using Projection::XXX.
Any thoughts on what could possibly cause this? This is on OSX, so this doesn't even apply.
The problem is that Width and Height are declared, not defined in your structs. Effectively, this means there is no storage allocated for them.
Now recall the signature for std::max:
template<typename T>
const T& max(const T&, const T&);
Note the references: this means the addresses of the arguments are to be taken. But, since Width and Height are only declared, they don't have any storage! Hence the linker error.
Now let's consider the rest of your question.
Your hand-written max works because you never take any pointers or references to the variables.
You might be unable to reproduce this on a toy example because, depending on the optimization level in particular, a sufficiently smart compiler might evaluate max at compile time and save the trouble of taking the addresses at runtime. For instance, compare the disasm for no optimization vs -O2 for gcc 7.2: the evaluation is indeed done at compile-time!
As for the fix, it depends. You have several options, to name a few:
Use constexpr getter functions instead of variables. In this case the values they return will behave more like temporary objects, allowing the addresses to be taken (and the compiler will surely optimize that away). This is the approach I'd suggest in general.
Use namespaces instead of structs. In this case the variables will also be defined in addition to being declared. The caveat is that you might get duplicate symbol errors if they are used in more than one translation unit. The fix for that is only in form of C++17 inline variables.
...speaking of which, C++17 also changes the rules for constexpr static member variables (they become inline by default), so you won't get this error if you just switch to this standard.
I'm reading Bjarne Stroustrup's book, "The C++ Programming Language" and I found an example explaining static_assert. What I understood is that static_assert only works with things that can be expressed by constant expressions. In other words, it must not include an expression that's meant to be evaluated at runtime.
The following example was used in the book (I did some changes in the code. But I don't think that should change anything that'd be produced by the original example code given in the book.)
#include <iostream>
using namespace std;
void f (double speed)
{
constexpr double C = 299792.468;
const double local_max = 160.0/(60*60);
static_assert(local_max<C,"can't go that fast");
}
int main()
{
f(3.25);
cout << "Reached here!";
return 0;
}
The above gives a compile error. Here's it compiled using ideone: http://ideone.com/C97oF5
The exact code from the book example:
constexpr double C = 299792.458;
void f(double speed)
{
const double local_max = 160.0/(60∗60);
static_assert(speed<C,"can't go that fast"); // yes this is error
static_assert(local_max<C,"can't go that fast");
}
The compiler does not know the value of speed at compile time. It makes sense that it cannot evaluate speed < C at compile time. Hence, a compile time error is expected when processing the line
static_assert(speed<C,"can't go that fast");
The language does not guarantee that floating point expressions be evaluated at compile time. Some compilers might support it but that's not to be relied upon.
Even though the values of the floating point variables are "constants" to a human reader, they are not necessarily evaluated at compile time. The error message from the compiler from the link you provided makes it clear.
static_assert expression is not an integral constant expression
You'll have to find a way to do the comparison using integral expressions. However, that seems to be a moot point. I suspect, what you really want to do is make sure that speed is within a certain limit. That makes sense only as a run time check.
Declaring const global variables has proven useful to determine some functioning parameters of an API. For example, on my API, the minimum order of numerical accuracy operators have is 2; thus, I declare:
const int kDefaultOrderAccuracy{2};
as a global variable. Would it be better to make this a static const public data member of the classes describing these operators? When, in general, is better to choose one over the other?
const int kDefaultOrderAccuracy{2};
is the declaration of a static variable: kDefaultOrderAccuracy has internal linkage. Putting names with internal linkage in a header is obviously an extremely bad idea, making it extremely easy to violate the One Definition Rule (ODR) in other code with external linkage in the same or other header, notably when the name is used in the body of an inline or template function:
Inside f.hpp:
template <typename T>
const T& max(const T &x, const T &y) {
return x>y ? x : y;
}
inline int f(int x) {
return max(kDefaultOrderAccuracy, x); // which kDefaultOrderAccuracy?
}
As soon as you include f.hpp in two TU (Translation Units), you violate the ODR, as the definition is not unique, as it uses a namespace static variable: which kDefaultOrderAccuracy object the definition designates depends on the TU in which it is compiled.
A static member of a class has external linkage:
struct constants {
static const int kDefaultOrderAccuracy{2};
};
inline int f(int x) {
return max(constants::kDefaultOrderAccuracy, x); // OK
}
There is only one constants::kDefaultOrderAccuracy in the program.
You can also use namespace level global constant objects:
extern const int kDefaultOrderAccuracy;
Context is always important.
To answer questions like this.
Also for naming itself.
If you as a reader (co-coder) need to guess what an identifier means, you start looking for more context, this may be supported through an API doc, often included in decent IDEs. But if you didn't provide a really great API doc (I read this from your question), the only context you get is by looking where your declaration is placed.
Here you may be interested in the name(s) of the containing library, subdirectory, file, namespace, or class, and last not least in the type being used.
If I read kDefaultOrderAccuracy, I see a lot of context encoded (Default, Order, Accuracy), where Order could be related for sales or sorting, and the k encoding doesn't say anything to me. Just to make you looking on your actual problem from a different perspective. C/C++ Identifiers have a poor grammar: they are restricted to rules for compound words.
This limitation of global identifiers is the most important reason why I mostly avoid global variables, even constants, sometimes even types. If its the meaning is limited to a given context, define a thing right within this context. Sometimes you first have to create this context.
Your explanation contains some unused context:
numerical operators
minimum precision (BTW: minimum doesn't mean default)
The problem of placing a definition into the right class is not very different from the problem to find the right place for a global: you have to find/create the right header file (and/or namespace).
As a side note, you may be interested to learn that also enum can be used to get cheap compile-time constants, and enums can also be placed into classes (or namespaces). Also a scoped enumeration is an option you should consider before introducing global constants. As with enclosing class definitions, the :: is a means of punctuation which separates more than _ or an in-word caseChange.
Addendum:
If you are interested in providing a useful default behaviour of your operations that can be overridden by your users, default arguments could be an option. If your API provides operators, you should study how the input/output manipulators for the standard I/O streams work.
my guess is that:
const takes up inline memory based on size of data value such as “mov ah, const value” for each use, which can be a really short command, in size overall, overall, based on input value.
whereas static values takes up a whole full data type, usually int, whatever that maybe on the current system for each static, maybe more, plus it may need a full memory access value to access the data, such as mov ah, [memory pointer], which is usually size of int on the system, for each use (with a full class it could even more complex). yet the static is still declared const so it may behave the same as the normal const type.
Changing the parens to curly braces seems to produce the exact same behavior in my program, even though semantically they seem to be quite different beasts. Is there a reason (memory usage, performance, etc.) to prefer one?
double pie = 3.14159;
myVal = int(pie); // type conversion using operator()
myVal = int{pie}; // uniform initialization syntax
[edit]
My actual code is a little different from the above example, perhaps that explains the narrowing issues:
int32_t result;
myVal = uint16_t(result); // myVal is between 0 and 65535
myVal = uint16_t{result}; // myVal is between 0 and 65535
First note that what you are doing there is not initialization, is a type conversion followed by an assignment. I strongly recommend C++ casting operators (static_cast in this case) over C casts and these constructor-based castings.
That said, the main difference between uniform initialization and the other is that uniform initialization doesn't allow (See the note) narrowing conversions such these you are doing, float to int. This is helpful when writting constants or initializing variables, since initializing an int with 3.141592654 has no sense at all because the fractional part will be stripped out.
NOTE: I remember the initial proposal for uniform-initialization explicitly stating that it disallows narrowing conversions, so if I had understood it correctly, code like yours should not compile.
I have tested it and seems like compilers emmit warnings about the narrowing conversions instead of aborting compilation. Indeed, that warnings are useful too, and you could allways use a -Werror flag.
I would like to give the users of my API the possibility to pass a custom format string.
Now, I know what kind of specifiers I am expecting (for a single double), and I would like to make clang aware of this.
The clang documentation (which actually just points to the gcc documentation) makes it seem as if I could only specify the format in terms of actual parameters to my function/method.
However, I would just like to tell clang: "If it contains one, and only one %f specifier (with whatever flags, width or precision the caller would like), it's OK"
I can't seem to find that information. Any pointers?
Thanks
Looking at the gcc documentation, I don't think there's a way to directly do what you want.
(I'm assuming that your goal is to require a format suitable for printing a single float.)
The closest thing I can think of, is if you have your function void myfunc(const char *fmt)
you could rewrite it as
extern void do_myfunc(const char *fmt); /* the real body of myfunc() */
inline void myfunc(const char *fmt) { /* put this in the header */
if (0) {
float f = 0.0f;
printf(fmt, f);
}
do_myfunc(fmt);
}
and rely on clang to remove the dead code. Of course, clang might complain about said dead code, then...