Archive for the ‘C++’ Tag

NetBeans and Qt5


After upgrading from NetBeans 8.0.1 and switching to Qt5 I noticed that the compiler C++ standard switch was set to c++0x and when setting the C++ standard to C++14 in the project settings the compiler standard switch is left out completely with the result that the compilation fails. I’m currently using the g++ 4.8 compiler, the documentation states that c++0x is deprecated and c++11 should be used instead and the switch for experimental C++14 support is c++1y.

Digging through the various make and project files showed the addition of -std=c++11 to QMAKE_CXXFLAGS was made only when the major version of Qt equalled 4. Oddly c++11 is added to a symbol called CONFIG if the major version is 5. These additions are found in qt-Release.pro and qt-Debug.pro project files. If the selected standard is set to C++14 the addition to CONFIG is missing. I haven’t been able to determine where the -std=c++0x comes from.

It’s clear that NetBeans 8.1 and earlier version don’t properly support Qt5. Switching back to Qt4 resulted in the correct standard switches been added for C++11 and C++14, the C++14 failed build failed because g++ 4.8 doesn’t recognise -std=c++14.

NetBeans can be used with Qt5 with the correct settings for the C++ standards. First set the standard to default:

Setting C++ standard to default

Setting C++ standard to default

Even if C++11 is be used this will suppress the addition of -std=c++0x. The required C++ standard option can be added using the custom definitions in the expert section of Qt project properties:

Custom definitions

Custom definitions

adding the required compiler switch for C++11:

Adding the C++ standard option

Adding the C++ standard option

The custom definition is truncated in the picture, in full it is:

equals(QT_MAJOR_VERSION, 5) { QMAKE_CXXFLAGS+="-std=c++11"}

The check for Qt 5 can be omitted if you don’t intend to swap between Qt4 and Qt5.

So the correct standards can be set when using Qt5 with NetBeans, experimental C++14 support in g++ 4.8 can also used by using c++1y instead. There are currently 3 g++ branches, the latest versions being 4.9, 5.3 and 6.1, these compilers accept -std=c++11 and -std=c++14, in addition 6.1 accepts -std=c++1z for the forthcoming C++17. The appropriate standard can be set depending on your compiler, if your using 6.1 then the custom definition can be deleted as the default standard id C++14.

In short if your using Qt5 with NetBeans always set the C++ compiler standard to default and specify the standard you want to use in Qt custom definitions.

Advertisements

Posted 9 June 2016 by element90 in Development, Linux

Tagged with , , , , ,

Migration to Qt5   Leave a comment


So far I’ve been using Qt 4.8 on both Linux and Windows 7. The compiler used on Windows 7 was Microsoft Visual Studio C++ version 10.0 which came with Visual Studio 2010 Express. The Microsoft compiler had poor support for C++11 features which meant I had to code my fractal software such that it would successfully compile on Linux and Windows.

Fed up with not being able to use C++11 fully on Windows led me to upgrade to Visual Studio 2015 Community. Since Windows 8, 8.1 and 10 have been released since I first released my software for Windows I went the whole hog and upgraded to Windows 10, upgraded to Qt5 built for 32-bit and Qt5 built for 64-bit using Visual Studio 2015 and upgraded QtCreator to version 4.0.0.

Over on Linux Mint the shift to Qt5 was easy, all I had to do was install the Qt5-default package:

Selecting Qt5

Selecting Qt5

If need be I can easily switch back to Qt4 by uninstalling Qt5-default and installing Qt4-default instead.

Building SaturnQt using Qt5 required just one change to its NetBeans project:

Select project properties

Select project properties


Add QtWidgets

Add QtWidgets

The location of Qt classes has been rearranged so QtWidgets is required for Qt5 but not for Qt4.

The project built without any problems and when SaturnQt was started some differences in appearance were evident, first the main window and the settings window for the Qt5 build:

Main window using Qt5

Main window using Qt5


Settings window using Qt5

Settings window using Qt5

and these are main and settings windows for the Qt4 build:

