## Friday, July 22, 2016

### How to disable cursor blinking in QtCreator

Tested on Qt 5.6.1 with QtCreator 4.0.2 on Linux.

1. Download and build this:
https://github.com/igogo/qt5noblink

2. Copy the resulting qt5noblink.so library to some non-temporary folder, say \$HOME.

Shouldn't be the QtCreator folder so that you don't lose the 2 files (the shell script and the library) if QtCreator gets removed or updated.

3. In this folder create an .sh file, let's call it "qtcreator.sh" with the following contents:

The last line is the full path to your QtCreator executable.

4. Make sure the .sh file is executable.

DONE.

By running this shell script QtCreator will start with cursor blinking disabled.

5. If you want to run this script by clicking on the QtCreator application icon, edit the qtcreator.desktop file.
Its location is either in:

\${HOME}/.local/share/applications/

and in my case it was called
"DigiaQt-qtcreator-community.desktop"
or in:

/usr/share/applications/

Open the .desktop file with a text editor and change the Exec=... line to point to your .sh script.

## Tuesday, June 7, 2016

### Unix domain sockets the easy way

Unix domain sockets are an effective IPC yet they have an 80's style API which makes it hard to learn and also makes your code harder to read, larger and more error-prone because you can never remember all the little details and exceptions like these:

• With Linux abstract sockets you have to fill in the whole "sun_path" of sockaddr even if your path string is shorter otherwise you get a bug hard to find.
• Before bind()-ing you have to unlink the socket path or you'll get a busy socket error after the server-socket restart, but then there are exceptions to this rule, how cute.

The quick and easy way to fix this is to hide away all the pesky stuff in a new header-only class, let's call it "Socket":

Socket.hpp:

Now creating & initializing a socket is as simple as this:

instead of this:

And finally here's some sample code using Socket.hpp, the client sends a string to the server and the server prints it and the app exits, no user interaction required:

## Tuesday, March 8, 2016

### How to create a custom kernel with BFQ on Fedora 23 with Nvidia binary drivers

BFQ is a block-layer I/O scheduler which greatly improves system responsiveness (up to 15 times) for users of HDD drives.

Since switching to Linux in 2008 the most annoying Linux issue to me has been ridiculously bad responsiveness of the OS when under I/O load, I've been wondering what exactly is the matter and these days I found out: apparently (most of) the blame is on CFQ - the current I/O scheduler on Linux.

I've been using BFQ for the past 2 days and had no issues and OS stuttering is pretty much gone.

Some distros ship with BFQ but Fedora (neither Ubuntu) doesn't ship with it, so here's the steps to create your own Linux kernel with BFQ enabled and used by default:

1. Install the devel packages to be able to compile the Linux kernel:

# dnf install kernel-devel openssl-devel

2. At the time of writing the latest version of BFQ was for the Linux 4.4 series, so grab the BFQ patches from here, you only need the 3 files starting with "000":
0001-block-cgroups-kconfig-build-bits-for-BFQ-v7r11-4.4.0.patch
0002-block-introduce-the-BFQ-v7r11-I-O-sched-for-4.4.0.patch
0003-block-bfq-add-Early-Queue-Merge-EQM-to-BFQ-v7r11-for.patch

3. Download a 4.4 Linux kernel, currently it's 4.4.4, from your favourite website, mine is lkml.org

4. Extract the files. From the command line can be done with:

\$ tar xf linux-4.4.4.tar.xz

this will create a new folder "linux-4.4.4" with the Linux source code.

5. Put the 3 patch files from step two into this folder.

6. Applying the patches.
Open a terminal in this folder, then for each file call the patch command:
patch -p1 < 0001-block-cgroups-kconfig-build-bits-for-BFQ-v7r11-4.4.0.patch
patch -p1 < 0002-block-introduce-the-BFQ-v7r11-I-O-sched-for-4.4.0.patch
patch -p1 <  0003-block-bfq-add-Early-Queue-Merge-EQM-to-BFQ-v7r11-for.patch

In case you're wondering what "-p1" is for: each .patch file contains patches to multiple files and these are marked inside the patch file twice as the "old" and "new" file, respectively "a" and "b" so we need to strip these "a" and "b" file path prefixes otherwise the patch command won't find the correct files it needs to patch, and "p1" strips the first prefix of a file path which is what we want.
For example, this way the file path "a/block/Kconfig.iosched" becomes "block/Kconfig.iosched".
Respectively "p0" doesn't strip anything and "p2" strips two folder names, etc.

