While searching the web for fast i/o in c++, this is the "best" (according to me) that I have come across
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
class FastInput {
public:
FastInput() {
m_dataOffset = 0;
m_dataSize = 0;
m_v = 0x80000000;
}
uint32_t ReadNext() {
if (m_dataOffset == m_dataSize) {
int r = read(0, m_buffer, sizeof(m_buffer));
if (r <= 0) return m_v;
m_dataOffset = 0;
m_dataSize = 0;
int i = 0;
if (m_buffer[0] < '0') {
if (m_v != 0x80000000) {
m_data[m_dataSize++] = m_v;
m_v = 0x80000000;
}
for (; (i < r) && (m_buffer[i] < '0'); ++i);
}
for (; i < r;) {
if (m_buffer[i] >= '0') {
m_v = m_v * 10 + m_buffer[i] - 48;
++i;
} else {
m_data[m_dataSize++] = m_v;
m_v = 0x80000000;
for (i = i + 1; (i < r) && (m_buffer[i] < '0'); ++i);
}
}
}
return m_data[m_dataOffset++];
}
public:
uint8_t m_buffer[32768];
uint32_t m_data[16384];
size_t m_dataOffset, m_dataSize;
uint32_t m_v;
};
class FastOutput {
public:
FastOutput() {
m_dataOffset = 0;
}
~FastOutput() {
}
void Flush() {
if (m_dataOffset) {
if (write(1, m_data, m_dataOffset));
m_dataOffset = 0;
}
}
void PrintUint(uint32_t v, char d) {
if (m_dataOffset + 11 > sizeof(m_data)) Flush();
if (v < 100000) {
if (v < 1000) {
if (v < 10) {
m_data[m_dataOffset + 0] = v + 48;
m_dataOffset += 1;
} else if (v < 100) {
m_data[m_dataOffset + 1] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 0] = v + 48;
m_dataOffset += 2;
} else {
m_data[m_dataOffset + 2] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 1] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 0] = v + 48;
m_dataOffset += 3;
}
} else {
if (v < 10000) {
m_data[m_dataOffset + 3] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 2] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 1] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 0] = v + 48;
m_dataOffset += 4;
} else {
m_data[m_dataOffset + 4] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 3] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 2] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 1] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 0] = v + 48;
m_dataOffset += 5;
}
}
} else {
if (v < 100000000) {
if (v < 1000000) {
m_data[m_dataOffset + 5] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 4] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 3] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 2] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 1] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 0] = v + 48;
m_dataOffset += 6;
} else if (v < 10000000) {
m_data[m_dataOffset + 6] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 5] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 4] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 3] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 2] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 1] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 0] = v + 48;
m_dataOffset += 7;
} else {
m_data[m_dataOffset + 7] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 6] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 5] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 4] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 3] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 2] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 1] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 0] = v + 48;
m_dataOffset += 8;
}
} else {
if (v < 1000000000) {
m_data[m_dataOffset + 8] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 7] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 6] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 5] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 4] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 3] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 2] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 1] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 0] = v + 48;
m_dataOffset += 9;
} else {
m_data[m_dataOffset + 9] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 8] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 7] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 6] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 5] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 4] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 3] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 2] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 1] = v - v / 10 * 10 + 48;
v /= 10;
m_data[m_dataOffset + 0] = v + 48;
m_dataOffset += 10;
}
}
}
m_data[m_dataOffset++] = d;
}
void PrintChar(char d) {
if (m_dataOffset + 1 > sizeof(m_data)) Flush();
m_data[m_dataOffset++] = d;
}
void ReplaceChar(int offset, char d) {
m_data[m_dataOffset + offset] = d;
}
public:
uint8_t m_data[32768];
size_t m_dataOffset;
};
int main()
{
;
}
But, it was nothing written about how to take input or give output.
It would be of great help, if you can tell how to take input a integer and a c++ string and give output, with an example.
The following code reads an unsigned integer value from standard input:
FastInput fi;
uint32_t value = fi.ReadNext();
To write an unsigned integer value to standard output:
FastOutput fo;
fo.PrintUint(123456, '\n');
fo.Flush();
But seriously: Forget about these classes. I cannot image how this class could be in any way useful for whatever you're trying to achieve.
Related
I have this expression
for (size_t i = 0; i < expression.size(); i++){
for (size_t j = i + 1; j < expression.size(); j++){
result += (expression.at(j) - expression.at(i));
}
result += (g - expression.at(i));
}
return result;
in the vector expression we have for example [1,2,3]. I am trying to get something like:
f1=[(2-1)+(3-1)]
r1 = g-1
h1 = r1+f1
f2=[3-2]
r2 = g-2
h2 = r2+f2
f3 = 0
r3 = g-3
h3 = r3+f3
then h1+h2+h3
What i am doing right now is in Θ(n^2). Is there a way to make it faster even without for loops?
Addition is commutative and associative so the operations can be reordered and grouped without changing the final result. (Note: not taking into account possible overflows in the intermediate calculations, which may be affected by the order and grouping of operations.)
In pseudo-code with n = expression.size() and x[k] = expression.at(k) the original code can be broken down as follows, with the intermediate results indicated in comments.
a = b = c = d = 0
for i = 0 to (n-1)
for j = (i+1) to (n-1)
a += x[j]
// == x[i+1] + x[i+2] + ... x[n-1]
// a == 0 * x[0] + 1 * x[1] + 2 * x[2] + 3 * x[3] + ... + (n-1) * x[n-1]
for i = 0 to (n-1)
for j = (i+1) to (n-1)
b += x[i];
// == (n-i-1) * x[i]
// b == (n-1) * x[0] + (n-2) * x[1] + ... + 2 * x[n-3] + 1 * x[n-2]
for i = 0 to (n-1)
c += g
// c == n * g
for i = 0 to (n-1)
d += expression.at(i))
// d == x[0] + x[1] + ... + x[n-1]
result = c + a - b - d
= n * g
+ (0 - (n-1) - 1) * x[0]
+ (1 - (n-2) - 1) * x[1]
+ ...
+ ((n-2) - 1 - 1) * x[n-2]
+ ((n-1) - 0 - 1) * x[n-1]
The latter result can be calculated directly from that formula, with one single O(n) loop.
I'm working on a 2D Graphics Engine, when I use the following code to rotate the images I get 'write access violation' exception for newBits if the image dimensions have even numbers. There is no problem on odd numbered dimensions.
Here is my image rotation code :
bool Graphics::Raster::rotate(float angle)
{
try {
unsigned int xOrigin{ mWidth / 2 };
unsigned int yOrigin{ mHeight / 2 };
std::array<Math::Vector2D, 4> boundingBoxVertices;
Math::Matrix2x2 rotationMatrix;
boundingBoxVertices[0].setX((float)xOrigin * -1.0f);
boundingBoxVertices[0].setY((float)yOrigin);
boundingBoxVertices[1].setX((float)(mWidth - xOrigin) * 1.0f);
boundingBoxVertices[1].setY((float)yOrigin);
boundingBoxVertices[2].setX((float)(mWidth - xOrigin) * 1.0f);
boundingBoxVertices[2].setY((float)(mHeight - yOrigin) * -1.0f);
boundingBoxVertices[3].setX((float)xOrigin * -1.0f);
boundingBoxVertices[3].setY((float)(mHeight - yOrigin) * -1.0f);
int x{ 0 }, y{ 0 }, maxX{ 0 }, minX{ 0 }, maxY{ 0 }, minY{ 0 };
rotationMatrix.setToRotation(angle);
for (size_t i = 0; i < 4; ++i) {
boundingBoxVertices[i] *= rotationMatrix;
boundingBoxVertices[i].round();
x = (int)boundingBoxVertices[i].getX();
y = (int)boundingBoxVertices[i].getY();
if (x < minX) {
minX = x;
}
if (x > maxX) {
maxX = x;
}
if (y < minY) {
minY = y;
}
if (y > maxY) {
maxY = y;
}
}
size_t newWidth = (size_t)(maxX - minX);
size_t newHeight = (size_t)(maxY - minY);
BYTE* newBits{ nullptr };
if (newBits = new BYTE[newWidth * newHeight * 4]{ 0 }) {
int newOrgX = newWidth / 2;
int newOrgY = newHeight / 2;
Math::Vector2D pixVec{ 0.0f, 0.0f };
int oldCoordX{ 0 };
int oldCoordY{ 0 };
int newCoordX{ 0 };
int newCoordY{ 0 };
unsigned int oldIndex{ 0 };
unsigned int newIndex{ 0 };
for (size_t i = 0; i < mWidth * mHeight; ++i) {
oldCoordX = i % mWidth - xOrigin;
oldCoordY = yOrigin - i / mWidth;
pixVec.setX((float)oldCoordX);
pixVec.setY((float)oldCoordY);
pixVec *= rotationMatrix;
pixVec.round();
newCoordX = (unsigned int)(pixVec.getX() + newOrgX);
newCoordY = (unsigned int)(newOrgY - pixVec.getY());
oldIndex = i * 4;
newIndex = (newCoordY * newWidth * 4) + ((newCoordX) * 4);
newBits[newIndex + 0] = m32Bits[oldIndex + 0];
newBits[newIndex + 1] = m32Bits[oldIndex + 1];
newBits[newIndex + 2] = m32Bits[oldIndex + 2];
newBits[newIndex + 3] = m32Bits[oldIndex + 3];
}
if (angle != 0.0f || angle != 90.0f || angle != 180.0f || angle != 270.0f || angle != 360.0f ||
angle != -0.0f || angle != -90.0f || angle != -180.0f || angle != -270.0f || angle != -360.0f ) {
for (size_t i = 0; i < newHeight; ++i) {
for (size_t j = 0; j < newWidth; ++j) {
if (j != 0 && j != newWidth - 1) {
if (newBits[(i * newWidth * 4) + (j * 4) + 0] == 0 &&
newBits[(i * newWidth * 4) + (j * 4) + 1] == 0 &&
newBits[(i * newWidth * 4) + (j * 4) + 2] == 0 &&
newBits[(i * newWidth * 4) + (j * 4) + 3] == 0) {
newBits[(i * newWidth * 4) + (j * 4) + 0] = (newBits[(i * newWidth * 4) + ((j - 1) * 4) + 0] +
newBits[(i * newWidth * 4) + ((j + 1) * 4) + 0]) / 2;
newBits[(i * newWidth * 4) + (j * 4) + 1] = (newBits[(i * newWidth * 4) + ((j - 1) * 4) + 1] +
newBits[(i * newWidth * 4) + ((j + 1) * 4) + 1]) / 2;
newBits[(i * newWidth * 4) + (j * 4) + 2] = (newBits[(i * newWidth * 4) + ((j - 1) * 4) + 2] +
newBits[(i * newWidth * 4) + ((j + 1) * 4) + 2]) / 2;
newBits[(i * newWidth * 4) + (j * 4) + 3] = (newBits[(i * newWidth * 4) + ((j - 1) * 4) + 3] +
newBits[(i * newWidth * 4) + ((j + 1) * 4) + 3]) / 2;
}
}
}
}
}
if (set32Bits(newBits, newWidth, newHeight)) {
delete[] newBits;
return true;
} else {
delete[] newBits;
return false;
}
} else {
throw Error::Exception(L"Resim çevirme işlemi için hafızada yer açılamadı", L"Resim Düzenleme Hatası");
}
} catch (Error::Exception& ex) {
Error::ShowError(ex.getErrorMessage(), ex.getErrorTitle());
return false;
}
}
What am I doing wrong here?
I can't use a third-party to rotate the images, I must use this function.
Thanks in advance.
The problem was a index problem when setting the newBits.
Here is the updated function :
BYTE* Graphics::RotateBits(const BYTE* bits, const int width, const int height, float angle, int* newWidth, int* newHeight)
{
try {
int xOrigin{ width / 2 };
int yOrigin{ height / 2 };
std::array<Math::Vector2D, 4> boundingBoxVertices;
Math::Matrix2x2 rotationMatrix;
boundingBoxVertices[0].setX((float)xOrigin * -1.0f);
boundingBoxVertices[0].setY((float)yOrigin);
boundingBoxVertices[1].setX((float)(width - xOrigin) * 1.0f);
boundingBoxVertices[1].setY((float)yOrigin);
boundingBoxVertices[2].setX((float)(width - xOrigin) * 1.0f);
boundingBoxVertices[2].setY((float)(height - yOrigin) * -1.0f);
boundingBoxVertices[3].setX((float)xOrigin * -1.0f);
boundingBoxVertices[3].setY((float)(height - yOrigin) * -1.0f);
int x{ 0 }, y{ 0 }, maxX{ 0 }, minX{ 0 }, maxY{ 0 }, minY{ 0 };
rotationMatrix.setToRotation(angle);
for (int i = 0; i < 4; ++i) {
boundingBoxVertices[i] *= rotationMatrix;
boundingBoxVertices[i].round();
x = (int)boundingBoxVertices[i].getX();
y = (int)boundingBoxVertices[i].getY();
if (x < minX) {
minX = x;
}
if (x > maxX) {
maxX = x;
}
if (y < minY) {
minY = y;
}
if (y > maxY) {
maxY = y;
}
}
*newWidth = (maxX - minX);
*newHeight = (maxY - minY);
BYTE* newBits = new BYTE[*newWidth * *newHeight * 4]{ 0 };
int newOrgX = *newWidth / 2;
int newOrgY = *newHeight / 2;
Math::Vector2D pixVec{ 0.0f, 0.0f };
int oldCoordX{ 0 };
int oldCoordY{ 0 };
int newCoordX{ 0 };
int newCoordY{ 0 };
int oldIndex{ 0 };
int newIndex{ 0 };
for (int i = 0; i < width * height; ++i) {
oldCoordX = i % width - xOrigin;
oldCoordY = yOrigin - i / width;
pixVec.setX((float)oldCoordX);
pixVec.setY((float)oldCoordY);
pixVec *= rotationMatrix;
pixVec.round();
newCoordX = (int)pixVec.getX() + newOrgX;
newCoordY = newOrgY - (int)pixVec.getY();
oldIndex = i * 4;
newIndex = (newCoordY * *newWidth * 4) + (newCoordX * 4);
if (newIndex >= 0 && newIndex <= *newWidth * *newHeight * 4 - 4) {
newBits[newIndex + 0] = bits[oldIndex + 0];
newBits[newIndex + 1] = bits[oldIndex + 1];
newBits[newIndex + 2] = bits[oldIndex + 2];
newBits[newIndex + 3] = bits[oldIndex + 3];
}
}
if (((int)angle) % 90) {
int index{ 0 };
int prevIndex{ 0 };
int nextIndex{ 0 };
for (int i = 0; i < *newHeight; ++i) {
for (int j = 0; j < *newWidth; ++j) {
if (j != 0 && j != *newWidth - 1) {
index = (i * *newWidth * 4) + (j * 4);
if (newBits[index + 0] == 0 &&
newBits[index + 1] == 0 &&
newBits[index + 2] == 0 &&
newBits[index + 3] == 0) {
prevIndex = (i * *newWidth * 4) + ((j - 1) * 4);
nextIndex = (i * *newWidth * 4) + ((j + 1) * 4);
newBits[index + 0] = (newBits[prevIndex + 0] + newBits[nextIndex + 0]) / 2;
newBits[index + 1] = (newBits[prevIndex + 1] + newBits[nextIndex + 1]) / 2;
newBits[index + 2] = (newBits[prevIndex + 2] + newBits[nextIndex + 2]) / 2;
newBits[index + 3] = (newBits[prevIndex + 3] + newBits[nextIndex + 3]) / 2;
}
}
}
}
}
return newBits;
} catch (Error::Exception& ex) {
Error::ShowError(ex.getErrorMessage(), ex.getErrorTitle());
return nullptr;
} catch (std::exception& ex) {
Error::ShowError((LPCWSTR)ex.what(), L"Bit Düzenleme Hatası");
return nullptr;
}
}
Ok I have a little problem with my code. This error disp when I try run it.
Unhandled exception at 0x012D4CBF in Dywan.exe: 0xC0000005: Access violation reading location 0x015E2348.
When ROZMIAR=257 or less then code works properly. But i need set higher value like 500. Error stucked at double odcien = dane[x][y] + dane[x + dlboku][y] + dane[x][y + dlboku] + dane[x + dlboku][y + dlboku];
Should i use dynamic arrays to this ?
double dane[ROZMIAR][ROZMIAR];
double wartoscinit = 0.0;
dane[0][0] = dane[0][ROZMIAR - 1] = dane[ROZMIAR - 1][0] = dane[ROZMIAR -1][ROZMIAR - 1] = wartoscinit;`
void comp_Fractal(){
for (int dlboku = ROZMIAR - 1; dlboku >= 2; dlboku /= 2, h /= 2.0) {
int polboku = dlboku / 2;
for (int x = 0; x<ROZMIAR - 1; x += dlboku) {
for (int y = 0; y<ROZMIAR - 1; y += dlboku) {
double odcien = dane[x][y] + dane[x + dlboku][y] + dane[x][y + dlboku] + dane[x + dlboku][y + dlboku];
odcien /= 4.0;
double wzor = (-h) + rand() * (2*h) / RAND_MAX;
dane[x + polboku][y + polboku] = odcien + wzor;
}
}
for (int x = 0; x<ROZMIAR - 1; x += polboku) {
for (int y = (x + polboku) % dlboku; y<ROZMIAR - 1; y += dlboku) {
double odcien =
dane[(x - polboku + ROZMIAR) % ROZMIAR][y] +
dane[(x + polboku) % ROZMIAR][y] +
dane[x][(y + polboku) % ROZMIAR] +
dane[x][(y - polboku + ROZMIAR) % ROZMIAR];
odcien /= 4.0;
double wzor = (-h) + rand() * (2*h) / RAND_MAX;
odcien = odcien + wzor;
dane[x][y] = odcien;
if (x == 0) dane[ROZMIAR - 1][y] = odcien;
if (y == 0) dane[x][ROZMIAR - 1] = odcien;
}
}
}
for (int i = 0; i<ROZMIAR - 1; i++)
for (int j = 0; j<ROZMIAR - 1; j++) {
if (dane[i][j] > maxY)
maxY = dane[i][j];
if (dane[i][j] < minY)
minY = dane[i][j];
}
}
When both dlboku, y and x are something like ROZMIAR - 2, following
dane[x + dlboku][y + dlboku];
will make you to access dane[ROZMIAR + ROZMIAR - 4][ROZMIAR + ROZMIAR - 4] which is out of bounds. You alvays had a problem with your code. It just large values of ROZMIAR which made it access out of allocated memory and crash.
When attempted to push back a vector of UINT, the progrma crashes with Critical error detected c0000374. Below is the initial code:
void Terrain::CreateIndexList(UINT Width, UINT Height){
UINT sz_iList = (Width - 1)*(Height - 1) * 6;
UINT *iList = new UINT[sz_iList];
for (int i = 0; i < Width; i++){
for (int j = 0; j < Height; j++){
iList[(i + j * (Width - 1)) * 6] = ((UINT)(2 * i));
iList[(i + j * (Width - 1)) * 6 + 1] = (UINT)(2 * i + 1);
iList[(i + j * (Width - 1)) * 6 + 2] = (UINT)(2 * i + 2);
iList[(i + j * (Width - 1)) * 6 + 3] = (UINT)(2 * i + 2);
iList[(i + j * (Width - 1)) * 6 + 4] = (UINT)(2 * i + 1);
iList[(i + j * (Width - 1)) * 6 + 5] = (UINT)(2 * i + 3);
}
}
for (int i = 0; i < sz_iList; i++){
Geometry.IndexVertexData.push_back(iList[i]);
}
delete[] iList;
}
The goal is to take the generated indices from the iList array and fill the Geometry.IndexVertexData vector array. While debugging this, I've created several other implementations of this:
//After creating the iList array:
Geometry.IndexVertexData.resize(sz_iList); //Fails with "Vector subscript out of range?"
UINT in = 0;
for (int i = 0; i < Width; i++){
for (int j = 0; j < Height; j++){
Geometry.IndexVertexData[(i + j*(Width - 1)) * 6] = iList[in];
in++;
Geometry.IndexVertexData[(i + j*(Width - 1)) * 6 + 1] = iList[in];
in++;
Geometry.IndexVertexData[(i + j*(Width - 1)) * 6 + 2] = iList[in];
in++;
Geometry.IndexVertexData[(i + j*(Width - 1)) * 6 + 3] = iList[in];
in++;
Geometry.IndexVertexData[(i + j*(Width - 1)) * 6 + 4] = iList[in];
in++;
Geometry.IndexVertexData[(i + j*(Width - 1)) * 6 + 5] = iList[in];
in++;
}
}
And a final, direct to vector implementation:
Geometry.IndexVertexData.reserve(sz_iList);
for (int index = 0; index < sz_iList; index+=6) {
Geometry.IndexVertexData[(i + j*(Width - 1)) * 6] = ((UINT)(2 * i));
Geometry.IndexVertexData[(i + j*(Width - 1)) * 6 + 1] = (UINT)(2 * i + 1);
Geometry.IndexVertexData[(i + j*(Width - 1)) * 6 + 2] = (UINT)(2 * i + 2);
Geometry.IndexVertexData[(i + j*(Width - 1)) * 6 + 3] = (UINT)(2 * i + 2);
Geometry.IndexVertexData[(i + j*(Width - 1)) * 6 + 4] = (UINT)(2 * i + 1);
Geometry.IndexVertexData[(i + j*(Width - 1)) * 6 + 5] = (UINT)(2 * i + 3);
}
sz_iList has a final value of 2166, resultant from a grid of 20x20 (400 total points) and is used to initialize sizes. In all cases, the vector array would not fully fill, crashing with Critical error detected c0000374. Am I doing something wrong?
Your sz_iList doesn't appear to be big enough. Let's use a simple example of Width = Height = 2;, then sz_iList = (2 - 1) * (2 - 1) * 6 = 6, right? But in your nested loops, the last iteration occurs when i = j = 1 (i is one less than Width and j is one less than Height), where (in the last line of your loop), you try to access element (i + j * (Width - 1)) * 6 + 5 = (1 + 1 * (2 - 1)) * 6 + 5 = (1 + 1 * 1) * 6 + 5 = 2 * 6 + 5 = 17, which is bigger than the size of your array. This results in undefined behavior.
can anyone see where i made a mistake here? I know that the algorithm will properly decrypt the encrypted data. however, most of the encrypted data is not the correct output, according to the RC6 paper.
// hexlify(string) turns a string into its hex representation: hexlify("AB") -> "4142"
// unhexlify(string) turns a string into its ASCII representation: unhexlify("4142") -> "AB"
// uint128_t is my own version of uint128, and Im pretty sure that the math is correct
// little_end(string, base) flips a string by bytes to get the little endian version of the string
// ROL/ROR(int, rotate x bits, bitsize of input int) does bitwise rotation
class RC6{
private:
unsigned int w, r, b, lgw;
std::vector <uint32_t> S;
uint128_t mod;
std::string mode;
void keygen(std::string KEY){
uint64_t p, q;
rc_pq(w, p, q);
KEY = hexlify(KEY);
unsigned int u = (unsigned int) ceil(w / 8.);
unsigned int c = (unsigned int) ceil(float(b) / u);
while ((KEY.size() >> 1) % u != 0)
KEY += zero;
std::vector <uint32_t> L;
for(unsigned int x = 0; x < c; x++)
L.push_back(toint(little_end(KEY.substr(2 * u * x, 2 * u), 16), 16));
S.push_back(p);
for(unsigned int i = 0; i < 2 * r + 3; i++)
S.push_back((S[i] + q) % mod);
uint32_t A = 0, B = 0, i = 0, j = 0;
uint32_t v = 3 * std::max(c, 2 * r + 4);
for(unsigned int s = 1; s < v + 1; s++){
A = S[i] = ROL((S[i] + A + B) % mod, 3, w);
B = L[j] = ROL((L[j] + A + B) % mod, (A + B) % w, w);
i = (i + 1) % (2 * r + 4);
j = (j + 1) % c;
}
}
public:
RC6(std::string KEY, std::string MODE, unsigned int W = 32, unsigned int R = 20, unsigned int B = 16){
w = W;
r = R;
b = B;
mod = uint128_t(1) << w;
lgw = (unsigned int) log2(w);
mode = MODE;
keygen(KEY);
}
std::string run(std::string DATA){
DATA = hexlify(DATA);
uint32_t A = toint(little_end(DATA.substr(0, 8), 16), 16), B = toint(little_end(DATA.substr(8, 8), 16), 16), C = toint(little_end(DATA.substr(16, 8), 16), 16), D = toint(little_end(DATA.substr(24, 8), 16), 16);
if (mode == "e"){
B += S[0];
D += S[1];
for(unsigned int i = 1; i < r + 1; i++){
uint64_t t = ROL((uint64_t) ((B * (2 * B + 1)) % mod), lgw, w);
uint64_t u = ROL((uint64_t) ((D * (2 * D + 1)) % mod), lgw, w);
A = ROL(A ^ t, u % w, w) + S[2 * i];
C = ROL(C ^ u, t % w, w) + S[2 * i + 1];
uint64_t temp = A; A = B % mod; B = C % mod; C = D % mod; D = temp % mod;
}
A += S[2 * r + 2];
C += S[2 * r + 3];
}
else{
C -= S[2 * r + 3];
A -= S[2 * r + 2];
for(int i = r; i > 0; i--){
uint64_t temp = D; D = C % mod; C = B % mod; B = A % mod; A = temp % mod;
uint64_t u = ROL((uint64_t) ((D * (2 * D + 1)) % mod), lgw, w);
uint64_t t = ROL((uint64_t) ((B * (2 * B + 1)) % mod), lgw, w);
C = ROR((C - S[2 * i + 1]) % mod, t % w, w) ^ u;
A = ROR((A - S[2 * i]) % mod, u % w, w) ^ t;
}
D -= S[1];
B -= S[0];
}
w >>= 2;
return unhexlify(little_end(makehex(A % mod, w)) + little_end(makehex(B % mod, w)) + little_end(makehex(C % mod, w)) + little_end(makehex(D % mod, w)));
}
};
of these tests vectors, only the first two are correct. the rest are not
data = "00000000000000000000000000000000";
key = "00000000000000000000000000000000";
ciphertext = "8fc3a53656b1f778c129df4e9848a41e";
data = "02132435465768798a9bacbdcedfe0f1";
key = "0123456789abcdef0112233445566778";
ciphertext = "524e192f4715c6231f51f6367ea43f18";
data = "00000000000000000000000000000000";
key = "000000000000000000000000000000000000000000000000";
ciphertext = "6cd61bcb190b30384e8a3f168690ae82";
data = "02132435465768798a9bacbdcedfe0f1";
key = "0123456789abcdef0112233445566778899aabbccddeeff0";
ciphertext = "688329d019e505041e52e92af95291d4";
data = "00000000000000000000000000000000";
key = "0000000000000000000000000000000000000000000000000000000000000000";
ciphertext = "8f5fbd0510d15fa893fa3fda6e857ec2";
data = "02132435465768798a9bacbdcedfe0f1";
key = "0123456789abcdef0112233445566778899aabbccddeeff01032547698badcfe";
ciphertext = "c8241816f0d7e48920ad16a1674e5d48";
did i mess up a uint somewhere? wrong little endian change?
I think I figured it out. Can anyone corroborate? I think that because I set b = 16 by default, I'm causing the errors. My harddrive is dead or I would have tested this already