How can I use quad precision math in a Qt project?
-
After reading this https://gcc.gnu.org/onlinedocs/gcc/Floating-Types.html I tried to add
-mfloat128
argument to GCC but the project did not compile as that option was not supported under my 4.8.5
Turned out that the article on GCC site was wrong and the argument should have been-lquadmath
. Then the project compiled, but failed to link:cd '/usr/home/leo/NetBeansProjects/QtApplication_1' /usr/local/bin/gmake -f Makefile CONF=Debug QMAKE=/usr/local/lib/qt5/bin/qmake "/usr/local/bin/gmake" -f nbproject/Makefile-Debug.mk QMAKE=/usr/local/lib/qt5/bin/qmake SUBPROJECTS= .build-conf gmake[1]: Entering directory '/usr/home/leo/NetBeansProjects/QtApplication_1' /usr/local/lib/qt5/bin/qmake VPATH=. -o qttmp-Debug.mk nbproject/qt-Debug.pro mv -f qttmp-Debug.mk nbproject/qt-Debug.mk "/usr/local/bin/gmake" -f nbproject/qt-Debug.mk dist/Debug/GNU-Generic/QtApplication_1 gmake[2]: Entering directory '/usr/home/leo/NetBeansProjects/QtApplication_1' /usr/local/lib/qt5/bin/uic newForm.ui -o ui_newForm.h g++ -c -pipe -O3 -lquadmath -g -std=c++11 -Wall -W -pthread -D_THREAD_SAFE -fPIC -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CONCURRENT_LIB -DQT_CORE_LIB -Inbproject -I. -I../../../../local/include/qt5/QtConcurrent -I../../../../local/include/qt5 -I../../../../local/include/qt5/QtWidgets -I../../../../local/include/qt5/QtGui -I../../../../local/include/qt5/QtCore -I. -I../../../../local/include -I. -I../../../../local/include -I../../../../local/lib/qt5/mkspecs/freebsd-clang -o build/Debug/GNU-Generic/main.o main.cpp g++ -c -pipe -O3 -lquadmath -g -std=c++11 -Wall -W -pthread -D_THREAD_SAFE -fPIC -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CONCURRENT_LIB -DQT_CORE_LIB -Inbproject -I. -I../../../../local/include/qt5/QtConcurrent -I../../../../local/include/qt5 -I../../../../local/include/qt5/QtWidgets -I../../../../local/include/qt5/QtGui -I../../../../local/include/qt5/QtCore -I. -I../../../../local/include -I. -I../../../../local/include -I../../../../local/lib/qt5/mkspecs/freebsd-clang -o build/Debug/GNU-Generic/newForm.cpp.o newForm.cpp.cc newForm.cpp.cc:191:6: warning: unused parameter 'pA' [-Wunused-parameter] void newForm::handleRubberBandChanged(QRect r, QPointF pA, QPointF pB){ ^ newForm.cpp.cc:191:6: warning: unused parameter 'pB' [-Wunused-parameter] /usr/local/lib/qt5/bin/moc -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CONCURRENT_LIB -DQT_CORE_LIB -I/usr/local/lib/qt5/mkspecs/freebsd-clang -I/usr/home/leo/NetBeansProjects/QtApplication_1/nbproject -I/usr/local/include/qt5/QtConcurrent -I/usr/local/include/qt5 -I/usr/local/include/qt5/QtWidgets -I/usr/local/include/qt5/QtGui -I/usr/local/include/qt5/QtCore -I. -I/usr/include/c++/v1 -I/usr/include/clang/3.4.1 -I/usr/include newForm.h -o moc_newForm.cpp g++ -c -pipe -O3 -lquadmath -g -std=c++11 -Wall -W -pthread -D_THREAD_SAFE -fPIC -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CONCURRENT_LIB -DQT_CORE_LIB -Inbproject -I. -I../../../../local/include/qt5/QtConcurrent -I../../../../local/include/qt5 -I../../../../local/include/qt5/QtWidgets -I../../../../local/include/qt5/QtGui -I../../../../local/include/qt5/QtCore -I. -I../../../../local/include -I. -I../../../../local/include -I../../../../local/lib/qt5/mkspecs/freebsd-clang -o build/Debug/GNU-Generic/moc_newForm.o moc_newForm.cpp clang++ -pthread -Wl,-rpath,/usr/local/lib -o dist/Debug/GNU-Generic/QtApplication_1 build/Debug/GNU-Generic/main.o build/Debug/GNU-Generic/newForm.cpp.o build/Debug/GNU-Generic/moc_newForm.o -L/usr/local/lib -lQt5Widgets -lQt5Gui -lQt5Concurrent -lQt5Core -lGL /usr/bin/ld: Dwarf Error: found dwarf version '4', this reader only handles version 2 information. build/Debug/GNU-Generic/newForm.cpp.o: In function `_ZN12QtConcurrent9MapKernelIPiZN7newForm18handleBtnCalculateEvEUlRiE_E12runIterationES1_iPv': newForm.cpp.cc:(.text+0x157): undefined reference to `__extenddftf2' newForm.cpp.cc:(.text+0x175): undefined reference to `__extenddftf2' newForm.cpp.cc:(.text+0x1a9): undefined reference to `__gttf2' newForm.cpp.cc:(.text+0x1c5): undefined reference to `__gttf2' newForm.cpp.cc:(.text+0x1e7): undefined reference to `__multf3' newForm.cpp.cc:(.text+0x202): undefined reference to `__multf3' newForm.cpp.cc:(.text+0x211): undefined reference to `__subtf3' newForm.cpp.cc:(.text+0x220): undefined reference to `__addtf3' newForm.cpp.cc:(.text+0x239): undefined reference to `__addtf3' newForm.cpp.cc:(.text+0x247): undefined reference to `__multf3' newForm.cpp.cc:(.text+0x256): undefined reference to `__addtf3' clang++: error: linker command failed with exit code 1 (use -v to see invocation) nbproject/qt-Debug.mk:224: recipe for target 'dist/Debug/GNU-Generic/QtApplication_1' failed gmake[2]: *** [dist/Debug/GNU-Generic/QtApplication_1] Error 1 gmake[2]: Leaving directory '/usr/home/leo/NetBeansProjects/QtApplication_1' nbproject/Makefile-Debug.mk:65: recipe for target '.build-conf' failed gmake[1]: *** [.build-conf] Error 2 gmake[1]: Leaving directory '/usr/home/leo/NetBeansProjects/QtApplication_1' nbproject/Makefile-impl.mk:39: recipe for target '.build-impl' failed gmake: *** [.build-impl] Error 2
How can I use quad precision math in a Qt project?
When I look at the toolchain in Netbeans options there is no mention ofclang
, onlygcc
andg++
. -
g++ -c -pipe -O3 -lquadmath -g -std=c++11 -Wall -W -pthread -D_THREAD_SAFE -fPIC -DQT_WIDGETS_LIB -DQT_GUI_LIB clang++ -pthread -Wl,-rpath,/usr/local/lib -o dist/Debug/GNU-Generic/QtApplication_1 build/Debug/GNU-Generic/main.o build/Debug/GNU-Generic/newForm.cpp.o build/Debug/GNU-Generic/moc_newForm.o -L/usr/local/lib -lQt5Widgets -lQt5Gui -lQt5Concurrent -lQt5Core -lGL clang++: error: linker command failed with exit code 1 (use -v to see invocation)
that's strange! Somehow it looks like you're mixing different compilers!
Did you check the Kit you use to build the project?newForm.cpp.cc:(.text+0x211): undefined reference to `__subtf3'
that means that you have to link against a library. Try to find out which one via:
ldd /path_to_/libquadmath.so
-
To add to @jsulm you don't appear to link neither against the standard math library nor quadmath. Additionally,
__extenddftf2
and the like are floating point emulation routines provided from g++ for devices without native support, why would you want them in the first place? On that same page why do you need extended floating point support? I had the need to use it only once in my entire life and for a problem where I had a badly behaved van der Waals force.PS.
The calculations with the standarddouble
type are by design done in an extended floating point register, so there's rarely a good reason to need more than the language provides. -
My biggest problem is that I am piecing together a project from:
- Netbeans, where tool chain specified
gcc
andg++
and had no mention ofclang
whatsoever; - Misleading info on GCC web site that stated I had to use
-mfloat128
; - and whatever tips I can find by googling;
so no, I am not sure I am doing it right. I do not need emulation routines.
The project was not compiling until I removed-mfloat128
and added-lquadmath
to CXX options. What's next I have no idea, this seems to be a very poorly documented feature.Perhaps Netbeans generates its own makefiles where it uses
clang
in place ofgcc
, I will have to look into that. Oracle does not support Netbeans and its developers do not answer any questions, so I am hung out to dry. - Netbeans, where tool chain specified
-
This appears to be caused by a bug in FreeBSD port of Qt5.
Its qmake-qt5 created qt-Debug.mk file that had clang in place of g++ for a linker:LINK = clang++ LFLAGS = -pthread -Wl,-rpath,/usr/local/lib
I tried compiling under Fedora linux and it built just fine using g++ all the way.
As to why I need quad precision math - it is due to the requirement to support very small numbers that round to 0 when
double
orlong double
is used. Especially whilelong double
optimizes into the FP instructions instead of MMX/SSE. -
As to why I need quad precision math - it is due to the requirement to support very small numbers that round to 0 when double or long double is used.
They must be really small, as
double
's dynamic range spans approximately between 10^308 and 10^-308. You might have a catastrophic cancellation problem somewhere in the code and this'd be a reason for the described behavior.PS.
Especially while long double optimizes into the FP instructions instead of MMX/SSE.
I don't see how the streaming extension would help here. Perhaps you could share a few details on what you're trying to achieve?
-
@nulluse said:
Are you referring to loss of precision as to catastrophic cancellation?
Yes, and no. Every floating point operation carries error. Once from rounding, and once from truncation, that's why FP operations are performed in registers larger than the actual type. (e.g. operations with
double
will be carried in 128bit registers or at least in 80bit ones, so to mitigate those two types of errors.). Additionally, floating point types are kept in normalized form.Catastrophic cancellation is a specific scenario where the relative error of the fp operation is unbound (absolute error is always within one to two epsilons). It happens most commonly when you subtract two numbers and those numbers are close numerically. When the result normalization occurs the exponent is shifted, but because of the limited size of the mantissa a lot of significant digits are simply lost. FP stability is quite an extensive topic, so this is only in broad strokes.
Further reading: http://steve.hollasch.net/cgindex/coding/ieeefloat.html
And what behaviour does it explain? I do not believe I described any program behaviours here, and rightly so as it has yet to be compiled.
I then must have misunderstood the following statement: "As to why I need quad precision math - it is due to the requirement to support very small numbers that round to 0 when double or long double is used.".
What I reckoned is you're in fact changing an existing program to accommodate that requirement. As this doesn't seem to be the case, I apologize, and if I may insert a suggestion here:
Use brute force methods (arbitrary/quad precision arithmetic) with some care. They are pretty slow, and don't support most of the functions you have available for float/double (e.g. exponents, logarithms etc.). My advice is to carefully consider the problem and choose a numerically stable algorithm that does the job with preference, instead of extending the precision.Kind regards.
-
Yes, we all understand what are the implications of using
__float128
and we have to support >30 decimal points for this application. I was not describing a computational problem when I said that 'the numbers rounded to 0'. This was to allude to using the numbers with the significant digits residing way further to the right than the 15th decimal point of thedouble
type. -
@nulluse said:
Yes, we all understand what are the implications of using __float128 and we have to support >30 decimal points for this application.
Sadly, in that case the 113 bit mantissa (about 34 significant decimal digits) of __float128 won't give you much leeway,
I was not describing a computational problem when I said that 'the numbers rounded to 0'. This was to allude to using the numbers with the significant digits residing way further to the right than the 15th decimal point of the double type.
Fair enough.