7. Although you just patched BFQ into your Linux source code, as of writing it's neither enabled nor chosen as the default I/O scheduler, so this has to be done manually from the linux "menuconfig":

\$ make menuconfig

it'll take a few minutes to execute, then you'll be presented with a menu list with the following labels at the bottom "Select", "Exit", "Help", "Save" and "Load". From the menu list (with the up/down arrow keys) go to "Enable the block layer  --->", hit "Enter" on the keyboard, in the new menu list go to
"IO Schedulers --->", hit "Enter" again and here's the actual BFQ options.
The "Pause" key on the keyboard enables/disables an option (an option with a star - is enabled, without it - disabled). So:

7.1 Make sure that "BFQ I/O scheduler" has a star to the left (reminder - press the "Pause" key). BFQ is now enabled.

7.2 Now make sure it's the default I/O scheduler:
Go down to "Default I/O scheduler (...) --->", in the new menu list make sure BFQ has an "(X)" to the left, that is, that it's the default scheduler. After this, choose "Select" to go back to the menu list up one level where you can see at the bottom the "Save" label, choose it with the "Tab" key, hit "Enter", then "< Ok >", "< Exit >" and "Exit" again and again until you exit the Linux "menuconfig" completely.
BFQ is now both enabled and chosen by default.

8. Compile the Linux kernel.

\$ make -j4

This starts the kernel compilation, if you have 8 cores use "make -j8" respectively. The compilation usually takes between 20 to 90 minutes depending on your computer performance.

9. Now the kernel has to be installed (as root!), first the so called modules:

# make modules_install

will take a few minutes to complete.

9.1 Copy your kernel to /boot:

# cp arch/x86/boot/bzImage /boot/vmlinuz-4.4.4

9.2 Create initrd:

# mkinitrd --force /boot/initramfs-4.4.4.img 4.4.4

10. Regenerate Grub config to add the new kernel to the boot list:

EFI motherboards:
# grub2-mkconfig -o /boot/efi/EFI/fedora/grub.cfg

BIOS motherboards:
# grub2-mkconfig -o /boot/grub2/grub.cfg

11. The kernel 4.4.4 is now fully installed but not registered with dkms. The Nvidia binary driver relies on dkms to automatically recompile its driver modules for any new kernel, so let's register our new kernel before rebooting the OS, otherwise after we reboot we'll get a broken desktop.

# dkms autoinstall -k 4.4.4

12. Reboot
You should now be running Linux with the BFQ scheduler used by default, to check it's true, from the command line do this:

\$ cat /sys/block/sda/queue/scheduler

It should print "noop deadline cfq [bfq]", the fact that "[bfq]" is there and it's in square brackets means it's enabled and used by default for your HDD (sda).

Congratulations!
Your OS stuttering when under I/O should now be a thing of the past.

More info about BFQ at:
http://algo.ing.unimo.it/people/paolo/disk_sched/
I'm not the author of BFQ, just a happy user.

## Thursday, November 14, 2013

### Quick Qt5 DBus Tutorial

With Qt one doesn't have to learn the details of DBus itself, rather Qt's high-level API for DBus.

Here's a classic usage example: a class registers itself as a DBus service to read incoming messages and reply to them, and the code from another process binds to the service, sends a message and reads back the reply. The class acting as a DBus service:

Pong.hpp:

```#ifndef APP_PONG_HPP_
#define APP_PONG_HPP_

#include <QtCore/QObject>

static const char * const kServiceName =     "org.example.QtDBus.PingExample";

namespace app {

class Pong : public QObject
{
Q_OBJECT

public slots:

Q_SCRIPTABLE QString
ping(const QString &arg);

Q_SCRIPTABLE int
price(const int seed);
};

} // namespace app
#endif
```

Pong.cpp:

```
#include "Pong.hpp"

#include <QtDBus/QtDBus>

namespace app  {

QString
Pong::ping(const QString &arg)
{
qDebug() << "arg =" << arg;
QMetaObject::invokeMethod(QCoreApplication::instance(), "quit");
return QString("%1, roger").arg(arg);
}

int
Pong::price(const int seed)
{
qDebug() << "seed =" << seed;
return seed * 4;
}

} // namespace app

```
And finally main.cpp, to test how it works two instances of the app must be started:
1. Launch the app with no arguments and the app will start the DBus listening service waiting in a queue.
2. Launch the app in parallel with any argument and the app will send and get back replies from app launched at step 1.

