Compare commits

..

7 Commits

Author SHA1 Message Date
Abdelrahman Said
e4893c150b Add split_mix_64 utility 2024-03-22 12:37:46 +00:00
Abdelrahman Said
05b9a22174 Add xoshiro256p generator 2024-03-22 12:21:03 +00:00
Abdelrahman Said
b8ce449e99 Update compile script 2024-03-22 12:20:49 +00:00
Abdelrahman Said
a6f0bf93d9 Create single state struct and add utility function for initialising it 2024-03-22 12:06:34 +00:00
Abdelrahman Said
80aeb3fc92 Update compile script to run the generators 2024-03-22 12:06:16 +00:00
Abdelrahman Said
f4afa5d7ea Add xoshiro256** generator 2024-03-22 11:52:56 +00:00
Abdelrahman Said
2708825924 Add Image struct 2024-03-22 11:52:40 +00:00
4 changed files with 136 additions and 32 deletions

View File

@@ -6,4 +6,12 @@ CFLAGS="-g -Wall -Werror "
XORSHIFT_SRC="xorshift.c ppm.c" XORSHIFT_SRC="xorshift.c ppm.c"
XORSHIFT_OUT=xorshift XORSHIFT_OUT=xorshift
echo "Cleaning outputs dir..."
rm -rf "./outputs/*"
echo -e "\nBuilding xorshift generators..."
(set -x ; $CC $CFLAGS $XORSHIFT_SRC -o $XORSHIFT_OUT) (set -x ; $CC $CFLAGS $XORSHIFT_SRC -o $XORSHIFT_OUT)
echo -e "\nTesting xorshift generators..."
./xorshift
echo "Generated"

10
ppm.c
View File

@@ -3,21 +3,21 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
void write_p6_ppm(const char *filepath, u64 width, u64 height, Pixel *data) { void write_p6_ppm(const char *filepath, Image *img) {
FILE *fp = fopen(filepath, "wb"); FILE *fp = fopen(filepath, "wb");
if (!fp) { if (!fp) {
return; return;
} }
char header[1024] = {0}; char header[1024] = {0};
sprintf(header, "P6\n%llu %llu\n255\n", (unsigned long long)width, sprintf(header, "P6\n%llu %llu\n255\n", (unsigned long long)img->width,
(unsigned long long)height); (unsigned long long)img->height);
u64 length = strlen(header); u64 length = strlen(header);
fwrite(&header, length, 1, fp); fwrite(&header, length, 1, fp);
u64 pixel_count = width * height; u64 pixel_count = img->width * img->height;
fwrite(data, sizeof(Pixel), pixel_count, fp); fwrite(img->data, sizeof(Pixel), pixel_count, fp);
fclose(fp); fclose(fp);
} }

8
ppm.h
View File

@@ -6,4 +6,10 @@ typedef struct {
u8 b; u8 b;
} Pixel; } Pixel;
void write_p6_ppm(const char *filepath, u64 width, u64 height, Pixel *data); typedef struct {
u64 width;
u64 height;
Pixel *data;
} Image;
void write_p6_ppm(const char *filepath, Image *img);

View File

