consolidate all repos to one for archive

This commit is contained in:
2025-01-28 13:46:42 +01:00
commit a6610fbc7a
5350 changed files with 2705721 additions and 0 deletions

View File

@@ -0,0 +1,37 @@
#pragma once
#include "Buffer.hpp"
class BitReader
{
public:
int k = 8;
Buffer buffer;
char x = 0;
size_t pos = 0;
int readInt()
{
int ret = buffer.buffer[pos];
pos += 4;
return ret;
}
char readByte()
{
x = buffer.buffer[pos];
pos++;
return x;
}
bool readBit()
{
if (k == 8)
{
readByte();
k = 0;
}
bool b = (x >> k) & 1;
k++;
return b;
}
};

View File

@@ -0,0 +1,39 @@
#pragma once
#include "Buffer.hpp"
class BitWriter
{
public:
int k = 0;
Buffer buffer;
char x = 0;
void writeByte(uint8_t x)
{
// f.write((char*)&x, 1);
buffer.add_end(&x, sizeof(uint8_t));
}
void writeInt(int x)
{
buffer.add_end((uint8_t *)&x, sizeof(x));
}
void writeBit(bool b)
{
if (k == 8)
{
writeByte(x);
k = 0;
x = 0;
}
x ^= (-b ^ x) & (1 << k);
k++;
}
void finish()
{
if (k > 0)
writeByte(x);
}
};

View File

@@ -0,0 +1,36 @@
#pragma once
#include <cstdint>
#include <string>
class Buffer
{
public:
uint8_t *buffer = nullptr;
size_t taken = 0;
size_t size = 0;
std::string file_path;
Buffer(size_t size);
Buffer();
~Buffer();
bool resize(size_t new_size);
int add_end(uint8_t *data, size_t data_size);
int add_middle(uint8_t *data, size_t data_size, size_t index);
// Removes data from buffer without checking if it's in the buffer
void remove_fast(uint8_t *data, size_t data_size);
void remove(size_t index, size_t data_size);
int find(uint8_t *data, size_t data_size);
void remove(uint8_t *data, size_t data_size);
void clear() { taken = 0; }
bool save_to_file();
bool save_to_file(std::string file_path);
bool load_from_file();
bool load_from_file(std::string file_path);
};

View File

@@ -0,0 +1,24 @@
#pragma once
#include "BitWriter.hpp"
#include <vector>
class Compressor
{
public:
Compressor() = default;
~Compressor() = default;
void compress(std::vector<uint8_t> &input);
BitWriter bitWriter;
private:
void two_bit_dif(int8_t num);
void tree_bit_dif(int8_t num);
void four_bit_dif(int8_t num);
void five_bit_dif(int8_t num);
void encode_diff(int8_t num);
void encode_abs(int16_t num);
void write_zero();
int numOfZeros = 0;
};

View File

@@ -0,0 +1,15 @@
#include "BitReader.hpp"
#include <vector>
class Decompressor
{
public:
std::vector<uint8_t> decompress();
BitReader bitReader;
private:
int8_t twoZero();
int8_t treeZero();
int8_t forZero();
int8_t fiveZero();
};

View File

