C++ base64_decode() return null - c++

I have decode a Base64 string and finally out a jpg image.
When I try to decode Base64 string with Base64 decode function which I found here I get an empty string .
Here is my code:
std::string decodedString, encodedString;
"encodedString is base64 string below."
decodedString = base64_decode(encodedString);
and its base64_decode function:
static const std::string base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
static inline bool is_base64(unsigned char c) {
return (isalnum(c) || (c == '+') || (c == '/'));
}
std::string base64_decode(std::string const& encoded_string) {
int in_len = encoded_string.size();
int i = 0;
int j = 0;
int in_ = 0;
unsigned char char_array_4[4], char_array_3[3];
std::string ret;
while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
char_array_4[i++] = encoded_string[in_]; in_++;
if (i ==4) {
for (i = 0; i <4; i++)
char_array_4[i] = base64_chars.find(char_array_4[i]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (i = 0; (i < 3); i++)
ret += char_array_3[i];
i = 0;
}
}
if (i) {
for (j = i; j <4; j++)
char_array_4[j] = 0;
for (j = 0; j <4; j++)
char_array_4[j] = base64_chars.find(char_array_4[j]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
}
return ret;
}
its my Base64:
/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcGBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCAIOAcADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD9/KKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoorz79qv9p7wh+xj+z14q+J/jy+l0/wn4PtPtl/NFH5spBdY0jjTI3O8joirkZZgKAPQaK/Lb/iMC/Y7/wCfz4lf+Ez/APba9g/YX/4OJv2bf+Chn7RGnfC7wBqniqLxZq9t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/wAITS//AIxR/wAOyP2bf+je/gf/AOEJpf8A8Yr3CigD8G/+Duf/AIJSeBfh5+yf4L+Mvwr+H/hLwUvgrVjpPiWDw5otvpsNzZ3u1YLiZYUVWMVwiRgkZ/0vHQDH889f3Y/tlfszaP8Atl/sqfED4Wa6EXTfHWh3OlNKy7vskrofJnA/vRShJF/2kFfw1fE74c6x8HviT4g8JeIbR7DXvC+pXGk6lbN963uYJWilQ/R0YfhQB/TF/wAGdf7dP/C+f2D9c+D2r3nm6/8ABvUf9BWRsvJpF6zyw4zy3lzi5Q44VTCOMiv1+r+On/g3U/bp/wCGD/8Agqf4B1bULz7J4T8cyf8ACHeICzbY1t7x0WKVj0CxXK28hbsiOO9f2LUAfyI/8HTXxok+MH/BaX4mW4lMtl4LtdM8OWnOdqxWcU0q+2LieeuF/wCDdv4Mx/HP/gs78B9KnhEtvpWuSeIZCRlYzp1tNfRsf+2sEYHuRXnH/BYHxXJ40/4KsftHX8jF/wDi5GvWyE944b+aFP8Ax2Na+xP+DPHwzFr3/BX8XUihn0XwRq17GT/CzPbQZ/75mb86AP6q6KKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAP/Z
Image is just A7 I've checked in a few web sites and it works fine.
And also this code block works in a different project perfectly fine.
By the way I'm using Clion 2017.3, Ubuntu 16.04, CXX_STANDARD 11

The algorithm you picked is terribly slow. Too many array accesses (this puts values the stack, instead of in registers), too many shifts and logical ops per byte.
Here is the main loop of a much simpler and efficient algorithm. Note that the output is not a string, since binary data can be encoded as well.
Being able to specify a custom encoding table is also important. That technique is often used to further obfuscate license keys and encryption related tasks.
size_t Base64Decode(const std::string& strSrc, void* pvDest, size_t nBytesMax, const char* szEncodingChars)
{
size_t nBytesOut = ((strSrc.length() * 6) + 7) / 8;
BYTE* pchOut = reinterpret_cast<BYTE*>(pvDest);
if (nBytesOut > nBytesMax)
return 0;
size_t nBytesIn = strSrc.length();
try
{
WORD w = 0; // work buffer
UINT nShift = 0; // shift left needed to align new glyph into buffer w
for (size_t i = 0; i < strSrc.length(); ++i, nShift += 6)
{
if (!szEncodingChars)
{
w |= (CharToNibble(strSrc[i]) << nShift);
}
else
{
const char* p = strchr(szEncodingChars, strSrc[i]);
if (!p)
throw std::exception("Not Base64");
w |= ((p - szEncodingChars) << nShift);
}
if ((nShift + 6) >= 8)
{
*pchOut++ = LOBYTE(w);
nBytesOut--;
w >>= 8;
nShift -= 8;
}
}
if (nBytesOut)
*pchOut++ = LOBYTE(w);
}
catch (std::exception&)
{
return 0;
}
return ((strSrc.length() * 6) + 7) / 8;
}
The other dependencies:
static const char kaDecodeLUT[256] =
{
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, // 0-9
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // A-O
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, // P-Z
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // a-o
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, // p-z
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
};
static BYTE CharToNibble(char ch)
{
char n = kaDecodeLUT[static_cast<BYTE>(ch)];
if (n < 0)
throw std::exception("Not Base64");
return static_cast<BYTE>(n);
}
I know this is not a direct answer to your question, but I felt I had to say something. The algorithm you picked is one the worst I've seen. I don't think it is worth spending much time on it, especially if it gives you trouble.

That was so annoying problem. I've tried so many algorithms and i've changed my code in so many ways.
If anyone wonders, here is my solution. my encodedString string had special-characters. (/n /r /t) Thats why i've just added some code before decoding code:
encoded.erase(std::remove(encoded.begin(), encoded.end(), '\n'), encoded.end());
encoded.erase(std::remove(encoded.begin(), encoded.end(), '\r'), encoded.end());
encoded.erase(std::remove(encoded.begin(), encoded.end(), '\t'), encoded.end());
After that decoder worked just fine.

Related

Create multiple objects for a simulation

Basically I wrote code to simulate one encoded data vector over a AWGN channel. The simulation but only works once. So I would like to create multiple objects or find a way to run the code multiple times depending on int N (for example int N = 1000000; in my case), so that I can calculate the BER (bit error rate).
I haven't found an elegant way to do that yet though...
I hope you understand my question.
Do you need more information?
Thank you!!
#include <iostream>
#include "encode.h"
#include "awgn.h"
#include "decode.h"
using namespace Eigen;
int main()
{
std::string code = "Hamming";
int dim_u, dim_mat_col, dim_mat_row, dim_mat_col_H, dim_mat_row_H;
MatrixXi P;
if (code == "Hamming")
{
dim_u = 4; // can also call it "k"
dim_mat_col = 7; // also serves as dim of x and y, or simply n
dim_mat_row = 4;
dim_mat_col_H = dim_mat_col;
dim_mat_row_H = dim_mat_col - dim_mat_row;
P = MatrixXi::Zero(dim_u, dim_mat_col - dim_u);
P << 1, 1, 0,
0, 1, 1,
1, 1, 1,
1, 0, 1;
}
if (code == "BCH")
{
dim_u = 7;
dim_mat_col = 15; // also serves as dim of x and y, or simply n
dim_mat_row = 7;
dim_mat_col_H = dim_mat_col;
dim_mat_row_H = dim_mat_col - dim_mat_row;
P = MatrixXi::Zero(dim_u, dim_mat_col - dim_u);
P << 1, 1, 1, 0, 1, 0, 0, 0,
0, 1, 1, 1, 0, 1, 0, 0,
0, 0, 1, 1, 1, 0, 1, 0,
0, 0, 0, 1, 1, 1, 0, 1,
1, 1, 1, 0, 0, 1, 1, 0,
0, 1, 1, 1, 0, 0, 1, 1,
1, 1, 0, 1, 0, 0, 0, 1;
}
if (code == "Golay")
{
dim_u = 12;
dim_mat_col = 24; // also serves as dim of x and y, or simply n
dim_mat_row = 12;
dim_mat_col_H = dim_mat_col;
dim_mat_row_H = dim_mat_col - dim_mat_row;
P = MatrixXi::Zero(dim_u, dim_mat_col - dim_u);
P << 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1,
0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0,
0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1,
1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0,
1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1,
1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0,
1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1,
1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0,
0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1,
0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0,
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1,
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1;
}
int N = 1000000; // number of simulations
bool c_hat_minus_c = 0;
int val = 0;
Encode vec(dim_u, dim_mat_row, dim_mat_col);
awgn channel(dim_mat_col);
Decode dec(dim_mat_col, dim_mat_row_H, dim_mat_col_H, P);
vec.encodeDataVector(dim_u, dim_mat_col, P);
// std::cout << "modulated x: " << vec.x << std::endl;
channel.addGausian(vec.x);
// std::cout << channel.y << std::endl;
c_hat_minus_c = dec.decodingalg(6000, channel.y, P, vec.x); // check if codeword is received correctly
// std::cout << channel.y << std::endl;
// std::cout << "val: " << val << std::endl;
}
If I wrap the stack allocated objects in a for loop like this:
for (int i = 0; i < N; i++)
{
Encode vec(dim_u, dim_mat_row, dim_mat_col);
awgn channel(dim_mat_col);
Decode dec(dim_mat_col, dim_mat_row_H, dim_mat_col_H, P);
vec.encodeDataVector(dim_u, dim_mat_col, P);
// std::cout << "modulated x: " << vec.x << std::endl;
channel.addGausian(vec.x);
// std::cout << channel.y << std::endl;
c_hat_minus_c = dec.decodingalg(6000, channel.y, P, vec.x); // check if codeword is received correctly
// std::cout << channel.y << std::endl;
// std::cout << "val: " << val << std::endl;
}
The program breaks and says:
/usr/include/eigen3/Eigen/src/Core/CommaInitializer.h:97: Eigen::CommaInitializer& Eigen::CommaInitializer::operator,(const Eigen::DenseBase&) [with OtherDerived = Eigen::Matrix<int, -1, -1>; XprType = Eigen::Matrix<int, -1, -1>]: Assertion `(m_col + other.cols() <= m_xpr.cols()) && "Too many coefficients passed to comma initializer (operator<<)"' failed.
Edit:
so I basically found out that it braks in encode.cpp
the second time it tries to initialize the Matrix G_
#include <iostream>
#include "encode.h"
#include "awgn.h"
#include <cstdlib> // rand and srand
#include <ctime> // For the time function
using namespace std;
using namespace Eigen;
Encode::Encode(int dim_u, int dim_mat_row, int dim_mat_col) //(7,4) Hamming code only up to now
{
// if (code == "Hamming")
// dim_u = 4;
// dim_mat_col = 7;
// dim_mat_row = 4;
u_ = RowVectorXi::Zero(dim_u);
G_ = MatrixXi::Zero(dim_mat_row, dim_mat_col);
}
void Encode::encodeDataVector(int dim_u, int dim_mat_col, MatrixXi &P)
{
// Get the system time.
unsigned seed = time(0);
// Seed the random number generator.
srand(seed);
for (int i = 0; i < dim_u; i++)
{
u_(i) = rand() % 2; // only zeros and ones
}
// cout << u_ << endl << endl;
MatrixXi I;
// I = MatrixXi::Zero(7, 7);
I = MatrixXi::Identity(dim_u, dim_u);
G_ << I, P; **<----- here**
// cout << G_ << endl << endl;
x = u_ * G_;
for (int i = 0; i < dim_mat_col; i++)
{
x(i) = x(i) % 2;
}
// std::cout << "correct codeword: " << x << std::endl;
// mapping for BPSK
for (int i = 0; i < dim_mat_col; i++)
{
if (x(i) == 0)
x(i) = 1;
else
x(i) = -1;
}
// awgn::awgn channel(dim_mat_col);
// channel.addGausian(this->x);
}
P is being passed by non-const reference, which means it may be modified by the functions you call. Passing a copy of P in each iteration makes sure that the modifications to P stay local to that iteration:
for (int i = 0; i < N; i++) {
MatrixXi P_copy = P;
...
}

MSVC compiler with /arch:AVX2 /fp:fast breaks C++ matrix inversion algorithm

I have matrix inversion algorithm and a 19x19 matrix for testing. Running it in Windows Subsystem for Linux with g++ produces the correct inverted matrix.
In Visual Studio 2017 on Windows it used to work as well. However after I upgraded to Visual Studio 2019, I get a matrix containing all zeros as result. Is MSVC broken or what else is wrong here?
So far I have tested replacing ==0.0/!=0.0 (that in some cases can be unsafe due to round-off) with greater/smaller than a tolerance value, but this does not work either.
The expected result (that I get with g++) is {5.26315784E-2,-1.25313282E-2, ... -1.25000000E-1}.
I compile with Visual Studio 2019 v142, Windows SDK 10.0.19041.0, Release x64, and I get {0,0,...0}. With Debug x64 I get a different (also wrong) result: all matrix entries are -1.99839720E18.
I use C++17 language standard, /O2 /Oi /Ot /Qpar /arch:AVX2 /fp:fast /fp:except-.
I have an i7-8700K that supports AVX2.
I also marked the place where it wrongly returns in Windows in the code. Any help is greatly appreciated.
EDIT: I just found out that the cause of the wrong behavior is /arch:AVX2 in combination with /fp:fast. But I don't understand why. /arch:SSE, /arch:SSE2 and /arch:AVX with /fp:fast work correctly, but not /arch:AVX2. How can different round-off or operation order here trigger entirely different behavior?
#include <iostream>
#include <string>
#include <vector>
using namespace std;
typedef unsigned int uint;
void println(const string& s="") {
cout << s << endl;
}
struct floatNxN {
uint N{}; // matrix size is NxN
vector<float> M; // matrix data
floatNxN(const uint N, const float* M) : N {N}, M(N*N) {
for(uint i=0; i<N*N; i++) this->M[i] = M[i];
}
floatNxN(const uint N, const float x=0.0f) : N {N}, M(N*N, x) { // create matrix filled with zeros
}
floatNxN() = default;
~floatNxN() = default;
floatNxN invert() const { // returns inverse matrix
vector<double> A(2*N*N); // calculating intermediate values as double is strictly necessary
for(uint i=0; i<N; i++) {
for(uint j=0; j< N; j++) A[2*N*i+j] = (double)M[N*i+j];
for(uint j=N; j<2*N; j++) A[2*N*i+j] = (double)(i+N==j);
}
for(uint k=0; k<N-1; k++) { // at iteration k==2, the content of A is already different in MSVC and g++
if(A[2*N*k+k]==0.0) {
for(uint i=k+1; i<N; i++) {
if(A[2*N*i+k]!=0.0) {
for(uint j=0; j<2*N; j++) {
const double t = A[2*N*k+j];
A[2*N*k+j] = A[2*N*i+j];
A[2*N*i+j] = t;
}
break;
} else if(i+1==N) {
return floatNxN(N);
}
}
}
for(uint i=k+1; i<N; i++) {
const double t = A[2*N*i+k]/A[2*N*k+k];
for(uint j=k; j<2*N; j++) A[2*N*i+j] -= A[2*N*k+j]*t;
}
}
double det = 1.0;
for(uint k=0; k<N; k++) det *= A[2*N*k+k];
if(det==0.0) {
return floatNxN(N);
}
for(int k=N-1; k>0; k--) {
for(int i=k-1; i>=0; i--) {
const double t = A[2*N*i+k]/A[2*N*k+k];
for(uint j=k; j<2*N; j++) A[2*N*i+j] -= A[2*N*k+j]*t;
}
}
floatNxN r = floatNxN(N);
for(uint i=0; i<N; i++) {
const double t = A[2*N*i+i];
for(uint j=0; j<N; j++) r.M[N*i+j] = (float)(A[2*N*i+N+j]/t);
}
return r;
}
string stringify() const { // converts matrix into string without spaces or newlines
string s = "{"+to_string(M[0]);
for(uint i=1; i<N*N; i++) s += ","+to_string(M[i]);
return s+"}";
}
};
int main() {
const float Md[19*19] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-30,-11,-11,-11,-11,-11,-11, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
12, -4, -4, -4, -4, -4, -4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 1, -1, 0, 0, 0, 0, 1,-1, 1,-1, 0, 0, 1,-1, 1,-1, 0, 0,
0, -4, 4, 0, 0, 0, 0, 1,-1, 1,-1, 0, 0, 1,-1, 1,-1, 0, 0,
0, 0, 0, 1, -1, 0, 0, 1,-1, 0, 0, 1,-1,-1, 1, 0, 0, 1,-1,
0, 0, 0, -4, 4, 0, 0, 1,-1, 0, 0, 1,-1,-1, 1, 0, 0, 1,-1,
0, 0, 0, 0, 0, 1, -1, 0, 0, 1,-1, 1,-1, 0, 0,-1, 1,-1, 1,
0, 0, 0, 0, 0, -4, 4, 0, 0, 1,-1, 1,-1, 0, 0,-1, 1,-1, 1,
0, 2, 2, -1, -1, -1, -1, 1, 1, 1, 1,-2,-2, 1, 1, 1, 1,-2,-2,
0, -4, -4, 2, 2, 2, 2, 1, 1, 1, 1,-2,-2, 1, 1, 1, 1,-2,-2,
0, 0, 0, 1, 1, -1, -1, 1, 1,-1,-1, 0, 0, 1, 1,-1,-1, 0, 0,
0, 0, 0, -2, -2, 2, 2, 1, 1,-1,-1, 0, 0, 1, 1,-1,-1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,-1,-1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,-1,-1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,-1,-1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1,-1,-1, 1, 0, 0, 1,-1,-1, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0,-1, 1, 0, 0, 1,-1, 1,-1, 0, 0, 1,-1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 1,-1,-1, 1, 0, 0,-1, 1, 1,-1
};
floatNxN M(19, Md);
floatNxN Mm1 = M.invert();
println(Mm1.stringify());
}
It seems that it is the comparison against literal 0 that breaks the algorithm with the optimizations on. Particularly the 1st one kills it, because the result would need to be exactly 0 for the correct action.
Generally instead of comparing a floating point value against literal zero, it is better to compare the absolute value against a very small constant.
This seems to work:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
typedef unsigned int uint;
void println(const string& s = "") {
cout << s << endl;
}
struct floatNxN {
const double epsilon = 1E-12;
uint N{}; // matrix size is NxN
vector<float> M; // matrix data
floatNxN(const uint N, const float* M) : N{ N }, M(N* N) {
for (uint i = 0; i < N * N; i++) this->M[i] = M[i];
}
floatNxN(const uint N, const float x = 0.0f) : N{ N }, M(N* N, x) { // create matrix filled with zeros
}
floatNxN() = default;
~floatNxN() = default;
floatNxN invert() const { // returns inverse matrix
vector<double> A(2 * N * N); // calculating intermediate values as double is strictly necessary
for (uint i = 0; i < N; i++) {
for (uint j = 0; j < N; j++) A[2 * N * i + j] = (double)M[N * i + j];
for (uint j = N; j < 2 * N; j++) A[2 * N * i + j] = (double)(i + N == j);
}
for (uint k = 0; k < N - 1; k++) { // at iteration k==2, the content of A is already different in MSVC and g++
if (fabs(A[2 * N * k + k]) < epsilon) { // comparing with 0 was the killer here
for (uint i = k + 1; i < N; i++) {
if (fabs(A[2 * N * i + k]) > epsilon) {
for (uint j = 0; j < 2 * N; j++) {
const double t = A[2 * N * k + j];
A[2 * N * k + j] = A[2 * N * i + j];
A[2 * N * i + j] = t;
}
break;
} else if (i + 1 == N) {
return floatNxN(N);
}
}
}
for (uint i = k + 1; i < N; i++) {
const double t = A[2 * N * i + k] / A[2 * N * k + k];
for (uint j = k; j < 2 * N; j++) A[2 * N * i + j] -= A[2 * N * k + j] * t;
}
}
double det = 1.0;
for (uint k = 0; k < N; k++) det *= A[2 * N * k + k];
if (fabs(det) < epsilon) {
return floatNxN(N);
}
for (int k = N - 1; k > 0; k--) {
for (int i = k - 1; i >= 0; i--) {
const double t = A[2 * N * i + k] / A[2 * N * k + k];
for (uint j = k; j < 2 * N; j++) A[2 * N * i + j] -= A[2 * N * k + j] * t;
}
}
floatNxN r = floatNxN(N);
for (uint i = 0; i < N; i++) {
const double t = A[2 * N * i + i];
for (uint j = 0; j < N; j++) r.M[N * i + j] = (float)(A[2 * N * i + N + j] / t);
}
return r;
}
string stringify() const { // converts matrix into string without spaces or newlines
string s = "{" + to_string(M[0]);
for (uint i = 1; i < N * N; i++) s += "," + to_string(M[i]);
return s + "}";
}
};
int main() {
const float Md[19 * 19] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-30,-11,-11,-11,-11,-11,-11, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
12, -4, -4, -4, -4, -4, -4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 1, -1, 0, 0, 0, 0, 1,-1, 1,-1, 0, 0, 1,-1, 1,-1, 0, 0,
0, -4, 4, 0, 0, 0, 0, 1,-1, 1,-1, 0, 0, 1,-1, 1,-1, 0, 0,
0, 0, 0, 1, -1, 0, 0, 1,-1, 0, 0, 1,-1,-1, 1, 0, 0, 1,-1,
0, 0, 0, -4, 4, 0, 0, 1,-1, 0, 0, 1,-1,-1, 1, 0, 0, 1,-1,
0, 0, 0, 0, 0, 1, -1, 0, 0, 1,-1, 1,-1, 0, 0,-1, 1,-1, 1,
0, 0, 0, 0, 0, -4, 4, 0, 0, 1,-1, 1,-1, 0, 0,-1, 1,-1, 1,
0, 2, 2, -1, -1, -1, -1, 1, 1, 1, 1,-2,-2, 1, 1, 1, 1,-2,-2,
0, -4, -4, 2, 2, 2, 2, 1, 1, 1, 1,-2,-2, 1, 1, 1, 1,-2,-2,
0, 0, 0, 1, 1, -1, -1, 1, 1,-1,-1, 0, 0, 1, 1,-1,-1, 0, 0,
0, 0, 0, -2, -2, 2, 2, 1, 1,-1,-1, 0, 0, 1, 1,-1,-1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,-1,-1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,-1,-1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,-1,-1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1,-1,-1, 1, 0, 0, 1,-1,-1, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0,-1, 1, 0, 0, 1,-1, 1,-1, 0, 0, 1,-1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 1,-1,-1, 1, 0, 0,-1, 1, 1,-1
};
floatNxN M(19, Md);
floatNxN Mm1 = M.invert();
println(Mm1.stringify());
}

OpenCV: create a square Structuring element for HIT-MISS

I want a function to create a "square inside a square" structuring element, like:
Mat explicit_kernel = (Mat_<int>(5, 5) <<
-1, -1, -1, -1, -1,
-1, 1, 1, 1, -1,
-1, 1, 1, 1, -1,
-1, 1, 1, 1, -1,
- 1, -1, -1, -1, -1);
So I tried to make an ugly loop:
Mat generate_kernel(int size)
{
if (size % 2 == 0)
{
printf("Input %i, not even, replaced by %i\n", size, size + 1);
size++;
}
Mat out = Mat::ones(size + 2, size + 2, CV_8S);
for (int i = 0; i <= size + 1; i++)
{
for (int j = 0; j <= size + 1; j++)
{
if (i == 0 || i == size - 1)
{
out.at<int>(i, j) = -1;
}
else
{
if (j == 0 || j == size - 1)
{
out.at<int>(i, j) = -1;
}
}
}
}
//Mat out = getStructuringElement(MORPH_RECT, Size(size, size), Point(-1, -1));
return out;
}
But I got an "Violation writting error", and anyway Im looking for an easier want,
The main purpose of the code is to make structuring element inside a loop:
- squares of size 1, size 3 ...
Thanks :)
I found a solution, considering that cv::Mat is a pointer, and creating a sub Matrix
Mat generate_kernel(int size)
{
if (size % 2 == 0)
{
printf("Input %i, not even, replaced by %i\n", size, size + 1);
size++;
}
Mat out = -1 * Mat::ones(size + 2, size + 2, CV_8S);
Mat center = Mat(out, Rect(1, 1, size, size));
center = Mat::ones(size, size, CV_8S);
return out;
}
This might already be handled by the cv::copyMakeBorder method.
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
Mat generate_kernel(int size, int outer_size=1)
{
if (size % 2 == 0)
{
printf("Input %i, not even, replaced by %i\n", size, size + 1);
size++;
}
Mat out = Mat::ones(size, size, CV_8S);
copyMakeBorder(out,
out,
outer_size, // top
outer_size, // bottom
outer_size, // left
outer_size, // right
BORDER_CONSTANT,
Scalar(-1.0));
return out;
}
int main(int argc, const char * argv[]) {
cout << "Size 1: " << generate_kernel(1) << endl;
cout << "Size 3: " << generate_kernel(3) << endl;
cout << "Size 5: " << generate_kernel(5) << endl;
return 0;
}
Which would generate the following....
Size 1: [ -1, -1, -1;
-1, 1, -1;
-1, -1, -1]
Size 3: [ -1, -1, -1, -1, -1;
-1, 1, 1, 1, -1;
-1, 1, 1, 1, -1;
-1, 1, 1, 1, -1;
-1, -1, -1, -1, -1]
Size 5: [ -1, -1, -1, -1, -1, -1, -1;
-1, 1, 1, 1, 1, 1, -1;
-1, 1, 1, 1, 1, 1, -1;
-1, 1, 1, 1, 1, 1, -1;
-1, 1, 1, 1, 1, 1, -1;
-1, 1, 1, 1, 1, 1, -1;
-1, -1, -1, -1, -1, -1, -1]

Meaning of "direction X-Y delta pairs for adjacent cells"

I'm trying to understand the game algorithm called "Boggle"
which finds words in an N*N matrix.
#include <cstdio>
#include <iostream>
using namespace std;
const int N = 6; // max length of a word in the board
char in[N * N + 1]; // max length of a word
char board[N+1][N+2]; // keep room for a newline and null char at the end
char prev[N * N + 1];
bool dp[N * N + 1][N][N];
// direction X-Y delta pairs for adjacent cells
int dx[] = {0, 1, 1, 1, 0, -1, -1, -1};
int dy[] = {1, 1, 0, -1, -1, -1, 0, 1};
bool visited[N][N];
bool checkBoard(char* word, int curIndex, int r, int c, int wordLen)
{
if (curIndex == wordLen - 1)
{
//cout << "Returned TRUE!!" << endl;
return true;
}
int ret = false;
for (int i = 0; i < 8; ++i)
{
int newR = r + dx[i];
int newC = c + dy[i];
if (newR >= 0 && newR < N && newC >= 0 && newC < N && !visited[newR] [newC] && word[curIndex+1] == board[newR][newC])
I do not understand this part:
// direction X-Y delta pairs for adjacent cells
int dx[] = {0, 1, 1, 1, 0, -1, -1, -1};
int dy[] = {1, 1, 0, -1, -1, -1, 0, 1};
Why do these array have the values they have and why does this work?
These arrays represent the possible combinations of row and column offsets from the current "cursor" location (which is an x,y coordinate tracked in the code as variables c,r):
// direction X-Y delta pairs for adjacent cells
int dx[] = {0, 1, 1, 1, 0, -1, -1, -1};
int dy[] = {1, 1, 0, -1, -1, -1, 0, 1};
For example, if you imagine a 3x3 square grid, and consider the central box to be the current location, then the other 8 surrounding cells are those indicated by these sets of row and column offsets. If we took the offsets at index 2 (dx[2] = 1 and dy[2] = 0), this would indicate the cell one row down (and zero shifting left/right).

Why is my program having an instance where "Vector Subscript out of Range"?

Bassicly my code is supposed to be taking ints from int tt[] in main()
const int tt[] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
The program then is exposed to give cordinates for a vector based on its sequential order and give cordinates for the texture if its gives #1. Based on my cout statement tiletype = tt[count]; I can tell the program crashes after reading the fith zero from int tt[] and gives the error Vector Subscript out of Range.
I assume the problem fall under this section of my code:
for(x = 1; x < c;++x)
{
for(y = 0; y < r;++y)
{
tiletype = tt[count];
cout <<tiletype<<", ";
vertices[a].position = sf::Vector2f((0+y)*ts,ts*(x+1)+80);
vertices[b].position = sf::Vector2f((0+y)*ts, (0+x)*ts+80);
vertices[d].position = sf::Vector2f(ts+(y*ts),(0+x)*ts+80);
vertices[e].position = sf::Vector2f(ts+(y*ts), ts*(x+1)+80);
vertices[a].texCoords = mapcords(tiletype,0);
vertices[b].texCoords = mapcords(tiletype,1);
vertices[d].texCoords = mapcords(tiletype,2);
vertices[e].texCoords = mapcords(tiletype,3);
a += 4; b += 4; d += 4; e += 4;count++;
}
row += 1;
cout <<endl<<"Row "<<row<<": "; y = 0;
}
This is the rest of the code.
#include <SFML/Graphics.hpp>
#include <iostream>
using namespace std;
using namespace sf;
Vector2f mapcords(int tt,int corner);
Vector2f mapcords(int tt,int corner)
{
if(tt ==0)
{
if (corner ==1)
{return Vector2f(48,8 );}
if(corner == 1)
{return Vector2f(48,0);}
if (corner ==2)
{return Vector2f(56, 0);}
if (corner == 3)
{return sf::Vector2f(56, 8);}
}
else{
if(corner ==0)
{return Vector2f(0,8 );}
if(corner == 1)
{return Vector2f(0,0);}
if (corner ==2)
{return Vector2f(8, 0);}
if (corner == 3)
{return sf::Vector2f(8, 8);}
}
return Vector2f(0,0 );
}
class drawmap : public sf::Drawable, public sf::Transformable
{
public:
bool load(const string& tileset,const int* tt, int ts, int r, int c, int num)
{
count =0; row =1; a = 0; b = 1; d = 2; e = 3;y=0;x=0;
tiletex.setRepeated(true);
if (!tiletex.loadFromFile(tileset))
return false;
tiletex.setRepeated(true);
vertices.setPrimitiveType(sf::Quads);
vertices.resize(2 * 2 * 4);
cout <<endl<<"Row "<<row<<": ";
for(x = 1; x < c;++x)
{
for(y = 0; y < r;++y)
{
tiletype = tt[count];
cout <<tiletype<<", ";
vertices[a].position = sf::Vector2f((0+y)*ts,ts*(x+1)+80);
vertices[b].position = sf::Vector2f((0+y)*ts, (0+x)*ts+80);
vertices[d].position = sf::Vector2f(ts+(y*ts),(0+x)*ts+80);
vertices[e].position = sf::Vector2f(ts+(y*ts), ts*(x+1)+80);
vertices[a].texCoords = mapcords(tiletype,0);
vertices[b].texCoords = mapcords(tiletype,1);
vertices[d].texCoords = mapcords(tiletype,2);
vertices[e].texCoords = mapcords(tiletype,3);
a += 4; b += 4; d += 4; e += 4;count++;
}
row += 1;
cout <<endl<<"Row "<<row<<": "; y = 0;
}
return true;
}
private:
int row;
int count;
int y,x;
int a,b,d,e;
int tiletype;
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
{
states.transform *= getTransform();
states.texture = &tiletex;
target.draw(vertices, states);
}
sf::VertexArray vertices;
sf::Texture tiletex;
};
Even if r and c are properly initialized to (I assume) 4, once you've looped to the point where y = 4 (ie. x is incrementing) you don't reset a, b, d or e - meaning on the fifth loop through, you have a = 16, b = 17, d = 19 and e = 20, but then you still try to access vertices[a] (and b and d and e). Since vertices just before this was resized to (2 * 2 * 4), or 16, you then access the vector out of its bounds. Hence, the vector subscript out of range error.
In order to hold enough vertices for 4 * the number of tiles you want to put in the vector, you're going to need to do something like:
vertices.resize(4 * r * c);