Main window using Qt4

Main window using Qt4


Settings window using Qt4

Settings window using Qt4

There are some obvious differences:

  • The window background colour is lighter using Qt5.
  • The height of the iterations box is the same as the zoom selection combobox using Qt5, they are not when using Qt4.
  • The list cursor is blue instead of green using Qt5.

There are other minor differences. In short Qt5 doesn’t match the MATE theme I’m currently using with Linux Mint. It should be possible to solve this issue and when I do I’ll post it on this blog.

Back to Windows. The project file for SaturnQt already had a check for Qt5 and automatically adds QtWidgets. QtCreator was then configured to use the 32-bit build of Qt 5.6 and to use the Visual Studio C++ version 14.0 compiler. The first build failed as std::max requires the inclusion of <algorithm> which is not required for Linux it has been added to the source code causing no issues for the Linux build. In addition there were a large number of warnings, I’ll cover these when I compare g++, clang++ and the Microsoft compiler in an other post.

Running the project successfully started SaturnQt on Windows 10:

Main window on Windows 10

Main window on Windows 10


Settings window on Windows 10.

Settings window on Windows 10.

I haven’t yet built a 64-bit version for Windows 10 as I need 64-bit libraries for MPIR and MPFR (for multi-precision arithmetic) and the QtCreator project file needs to be modified to support 64-bit builds. There will be a post on building 64-bit versions of my software for Windows in due course.

Qt5 versions of my software will not be available until I’ve finished the next versions and sorted out the release packages which will be affected by the transition to Qt5.

C++ Numeric Pitfalls   Leave a comment


C++ is a general perpose object orientated language and is by no means perfect. There are many pitfalls in its use, a “pitfall” is where the code in question compiles and links but when it is run it does something unexpected. For this post I’m restricting the scope to numerical functions, I fell into two of these traps through the course of developing the new version of Saturn and Titan.

The problem is best illustrated with a couple of pictures:

Saturn Version 4.0.0 (beta)

Saturn Version 4.0.0 (beta)


Saturn Version 3.0.1

Saturn Version 3.0.1

As part of the testing my software I load a great many seed files into the new software. A seed file is a PNG image with fractal parameters embedded saved by Saturn and they are useful for determing whether the new version still works as expected, in the case shown about the resulting image was certainly not expected as it shows the symptoms of not enough precision. The seed file is correctly reproduced using the previous version, so what’s changed?

In earlier testing I found problems with the std::complex standard template library regarding the handling of nan (not a number) and inf (infinity) when using the clang++ compiler. Those problems were fixed by implementing a new complex class for handling only long doubles which is when I found a pitfall. Somewhere in the class precision was being lost, I had noted an oddity in power of -1 determined using the new class verses the old class when complex values where used for both the value and the power, the result included a very small value for the imaginary part for both classes except that the std::complex value was the smaller of the two.

Part of the power function is to take the log of the input value, -1 results in PI in the imaginary part, so this test program was used to investigate:

#include <iostream>
#include <iomanip>
#include <complex>
#include "ldcomplex.h"

using namespace std;

std::string longdoubleToString(long double value)
{
    std::stringstream str;
    str << std::setprecision(std::numeric_limits<long double>::digits10) << value;
    return std::string(str.str());
}

int main(int argc, char** argv)
{
    std::complex<long double> a(-1, 0);
    ld::complex b(-1, 0);
    
    a = std::log(a);
    b = ld::log(b);
    
    std::cout << "std::complex<long double> log(-1 + 0i)" << std::endl;
    std::cout << "a.r = " << longdoubleToString(real(a)) << std::endl;
    std::cout << "a.i = " << longdoubleToString(imag(a)) << std::endl;
    std::cout << "ld::complex<long double> log(-1 + 0i)" << std::endl;
    std::cout << "b.r = " << longdoubleToString(real(b)) << std::endl;
    std::cout << "b.i = " << longdoubleToString(imag(b)) << std::endl;
    std::cout << "PIl = " << longdoubleToString(M_PIl) << std::endl;
    std::cout << "PI  = " << longdoubleToString(M_PI) << std::endl;

    return 0;
}

