Does Visual Studio provide the C library’s isnormal()? - c++

I’m building a C++ library with Visual Studio Express 2013. I’d like to call the isnormal function from cmath, but the VS library only seems to have _isnan and _finite (and they’re in cfloat, not cmath).
It also provides _fpclass, which I assume corresponds to fpclassify. Is the following macro a suitable replacement for isnormal?
#ifdef _WIN32
#define isnormal(x) (_fpclass(x) == _FPCLASS_NN || _fpclass(x) == _FPCLASS_PN)
#endif

According to this blog post isnormal is at least present in MSVC2013's <math.h>. Therefore, in <cmath> you should find the corresponding std::isnormal (You remembered to use namespace std, right?). If not, you'll have to fall back to the C header.
(Or maybe fix/update your MSVC installation - MGetz' comment shows that his VS2013 Express installation has std::isnormal)

Related

Using OpenBLAS LAPACKE in Visual Studio

i need some linear algebra in my project and want use OpenBLAS for this. I downloaded the precompiled version (64bit version) and unpacked it to my projectfolder. In Visual Studio, i added include-, bin-, and lib-folder to my Project and ran the this example without problems.
Next, i wanted to look at LAPACK, so i added lapacke.h to the includes, which is in the same directory as cblas.h and is included in the official download. But now i get hundreds of errors, for every function, as if a lib file was missing or something. E.g. for this line
85 lapack_complex_float lapack_make_complex_float( float re, float im );
i get
PATH\include\lapacke.h(85): error C2146: syntax error: missing ';' before identifier 'lapack_make_complex_float'
I can't find any further information on how to set up OpenBLAS/LAPACK, they usually just say 'include the files', which i have. Otherwise the cblas example wouldn't run either. And the (relevant) examples i can find only use cblas.h, not lapacke.h
Can some tell me what i'm doing wrong?
The problem is that OpenBlas uses C99 _Complex by default. This is not supported by Visual C++. You can solve this by using standard library definitions before including lapacke.h:
#include <complex>
#define lapack_complex_float std::complex<float>
#define lapack_complex_double std::complex<double>
#include <lapacke.h>
Using std::complex is problematic unless OpenBLAS was built with LAPACK_COMPLEX_CPP otherwise the library uses a different complex type internally, usually C99 _Complex.
Modern versions of the Microsoft compiler (e.g. the one in VSTUDIO 2022) support a similar "_Complex" mechanism. Therefore I include the following header file prior to "lapacke.h"
#ifdef _MSC_VER
#include <complex.h>
#define LAPACK_COMPLEX_CUSTOM
typedef _Dcomplex lapack_complex_float;
typedef _Fcomplex lapack_complex_double;
#define lapack_complex_float_real(z) (real(z))
#define lapack_complex_float_imag(z) (imag(z))
#endif // _MSC_VER
See the lapack.h header file that ships with OpenBLAS how #define LAPACK_COMPLEX_CUSTOM overrides complex variable type definitions

TBB on Windows XP (using in OpenCV) - error entry point InitializeCriticalSectionEx

I tried to compile TBB which I want to use on OpenCV. I am using Windows XP and Visual Studio 2010 C++. When I compiled TBB 4.4 I got the error
"The procedure entry point InitializeCriticalSectionEx could not be located in the dynamic link library KERNEL32.dll."
The error is similar but under little different conditions like here:
http://answers.opencv.org/question/6151/opencv_createsamplesexe-entry-point-problem-with-xp/
In my case I cannot run the program at all. I tried the solution described there, so I renamed InitializeCriticalSectionEx to InitializeCriticalSection and removed parameter 2 and 3.
OpenCV claimes the bug is not on their side. I know OpenCV uses this:
#if (_WIN32_WINNT >= 0x0600)
InitializeCriticalSectionEx(&cs, 1000, 0);
#else
InitializeCriticalSection(&cs);
#endif
I know this should not make any problems but I commented some lines to keep InitializeCriticalSection(&cs); only. I recompiled the OpenCV and still the same error. Finally I have found in TTB:
tbb44_20160627oss\include\tbb\machine\windows_api.h
__TBB_WINBASEAPI BOOL WINAPI TryEnterCriticalSection( LPCRITICAL_SECTION );
__TBB_WINBASEAPI BOOL WINAPI InitializeCriticalSectionAndSpinCount( LPCRITICAL_SECTION, DWORD );
// Overloading WINBASEAPI macro and using local functions missing in Windows XP/2003
#define InitializeCriticalSectionEx inlineInitializeCriticalSectionEx
I also find the word "InitializeCriticalSectionEx" in opencv_core310d.dll and opencv_core310.dll. Does the overload really work and why I got the error? How could I fix it?
Update:
the definition in OpenCV
#ifndef _WIN32_WINNT // This is needed for the declaration of TryEnterCriticalSection in winbase.h with Visual Studio 2005 (and older?)
#define _WIN32_WINNT 0x0400 // http://msdn.microsoft.com/en-us/library/ms686857(VS.85).aspx
#endif
"The procedure entry point InitializeCriticalSectionEx could not be located in the dynamic link library KERNEL32.dll."
This is a standard error that Windows displays when you try to run a program that contains a statically-bound call to a function in a DLL that does not exist.
The InitializeCriticalSectionEx function is not available on Windows XP, but the version of the library that you have contains code that calls this function.
OpenCV claimes the bug is not on their side. I know OpenCV uses this:
#if (_WIN32_WINNT >= 0x0600)
InitializeCriticalSectionEx(&cs, 1000, 0);
#else
InitializeCriticalSection(&cs);
#endif
OpenCV's workaround is a compile-time solution. It determines at the point when the library is compiled which version of Windows is being targeted, and uses that information to generate a call to the appropriate version of the function.
There are two possibilities for why this is going wrong in your case:
You are using the OpenCV library in binary form, and the binary that you have was compiled to target Windows Vista and later. You can solve this by obtaining the source code for OpenCV and compiling it yourself, either as a DLL or a static library.
You are compiling with _WIN32_WINNT set to 0x0600 or later. By default, the Windows headers define this symbol to the latest available version. You have to explicitly define an earlier target version if you want it. To arrange for targeting Windows XP, add the following code at the top of your code file (probably in your precompiled header):
#include <WinSDKVer.h>
#define _WIN32_WINNT _WIN32_WINNT_WINXP
#include <SDKDDKVer.h>

Search for avaliable library before #pragma comment in c++?

I have a piece of code which relies on the "Xinput.lib" file provided by windows in order to interface with a xbox controller.
Recently I installed VS2012 which seems to have caused "Xinput.lib" to no longer be available to the compiler. I found a workaround where I instead I use "Xinput9_1_0.lib" on the system running the VS2012 compiler. This however causes a problem since I am developing on multiple systems where one is running VS2012 and the other is running VS2010. To compile I have to change between "Xinput9_1_0.lib" and "Xinput.lib" within the code.
What I am wondering is if there is a way to search for the available library before using #pragma comment to link the library?
Something like this (I realize this is in no way valid, just a demonstration of intent):
if("Xinput.lib" exists) {
#pragma comment(lib,"Xinput.lib")
}
else if("Xinput9_1_0.lib" exists) {
#pragma comment(lib,"Xinput9_1_0.lib")
}
Use the macro for the particular version of VS you're interested in:
#ifdef MSC_VER < 1700 //pre 2012
#pragma comment(lib,"Xinput.lib")
#else
#pragma comment(lib,"Xinput9_1_0.lib")
#endif

Automatically Including OpenCV Libraries of Different Versions

I've been automatically including the opencv library files for my c++ code on Visual Studio 2008 on Windows 7 with the following code:
#ifndef NDEBUG
#pragma comment(lib, "opencv_core231d.lib")
#pragma comment(lib, "opencv_highgui231d.lib")
#pragma comment(lib, "opencv_imgproc231d.lib")
#else
#pragma comment(lib, "opencv_core231.lib")
#pragma comment(lib, "opencv_highgui231.lib")
#pragma comment(lib, "opencv_imgproc231.lib")
#endif
but I run into trouble when the system has a different version of the opencv library installed because the .lib files have the version (in this case, 2.31) in the filename. Is there a good way to automatically or near-automatically detect what version of the opencv library is available then slide in the appropriate version string into the pragma?
There are small changes between different OpenCV versions - not much, but enough to crash your app when you change from 2.0 to 2.2 or from 2.2 to 2.3.1. Also, the beta 2.4 release has enough changes from previous ones.
So best is to test your app with an OpenCV version, and deliver it with those dlls only.
A small example:
Mat a(3,3,CV_8UC3);
a.setTo( Scalar(10) ); // in 2.3.1 will set all channels to 10,
// in 2.2 will only set first channel.
The corresponding 2.2 call would be
a.setTo(Scalar::all(10));
Or
a = 0; // runs fine on 2.3.1. Equivalent to setTo().
// Does not compile on earlier versions
Another example is cv::drawPoly(), which has a different signature on 2.2 and 2.3.1.
Given the fact that those changes are not well documented, the chance to miss one of them by mistake is really high.
I have worked out a solution to having code run on various versions of OPENCV by merging the following articles:
How to make a string out of macros
Concatenating strings in macros
Pragma statements in #defines with support for VS2008 here on MSDN
Bonus: How to have global settings defined in a solution
As noted, this can cause some serious grief if you pop between incompatible versions but for those versions and features supported this may be useful to some. Use this technique to set the opencv version once and have your code automatically link to the desired version by either
define the OPENCV_VERSIONin one place in your source code
Define it in a Property Sheet
Define it in a system environment variable.
My code ended up like so:
#include <iostream>
// #define OPENCV_VERSION $(OPENCV_VERSION)
// #define OPENCV_VERSION 220
#define QUOTE(name) #name
#define STR(macro) QUOTE(macro)
#define LINK_TO_OPENCV(libname) __pragma(comment(lib, "opencv_" #libname STR(OPENCV_VERSION)))
#define LINK_TO_OPENCV_DEBUG(libname) __pragma(comment(lib, "opencv_" #libname STR(OPENCV_VERSION) "d"))
#ifndef NDEBUG
LINK_TO_OPENCV_DEBUG("core")
LINK_TO_OPENCV_DEBUG("highgui")
LINK_TO_OPENCV_DEBUG("imgproc")
#else
LINK_TO_OPENCV("core")
LINK_TO_OPENCV("highgui")
LINK_TO_OPENCV("imgproc")
#endif
int main()
{
std::cout << STR(LINK_TO_OPENCV("core")) << "\n";
return 0;
}
And now to set the OPENCV_VERSION anywhere you like. For example, you can have a single header file included by everyone that has the line:
#define OPENCV_VERSION 220
Or you can goto Project->Properties->C/C++->Preprocessor and set Preprocessor Definitions to OPENCV_VERSION=220. Or you can do the same thing in a shared property sheet for the entire solution.
Or, and this is important, you can use this technique to define a global environment variable in windows itself called OPENCV_VERSION_ENV and set its value to the version code (say, 220). Then you can put set the preprocessor definition to OPENCV_VERSION=$(OPENCV_VERSION_ENV) and you will bring in the environment variable into the link command. You CANNOT do a #define OPEN_VERSION $(OPENCV_VERSION_ENV) but since the property pages will automatically translate $(macros) we can get environment variables there.

Using TR1 libraries in GCC and MSVC

I would like to use the TR1 libraries that ship with modern versions of GCC and MSVC, but there are subtle differences: in GCC, I have to say
#include <tr1/memory>
std::tr1::shared_ptr<int> X;
while in MSVC I have to say
#include <memory>
std::shared_ptr<int> X;
I have two questions: 1) Does MSVC automatically operate in C++0x-mode (equivalent to GCC's std=c++0x), or does it also work in C++98/03 mode by default? 2) How can I unify the includes and namespaces? I was thinking about a preprocessor macro of the sort "INCLUDE_TR1(memory)" or something like that.
To clarify, I want to use the traditional, standard C++98/03; not C++0x (otherwise there'd be no problem).
I'd be most grateful for any suggestions!
VC++ 2010 only operates in C++0x mode; previous versions had no C++0x support. That said, much of the standard library in VC++ 2010 is is still based on TR1 (e.g. std::result_of<> uses the TR1 result_of protocol instead of being decltype-based); in fact, much of the standard library in VC++ 2010 is not actually defined in namespace std, but rather in namespace std::tr1 and pulled into namespace std with a using directive.
Use Boost.TR1 -- it will #include the appropriate headers according to your platform, or if your platform doesn't have TR1 support, #include the corresponding Boost implementations and pull them into namespace std::tr1 with using declarations.
VC++ 2010 always operates in C++0x mode, but the classes exist in both the std and std::tr1 namespaces. You’ll have to detect the compiler with an #if _MSC_VER to choose which headers to include (see this answer).
The Boost.TR1 library can automatically include your compiler’s headers and fill in any missing functionality using Boost. It might help.
OK, after having several inconsistent and unsurmountable problems with Boost.TR1, especially when trying to use GCC's native TR1 libraries, I decided to ditch Boost entirely and use a small #define workaround. Here is my "tr1.h":
#ifndef _TR1_INCLUDE_H
#define _TR1_INCLUDE_H
/** Usage: #include TR1INCLUDE(unordered_map)
**
** Configuration: Define HAVE_TR1_SUBDIR if you need #include <tr1/unordered_map>; otherwise we take #include <unordered_map>.
**
**/
#define QUOTE(arg) <arg>
#ifdef HAVE_TR1_SUBDIR
# define TR1IFY(arg) tr1/arg
#else
# define TR1IFY(arg) arg
#endif
#define TR1INCLUDE(arg) QUOTE(TR1IFY(arg))
#endif
Now I can just write my programs like this:
#include "tr1.h"
#include TR1INCLUDE(unordered_map)
The different versions of MSVC have the features they have. There is no way of turning them on or off.
Some of them might also have both tr1 and std versions of some features. With slightly different semantics!