main.cpp:

```#include "Pong.hpp"

#include <QtCore>
#include <QtDBus/QtDBus>

static void
RegisterAndListen(QCoreApplication *app)
{
if (!QDBusConnection::sessionBus().registerService (kServiceName)) {
qDebug() << QDBusConnection::sessionBus().lastError().message();
return;
}

app::Pong pong;
QDBusConnection::sessionBus().registerObject("/", &pong,
QDBusConnection::ExportAllSlots);

app->exec();
}

static void
SendMessagesAndReadBack()
{
QDBusInterface iface(kServiceName, "/", "", QDBusConnection::sessionBus());
if (!iface.isValid()) {
qDebug() << QDBusConnection::sessionBus().lastError().message();
return;
}

QDBusReply int_reply = iface.call("price", 20);
if (int_reply.isValid()) {
qDebug() << "Int reply was:" << int_reply.value();
} else {
qDebug() << "Int call failed: " << int_reply.error().message();
}

QDBusReply str_reply = iface.call("ping", "Get back!");
if (str_reply.isValid()) {
qDebug() << "Str reply was:" << str_reply.value();
} else {
qDebug() << "Str call failed:" << str_reply.error().message();
}
}

int
main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);

if (!QDBusConnection::sessionBus().isConnected()) {
qDebug() << "Can't connect to the D-Bus session bus.\n"
"To start it, run: eval `dbus-launch --auto-syntax`";
return 1;
}

if (argc == 1) {
RegisterAndListen(&app);
} else {
SendMessagesAndReadBack();
}

return 0;
}
```
Usage example, open two terminals (cmd.exe in windows) and start the same app as a server (DBus service) then as a client:
Start the server (no args) in one terminal:
\$./app

Start the client (any args) in another terminal:
\$./app lkjsdlfj

Result printed in server (Pong) terminal:

```seed = 20
arg = "Get back!"
```
Result printed in client terminal:
```Int reply was: 80
Str reply was: "Get back!, roger"
```

That's it.

Matrix rotations

## Rotation matrices [OpenGL]

Must be viewed with Firefox

To create an OpenGL 4x4 rotation matrix about the X, Y or Z axis one must follow two steps:

1. Observe the changes that follow from the rotation about a given axis
2. Put the observed changes into the proper field of a 4x4 matrix
This way one gets a so called "rotation matrix" about the chosen axis and anything (a point/line/mesh) multiplied by this matrix gets rotated about the corresponding axis.

1. Observing the changes

To observe the changes caused by a rotation about a given axis means noticing how the other two axes change.
For example, if one wants to create a matrix that rotates about the Z axis, one must observe what happens to the coordinates of X and Y axes.

For this reason, one needs to know:

• 1.1 How rotations map to sines and cosines.
• 1.2 How to map the changes to sines and cosines.

It's much easier to do this on paper, that is, one needs a picture of how the sine and cosine work (explained below):

Img 1. Sin/cos picture

and a picture of a rotated coordinate system, in this case around the Z axis:

Img 2. Rotated coordinate system (about Z)

Now on with the magic. On img2 the coord sys is rotated counter-clockwise by 30° about the Z axis, X' and Y' are the X and Y axes rotated by 30°. Notice that each axis lives in 3 dimensions, the coordinates of the axes (before rotation) are:
X: (x=1.0, y=0.0, z=0.0)
Y: (x=0.0, y=1.0, z=0.0)
Z: (x=0.0, y=0.0, z=1.0)
Which resemble the identity matrix.

We must define their coordinates after rotation, so we're after 9 new numbers, 3 for each coordinate, but since the Z coordinate stays the same (because we're rotating about it) we're only after 2 coordinates (6 new numbers).

The X axis new coordinates:

As point out above each axis has 3 coordinates: x, y and z. Let's look at how the coordinates of the X axis change.

Coordinate x: at 0° of rotation its value is 1.0, at 30° its value gets smaller. From img1 we can see that such behavior is exhibited by cos(theta) (cos=cosine, theta=degrees in radians) - at 0° its value is also 1.0 and as we add degrees its value goes down. So now we know how to define the new x coordinate of the X axis after a counter-clockwise rotation about the Z axis:

Rotation matrix

 X Axis Y Axis Z Axis W cos(theta)