Running the test program:

std::complex<long double> log(-1 + 0i)
a.r = 0
a.i = 3.14159265358979324
ld::complex<long double> log(-1 + 0i)
b.r = 0
b.i = 3.14159265358979312
PIl = 3.14159265358979324
PI  = 3.14159265358979312

The value of PI for ld:complex differs from that of std::complex, the value produced by ld::complex matches the double value (M_PI) and not the long double value (M_PIl). So the loss of precision indicates that a double value is being introduced in the log function.

    inline complex log(const complex& z)
    {
        return complex(std::log(ld::abs(z)), arg(z));
    }

Note: the qualification of log and abs, arg is not qualified as it already in the ld namespace. I return to why the abs function is qualified, later, even tough it also in the ld namespace.

    inline long double arg(const complex& z) { return atan2(z.imag(), z.real()); }

The arg function is the cause of the problem, atan2 isn’t qualified and because it isn’t qualified the C function atan2 is called which is applied to doubles, the inputs are cast from long double to double and the output is cast from double to long double. The atan2 function in C has two sister versions atan2f for floats and atan2l for long doubles, in C++ when the std namespace is used all versions have the same name and the version called is determined by type.

Changing the code to:

    inline long double arg(const complex& z) { return std::atan2(z.imag(), z.real()); }

solves the problem. Checking the rest of class showed that this was the only occurance of an unqualified call to a numeric function.

Returning to the use of ld::abs function, it is qualified to make it obvious that function isn’t the C abs function. The C abs function has an integer input and an integer output, to perform the same function on float, double and long double there are functions fabsf, fabs and fabsl, C++ uses abs for float, double, long double and std::complex, the std:: standard namespace in not used and float, double or long double is used the call to abs casts the input value to integer and the output value to the required type. This NOT what is wanted and is the second pitfall.

When using numeric functions in C++ to get the right versions the std namespace MUST be used either by qualifying the name or via a using namespace statement.

When using the maths functions values in your code you may be ignorant of the fact that when the std namespace is not used all the functions (except abs) are casting to and from double and that the double versions of the functions are being called.

Posted 19 August 2013 by element90 in Development, Programming

Tagged with , ,

When is C++ long double not long double?   3 comments


When the compiler is Microsoft’s. The data type long double exists and can be used but there is no difference between long double and double.

Saturn and Titan have been developed on Linux using the g++ and clang++ compilers, long double occupies 128 bits (only 80 bits are used) and double occupies 64 bits. I used the long double datatype because it allowed deeper zooms than double before the generated picture degrades due to lack of precision. I introduced code to check the required precision to correctly generate fractals as the level of zoom increased, the initial shift from long double works most of the time, for some reason when long double is in fact double it doesn’t. Update: the example fractal illustrating the problem doesn’t shift to multi-precision because it is one of those fractals that the automatic mechanism doesn’t work, zooming in further with the Linux version exhibits the same problem it just does it later because of the greater precision of long doubles.

For Windows versions of Saturn and Titan the testing was cursory so I missed this problem which is present in all released versions of Saturn and Titan to date.

The problem is best illustrated using two screen shots of the yet to be released version 4.0.0 of Saturn, one running on Windows and the other on Linux.

Saturn 4.0.0 on Windows 7

Saturn 4.0.0 on Windows 7

Saturn 4.0.0 on Linux

Saturn 4.0.0 on Linux

So I now have to add code to Saturn and Titan to account for Microsoft defining long double as double.

More on an Unexpected Difference   2 comments


In the post “An Unexpected Difference” I fixed a problem related to std::complex<long double> and the clang++ compiler, at the end of the post I mentioned that there are other problems with std::complex using that compiler. The following image was produced from a seed file using Titan 3.0.0.

Successfully reproduced by Titan 3.0.0

Successfully reproduced by Titan 3.0.0