@@ -4,15 +4,29 @@
#include <stdlib.h> #include <stdlib.h>
#include <time.h> #include <time.h>
typedef struct {
u64 seed;
} SplitMix64State;
typedef struct { typedef struct {
u64 x; u64 x;
u64 y; u64 y;
u64 z; u64 z;
u64 w; u64 w;
} XORShift256; } XOR256State;
void test_xorshift_256(Pixel *data, u64 w, u64 h); typedef u64(RandGenFunc)(void *s);
u64 xorshift_256_generate(XORShift256 *state);
void test_xorshift_256(Image *img);
u64 xorshift_256_generate(void *s);
void test_xoshiro_256ss(Image *img);
u64 xoshiro_256ss_generate(void *s);
void test_xoshiro_256p(Image *img);
u64 xoshiro_256p_generate(void *s);
u64 rol64(u64 x, u64 bits);
XOR256State init_xor_256_state();
void write_image_data(Image *img, RandGenFunc *gen_rand, void *s);
u64 split_mix_64(SplitMix64State *state);
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
struct timespec ts = {0}; struct timespec ts = {0};
@@ -25,36 +39,28 @@ int main(int argc, char *argv[]) {
u64 length = w * h; u64 length = w * h;
Pixel data[length]; Pixel data[length];
test_xorshift_256(data, w, h); Image img = {
.width = w,
.height = h,
.data = data,
};
write_p6_ppm("./outputs/xorshift_256.ppm", w, h, data); test_xorshift_256(&img);
test_xoshiro_256ss(&img);
test_xoshiro_256p(&img);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
void test_xorshift_256(Pixel *data, u64 w, u64 h) { void test_xorshift_256(Image *img) {
XORShift256 state = { XOR256State state = init_xor_256_state();
.x = lrand48(), write_image_data(img, xorshift_256_generate, (void *)&state);
.y = lrand48(), write_p6_ppm("./outputs/xorshift256.ppm", img);
.z = lrand48(),
.w = lrand48(),
};
for (u64 y = 0; y < h; ++y) {
for (u64 x = 0; x < w; ++x) {
u64 i = y * w + x;
u8 pixel = xorshift_256_generate(&state) % UINT8_MAX;
data[i] = (Pixel){
.r = pixel,
.g = pixel,
.b = pixel,
};
}
}
} }
u64 xorshift_256_generate(XORShift256 *state) { u64 xorshift_256_generate(void *s) {
XOR256State *state = (XOR256State *)s;
u64 t = state->x ^ (state->x << 11); u64 t = state->x ^ (state->x << 11);
state->x = state->y; state->x = state->y;
@@ -64,3 +70,87 @@ u64 xorshift_256_generate(XORShift256 *state) {
return state->w; return state->w;
} }
void test_xoshiro_256ss(Image *img) {
XOR256State state = init_xor_256_state();
write_image_data(img, xoshiro_256ss_generate, (void *)&state);
write_p6_ppm("./outputs/xoshiro256ss.ppm", img);
}
u64 xoshiro_256ss_generate(void *s) {
XOR256State *state = (XOR256State *)s;
const u64 result = rol64(state->z * 5, 7) * 9;
const u64 t = state->z << 17;
state->y ^= state->w;
state->x ^= state->z;
state->z ^= state->y;
state->w ^= state->x;
state->y ^= t;
state->x = rol64(state->x, 45);
return result;
}
void test_xoshiro_256p(Image *img) {
XOR256State state = init_xor_256_state();
write_image_data(img, xoshiro_256p_generate, (void *)&state);
write_p6_ppm("./outputs/xoshiro256p.ppm", img);
}
u64 xoshiro_256p_generate(void *s) {
XOR256State *state = (XOR256State *)s;
const u64 result = state->w + state->x;
const u64 t = state->z << 17;
state->y ^= state->w;
state->x ^= state->z;
state->z ^= state->y;
state->w ^= state->x;
state->y ^= t;
state->x = rol64(state->x, 45);
return result;
}
u64 rol64(u64 x, u64 bits) { return (x << bits) | (x >> (64 - bits)); }
XOR256State init_xor_256_state() {
SplitMix64State sm64 = {.seed = lrand48()};
return (XOR256State){
.x = split_mix_64(&sm64),
.y = split_mix_64(&sm64),
.z = split_mix_64(&sm64),
.w = split_mix_64(&sm64),
};
}
void write_image_data(Image *img, RandGenFunc *gen_rand, void *s) {
for (u64 y = 0; y < img->height; ++y) {
for (u64 x = 0; x < img->width; ++x) {
u64 i = y * img->width + x;
u8 pixel = gen_rand(s) % UINT8_MAX;
img->data[i] = (Pixel){
.r = pixel,
.g = pixel,
.b = pixel,
};
}
}
}
u64 split_mix_64(SplitMix64State *state) {
state->seed += 0x9E3779B97f4A7C15;
u64 result = state->seed;
result = (result ^ (result >> 30)) * 0xBF58476D1CE4E5B9;
result = (result ^ (result >> 27)) * 0x94D049BB133111EB;
return result ^ (result >> 31);
}