Coordinate y: at 0° its value is zero and at 30° its value starts growing, looking at img1 we can see that such behavior exhibits the function sin(theta), so now we know the new y coordinate of the X axis:

Rotation matrix

 X Axis Y Axis Z Axis W cos(theta) sin(theta)

Coordinate z: at 0° its value is 0.0, at 30° it stays zero, which means it doesn't correspond to the sine nor cosine, hence its value follows from the identity matrix which is zero.
Coordinate w: its value must be taken from the identity matrix which in this case is also zero:

Rotation matrix

 X Axis Y Axis Z Axis W cos(theta) sin(theta) 0.0 0.0

The Y axis new coordinates:

Coordinate x: its value starts with zero and at 30° of rotation its value becomes negative. From img1 we can see that −sin(theta) is what we're looking for: its value at zero degrees is zero and if we invert it (notice the negative sign I put in front of it) we get negative values as degrees are added.

Rotation matrix

 X Axis Y Axis Z Axis W cos(theta) −sin(theta) sin(theta) 0.0 0.0

Coordinate y: its value is 1.0 (maximum value) at 0° and as more degrees are added the value becomes smaller. From img1 we can see that it corresponds to cos(theta): at 0° its value is at maximum value (1.0) and as we add more degrees its value goes down.
Coordinate z: its value stays the same regardless, so we take the value from the identity matrix, which is 0.0.
Coordinate w: always from the identity matrix which is 0.0;

Rotation matrix

 X Axis Y Axis Z Axis W cos(theta) −sin(theta) sin(theta) cos(theta) 0.0 0.0 0.0 0.0

The Z axis new coordinates:

The Z axis coordinates stay the same since we rotate about it, so we take its values from the identity matrix which are (0.0, 0.0, 1.0, 0.0).

Rotation matrix

 X Axis Y Axis Z Axis W cos(theta) −sin(theta) 0.0 sin(theta) cos(theta) 0.0 0.0 0.0 1.0 0.0 0.0 0.0