I won’t show you image produced by the new version of Saturn because it is a featureless rectangle. I discovered that failure to reproduce this fractal was again due to clang++.

The fractal type is “Combination 3” and it has the following formula:

z = transform(z)
z = (αz
β + γ)δ + (εzζ + η)θ

z0 = 0
α = the location in the complex plane
β = 2
γ = -1
δ = 3
ε = the location in the complex plane
ζ = -7
η = 1
θ = -1
There are no transforms defined so z = transform(z) does nothing.

Using clang++ the first iteration for all locations results in -nan – nan i so calculation stops after one iteration resulting in a featureless rectangle. So why does this happen?

The error occurs in the second expression of the formula, zero is raised to the power -7 which is infinity, it is then multiplied by the location in complex plane and has 1 added to it so it is still infinity, then infinity is raised to the power -1 which is the same as dividing 1 by infinity which sould result in zero, using g++ it does but using clang++ the result is nan + nan i. Any calculation involving nan (or -nan) results in nan. When printing the value of an std::complex or long double number inf, -inf, nan and -nan can result, nan means not a number and for some strange reason can be printed with a sign which is nonsensical as it is NOT A NUMBER.

Regarding infinity, it can be signed and for complex numbers it can be represented as inf in one of the components of the complex number and the other may contain nan, complex numbers can also have both components inf and they may or may not be signed. In all cases if either of the components is inf or -inf the result of using it to divide another number is zeo unless the number itself is zero in which case the result is nan + nan i as zero divided by infinity is undefined.

Here is a comparision of the results produced by g++ and clang++.

g++

(0,0)^(-7,0) = (inf, nan)
(0,0)^-7 = (inf, -nan)
(0,0)^(-1,0) = (inf, nan)
(inf,nan)^(-1,0) = (0,0)
1/0 = inf
(0,1)/(0,0) = (-nan, -inf)
(1,0)/(0,0) = (inf, -nan)

clang++

(0,0)^(-7,0) = (inf, nan)
(0,0)^-7 = (-nan, -nan)
(0,0)^(-1,0) = (inf, nan)
(inf,nan)^(-1,0) = (nan,nan)
1/0 = inf
(0,1)/(0,0) = (-nan, -inf)
(1,0)/(0,0) = (-nan, -nan)

The differences affect calculations that involve infinity which in some circumstances is not a problem because an operation on infinity can result in zero but once both components of a complex number are nan then any operation with that value will result in not a number.

Delving into the guts of GNU complex template library, the code for a complex number to a complex power is:

  inline __complex__ long double
  __complex_pow(const __complex__ long double& __x,
		const __complex__ long double& __y)
  { return __builtin_cpowl(__x, __y); }

This code is called for both g++ and clang++, it looks a bit strange as it uses C99 types to handle complex numbers using the compiler’s internal routines which means that the built routine for complex power in the clang++ compiler is at fault.

For division of a complex number the following is called:

      template<class _Tp>
        complex&
        operator/=(const complex<_Tp>& __z)
	{
	  _ComplexT __t;
	  __real__ __t = __z.real();
	  __imag__ __t = __z.imag();
	  _M_value /= __t;
	  return *this;
	}

Again C99 types are used so the /= is compiled to call the C99 complex code, so again the fault is with clang++.

I could ignore clang++ and just use g++, however, the supported OS X compiler for C++ is clang++. For multi-precision I found that although std::complex<mpfr::mpreal> worked on Linux it failed dismally on Windows, so I produced a non-template complex class specific to mpfr::mpreal based on the non-specialised code in the GNU template library. So all I needed to do was produce a similar class for long double and then I found that I had opened a can worms.

The generic code for a complex number to a complex power used if the std::complex<T> is used with a T other than float, double or long double is:

  template<typename _Tp>
    inline complex<_Tp>
    __complex_pow(const complex<_Tp>& __x, const complex<_Tp>& __y)
    { return __x == _Tp() ? _Tp() : std::exp(__y * std::log(__x)); }

