I have an implementation of SHA-3 hash algorithm in C, it works correctly with not-empty files, but when I try to get a digest of an empty file, I get the wrong digest.
For example, if hash a file with only "a" letter, I get:
be5215abf72333a73b992dafdf4ab59884b948452e0015cfaddaa0b87a0e4515
But, when I hash empty file, I get
0000000000000000000000000000000000000000000000000000000000000000
I expected:
a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a
(https://en.wikipedia.org/wiki/SHA-3#Examples_of_SHA-3_variants)
Can anyone tell me what is wrong in my implementation?
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#define index(x, y) (((x) % 5) + 5 * ((y) % 5))
#define KECCAK_ROUNDS 24
#define Plen 200
typedef unsigned int uint;
const uint64_t round_constants[KECCAK_ROUNDS] =
{
0x0000000000000001, 0x0000000000008082, 0x800000000000808A, 0x8000000080008000,
0x000000000000808B, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009,
0x000000000000008A, 0x0000000000000088, 0x0000000080008009, 0x000000008000000A,
0x000000008000808B, 0x800000000000008B, 0x8000000000008089, 0x8000000000008003,
0x8000000000008002, 0x8000000000000080, 0x000000000000800A, 0x800000008000000A,
0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008
};
/* --------------------------------------------------------------------------- */
static uint64_t
rol(uint64_t a, uint offset)
{
if (offset == 0) {
return a;
}
return (a << offset) | (a >> (64 - offset));
}
static void
theta(uint64_t *A)
{
uint64_t C[5], D[5];
for (uint x = 0; x < 5; ++x) {
C[x] = 0;
for (uint y = 0; y < 5; ++y) {
C[x] ^= A[index(x, y)];
}
}
for (uint x = 0; x < 5; ++x) {
D[x] = rol(C[(x + 1) % 5], 1) ^ C[(x + 4) % 5];
}
for (uint x = 0; x < 5; ++x) {
for (uint y = 0; y < 5; ++y) {
A[index(x, y)] ^= D[x];
}
}
}
static void
rho(uint64_t *A)
{
uint newX, newY, ro[KECCAK_ROUNDS];
ro[index(0, 0)] = 0;
uint x = 1;
uint y = 0;
for (uint t = 0; t < KECCAK_ROUNDS; ++t) {
ro[index(x, y)] = ((t + 1) * (t + 2) / 2) % 64;
newX = (0 * x + 1 * y) % 5;
newY = (2 * x + 3 * y) % 5;
x = newX;
y = newY;
}
for (x = 0; x < 5; ++x) {
for (y = 0; y < 5; ++y) {
A[index(x, y)] = rol(A[index(x, y)], ro[index(x, y)]);
}
}
}
static void
pi(uint64_t *A)
{
uint64_t tempA[25];
for (uint x = 0; x < 5; ++x) {
for (uint y = 0; y < 5; ++y) {
tempA[index(x, y)] = A[index(x, y)];
}
}
for (uint x = 0; x < 5; ++x) {
for (uint y = 0; y < 5; ++y) {
A[index(0 * x + 1 * y, 2 * x + 3 * y)] = tempA[index(x, y)];
}
}
}
static void
chi(uint64_t *A)
{
uint64_t C[5];
for (uint y = 0; y < 5; ++y) {
for (uint x = 0; x < 5; ++x) {
C[x] = A[index(x, y)] ^ ((~A[index(x + 1, y)]) & A[index(x + 2, y)]);
}
for (uint x = 0; x < 5; ++x) {
A[index(x, y)] = C[x];
}
}
}
static void
iota(uint64_t *A, uint indexRound)
{
A[index(0, 0)] ^= round_constants[indexRound];
}
static void
keccakf(void *state)
{
for (uint i = 0; i < KECCAK_ROUNDS; ++i) {
theta(state);
rho(state);
pi(state);
chi(state);
iota(state, i);
}
}
static void
xorin(uint8_t *dest, const uint8_t *src, size_t len)
{
for (size_t i = 0; i < len; ++i) {
dest[i] ^= src[i];
}
}
static void
setout(uint8_t *dest, const uint8_t *src, size_t len)
{
for (size_t i = 0; i < len; ++i) {
dest[i] = src[i];
}
}
/* The sponge-based hash construction. */
static void
hash(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen, size_t rate, uint8_t delim)
{
if ((out == NULL) || ((in == NULL) && inlen != 0) || (rate >= Plen)) {
return;
}
uint8_t a[Plen] = { 0 /* 0, 0, 0, ... */ };
while (inlen >= rate) {
xorin(a, in, rate);
keccakf(a);
in += rate;
inlen -= rate;
}
a[inlen] ^= delim;
a[rate - 1] ^= 0x80;
xorin(a, in, inlen);
keccakf(a);
while (outlen >= rate) {
setout(out, a, rate);
keccakf(a);
out += rate;
outlen -= rate;
}
setout(out, a, outlen);
memset(a, '\0', Plen);
}
int
sha3_stream (FILE *stream, void *resblock, size_t databitlen)
{
size_t SHA3_BLOCK = databitlen / 8;
size_t bytesread;
uint8_t *in = malloc (databitlen);
if (!in)
return 1;
while ((bytesread = fread(in, sizeof(char), SHA3_BLOCK, stream)) != 0)
hash(resblock, SHA3_BLOCK, in, bytesread, Plen - (databitlen / 4), 0x06);
free(in);
return 0;
}
int main(int argc, char **argv)
{
/* 32 it is SHA3-256 BLOCK */
/* here used 256 bits digest lenght */
for (int i = 1; i < argc; ++i)
{
uint8_t *out = malloc(32);
FILE *fp = fopen(argv[i], "r");
sha3_stream(fp, out, 256);
for (int j = 0; j < 32; ++j)
printf("%02x", out[j]);
printf(" %s\n", argv[i]);
free(out);
}
}
As said user2722968:
"The while-loop in sha3_stream will not execute at all for an empty file, because you are at EOF on the first iteration. Therefor resblock stays all zero; switch to a do-while loop where the EOF-condition is checked after each iteration, not before."
So, correct code is:
bytesread = fread(in, sizeof(char), SHA3_BLOCK, stream);
do {
hash(resblock, SHA3_BLOCK, in, bytesread, Plen - (databitlen / 4), 0x06);
} while ((bytesread = fread(in, sizeof(char), SHA3_BLOCK, stream)) != 0);
Instead wrong:
while ((bytesread = fread(in, sizeof(char), SHA3_BLOCK, stream)) != 0)
hash(resblock, SHA3_BLOCK, in, bytesread, Plen - (databitlen / 4), 0x06);
Related
i have to code a sudoku ocr for school in C.
I use an edge detection algorithm which returns a bmp file.
However, the returned file only shows 1/3 of the expected output.
Please can someone tell me what is wrong in my code :)
input image (BMP file)
output image (BMP file)
and here's my code :
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#include <math.h>
#include <string.h>
#include <stdbool.h>
#include <assert.h>
#define MAX_BRIGHTNESS 255
// C99 doesn't define M_PI (GNU-C99 does)
#define M_PI 3.14159265358979323846264338327
/*
* Loading part taken from
* http://www.vbforums.com/showthread.php?t=261522
* BMP info:
* http://en.wikipedia.org/wiki/BMP_file_format
*
* Note: the magic number has been removed from the bmpfile_header_t
* structure since it causes alignment problems
* bmpfile_magic_t should be written/read first
* followed by the
* bmpfile_header_t
* [this avoids compiler-specific alignment pragmas etc.]
*/
typedef struct {
uint8_t magic[2];
} bmpfile_magic_t;
typedef struct {
uint32_t filesz;
uint16_t creator1;
uint16_t creator2;
uint32_t bmp_offset;
} bmpfile_header_t;
typedef struct {
uint32_t header_sz;
int32_t width;
int32_t height;
uint16_t nplanes;
uint16_t bitspp;
uint32_t compress_type;
uint32_t bmp_bytesz;
int32_t hres;
int32_t vres;
uint32_t ncolors;
uint32_t nimpcolors;
} bitmap_info_header_t;
typedef struct {
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t nothing;
} rgb_t;
// Use short int instead `unsigned char' so that we can
// store negative values.
typedef short int pixel_t;
pixel_t *load_bmp(const char *filename,
bitmap_info_header_t *bitmapInfoHeader)
{
FILE *filePtr = fopen(filename, "rb");
if (filePtr == NULL) {
perror("fopen()");
return NULL;
}
bmpfile_magic_t mag;
if (fread(&mag, sizeof(bmpfile_magic_t), 1, filePtr) != 1) {
fclose(filePtr);
return NULL;
}
// verify that this is a bmp file by check bitmap id
// warning: dereferencing type-punned pointer will break
// strict-aliasing rules [-Wstrict-aliasing]
if (*((uint16_t*)mag.magic) != 0x4D42) {
fprintf(stderr, "Not a BMP file: magic=%c%c\n",
mag.magic[0], mag.magic[1]);
fclose(filePtr);
return NULL;
}
bmpfile_header_t bitmapFileHeader; // our bitmap file header
// read the bitmap file header
if (fread(&bitmapFileHeader, sizeof(bmpfile_header_t),
1, filePtr) != 1) {
fclose(filePtr);
return NULL;
}
// read the bitmap info header
if (fread(bitmapInfoHeader, sizeof(bitmap_info_header_t),
1, filePtr) != 1) {
fclose(filePtr);
return NULL;
}
if (bitmapInfoHeader->compress_type != 0)
fprintf(stderr, "Warning, compression is not supported.\n");
// move file point to the beginning of bitmap data
if (fseek(filePtr, bitmapFileHeader.bmp_offset, SEEK_SET)) {
fclose(filePtr);
return NULL;
}
// allocate enough memory for the bitmap image data
pixel_t *bitmapImage = malloc(bitmapInfoHeader->bmp_bytesz *
sizeof(pixel_t));
// verify memory allocation
if (bitmapImage == NULL) {
fclose(filePtr);
return NULL;
}
// read in the bitmap image data
size_t pad, count=0;
unsigned char c;
pad = 4*ceil(bitmapInfoHeader->bitspp*bitmapInfoHeader->width/32.) - bitmapInfoHeader->width;
for(size_t i=0; i<bitmapInfoHeader->height; i++){
for(size_t j=0; j<bitmapInfoHeader->width; j++){
if (fread(&c, sizeof(unsigned char), 1, filePtr) != 1) {
fclose(filePtr);
return NULL;
}
bitmapImage[count++] = (pixel_t) c;
}
fseek(filePtr, pad, SEEK_CUR);
}
// If we were using unsigned char as pixel_t, then:
// fread(bitmapImage, 1, bitmapInfoHeader->bmp_bytesz, filePtr);
// close file and return bitmap image data
fclose(filePtr);
return bitmapImage;
}
// Return: true on error.
bool save_bmp(const char *filename, const bitmap_info_header_t *bmp_ih,
const pixel_t *data)
{
FILE* filePtr = fopen(filename, "wb");
if (filePtr == NULL)
return true;
bmpfile_magic_t mag = {{0x42, 0x4d}};
if (fwrite(&mag, sizeof(bmpfile_magic_t), 1, filePtr) != 1) {
fclose(filePtr);
return true;
}
const uint32_t offset = sizeof(bmpfile_magic_t) +
sizeof(bmpfile_header_t) +
sizeof(bitmap_info_header_t) +
((1U << bmp_ih->bitspp) * 4);
const bmpfile_header_t bmp_fh = {
.filesz = offset + bmp_ih->bmp_bytesz,
.creator1 = 0,
.creator2 = 0,
.bmp_offset = offset
};
if (fwrite(&bmp_fh, sizeof(bmpfile_header_t), 1, filePtr) != 1) {
fclose(filePtr);
return true;
}
if (fwrite(bmp_ih, sizeof(bitmap_info_header_t), 1, filePtr) != 1) {
fclose(filePtr);
return true;
}
// Palette
for (size_t i = 0; i < (1U << bmp_ih->bitspp); i++) {
const rgb_t color = {(uint8_t)i, (uint8_t)i, (uint8_t)i};
if (fwrite(&color, sizeof(rgb_t), 1, filePtr) != 1) {
fclose(filePtr);
return true;
}
}
// We use int instead of uchar, so we can't write img
// in 1 call any more.
// fwrite(data, 1, bmp_ih->bmp_bytesz, filePtr);
// Padding: http://en.wikipedia.org/wiki/BMP_file_format#Pixel_storage
size_t pad = 4*ceil(bmp_ih->bitspp*bmp_ih->width/32.) - bmp_ih->width;
unsigned char c;
for(size_t i=0; i < bmp_ih->height; i++) {
for(size_t j=0; j < bmp_ih->width; j++) {
c = (unsigned char) data[j + bmp_ih->width*i];
if (fwrite(&c, sizeof(char), 1, filePtr) != 1) {
fclose(filePtr);
return true;
}
}
c = 0;
for(size_t j=0; j<pad; j++)
if (fwrite(&c, sizeof(char), 1, filePtr) != 1) {
fclose(filePtr);
return true;
}
}
fclose(filePtr);
return false;
}
// if normalize is true, map pixels to range 0..MAX_BRIGHTNESS
void convolution(const pixel_t *in, pixel_t *out, const float *kernel,
const int nx, const int ny, const int kn,
const bool normalize)
{
assert(kn % 2 == 1);
assert(nx > kn && ny > kn);
const int khalf = kn / 2;
float min = FLT_MAX, max = -FLT_MAX;
if (normalize)
for (int m = khalf; m < nx - khalf; m++)
for (int n = khalf; n < ny - khalf; n++) {
float pixel = 0.0;
size_t c = 0;
for (int j = -khalf; j <= khalf; j++)
for (int i = -khalf; i <= khalf; i++) {
pixel += in[(n - j) * nx + m - i] * kernel[c];
c++;
}
if (pixel < min)
min = pixel;
if (pixel > max)
max = pixel;
}
for (int m = khalf; m < nx - khalf; m++)
for (int n = khalf; n < ny - khalf; n++) {
float pixel = 0.0;
size_t c = 0;
for (int j = -khalf; j <= khalf; j++)
for (int i = -khalf; i <= khalf; i++) {
pixel += in[(n - j) * nx + m - i] * kernel[c];
c++;
}
if (normalize)
pixel = MAX_BRIGHTNESS * (pixel - min) / (max - min);
out[n * nx + m] = (pixel_t)pixel;
}
}
/*
* gaussianFilter:
* http://www.songho.ca/dsp/cannyedge/cannyedge.html
* determine size of kernel (odd #)
* 0.0 <= sigma < 0.5 : 3
* 0.5 <= sigma < 1.0 : 5
* 1.0 <= sigma < 1.5 : 7
* 1.5 <= sigma < 2.0 : 9
* 2.0 <= sigma < 2.5 : 11
* 2.5 <= sigma < 3.0 : 13 ...
* kernelSize = 2 * int(2*sigma) + 3;
*/
void gaussian_filter(const pixel_t *in, pixel_t *out,
const int nx, const int ny, const float sigma)
{
const int n = 2 * (int)(2 * sigma) + 3;
const float mean = (float)floor(n / 2.0);
float kernel[n * n]; // variable length array
fprintf(stderr, "gaussian_filter: kernel size %d, sigma=%g\n",
n, sigma);
size_t c = 0;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++) {
kernel[c] = exp(-0.5 * (pow((i - mean) / sigma, 2.0) +
pow((j - mean) / sigma, 2.0)))
/ (2 * M_PI * sigma * sigma);
c++;
}
convolution(in, out, kernel, nx, ny, n, true);
}
/*
* Links:
* http://en.wikipedia.org/wiki/Canny_edge_detector
* http://www.tomgibara.com/computer-vision/CannyEdgeDetector.java
* http://fourier.eng.hmc.edu/e161/lectures/canny/node1.html
* http://www.songho.ca/dsp/cannyedge/cannyedge.html
*
* Note: T1 and T2 are lower and upper thresholds.
*/
pixel_t *canny_edge_detection(const pixel_t *in,
const bitmap_info_header_t *bmp_ih,
const int tmin, const int tmax,
const float sigma)
{
const int nx = bmp_ih->width;
const int ny = bmp_ih->height;
pixel_t *G = calloc(nx * ny * sizeof(pixel_t), 1);
pixel_t *after_Gx = calloc(nx * ny * sizeof(pixel_t), 1);
pixel_t *after_Gy = calloc(nx * ny * sizeof(pixel_t), 1);
pixel_t *nms = calloc(nx * ny * sizeof(pixel_t), 1);
pixel_t *out = malloc(bmp_ih->bmp_bytesz * sizeof(pixel_t));
if (G == NULL || after_Gx == NULL || after_Gy == NULL ||
nms == NULL || out == NULL) {
fprintf(stderr, "canny_edge_detection:"
" Failed memory allocation(s).\n");
exit(1);
}
gaussian_filter(in, out, nx, ny, sigma);
const float Gx[] = {-1, 0, 1,
-2, 0, 2,
-1, 0, 1};
convolution(out, after_Gx, Gx, nx, ny, 3, false);
const float Gy[] = { 1, 2, 1,
0, 0, 0,
-1,-2,-1};
convolution(out, after_Gy, Gy, nx, ny, 3, false);
for (int i = 1; i < nx - 1; i++)
for (int j = 1; j < ny - 1; j++) {
const int c = i + nx * j;
// G[c] = abs(after_Gx[c]) + abs(after_Gy[c]);
G[c] = (pixel_t)hypot(after_Gx[c], after_Gy[c]);
}
// Non-maximum suppression, straightforward implementation.
for (int i = 1; i < nx - 1; i++)
for (int j = 1; j < ny - 1; j++) {
const int c = i + nx * j;
const int nn = c - nx;
const int ss = c + nx;
const int ww = c + 1;
const int ee = c - 1;
const int nw = nn + 1;
const int ne = nn - 1;
const int sw = ss + 1;
const int se = ss - 1;
const float dir = (float)(fmod(atan2(after_Gy[c],
after_Gx[c]) + M_PI,
M_PI) / M_PI) * 8;
if (((dir <= 1 || dir > 7) && G[c] > G[ee] &&
G[c] > G[ww]) || // 0 deg
((dir > 1 && dir <= 3) && G[c] > G[nw] &&
G[c] > G[se]) || // 45 deg
((dir > 3 && dir <= 5) && G[c] > G[nn] &&
G[c] > G[ss]) || // 90 deg
((dir > 5 && dir <= 7) && G[c] > G[ne] &&
G[c] > G[sw])) // 135 deg
nms[c] = G[c];
else
nms[c] = 0;
}
// Reuse array
// used as a stack. nx*ny/2 elements should be enough.
int *edges = (int*) after_Gy;
memset(out, 0, sizeof(pixel_t) * nx * ny);
memset(edges, 0, sizeof(pixel_t) * nx * ny);
// Tracing edges with hysteresis . Non-recursive implementation.
size_t c = 1;
for (int j = 1; j < ny - 1; j++)
for (int i = 1; i < nx - 1; i++) {
if (nms[c] >= tmax && out[c] == 0) { // trace edges
out[c] = MAX_BRIGHTNESS;
int nedges = 1;
edges[0] = c;
do {
nedges--;
const int t = edges[nedges];
int nbs[8]; // neighbours
nbs[0] = t - nx; // nn
nbs[1] = t + nx; // ss
nbs[2] = t + 1; // ww
nbs[3] = t - 1; // ee
nbs[4] = nbs[0] + 1; // nw
nbs[5] = nbs[0] - 1; // ne
nbs[6] = nbs[1] + 1; // sw
nbs[7] = nbs[1] - 1; // se
for (int k = 0; k < 8; k++)
if (nms[nbs[k]] >= tmin && out[nbs[k]] == 0) {
out[nbs[k]] = MAX_BRIGHTNESS;
edges[nedges] = nbs[k];
nedges++;
}
} while (nedges > 0);
}
c++;
}
free(after_Gx);
free(after_Gy);
free(G);
free(nms);
return out;
}
int main(const int argc, const char ** const argv)
{
if (argc < 2) {
printf("Usage: %s image.bmp\n", argv[0]);
return 1;
}
static bitmap_info_header_t ih;
const pixel_t *in_bitmap_data = load_bmp(argv[1], &ih);
if (in_bitmap_data == NULL) {
fprintf(stderr, "main: BMP image not loaded.\n");
return 1;
}
printf("Info: %d x %d x %d\n", ih.width, ih.height, ih.bitspp);
const pixel_t *out_bitmap_data =
canny_edge_detection(in_bitmap_data, &ih, 45, 50, 1.0f);
if (out_bitmap_data == NULL) {
fprintf(stderr, "main: failed canny_edge_detection.\n");
return 1;
}
if (save_bmp("out.bmp", &ih, out_bitmap_data)) {
fprintf(stderr, "main: BMP image not saved.\n");
return 1;
}
free((pixel_t*)in_bitmap_data);
free((pixel_t*)out_bitmap_data);
return 0;
}
This isn't really an answer, but I wanted to post the image I obtained from the code.
I took two actions on the .jpg posted a) reduce to 256 colours, b) save as 8-bit .bmp, done with an image editor.
Then after running the code I converted the 8-bit .bmp output to .png to post here.
I only changed one thing for MSVC, the VLA
//float kernel[n * n]; // variable length array
float *kernel = malloc(n * n * sizeof (float));
with free(kernel) at the end of the function. Although there were still several compiler warnings, they didn't seem to be material here, but it's still worth fixing them.
I'm trying to edit this kernel. c, it doesn't support cursor. I wrote over 25 lines, and it doesn't show more than 25 and I can't go up or down to see the rest. here is the whole code, except the main function.
uint8_t make_color(enum vga_color fg, enum vga_color bg) {
return fg | bg << 4;}
static const size_t VGA_WIDTH = 80;
static const size_t VGA_HEIGHT = 25;
uint16_t make_vgaentry(char c, uint8_t color) {
uint16_t c16 = c;
uint16_t color16 = color;
return c16 | color16 << 8;}
size_t strlen(const char* str) {
size_t ret = 0;
while ( str[ret] != 0 )
ret++;
return ret;}
static const size_t VGA_WIDTH = 80;
static const size_t VGA_HEIGHT = 25;
size_t terminal_row;
size_t terminal_column;
uint8_t terminal_color;
uint16_t* terminal_buffer;
void terminal_initialize() {
terminal_row = 0;
terminal_column = 0;
terminal_color = make_color(COLOR_LIGHT_GREY, COLOR_BLACK);
terminal_buffer = (uint16_t*) 0xB8000;
for (size_t y = 0; y < VGA_HEIGHT; y++) {
for (size_t x = 0; x < VGA_WIDTH; x++) {
const size_t index = y * VGA_WIDTH + x;
terminal_buffer[index] = make_vgaentry(' ',
terminal_color);
}}}
void terminal_setcolor(uint8_t color) {
terminal_color = color;
}
void terminal_putentryat(char c, uint8_t color, size_t x, size_t y)
{
const size_t index = y * VGA_WIDTH + x;
if(y>VGA_HEIGHT){
size_t index = (VGA_HEIGHT - 1) * VGA_WIDTH;
for(size_t x = 0; x < VGA_WIDTH; ++x)
{
terminal_buffer[index + x] = vga_entry(' ', terminal_color);
}
}
else
terminal_buffer[index] = make_vgaentry(c, color);}
void terminal_putchar(char c) {
terminal_putentryat(c, terminal_color, terminal_column,
terminal_row);
if (++terminal_column == VGA_WIDTH) {
terminal_column = 0;
if (++terminal_row == VGA_HEIGHT)
terminal_row = 0;}
else if (c == '\n')
{
terminal_row = terminal_row + 1;
terminal_column = 0;
}
}
void terminal_writestring(const char* data) {
size_t datalen = strlen(data);
for (size_t i = 0; i < datalen; i++)
terminal_putchar(data[i]);}
i need to have scrolling like the one in the terminal, line by line.
void terminal_scrollUp(void)
{
for (size_t y = 1; y < VGA_HEIGHT; y++)
{
for (size_t x = 0; x < VGA_WIDTH; x++)
{
const size_t index = y * VGA_WIDTH + x;
terminal_buffer[index - VGA_WIDTH] = terminal_buffer[index];
}
}
for(size_t col = 0; col < VGA_WIDTH; col++)
{
terminal_putentryat(' ', terminal_color, col, VGA_HEIGHT - 1);
}
}
void terminal_putchar(char c)
{
terminal_putentryat(c, terminal_color, terminal_column, terminal_row);
if (++terminal_column == VGA_WIDTH || c == '\n')
{
terminal_column = 0;
if(terminal_row == VGA_HEIGHT - 1)
{
terminal_scrollUp();
}
else
{
terminal_row++;
}
}
}
The text displayed on the screen is taken directly from the memory. If you move the contents of that memory it will look like the text moved.
So if you move from the second to the last "line" one line up (to the beginning of the display memory are) while setting the last "line" to all zeroes, then it will look like it scrolled.
Something like:
char *ptr_to_first_line = terminal_buffer;
char *ptr_to_second_line = terminal_buffer + VGA_WIDTH * 2; // *2 because of the attribute byte
char *ptr_to_last_line = terminal_buffer + (VGA_WIDTH * 2) * (VGA_HEIGHT - 1); // -1 to get the beginning of the last line
char *ptr_to_end = terminal_buffer + VGA_WIDTH * 2 * VGA_HEIGHT;
// Move (copy, overlapping memory okay) the memory, making appear as it's scrolling
// This copies from the second line to the first line, the third line to the second line, etc.
memmove(ptr_to_first_line, ptr_to_second_line, ptr_to_end - ptr_to_second_line);
// Clear the last line so it appears empty
memset(ptr_to_last_line, 0, VGA_WIDTH * 2);
All you have to do after this is to place the cursor at the beginning of the last line.
#include <stdio.h>
#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
int getCharNum(int a) { return a / (8 * sizeof(char)); }
int getBitNum(int a) { return a % (8 * sizeof(char)); }
int fromCharNum(int a) { return a * 8 * sizeof(char); }
int get2DimI(int a) { return getCharNum(a) / 187500; }
int get2DimJ(int a) { return getCharNum(a) % 187500; }
void rle_compress(char *src, char *dst, int ls, int *ld) {
uint8_t t[129];
int i, j = 0, k = 0, keep;
char out[187500];
t[0] = src[j];
while (j++ < ls) {
t[1] = src[j];
if (t[0] != t[1]) {
i = 1;
if (j < ls)
do
t[++i] = src[++j];
while (j < ls && i < 128 && t[i] != t[i - 1]);
if ((keep = t[i] == t[i - 1]))
--i;
out[k++] = (char)i;
t[0] = t[i];
if (!keep)
continue;
}
i = 2;
do
t[1] = src[++j];
while (++i < 130 && t[0] == t[1]);
out[k++] = i + 125;
out[k++] = t[0];
t[0] = t[1];
}
ld = &k;
dst = out;
}
void rle_extract(char *src, char *dst, int ls) {
int i, j, l = 0, k = 0, max;
char out[187500];
j = 0;
while (k + 2 < ls) {
i = src[k++]; //segfault
j = src[k++];
max = i + (i < 128 ? 1 : -126);
while (max--)
out[l++] = j;
}
dst = out;
return 0;
}
int main(void) {
int32_t n = 0;
scanf("%d", &n);
int32_t a[n];
int32_t b[] = { -1, -1, -1 };
char **count;
count = (char**)malloc(1000 * sizeof(char*));
int count_l[] = { [999] = 0 };
for (int i = 0; i < 1000; ++i) {
count[i] = (char*)malloc(187500 * sizeof(char));
char *temp = NULL;
rle_compress(count[i], temp, 187500, &count_l[i]);
free(count[i]);
count[i] = temp;
}
for (int i = 0; i < n; i++)
scanf("%d", &a[i]);
for (int i = 0; i < n; i++) {
char *src = count[get2DimI(a[i]) / 187500];
char dst[187500];
rle_extract(src, dst, count_l[i / 187500]);
dst[get2DimJ(a[i])] ^= 1 << (getBitNum(a[i]));
rle_compress(dst, count[get2DimI(a[i]) / 187500], 187500, &count_l[i]);
}
int32_t mv = 187500000 / (8 * sizeof(char));
int j = 0;
for (int i = 0; i < mv; i++) {
char *src = count[i / 187500];
char dst[187500];
rle_extract(src, dst, count_l[i / 187500]);
int32_t x = dst[i % 187500];
if (x == 0)
continue;
for (int k = 0; k < 8 * sizeof(char); k++) {
if ((x >> (k)) & 1) {
b[j++] = fromCharNum(i) + k;
}
}
//free(dst);
}
int m1 = min(b[0], min(b[1], b[2])),
m3 = max(b[0], max(b[1], b[2])),
m2 = b[0] + b[1] + b[2] - m1 - m3;
printf("%d %d %d", m1, m2, m3);
for (int i = 0; i < 1000; ++i)
free(count[i]);
free(count);
return 0;
}
How to fix this code?
I'm trying to compress byte array (which should compress greatly as n should be <=1500000 and numbers are from 0 to 1.5*10^9), but code gives me segfault on all testing inputs which I've tried. Without compress everything worked like a charm, but needed a lot of memory (and limits are 64MiB).
The code is obscure but there are some major problems:
void rle_extract(char *src, char *dst, int ls) does not take the output buffer from its caller, nor does it return a pointer to it: dst = out; just updates the argument value, not the caller's variable passed as an argument. Furthermore return 0; from a void function is incorrect too.
in any case, rle_extract should not return its local out buffer because it is only defined during the execution of the function and is discarded as soon as the function returns.
You should either pass the buffer as an argument or allocate it locally and return the pointer to the caller.
There might be other problems, there is no explanation for what the code is supposed to do.
I am running the c code of Shannon-Fano compression algorithm. The program is compiling better but while executing, I get the segmentation fault (core dump) error. Similar questions have been already answered but I tried most of them but could not get sucess in resolving this error. please help me out.
The program code is:
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
/***********************************************/
int Compress(int* input, int* output, int inputSize);
int main(int argc, char *argv[])
{
char* str = "This is an example for Shannon–Fano coding";
printf("%s",str);
int* originalData = originalData = (int*)str;
int originalDataSize = strlen(str);
int* compressedData = (int*)malloc(originalDataSize * (101 / 100) + 384);
int compressedDataSize = Compress(originalData, compressedData, originalDataSize);
return 0;
}
typedef struct {
int* BytePointer;
int BitPosition;
} BitStream;
typedef struct {
int Symbol;
int Count;
int Code;
int Bits;
} Symbol;
void initBitStream(BitStream* stream, int* buffer)
{
stream->BytePointer = buffer;
stream->BitPosition = 0;
}
void writeBits(BitStream* stream, int x, int bits)
{
int* buffer = stream->BytePointer;
int bit = stream->BitPosition;
int mask = 1 << (bits - 1);
for (int count = 0; count < bits; ++count)
{
*buffer = (*buffer & (0xff ^ (1 << (7 - bit)))) + ((x & mask ? 1 : 0) << (7 - bit));
x <<= 1;
bit = (bit + 1) & 7;
if (!bit)
{
++buffer;
}
}
stream->BytePointer = buffer;
stream->BitPosition = bit;
}
void histogram(int* input, Symbol* sym, int size)
{
Symbol temp;
int i, swaps;
for (i = 0; i < 256; ++i)
{
sym[i].Symbol = i;
sym[i].Count = 0;
sym[i].Code = 0;
sym[i].Bits = 0;
}
for (i = size; i; --i)
{
sym[*input++].Count++;
}
do
{
swaps = 0;
for (i = 0; i < 255; ++i)
{
if (sym[i].Count < sym[i + 1].Count)
{
temp = sym[i];
sym[i] = sym[i + 1];
sym[i + 1] = temp;
swaps = 1;
}
}
} while (swaps);
}
void makeTree(Symbol* sym, BitStream* stream, int code, int bits, int first, int last)
{
int i, size, sizeA, sizeB, lastA, firstB;
if (first == last)
{
writeBits(stream, 1, 1);
writeBits(stream, sym[first].Symbol, 8);
sym[first].Code = code;
sym[first].Bits = bits;
return;
}
else
{
writeBits(stream, 0, 1);
}
size = 0;
for (i = first; i <= last; ++i)
{
size += sym[i].Count;
}
sizeA = 0;
for (i = first; sizeA < ((size + 1) >> 1) && i < last; ++i)
{
sizeA += sym[i].Count;
}
if (sizeA > 0)
{
writeBits(stream, 1, 1);
lastA = i - 1;
makeTree(sym, stream, (code << 1) + 0, bits + 1, first, lastA);
}
else
{
writeBits(stream, 0, 1);
}
sizeB = size - sizeA;
if (sizeB > 0)
{
writeBits(stream, 1, 1);
firstB = i;
makeTree(sym, stream, (code << 1) + 1, bits + 1, firstB, last);
}
else
{
writeBits(stream, 0, 1);
}
}
int Compress(int* input, int* output, int inputSize)
{
Symbol sym[256], temp;
BitStream stream;
int i, totalBytes, swaps, symbol, lastSymbol;
if (inputSize < 1)
return 0;
initBitStream(&stream, output);
histogram(input, sym, inputSize);
for (lastSymbol = 255; sym[lastSymbol].Count == 0; --lastSymbol);
if (lastSymbol == 0)
++lastSymbol;
makeTree(sym, &stream, 0, 0, 0, lastSymbol);
do
{
swaps = 0;
for (i = 0; i < 255; ++i)
{
if (sym[i].Symbol > sym[i + 1].Symbol)
{
temp = sym[i];
sym[i] = sym[i + 1];
sym[i + 1] = temp;
swaps = 1;
}
}
} while (swaps);
for (i = 0; i < inputSize; ++i)
{
symbol = input[i];
writeBits(&stream, sym[symbol].Code, sym[symbol].Bits);
}
totalBytes = (int)(stream.BytePointer - output);
if (stream.BitPosition > 0)
{
++totalBytes;
}
return totalBytes;
}
I created a header file called ofdm.h which includes all the function prototypes. Then I created a source file called ofdm.c, which includes the source code of all the functions declared in ofdm.h . After that I started coding in main.c, but when I run it I get the error: undefined reference to '(function name)'. I get this error for all my functions.
Below you can find the source code of all my three files.
ofdm.h
#ifndef OFDM_H_INCLUDED
#define OFDM_H_INCLUDED
typedef struct {
double real, img;
} Complex;
char** split(char *s, const char *delim);
void parseComplex(Complex *c, char *line);
void rbits(short* buf, int nbits);
void printbinary(short* buf, int len);
void printcomplex(Complex* buf, int len);
long bin2dec(short *bin, int len);
void dec2bin(long dec, short *bin, int len);
void binaryadd(short *bin1, short *bin2, short *erg, int len);
void leftshift(short *bin,short *erg,int shifts, int len);
void binarymult(short *bin1, short *bin2, short *erg, int len);
void binarypower(short *bin,short *erg,int power, int len);
void scrambler(short *seed, short *input, short *output, int len, int seedlen);
void encoder(short *input, short *output, int inputlen);
void interleaver(short *input, short *output, int N_CBPS,int N_BPSC);
void deinterleaver(short *input, short *output, int N_CBPS,int N_BPSC);
void fixed_point(short* input, int nbits);
void fixed_point_complex(Complex* input, int nbits);
void defixed_point(short* input, int nbits);
void BPSKmapping(short* input, short* output, int nbits);
void BPSKdemapping(short* input, short* output, int nbits);
void QPSKmapping(short* input, Complex* output, int nbits);
void QPSKdemapping(Complex* input, short* output, int nbits);
void IFFT_BPSK(short* input, Complex* output, Complex* twidder);
void IFFT_QPSK(Complex* input, Complex* output, Complex* twidder);
double uniform(double a, double b);
double gauss(double mean, int SNRdb);
void ChannelModel(Complex R[], Complex S[], int SNRdb);
#endif
ofdm.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "ofdm.h"
char** split(char* string, const char* delim)
{
char* p;
int i = 0;
char** array = malloc(strlen(string) * sizeof(char*));
p = strtok(string, delim);
while(p != NULL)
{
array[i] = malloc(sizeof(char));
array[i++] = p;
p = strtok(NULL, delim);
}
return array;
}
void parseComplex(Complex *cmplx, char *number)
{
char *copy = number;
if(strchr(copy, ' ') != NULL)
{
char **result = split(copy, " ");
cmplx->real = atof(*result++);
char *sign = *result++;
cmplx->img = atof(*result++);
if(sign[0] == '-')
cmplx->img = -(cmplx->img);
}
else if(strchr(copy, 'j') != NULL)
{
cmplx->real = 0;
cmplx->img = atof(copy);
}
else
{
cmplx->real = atof(copy);
cmplx->img = 0;
}
}
void rbits(short* buf, int nbits)
{
int i;
for(i = 0; i < nbits; i++)
buf[i] = (rand() % 2);
}
void printbinary(short* buf, int len)
{
int i;
for(i = 0; i < len; i++)
{
printf("%d\t", buf[i]);
}
printf("\n\n\n");
}
void printcomplex(Complex* buf, int len)
{
int i;
for(i = 0; i < len; i++)
{
printf("%.0lf %.0lf\t", buf[i].real, buf[i].img);
}
printf("\n\n");
}
long bin2dec(short *bin, int len)
{
long dec = 0;
int i;
for(i = 0;i < len;i++)
{
dec += bin[i]*pow(2.0,(double) (len - i -1));
}
return dec;
}
void dec2bin(long dec, short *bin, int len)
{
long temp = dec;
int i;
for(i = 0;i<len;i++)
{
bin[len - 1 - i] = temp % 2;
temp = temp/2;
}
}
void binaryadd(short *bin1, short *bin2, short *erg, int len)
{
int i;
short carry = 0;
short oldcarry = 0;
for(i = len - 1; i >= 0; i--)
{
if((bin1[i] + bin2[i] + oldcarry) > 1)
{
carry = 1;
}
else
{
carry = 0;
}
erg[i] = (bin1[i] + bin2[i] + oldcarry) % 2;
oldcarry = carry;
}
}
void leftshift(short *bin,short *erg,int shifts, int len)
{
int i;
for(i = 0;i < len - shifts;i++)
{
erg[i] = bin[i + shifts];
}
for(i = len - shifts;i < len;i++)
{
erg[i] = 0;
}
}
void binarymult(short *bin1, short *bin2, short *erg, int len)
{
int i;
short temp[len - 1];
for(i = 0;i < len;i++)
{
erg[i] = 0;
}
for(i = 0;i < len;i++)
{
if(bin2[i] == 1)
{
leftshift(bin1,temp,len - 1 - i,len);
binaryadd(temp,erg,erg,len);
}
}
}
void binarypower(short *bin,short *erg,int power, int len)
{
int i;
short temp[len - 1];
for(i = 0;i < len;i++)
{
temp[i] = 0;
}
temp[len - 1] = 1;
if(power > 1)
binarypower(bin,temp,power - 1,len);
binarymult(temp,bin,erg,len);
}
void scrambler(short *seed, short *input, short *output, int len, int seedlen)
{
int i;
short carry;
short sequence[len - 1];
for(i = 0; i < len; i++)
{
sequence[i] = (seed[0] + seed[3]) % 2;
carry = (seed[0] + seed[3]) % 2;
leftshift(seed,seed,1,seedlen);
seed[seedlen - 1] = carry;
output[i] = (sequence[i] + input[i]) % 2;
}
}
void encoder(short *input, short *output, int inputlen)
{
int i;
short SR[7] = {0,0,0,0,0,0,0};
short A;
short B;
for(i = 0; i < inputlen;i++)
{
leftshift(SR,SR,1,7);
SR[6] = input[i];
A = (SR[6] + SR[4] + SR[3] + SR[1] + SR[0]) % 2;
B = (SR[6] + SR[5] + SR[4] + SR[3] + SR[0]) % 2;
output[2*i] = A;
output[2*i + 1] = B;
}
}
/*
void decoder(short *input, short *output, int inputlen)
{
int i;
short SR[7] = {0}
short A;
short B;
short C1;
short C2;
for(i = 0; i < intputlen; i++)
{
leftshift(SR, SR, 1, 7)
SR[6] = input[i];
C1 = (SR[6] + SR[4] + SR[3] + SR[1] + SR[0]) / 2;
C2 = (SR[6] + SR[5] + SR[4] + SR[3] + SR[0]) / 2;
A = (SR[6] + SR[4] + SR[3] + SR[1] + SR[0]) - (2 * C1);
B = (SR[6] + SR[5] + SR[4] + SR[3] + SR[0]) - (2 * C2);
output[2*i] = A; // output[i/2] = A;
output[2*i + 1] = B; // output[i/2 + 1] = B;
}
}
*/
void interleaver(short *input, short *output, int N_CBPS,int N_BPSC)
{
int i;
int t;
int k;
int s;
short first_permutuation[N_CBPS - 1];
for (k = 0; k < N_CBPS; k++)
{
i = (N_CBPS/16)*(k % 16) + (k/16);
first_permutuation[i] = input[k];
}
s = fmax(N_BPSC/2,1);
for(i = 0; i < N_CBPS;i++)
{
t = s*(i/s) + (i + N_CBPS - ((16*i)/N_CBPS)) % s;
output[t] = first_permutuation[i];
}
}
void fixed_point(short* input, int nbits)
{
int i;
for(i = 0; i < nbits; i++)
{
if(input[i] < 0)
input[i] *= 32768;
else input[i] *= 32767;
}
}
void fixed_point_complex(Complex* input, int nbits)
{
int i;
for(i = 0; i < nbits; i++)
{
if(input[i].real == -1 || input[i].img == -1)
input[i] *= 32768;
else input[i] *= 32767;
}
}
void defixed_point(short* input, int nbits)
{
int i;
for(i = 0; i < nbits; i++)
{
if(input[i] < 0)
input[i] /= 32768;
else input[i] /= 32767;
}
}
void IFFT_BPSK(short* input, Complex* output, Complex* twidder)
{
int i, k;
for(i = 0; i < 64; i++)
{
for(k = 0; k < 64; k++)
{
output[i].real += (twidder[i][k].real * input[i]) / 64;
output[i].img += (twidder[i][k].img * input[i]) / 64;
}
}
}
void IFFT_QPSK(Complex* input, Complex* output, Complex* twidder)
{
int i, k;
for(i = 0; i < 64; i++)
{
for(k = 0; k < 64; k++)
{
output[i].real += (twidder[i][k].real * input[i].real) / 64;
output[i].img += (twidder[i][k].img * input[i].img) / 64;
}
}
}
void IFFT_QPSK2(Complex* input, Complex* output, Complex* twidder, int nbits)
{
int a, b, c, d, e, f, g, h, blocks;
int count1 = 7, count2 = 20, count3 = 28, count4 = 41;
int next = 0;
Complex ifft_qpsk_output[64];
blocks = nbits / 48;
for(a = 1; a <= blocks; a++)
{
// pilots
output[7].real = 32767;
output[21].real = 32767;
output[42].real = 32767;
output[56].real = -32768;
// some data
output[40].real = input[26 + (next * 48)].real;
output[40].img = input[26 + (next * 48)].img;
output[41].real = input[27 + (next * 48)].real;
output[41].img = input[27 + (next * 48)].img;
// zeroes
for(b = 28; b <= 39; b++)
output[b].real = 0;
// other data
for(c = 0; c <= 6; c++)
{
output[c].real = input[c + (next * 48)].real;
output[c].img = input[c + (next * 48)].img;
}
for(d = 8; d <= 20; d++)
{
output[d].real = input[count1++ + (next * 48)].real;
output[d].img = input[count1++ + (next * 48)].img;
}
for(e = 22; e <= 27; e++)
{
output[e].real = input[count2++ + (next * 48)].real;
output[e].img = input[count2++ + (next * 48)].img;
}
for(f = 43; f <= 55; f++)
{
output[f].real = input[count3++ + (next * 48)].real;
output[f].img = input[count3++ + (next * 48)].img;
}
for(h = 57; h <= 63; h++)
{
output[h].real = input[count4++ + (next * 48)].real;
output[h].img = input[count4++ + (next * 48)].img;
}
// IFFT function goes here
IFFT_QPSK(output, ifft_qpsk_output, twidder);
printcomplex(ifft_qpsk_output, 64);
next++;
}
}
void IFFT_BPSK2(short* input, short* output, Complex* twidder, int nbits)
{
int a, b, c, d, e, f, g, h, blocks;
int count1 = 7, count2 = 20, count3 = 28, count4 = 41;
int next = 0;
Complex ifft_bpsk_output[64];
blocks = nbits / 48;
for(a = 1; a <= blocks; a++)
{
// pilots
output[7] = 32767;
output[21] = 32767;
output[42] = 32767;
output[56] = -32768;
// some data
output[40] = input[26 + (next * 48)];
output[41] = input[27 + (next * 48)];
// zeroes
for(b = 28; b <= 39; b++)
output[b] = 0;
// other data
for(c = 0; c <= 6; c++)
output[c] = input[c + (next * 48)];
for(d = 8; d <= 20; d++)
output[d] = input[count1++ + (next * 48)];
for(e = 22; e <= 27; e++)
output[e] = input[count2++ + (next * 48)];
for(f = 43; f <= 55; f++)
output[f] = input[count3++ + (next * 48)];
for(h = 57; h <= 63; h++)
output[h] = input[count4++ + (next * 48)];
// IFFT function goes here
IFFT_BPSK(output, ifft_bpsk_output, twidder);
printcomplex(ifft_bpsk_output, 64);
next++;
}
}
void BPSKmapping(short* input, short* output, int nbits)
{
int i;
for(i = 0; i < nbits; i++)
{
if(input[i] == 0)
output[i] = -1;
else output[i] = 1;
}
}
void BPSKdemapping(short* input, short* output, int nbits)
{
int i;
for(i = 0; i < nbits; i++)
{
if(input[i] == -1)
output[i] == 0;
else output[i] == 1;
}
}
void QPSKmapping(short* input, Complex* output, int nbits)
{
int i;
for(i = 0; i < nbits; i += 2)
{
if(input[i] == 0 && input[i+1] == 0)
{
output[i].real = -1;
output[i+1].img = -1;
}
else if(input[i] == 0 && input[i+1] == 1)
{
output[i].real = -1;
output[i+1].img = 1;
}
else if(input[i] == 1 && input[i+1] == 0)
{
output[i].real = 1;
output[i+1].img = -1;
}
else
{
output[i].real = 1;
output[i+1].img = 1;
}
}
}
void QPSKdemapping(Complex* input, short* output, int nbits)
{
int i;
for(i = 0; i < nbits; i += 2)
{
if(input[i].real == -1 && input[i+1].img == -1)
{
output[i] = 0;
output[i+1] = 0;
}
else if(input[i].real == -1 && input[i+1].img == 1)
{
output[i] = 0;
output[i+1] = 1;
}
else if(input[i].real == 1 && input[i+1].img == -1)
{
output[i] = 1;
output[i+1] = 0;
}
else
{
output[i] = 1;
output[i+1] = 1;
}
}
}
//Channel Begin
double uniform(double a, double b)
{
double c;
double d;
static int firstcall = 1;
c = b - a;
if(firstcall == 1)
{
srand((unsigned int)time(NULL));
firstcall = 0;
}
d = a + (double)rand() / RAND_MAX * c;
return d;
}
double gauss(double mean, int SNRdb)
{
double dGaussNum;
double x = 0;
int i;
double sigma;
sigma = 1 / pow(10, (double)SNRdb / 10);
for(i = 0;i < 12; i ++)
{
x = x + uniform(0,1);
}
x = x - 6;
dGaussNum = mean + sqrt(sigma) * x;
return dGaussNum;
}
void ChannelModel(Complex R[], Complex S[], int SNRdb)
{
int i;
for (i=0;i<N+L;i++)
{
R[i].real = S[i].real + gauss(0, SNRdb);
R[i].img = S[i].img + gauss(0, SNRdb);
}
}
//Channel End
void deinterleaver(short *input, short *output, int N_CBPS,int N_BPSC)
{
int i;
int t;
int k;
int s;
short first_permutuation[N_CBPS - 1];
s = fmax(N_BPSC/2,1);
for (t = 0; t < N_CBPS; t++)
{
i = s*(t/s) + (t + ((16*t)/N_CBPS)) % s;
first_permutuation[i] = input[t];
}
for(i = 0; i < N_CBPS;i++)
{
k = 16*i - (N_CBPS - 1)*((16*i)/N_CBPS);
output[k] = first_permutuation[i];
}
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "ofdm.h"
int main(int argc, char *argv[])
{
short seed[8];
int bits, i, j, k;
char mode[5], line[1024];
/* Complex twidder[64][64];
FILE *file = fopen("twidder_factor.txt", "r");
i = 0;
while(fgets(line, sizeof(line), file ) != NULL)
{
k = j = 0;
char **result = split(line, "\t");
while(result[k] != NULL)
{
parseComplex(&twidder[i][j], result[k++]);
j++;
}
i++;
}
*/
printf("How many bits do you want to transmit?: ");
scanf("%d", &bits);
short* start_input;
short* scrambler_output;
short* encoder_output;
short* interleaver_output;
short* bpsk_mapper_output;
short* ifft_bpsk_input[64];
Complex* qpsk_mapper_output;
Complex ifft_qpsk_input[64];
start_input = malloc(sizeof(short) * bits);
scrambler_output = malloc(sizeof(short) * bits);
encoder_output = malloc(sizeof(short) * (bits * 2));
interleaver_output = malloc(sizeof(short) * (bits * 2));
bpsk_mapper_output = malloc(sizeof(short) * (bits * 2));
qpsk_mapper_output = malloc(sizeof(Complex) * (bits * 2));
if(qpsk_mapper_output == NULL)
{
fprintf(stderr, "Couldn't allocate that much memory!\n");
return 1;
}
srand(time(NULL));
rbits(seed, 8);
rbits(start_input, bits);
printf("Which modulation type to you want to use? (type BPSK or QPSK): ");
scanf("%s", mode);
if((strcmp(mode, "BPSK") == 0) || (strcmp(mode, "bpsk") == 0))
{
printf("\nSelected modulation type: BPSK\n\n\n");
printf("SCRAMBLER OUTPUT:\n\n");
scrambler(seed, start_input, scrambler_output, bits, 8);
printbinary(scrambler_output, bits);
printf("ENCODER OUTPUT:\n\n");
encoder(scrambler_output, encoder_output, bits);
printbinary(encoder_output, bits*2);
printf("INTERLEAVER OUTPUT:\n\n");
interleaver(encoder_output, interleaver_output, bits, 1);
printbinary(interleaver_output, bits*2);
printf("MAPPER OUTPUT:\n\n");
BPSKmapping(interleaver_output, bpsk_mapper_output, bits*2);
printbinary(bpsk_mapper_output, bits*2);
printf("FIXED-POINT OUTPUT:\n\n");
fixed_point(bpsk_mapper_output, bits*2);
printbinary(bpsk_mapper_output, bits*2);
/*
printf("IFFT OUTPUT:\n\n");
IFFT_BPSK(bpsk_mapper_output, ifft_bpsk_input, twidder, bits*2)
defixed_point(bpsk_mapper_output, bits*2);
printbinary(bpsk_mapper_output, bits*2);
*/ }
else if((strcmp(mode, "QPSK") == 0) || (strcmp(mode, "qpsk") == 0))
{
printf("\nSelected modulation type: QPSK\n\n\n");
printf("SCRAMBLER OUTPUT:\n\n");
scrambler(seed, start_input, scrambler_output, bits, 8);
printbinary(scrambler_output, bits);
printf("ENCODER OUTPUT:\n\n");
encoder(scrambler_output, encoder_output, bits);
printbinary(encoder_output, bits*2);
printf("INTERLEAVER OUTPUT:\n\n");
interleaver(encoder_output, interleaver_output, bits, 2);
printbinary(interleaver_output, bits*2);
printf("MAPPER OUTPUT:\n\n");
QPSKmapping(interleaver_output, qpsk_mapper_output, bits*2);
printcomplex(qpsk_mapper_output, bits*2);
/*
printf("FIXED-POINT OUTPUT:\n\n");
fixed_point_complex(qpsk_mapper_output, bits*2);
printcomplex(qpsk_mapper_output, bits*2);
printf("IFFT OUTPUT:\n\n");
IFFT_QPSK(qpsk_mapper_output, ifft_qpsk_input, twidder, bits*2)
defixed_point(qpsk_mapper_output, bits*2);
printbinary(qpsk_mapper_output, bits*2);
*/ }
else
{
printf("That's an invalid modulation type!\n");
free(start_input);
free(scrambler_output);
free(encoder_output);
free(interleaver_output);
free(bpsk_mapper_output);
free(qpsk_mapper_output);
return 0;
}
free(start_input);
free(scrambler_output);
free(encoder_output);
free(interleaver_output);
free(bpsk_mapper_output);
free(qpsk_mapper_output);
system("PAUSE");
return 0;
}
If you could help me to solve this problem I would be glad. I think there is some kind of linking problem between my library and the main source file.
Thanks in advance.
I guess you are compiling only main.c. You should also include ofdm.c.
$ gcc -Wall main.c ofdm.c -o output
Since you get this error for all your functions, it can't be a typo. My best guess is that you are not linking the two files.
If using gcc, this is done in the following way:
gcc -o main.o -c main.c
gcc -o ofdm.o -c ofdm.c
gcc -o program main.o ofdm.o
Note that -c means it should compile, but not try to create an executable. This means that linking is not done.
Once both files are compiled, you would then link them together.
When you're learning new things, it helps to learn one new thing at a time. Put your source code into version control, then simplify it to get a clean compile.
main.c
#include "ofdm.h"
int main(int argc, char *argv[])
{
return 0;
}
ofdm.c
#include "ofdm.h"
void leftshift(short *bin,short *erg,int shifts, int len)
{
int i;
for(i = 0;i < len - shifts;i++)
{
erg[i] = bin[i + shifts];
}
for(i = len - shifts;i < len;i++)
{
erg[i] = 0;
}
}
ofdm.h
#ifndef OFDM_H_INCLUDED
#define OFDM_H_INCLUDED
void leftshift(short *bin,short *erg,int shifts, int len);
#endif
Then, to compile with gcc . . .
$ gcc -Wall -c ofdm.c
$ gcc -Wall -c main.c
$ gcc -Wall *.o
That should give you a program that does nothing, successfully. Now you can start to build it up again from your version-controlled source.
Add one function at a time.
Edit it to get a clean compile.
Edit it to pass sane tests.
I came here with the same issue while using ESP-IDF as a beginner. What solved this for me was that I just forgot to add all the necessary sources in the idf_component_register function call.