The W axis (which isn't really an axis) stays the same hence we take its values from the identity matrix.

There we go, the full rotation matrix around the Z axis in counter-clockwise direction looks this way:

Rotation matrix

 X Axis Y Axis Z Axis W cos(theta) −sin(theta) 0.0 0.0 sin(theta) cos(theta) 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0

2. Put the changes into source code

In your source code, given that you store your matrix as an array of 16 floats, as explained at
classicaladjoint.blogspot.com/2013/07/matrices.html
the layout of the rotation matrix will look like this:

```float arr[16];
```

Rotation matrix in C/C++ source code

 X Axis Y Axis Z Axis W arr[0] = cos(theta) arr[4] = −sin(theta) arr[8] = 0.0 arr[12] = 0.0 arr[1] = sin(theta) arr[5] = cos(theta) arr[9] = 0.0 arr[13] = 0.0 arr[2] = 0.0 arr[6] = 0.0 arr[10] = 1.0 arr[14] = 0.0 arr[3] = 0.0 arr[7] = 0.0 arr[11] = 0.0 arr[15] = 1.0

where theta stands for degrees in radians, to convert degrees to radians multiply them by Pi/180.0. From the matrix follows that one has to calculate only 4 fields, assuming a rotation of 30 degrees:

```const float PI = 3.1415926;
const float radians = PI/180 * 30;

// ... matrix.identity(), then:
arr[0] = cos(radians);
arr[1] = sin(radians);

arr[4] = −sin(radians);
arr[5] = cos(radians);
```

Yes, at the end of the day as you can see only 4 fields out 16 need to be calculated, the other 12 values come from the 4x4 identity matrix.

## Saturday, July 27, 2013

### Matrix Layout in math OpenGL and code

Matrices
Must be viewed with Firefox

There are 3 areas in which the layout of matrices is different in each case: (1) mathematically, (2) in OpenGL/DirectX, (3) in source code (memory). Lots of programmers spend a lot of time figuring it out (and still not getting it), so I hope this helps.
(1) Matrices mathematically
Mathematically the layout of a 4x4 matrix M is:   $\left[\begin{array}{cccc}{m}_{\mathrm{11}}& {m}_{\mathrm{12}}& {m}_{\mathrm{13}}& {m}_{\mathrm{14}}\\ {m}_{\mathrm{21}}& {m}_{\mathrm{22}}& {m}_{\mathrm{23}}& {m}_{\mathrm{24}}\\ {m}_{\mathrm{31}}& {m}_{\mathrm{32}}& {m}_{\mathrm{33}}& {m}_{\mathrm{34}}\\ {m}_{\mathrm{41}}& {m}_{\mathrm{42}}& {m}_{\mathrm{43}}& {m}_{\mathrm{44}}\end{array}\right]$

where mrc stands for the element m of matrix M at row r and column c, for example m23 stands for the element in matrix M at row 2 and column 3.

For example, in this matrix M:   $\left[\begin{array}{cccc}0.32& 3.04& 0.82& 3.17\\ 5.01& 3.98& 8.83& 9.83\\ 8.88& 6.44& 4.32& 2.43\\ 9.64& 3.23& 4.04& 9.28\end{array}\right]$

element m23 = 8.83, m14 = 3.17, m41 = 9.64, m22 = 3.98, m44 = 9.28, m51 = doesn't exist.

(2) Matrices in OpenGL/DirectX
Each axis (X, Y, Z, W) in a matrix in OpenGL is laid out in (or shall we say "interpreted as") columns, not rows, that's why matrices in OpenGL are said to be "column-major".
On the contrary, Microsoft's DirectX treats each row, not column, as an axis, that's why matrices in DirectX are said to be "row-major".

For example, the X axis in the above matrix is read/interpreted

by OpenGL as:   $\left[\begin{array}{cccc}0.32& 5.01& 8.88& 9.64\end{array}\right]$ which mathematically equals to $\left[\begin{array}{cccc}{m}_{11}& {m}_{21}& {m}_{31}& {m}_{41}\end{array}\right]$

by DirectX as:   $\left[\begin{array}{cccc}0.32& 3.04& 0.82& 3.17\end{array}\right]$ which mathematically equals to $\left[\begin{array}{cccc}{m}_{11}& {m}_{12}& {m}_{13}& {m}_{14}\end{array}\right]$

One more example, the Z axis in the above matrix is read/interpreted

by OpenGL as:   $\left[\begin{array}{cccc}0.82& 8.83& 4.32& 4.04\end{array}\right]$ which mathematically equals to $\left[\begin{array}{cccc}{m}_{13}& {m}_{23}& {m}_{33}& {m}_{43}\end{array}\right]$

by DirectX as:   $\left[\begin{array}{cccc}8.88& 6.44& 4.32& 2.43\end{array}\right]$ which mathematically equals to $\left[\begin{array}{cccc}{m}_{31}& {m}_{32}& {m}_{33}& {m}_{34}\end{array}\right]$

(3) Matrices in source code (memory)
A 4x4 matrix in C/C++ is usually stored as either

a) An array of numbers (typically floats):

float arr[16];

The advantage of this approach is that since OpenGL requires the matrices to be sent to it as an array of numbers, you don't have to do any extra work/conversion since your matrix is already stored as an array of numbers (floats) in your source code (memory).

b) As 16 variables whose names are usually mnemonics of the elements of a matrix represented mathematically as mrc:

float m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44;

So for example m34 is a var with a mnemonic name which conveniently suggests that it stands for the element at row 3 column 4. The advantage of this approach is that the elements of the matrix from source code are called the same as in matrices represented mathematically (in math books), but the disadvantage is that you obviously need to convert the 16 vars of the matrix to an array before sending the matrix/data to OpenGL since as stated before, OpenGL requires matrices to be sent as an array of numbers.