This code is seriously flawed, if __x is zero the result is zero regardless of the value of __y, if __y has a negative real part and the imaginary part is zero the answer should be infinity (inf, nan) and if both parts are zero the answer should be not a number (nan, nan).

Elsewhere there is this:

  // 26.2.5/13
  // XXX: This is a grammar school implementation.
  template<typename _Tp>
    template<typename _Up>
    complex<_Tp>&
    complex<_Tp>::operator*=(const complex<_Up>& __z)
    {
      const _Tp __r = _M_real * __z.real() - _M_imag * __z.imag();
      _M_imag = _M_real * __z.imag() + _M_imag * __z.real();
      _M_real = __r;
      return *this;
    }

  // 26.2.5/15
  // XXX: This is a grammar school implementation.
    std::cout << "1/0 = " << z_1 << std::endl;

  template<typename _Tp>
    template<typename _Up>
    complex<_Tp>&
    complex<_Tp>::operator/=(const complex<_Up>& __z)
    {
      const _Tp __r =  _M_real * __z.real() + _M_imag * __z.imag();
      const _Tp __n = std::norm(__z);
      _M_imag = (_M_imag * __z.real() - _M_real * __z.imag()) / __n;
      _M_real = __r / __n;
      return *this;
    }

For multiplication the code fails if both values are infinity where at least one of the components is nan as the result is not a number instead of infinity. For division by infinity the result is non a number even if both compnents are +inf or -inf as the values of _M_real and _M_imag will be set to infinity divided by infinity which is not a number or not a number divided by not a number, the answer should be zero. It should be that much of a surprise that this code is faulty as it does say “This is a grammar school implementation.” as a comment for both routines.

This means that for “Combination 3” Saturn would fail to correctly produce the fractal image once multi-precision was required. As I had to correct the multi-precision complex class I also created a new class for long doubles. I’ve corrected all the methods that produced faulty results, the routines are:

real abs(complex)
real norm(complex)
complex pow(complex, complex)
complex pow(complex, real)
complex operator/=(complex)
complex operator*=(complex)
complex sqrt(complex)

where real is long double or mpfr::real and complex is mpfr::mpcomplex or ld::complex.

Since extra code had been added to correctly handle infinity and zero to the power zero I had expected an adverse affect on performance, happily I was wrong for most of the seed files I’ve tried so far the time to produce the image is shorter, there are some exceptions where it takes longer but the differences are small.

The fact that the code is quicker is not entirely unexpected, several years ago I had compared the performance of different versions of the g++ compiler (I’ve since lost figeres) the performance degraded with the introduction of a newer version I can’t remember which one but examining the assembler code produced by the newer slower version showed that it specifically called subroutines for simple addition, subtraction and multiplication of complex numbers, the older version operated on registers and did not call subroutines, the call overhead is the cause of the degraded performance. The new complex class specific to long doubles when compiled probably doesn’t call built in subroutines either.

Posted 5 July 2013 by element90 in Fractal, Programming, Software

Tagged with , , , ,

An Unexpected Difference   Leave a comment


While testing the version of Saturn I found some seed files that were not reproduced correctly. The following picture is an example:

Quincunx

Quincunx

which the new version of Saturn reproduced as …

Incorrect Quincunx

Incorrect Quincunx

At least with fractal applications bugs manifest themselves visually. So, where did the black areas come from?

After checking the usual things like the formula and all the settings used were the same and that the image was correctly reproduced by version 3.0.1 it was clear that a debug session was required. The cause of the problem was unexpected, the fractal has an unnecessarily large bailout value and the iterations for the new black areas reach inf – nan i (inf is infinity and nan is not a number), the bailout condition uses the std::norm of the iteration value which is returned by clang++ as nan. Odd.

After further investigation I discovered that if I built Saturn using the g++ compiler instead of the clang++ compiler the seed file is reproduced correctly. The difference being that g++ returns inf for the std::norm of inf – nan i and not nan.