@@ -0,0 +1,114 @@
#include <iostream>
#include <vector>
#include <fstream>
#include <chrono>
#include <ctime>
#include <random>
#include "Compressor.hpp"
#include "Decompressor.hpp"
/*
• Prikažite graf ali tabelo kompresijskega razmerja
• Prikažite graf ali tabelo časa kompresije
• Prikažite graf ali tabelo časa dekompresije
• 5-10 stavkov ugotovitev
• Uporabite N števil
• N = {5, 50, 500, 5000}
• Naključno generirana števila na intervalu od 0 do 255
• Števila (na intervalu med 0 in 255), ki se med seboj razlikujejo za M
(razlika med sosednjima številoma je med 0 in M)
• M = {5, 10, 15, 30}
• Primer: N = 5 in M = 5; podatki: 135, 133, 136, 141, 141
55 53 53 53 53 53 10 10 11 11 11 11
00110111 000000 01011 10100101011 01000 000010 01010 11
*/
void genRandNum(int N, int M, std::vector<uint8_t> &vec)
{
std::random_device rand_dev;
std::mt19937 generator(rand_dev());
std::uniform_real_distribution<double> distr(0.0, 1.0);
uint8_t last = 0;
uint8_t max = 255;
uint8_t min = 0;
for (int i = 0; i < N; i++)
{
// std::cout << 25 + static_cast<int>((distr(generator) * (63 - 25 + 1))) << '\n';
float r = distr(generator);
uint8_t num = min + (r * (max - min));
max = num + M;
if (max > 255)
max = 255;
min = num - M;
if (min < 0)
min = 0;
vec.push_back(num);
}
}
int main()
{
auto start = std::chrono::system_clock::now();
std::vector<int> N = {5, 50, 500, 5000, 50000};
std::vector<int> M = {2, 5, 10, 15, 30, 60};
printf("N, \t M, \t Compress time, \tDecompress time, \t Input size, \t Output size, \t Compression ratio, \n");
for (size_t i = 0; i < N.size(); i++)
{
for (size_t j = 0; j < M.size(); j++)
{
std::vector<uint8_t> input;
genRandNum(N[i], M[j], input);
Compressor compressor;
auto startCom = std::chrono::system_clock::now();
compressor.compress(input);
auto endCom = std::chrono::system_clock::now();
Decompressor decompressor;
decompressor.bitReader.buffer.add_end(compressor.bitWriter.buffer.buffer, compressor.bitWriter.buffer.taken);
auto startDec = std::chrono::system_clock::now();
std::vector<uint8_t> output = decompressor.decompress();
auto endDec = std::chrono::system_clock::now();
for (size_t k = 0; k < input.size(); k++)
{
if (input[k] != output[k])
{
printf("Error\n");
return 0;
}
}
std::chrono::duration<double> compTime = endCom - startCom;
std::chrono::duration<double> decTime = endDec - startDec;
printf("%d,\t %d,\t ", N[i], M[j]);
printf("%f,\t\t", compTime.count());
printf("%f,\t\t ", decTime.count());
uint64_t input_size = N[i] * sizeof(uint8_t);
uint64_t output_size = compressor.bitWriter.buffer.taken;
printf("%ld,\t\t ", input_size);
printf("%ld,\t\t ", output_size);
printf("%f,\t", (float)input_size / (float)output_size);
printf("\n");
}
printf("\n");
}
auto end = std::chrono::system_clock::now();
std::chrono::duration<double> decTime = end - start;
printf("Total time: %f\n", decTime.count());
return 0;
}

View File

@@ -0,0 +1,27 @@
CC=g++
CFLAGS= -std=c++23
INCLUDE_DIR= include
SRC_DIR= src
# Get all cpp files from src directory
SRCS := $(wildcard $(SRC_DIR)/*.cpp)
all: main
main: main.cpp $(SRCS)
$(CC) $(CFLAGS) -o3 -I$(INCLUDE_DIR) $(SRCS) main.cpp -o main
debug: main.cpp $(SRCS)
$(CC) $(CFLAGS) -I$(INCLUDE_DIR) $(SRCS) -g main.cpp -o main
run: main
./main
zip:
zip -r main.zip src include makefile main.cpp
clean:
rm main main.zip

View File

@@ -0,0 +1,153 @@
#include "Buffer.hpp"
#include <iostream>
#include <fstream>
#include <cstring>
Buffer::Buffer()
{
buffer = nullptr;
size = 0;
taken = 0;
}
Buffer::Buffer(size_t size)
{
this->size = size;
this->buffer = new uint8_t[size];
}
Buffer::~Buffer()
{
if (buffer)
delete[] buffer;
}
bool Buffer::resize(size_t new_size)
{
if (size >= new_size)
return true;
if (new_size < size * 2)
new_size = size * 2;
uint8_t *new_buffer = (uint8_t *)realloc(buffer, new_size);
if (!new_buffer)
{
printf("Error resizing buffer\n");
return false;
}
buffer = new_buffer;
size = new_size;
return true;
}
int Buffer::add_end(uint8_t *data, size_t data_size)
{
if (taken + data_size > size)
if (!resize(size + data_size))
return -1;
memcpy(buffer + taken, data, data_size);
taken += data_size;
return taken - data_size;
}
int Buffer::add_middle(uint8_t *data, size_t data_size, size_t index)
{
if (taken + data_size > size)
if (!resize(size + data_size))
return -1;
memmove(buffer + index + data_size, buffer + index, taken - index);
memcpy(buffer + index, data, data_size);
taken += data_size;
return index;
}
void Buffer::remove_fast(uint8_t *data, size_t data_size)
{
int64_t index = data - buffer;
if (index < 0 || index > taken || index + data_size > taken)
{
printf("Error removing from buffer\n");
return;
}
memmove(buffer + index, buffer + index + data_size, taken - index - data_size);
taken -= data_size;
}
void Buffer::remove(size_t index, size_t data_size)
{
if (index + data_size > taken)
{
printf("Error removing from buffer\n");
return;
}
memmove(buffer + index, buffer + index + data_size, taken - index - data_size);
taken -= data_size;
}
int Buffer::find(uint8_t *data, size_t data_size)
{
for (int i = 0; i < taken; i++)
if (memcmp(buffer + i, data, data_size) == 0)
return i;
return -1;
}
void Buffer::remove(uint8_t *data, size_t data_size)
{
int index = find(data, data_size);
if (index == -1)
{
printf("Error removing from buffer\n");
return;
}
remove(index, data_size);
}
bool Buffer::save_to_file()
{
std::ofstream file(this->file_path, std::ios::binary | std::ios::out);
if (!file.is_open())
{
printf("Error saving file\n");
return false;
}
file.write((char *)this->buffer, this->taken);
file.close();
return true;
}
bool Buffer::save_to_file(std::string file_path)
{
this->file_path = file_path;
return save_to_file();
}
bool Buffer::load_from_file()
{
std::ifstream file(this->file_path, std::ios::binary | std::ios::in);
if (!file.is_open())
return false;
file.seekg(0, std::ios::end);
size_t file_size = file.tellg();
resize(file_size);
file.seekg(0, std::ios::beg);
file.read((char *)buffer, size);
if (file)
taken = file_size;
else
taken = file.gcount();
file.close();
return true;
}
bool Buffer::load_from_file(std::string file_path)
{
this->file_path = file_path;
return load_from_file();
}

View File

@@ -0,0 +1,158 @@
#include "Compressor.hpp"
void Compressor::two_bit_dif(int8_t num)
{
bitWriter.writeBit(0);
bitWriter.writeBit(0);
if (num < 0)
num += 2;
else
num += 1;
bitWriter.writeBit(num & 2);
bitWriter.writeBit(num & 1);
}
void Compressor::tree_bit_dif(int8_t num)
{
bitWriter.writeBit(0);
bitWriter.writeBit(1);
if (num < 0)
num += 6;
else
num += 1;
bitWriter.writeBit(num & 4);
bitWriter.writeBit(num & 2);
bitWriter.writeBit(num & 1);
}
void Compressor::four_bit_dif(int8_t num)
{
bitWriter.writeBit(1);
bitWriter.writeBit(0);
if (num < 0)
num += 14;
else
num += 1;
bitWriter.writeBit(num & 8);
bitWriter.writeBit(num & 4);
bitWriter.writeBit(num & 2);
bitWriter.writeBit(num & 1);
}
void Compressor::five_bit_dif(int8_t num)
{
bitWriter.writeBit(1);
bitWriter.writeBit(1);
if (num < 0)
num += 30;
else
num += 1;
bitWriter.writeBit(num & 16);
bitWriter.writeBit(num & 8);
bitWriter.writeBit(num & 4);
bitWriter.writeBit(num & 2);
bitWriter.writeBit(num & 1);
}
void Compressor::encode_diff(int8_t num)
{
bitWriter.writeBit(0);
bitWriter.writeBit(0);
if (-2 <= num && num <= 2)
two_bit_dif(num);
else if (-6 <= num && num <= 6)
tree_bit_dif(num);
else if (-14 <= num && num <= 14)
four_bit_dif(num);
else if (-30 <= num && num <= 30)
five_bit_dif(num);
}
void Compressor::encode_abs(int16_t num)
{
bitWriter.writeBit(1);
bitWriter.writeBit(0);
if (num < 0)
{
bitWriter.writeBit(1);
num = -num;
}
else
{
bitWriter.writeBit(0);
}
uint8_t numOfBits = num;
for (int i = 7; i >= 0; i--)
bitWriter.writeBit(numOfBits & 1 << i);
}
void Compressor::write_zero()
{
bitWriter.writeBit(0);
bitWriter.writeBit(1);
numOfZeros--;
bitWriter.writeBit(numOfZeros & 4);
bitWriter.writeBit(numOfZeros & 2);
bitWriter.writeBit(numOfZeros & 1);
numOfZeros = 0;
}
void Compressor::compress(std::vector<uint8_t> &input)
{
std::vector<int16_t> diference;
diference.push_back(input[0]);
for (size_t i = 1; i < input.size(); i++)
{
diference.push_back(input[i] - input[i - 1]);
}
bitWriter.writeByte(diference[0]);
for (size_t i = 1; i < diference.size(); i++)
{
int16_t j = diference[i];
if (j == 0)
{
if (numOfZeros == 8)
{
write_zero();
}
numOfZeros++;
}
else
{
if (numOfZeros > 0)
{
write_zero();
}
if (-30 <= j && j <= 30)
encode_diff(j);
else
encode_abs(j);
numOfZeros = 0;
}
}
if (numOfZeros > 0)
{
write_zero();
}
bitWriter.writeBit(1);
bitWriter.writeBit(1);
bitWriter.finish();
}

View File

@@ -0,0 +1,125 @@
#include "Decompressor.hpp"
int8_t Decompressor::twoZero()
{
int8_t val = 0;
for (int i = 1; i >= 0; i--)
val |= bitReader.readBit() << i;
if (val & 2)
return val - 1;
else
return val - 2;
}
int8_t Decompressor::treeZero()
{
int8_t val = 0;
for (int i = 2; i >= 0; i--)
val |= bitReader.readBit() << i;
if (val & 4)
return val - 1;
else
return val - 6;
}
int8_t Decompressor::forZero()
{
int8_t val = 0;
for (int i = 3; i >= 0; i--)
val |= bitReader.readBit() << i;
if (val & 8)
return val - 1;
else
return val - 14;
}
int8_t Decompressor::fiveZero()
{
int8_t val = 0;
for (int i = 4; i >= 0; i--)
val |= bitReader.readBit() << i;
if (val & 16)
return val - 1;
else
return val - 30;
}
std::vector<uint8_t> Decompressor::decompress()
{
std::vector<uint8_t> output;
bool end = false;
uint8_t previus = bitReader.readByte();
output.push_back(previus);
do
{
uint8_t type = bitReader.readBit() << 1 | bitReader.readBit();
switch (type)
{
case 0:
{
uint8_t numOfZero = bitReader.readBit() << 1 | bitReader.readBit();
int8_t diff = 0;
switch (numOfZero)
{
case 0:
diff = twoZero();
break;
case 1:
diff = treeZero();
break;
case 2:
diff = forZero();
break;
case 3:
diff = fiveZero();
break;
}
previus += diff;
output.push_back(previus);
}
break;
case 1:
{
uint8_t numOfZero = bitReader.readBit() << 2 | bitReader.readBit() << 1 | bitReader.readBit();
numOfZero++;
for (size_t i = 0; i < numOfZero; i++)
{
output.push_back(previus);
}
}
break;
case 2:
{
uint8_t sign = bitReader.readBit();
int16_t diff = 0;
for (int i = 7; i >= 0; i--)
{
uint8_t bit = bitReader.readBit();
diff |= bit << i;
}
if (sign)
diff = -diff;
previus += diff;
output.push_back(previus);
}
break;
case 3:
end = true;
break;
default:
break;
}
} while (!end);
return output;
}