Since people mostly favor the first approach let's explore it. Let's take a 4x4 matrix with random numbers for its XYZW axes (W isn't really an axis but you get the point):

float arr[] = {9.15, 23.9, 20.3, 0.4, 0.3, 0.72, 4.32, 0.88, 14.2, 38.0, 50.5, 29.3, 4.42, 22.7, 39.9, 18.2};

In memory (source code) we refer to each element of this matrix by its array index which ranges from 0 to 15,
for example arr[0] = 9.15, arr[1] = 23.9, arr[16] = doesn't exist. Since OpenGL interprets the columns, not the rows, of a matrix as the XYZW axes here's how OpenGL views the array arr as a matrix:

 Axis X Axis Y Axis Z W 9.15 0.3 14.2 4.42 23.9 0.72 38.0 22.7 20.3 4.32 50.5 39.9 0.4 0.88 29.3 18.2
which corresponds to the arr indices:
 Axis X Axis Y Axis Z W arr[0] arr[4] arr[8] arr[12] arr[1] arr[5] arr[9] arr[13] arr[2] arr[6] arr[10] arr[14] arr[3] arr[7] arr[11] arr[15]

That's why, to OpenGL axis Y = [0.3, 0.72, 4.32, 0.88] whose indices in our float array arr are 4, 5, 6, and 7 accordingly. So if you wanna change the values of the Y axis from our array arr to say [10.0, 12.3, 9.41, 15.0] you must be careful to use the correct array indices:

arr[4] = 10.0;
arr[5] = 12.3;
arr[6] = 9.41;
arr[7] = 15.0;

Now that we changed the values of the Y axis from our array arr, the above matrix/array looks like this in source code (memory):

float arr[] = { 9.15, 23.9, 20.3, 0.4, 10.0, 12.3, 9.41, 15.0, 14.2, 38.0, 50.5, 29.3, 4.42, 22.7, 39.9, 18.2};

And OpenGL views it like this:

 Axis X Axis Y Axis Z W 9.15 10.0 14.2 4.42 23.9 12.3 38.0 22.7 20.3 9.41 50.5 39.9 0.4 15.0 29.3 18.2

The same logic applies to the other axes. It _is_ quite confusing and takes quite some time to remember and get used to these nuances.

Bonus: translate (multiply) a vector by a translation matrix
Translation matrix:
 Axis X Axis Y Axis Z W arr[0] = 1 arr[4] = 0 arr[8] = 0 arr[12] arr[1] = 0 arr[5] = 1 arr[9] = 0 arr[13] arr[2] = 0 arr[6] = 0 arr[10] = 1 arr[14] arr[3] = 0 arr[7] = 0 arr[11] = 0 arr[15] = 1
*
 vec4 x y z w
=
 vec4 result x + arr[12] y + arr[13] z + arr[14] w

Notice a few points:
• w of vec4 must be equal to 1.0 because arr[12], arr[13] and arr[14] are multiplied by it and added to x, y, z respectively which is all there is to translation.
• observe the values of the gray, blue and red cells in the matrix so that after multiplication each field in vec4 will be equal to its own value plus arr[12], arr[13] or arr[14] accordingly.
• arr[12], arr[13] and arr[14] are input fields which control how much vec4 will be translated in the x, y and z directions accordingly.

## Exercise

Translate vector (1.5, 0.3, 0.5, 1.0) by x=1.2, y=2.3, z=0.7

Mathematical solution:

Programming solution using column major notation like OpenGL:

General idea:

Actual code:

## Wednesday, June 26, 2013

### The classical adjoint

Classical Adjoint

The classical adjoint of a matrix M, denoted adj M, is the transposed matrix of cofactors of M.
C{xy} is the cofactor of M at row x and column y:

${\left[\begin{array}{ccc}{C}^{\left\{11\right\}}=+\left|\begin{array}{cc}2& -2\\ 4& -1\end{array}\right|=6& {C}^{\left\{12\right\}}=-\left|\begin{array}{cc}0& -2\\ 1& -1\end{array}\right|=-2& {C}^{\left\{13\right\}}=+\left|\begin{array}{cc}0& 2\\ 1& 4\end{array}\right|=-2\\ {C}^{\left\{21\right\}}=-\left|\begin{array}{cc}-3& 3\\ 4& -1\end{array}\right|=9& {C}^{\left\{22\right\}}=+\left|\begin{array}{cc}-4& 3\\ 1& -1\end{array}\right|=1& {C}^{\left\{23\right\}}=-\left|\begin{array}{cc}-4& -3\\ 1& 4\end{array}\right|=13\\ {C}^{\left\{31\right\}}=+\left|\begin{array}{cc}-3& 3\\ 2& -2\end{array}\right|=0& {C}^{\left\{32\right\}}=-\left|\begin{array}{cc}-4& 3\\ 0& -2\end{array}\right|=-8& {C}^{\left\{33\right\}}=+\left|\begin{array}{cc}-4& -3\\ 0& 2\end{array}\right|=-8\end{array}\right]}^{T}=$

${\left[\begin{array}{ccc}6& -2& -2\\ 9& 1& 13\\ 0& -8& -8\end{array}\right]}^{T}=\left[\begin{array}{ccc}6& 9& 0\\ -2& 1& -8\\ -2& 13& -8\end{array}\right]$