A side effect of nan being returned is that the bailout condition is not met and calculation continues using nan which always results in nan and is very slow, the locations where the problem occurs are coloured using the inner colouring method which is to colour the location black. To work around the problem the bailout condition is deemed to have been met if either the real or imaginary components are nan, inf or -inf. The change wasn’t sufficient, the time to complete the picture was much reduced but the black areas remained, this was because nan was added to the colour statistics and when the colour was determined nan was used to determine how close the colour was to one colour and the next in the colour map resulting incorrectly with black. To stop that happening the iteration value is only added to the colour statistics if is not nan.

I have since found that there are more problems with clang++ and std::complex that the fixes for this fractal do not address but that is for a future post.

Posted 2 July 2013 by element90 in Fractal, Programming, Software

Tagged with , , , ,

I Knew it was too easy – part 2   Leave a comment


At the end of the the post “I knew it was too easy” I mentioned that easiest method to get the parameter data out of Saturn seed files was to read the file directly and extract the keys and their values from the tEXt chunks. It was simple to implement and so I continued with development of version 4.0.0 of Saturn, today I noticed that when loading a seed file the wrong colour map was used, a colour map called Greyscale was unexpectedly used. The Greyscale colour map is a simple “auto” generated colour map which is defined as a single cycle sine wave for the red, green and blue components, the expected colour map was also an auto generated colour map. The problem turns out to be that the keys, “colour0”, “colour1” and “colour2” and their data were not extracted from the seed file, so that when the data was requested empty strings were returned and the default values were used instead which corresponds to the Greyscale colour map.

So why weren’t the keys and their data extracted from the seed file? Using a Linux utility called pngmeta all the keys and their data can be printed for any PNG file and that showed that the seed file did indeed contain the keys and their data for the “auto” generated colour map. But what exactly is in the file? Using a hex editor the answer is that Qt had embedded the colour map data using zTXt chunks and not tEXt chunks. The difference between zTXt and tEXt is that zTXt compresses the data but not the key, the data for the “colour0” was 46 characters, the length of the compressed data in the zEXt chunk is 120 bytes, the length of the data for “colour1” and “colour2” are 48 bytes each and the compressed size is again 120 bytes. This makes no sense, the compressed data is larger than the data to be compressed!

PNG files only support zlib compression (as far as I know). I initially looked for documentation on zlib which of course would have a C interface. Saturn is written in C++ so some method of accessing zlib’s functionality from C++ would be preferred, my initial thought was “Does Boost handle zlib decompression?”, after a bit of searching the answer is, “Yes, it does”.

I loaded the compressed data into a std::vector and then passed it to a utility routine to convert it into std::string:

std::string uncompress(std::vector<char>& buffer)
{
    std::string str;
    io::filtering_ostream os;
    os.push(io::zlib_decompressor());
    os.push(io::back_inserter(str));
    int size = buffer.size();
    for (int i = 0; i < size; i++)
    {
        os.put(buffer[i]);
    }
    // the above loop could be replaced using
    //
    // os.write(reinterpret_cast<char*>(&buffer[0]), buffer.size());
    //
    // or
    //
    // os.write(buffer.data(), buffet.size()); // C++11
    //
    return str;
}

A fragment of code on its own, usually results in questions such as “Where is io defined?” and “What headers should I include?”, so here are the missing pieces required to compile the code:

#include <boost/iostreams/device/back_inserter.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/zlib.hpp>

namespace io = boost::iostreams;

At one time the different path delimiters used on Windows and Unix/Linux meant that different include statements had be used and were selected by condition compilation, fortunately the Microsoft C++ compiler I use happily accepts Unix style delimiters.

I’ve used some C++11 features in my code, I would use more except that compiler support is not yet complete and as I release Saturn and Titan for Linux and Windows I have to take account of the compiler that has the least support and that is Microsoft’s. The sooner better C++11 support is more widespread the better as much cleaner code can written.

So now all the embedded data can be extracted from Saturn seed files, so the next release is one step closer.

Posted 8 May 2013 by element90 in Programming, Software

Tagged with , , , ,

%d bloggers like this: