From f0ee2353fc91ab99088cacbc58bd62fc6605c7d8 Mon Sep 17 00:00:00 2001 From: Sam Date: Fri, 5 Feb 2021 15:56:47 +0000 Subject: [PATCH 1/8] Initial test version using faster xorshift RNG. --- build-clang.sh | 2 + .../c/java_2_times_faster_than_c_xorshift.c | 135 ++++++++++++++++++ src/main/c/xorshift_rng.c | 35 +++++ .../Java2TimesFasterThanCXORShift.java | 110 ++++++++++++++ .../com/xemantic/test/howfast/XORShift.java | 60 ++++++++ 5 files changed, 342 insertions(+) create mode 100644 src/main/c/java_2_times_faster_than_c_xorshift.c create mode 100644 src/main/c/xorshift_rng.c create mode 100644 src/main/java/com/xemantic/test/howfast/Java2TimesFasterThanCXORShift.java create mode 100644 src/main/java/com/xemantic/test/howfast/XORShift.java diff --git a/build-clang.sh b/build-clang.sh index 0950caa..492cace 100755 --- a/build-clang.sh +++ b/build-clang.sh @@ -2,4 +2,6 @@ mkdir -p build/clang gcc -O3 -o build/clang/almost_pseudo_random src/main/c/almost_pseudo_random.c -lm +gcc -O3 -o build/clang/xorshift_rng src/main/c/xorshift_rng.c gcc -O3 -o build/clang/java_2_times_faster_than_c src/main/c/java_2_times_faster_than_c.c -lm +gcc -O3 -o build/clang/java_2_times_faster_than_c_xorshift src/main/c/java_2_times_faster_than_c_xorshift.c -lm diff --git a/src/main/c/java_2_times_faster_than_c_xorshift.c b/src/main/c/java_2_times_faster_than_c_xorshift.c new file mode 100644 index 0000000..6703138 --- /dev/null +++ b/src/main/c/java_2_times_faster_than_c_xorshift.c @@ -0,0 +1,135 @@ +/* + * Copyright 2021 Kazimierz Pogoda + * + * This file is part of java-2-times-faster-than-c. + * + * java-2-times-faster-than-c is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * java-2-times-faster-than-c is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with shader-web-background. If not, see . + */ + +#include +#include +#include +#include + +const int MAX_PAYLOAD_SIZE = 50; +const int INITIAL_NODE_COUNT = 10000; +const long MUTATION_COUNT = 1000000L; +const int MAX_MUTATION_SIZE = 200; + +struct xorshift64s_state { + uint64_t a; +}; + +double xorshift64s(struct xorshift64s_state *state) { + uint64_t x = state->a; /* The state must be seeded with a nonzero value. */ + x ^= x >> 12; // a + x ^= x << 25; // b + x ^= x >> 27; // c + state->a = x; + uint64_t rand_val = x * UINT64_C(0x2545F4914F6CDD1D); + + // mix to a double + uint32_t a = rand_val >> 32; + uint32_t b = rand_val & 0xFFFFFFFF; + return ((a >> 5) * 67108864.0 + (b >> 6)) * (1.0 / 9007199254740991.0); +} + +typedef struct Node Node; + +struct Node { + long id; + int size; + char *payload; + Node *previous; + Node *next; +} NodeDef; + +Node *new_node(long id, struct xorshift64s_state * rng_state) { + int size = (int) (xorshift64s(rng_state) * MAX_PAYLOAD_SIZE); + int charId = (char) id; + Node *node = malloc(sizeof(NodeDef)); + node->id = id; + node->size = size; + char *payload = malloc(sizeof(char) * size); + for (int i = 0; i < size; i++) { + payload[i] = (char) i; + } + node->payload = payload; + return node; +} + +void join(Node *alfa, Node *beta) { + alfa->previous = beta; + alfa->next = beta; + beta->previous = alfa; + beta->next = alfa; +} + +void delete(Node *node) { + node->next->previous = node->previous; + node->previous->next = node->next; + free(node->payload); + free(node); +} + +void insert(Node *previous, Node *node) { + node->next = previous->next; + node->previous = previous; + previous->next->previous = node; + previous->next = node; +} + +int main() { + long node_id = 0; + struct xorshift64s_state rng_state = { + .a = 42, + }; + Node *head = new_node(node_id++, &rng_state); + join(head, new_node(node_id++, &rng_state)); + for (int i = 2; i < INITIAL_NODE_COUNT; i++) { + insert(head, new_node(node_id++, &rng_state)); + } + long node_count = INITIAL_NODE_COUNT; + for (long i = 0; i < MUTATION_COUNT; i++) { + int delete_count = (int) (xorshift64s(&rng_state) * (double) MAX_MUTATION_SIZE); + if (delete_count > (node_count - 2)) { + delete_count = (int) node_count - 2; + } + for (int j = 0; j < delete_count; j++) { + Node *to_delete = head; + head = head->previous; + delete(to_delete); + } + node_count -= delete_count; + int insert_count = (int) (xorshift64s(&rng_state) * (double) MAX_MUTATION_SIZE); + for (int j = 0; j < insert_count; j++) { + insert(head, new_node(node_id++, &rng_state)); + head = head->next; + } + node_count += insert_count; + } + long checksum = 0; + Node *traveler = head; + do { + checksum += traveler->id + traveler->size; + if (traveler->size > 0) { + checksum += traveler->payload[0]; + checksum += traveler->payload[traveler->size - 1]; + } + } while ( + (traveler = traveler->next) != head + ); + printf("node count: %lu\n", node_count); + printf("checksum: %lu\n", checksum); +} diff --git a/src/main/c/xorshift_rng.c b/src/main/c/xorshift_rng.c new file mode 100644 index 0000000..9675aed --- /dev/null +++ b/src/main/c/xorshift_rng.c @@ -0,0 +1,35 @@ +#include +#include + +const long ITERATION_COUNT = 1000000000L; + +struct xorshift64s_state { + uint64_t a; +}; + +double xorshift64s(struct xorshift64s_state *state) { + uint64_t x = state->a; /* The state must be seeded with a nonzero value. */ + x ^= x >> 12; // a + x ^= x << 25; // b + x ^= x >> 27; // c + state->a = x; + uint64_t rand_val = x * UINT64_C(0x2545F4914F6CDD1D); + + // mix to a double + uint32_t a = rand_val >> 32; + uint32_t b = rand_val & 0xFFFFFFFF; + + return ((a >> 5) * 67108864.0 + (b >> 6)) * (1.0 / 9007199254740991.0); +} + +int main(void) { + struct xorshift64s_state rng_state = { + .a = 42 + }; + + double checksum = 0; + for (long i = 0; i < ITERATION_COUNT; i++) { + checksum += xorshift64s(&rng_state); + } + printf("checksum: %f\n", checksum); +} diff --git a/src/main/java/com/xemantic/test/howfast/Java2TimesFasterThanCXORShift.java b/src/main/java/com/xemantic/test/howfast/Java2TimesFasterThanCXORShift.java new file mode 100644 index 0000000..a6fce28 --- /dev/null +++ b/src/main/java/com/xemantic/test/howfast/Java2TimesFasterThanCXORShift.java @@ -0,0 +1,110 @@ +/* + * Copyright 2021 Kazimierz Pogoda + * + * This file is part of java-2-times-faster-than-c. + * + * java-2-times-faster-than-c is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * java-2-times-faster-than-c is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with shader-web-background. If not, see . + */ + +package com.xemantic.test.howfast; + +public class Java2TimesFasterThanCXORShift { + + private static final int MAX_PAYLOAD_SIZE = 50; + private static final int INITIAL_NODE_COUNT = 10000; + private static final long MUTATION_COUNT = 1000000L; + private static final int MAX_MUTATION_SIZE = 200; + + private static class Node { + + private long id; + private byte[] payload; + private Node previous; + private Node next; + + private Node(long id, xorshift64s_rng rng) { + this.id = id; + int size = (int) (rng.get_rand() * (double) MAX_PAYLOAD_SIZE); + byte[] data = new byte[size]; + for (int i = 0; i < size; i++) { + data[i] = (byte) i; + } + payload = data; + } + + void join(Node node) { + previous = node; + next = node; + node.previous = this; + node.next = this; + } + + void delete() { + next.previous = previous; + previous.next = next; + // free memory (which is explicit in C and implicit in Java) + } + + void insert(Node node) { + node.next = next; + node.previous = this; + next.previous = node; + next = node; + } + + } + + public static void main(String[] args) { + long nodeId = 0; + xorshift64s_rng rng = new xorshift64s_rng(42); + Node head = new Node(nodeId++, rng); + head.join(new Node(nodeId++, rng)); + for (int i = 2; i < INITIAL_NODE_COUNT; i++) { + head.insert(new Node(nodeId++, rng)); + } + long nodeCount = INITIAL_NODE_COUNT; + for (long i = 0; i < MUTATION_COUNT; i++) { + int deleteCount = (int) (rng.get_rand() * (double) MAX_MUTATION_SIZE); + if (deleteCount > (nodeCount - 2)) { + deleteCount = (int) nodeCount - 2; + } + for (int j = 0; j < deleteCount; j++) { + Node toDelete = head; + head = head.previous; + toDelete.delete(); + } + nodeCount -= deleteCount; + int insertCount = (int) (rng.get_rand() * (double) MAX_MUTATION_SIZE); + for (int j = 0; j < insertCount; j++) { + head.insert(new Node(nodeId++, rng)); + head = head.next; + } + nodeCount += insertCount; + } + long checksum = 0; + Node traveler = head; + do { + checksum += traveler.id + traveler.payload.length; + if (traveler.payload.length > 0) { + checksum += traveler.payload[0]; + checksum += traveler.payload[traveler.payload.length - 1]; + } + } while ( + (traveler = traveler.next) != head + ); + System.out.println("node count: " + nodeCount); + System.out.println("checksum: " + checksum); + } + +} diff --git a/src/main/java/com/xemantic/test/howfast/XORShift.java b/src/main/java/com/xemantic/test/howfast/XORShift.java new file mode 100644 index 0000000..347292e --- /dev/null +++ b/src/main/java/com/xemantic/test/howfast/XORShift.java @@ -0,0 +1,60 @@ +/* + * Copyright 2021 Kazimierz Pogoda + * + * This file is part of java-2-times-faster-than-c. + * + * java-2-times-faster-than-c is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * java-2-times-faster-than-c is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with shader-web-background. If not, see . + */ + +package com.xemantic.test.howfast; + +class xorshift64s_rng { + private long state; + + xorshift64s_rng(long state) { + this.state = state; + } + + double get_rand() { + long x = this.state; /* The state must be seeded with a nonzero value. */ + x ^= x >>> 12; // a + x ^= x << 25; // b + x ^= x >>> 27; // c + this.state = x; + + long rand_val = x * 0x2545F4914F6CDD1DL; + + // mix to a double + long a = (rand_val >>> 32) & 0xFFFFFFFFL; + long b = rand_val & 0xFFFFFFFFL; + + return ((a >> 5) * 67108864.0 + (b >> 6)) * (1.0 / 9007199254740991.0); + } +} + +public class XORShift { + + private static final long ITERATION_COUNT = 1000000000L; + + public static void main(String[] args) { + xorshift64s_rng rng = new xorshift64s_rng(42); + + double checksum = 0; + for (long i = 0; i < ITERATION_COUNT; i++) { + checksum += rng.get_rand(); + } + System.out.println("checksum: " + checksum); + } + +} From 452bf0c2823ddadca5c88fed3715f70ea16303e9 Mon Sep 17 00:00:00 2001 From: Sam Date: Fri, 5 Feb 2021 16:46:00 +0000 Subject: [PATCH 2/8] Updated licenses on my files and added rust xorshift versions. --- build-clang.sh | 8 +- build-gcc.sh | 8 +- build-rs.sh | 3 + src/main/c/xorshift_rng.c | 19 ++++ src/main/rust/rng.rs | 43 +++++++++ src/main/rust/rust_raw_xorshift.rs | 119 +++++++++++++++++++++++++ src/main/rust/rust_safer_xorshift.rs | 125 +++++++++++++++++++++++++++ src/main/rust/xorshift_rng.rs | 15 ++++ 8 files changed, 333 insertions(+), 7 deletions(-) create mode 100644 src/main/rust/rng.rs create mode 100644 src/main/rust/rust_raw_xorshift.rs create mode 100644 src/main/rust/rust_safer_xorshift.rs create mode 100644 src/main/rust/xorshift_rng.rs diff --git a/build-clang.sh b/build-clang.sh index 492cace..ca38ff7 100755 --- a/build-clang.sh +++ b/build-clang.sh @@ -1,7 +1,7 @@ #!/usr/bin/env sh mkdir -p build/clang -gcc -O3 -o build/clang/almost_pseudo_random src/main/c/almost_pseudo_random.c -lm -gcc -O3 -o build/clang/xorshift_rng src/main/c/xorshift_rng.c -gcc -O3 -o build/clang/java_2_times_faster_than_c src/main/c/java_2_times_faster_than_c.c -lm -gcc -O3 -o build/clang/java_2_times_faster_than_c_xorshift src/main/c/java_2_times_faster_than_c_xorshift.c -lm +clang -O3 -o build/clang/almost_pseudo_random src/main/c/almost_pseudo_random.c -lm +clang -O3 -o build/clang/java_2_times_faster_than_c src/main/c/java_2_times_faster_than_c.c -lm +clang -O3 -o build/clang/xorshift_rng src/main/c/xorshift_rng.c +clang -O3 -o build/clang/java_2_times_faster_than_c_xorshift src/main/c/java_2_times_faster_than_c_xorshift.c diff --git a/build-gcc.sh b/build-gcc.sh index 9f24680..2343e79 100755 --- a/build-gcc.sh +++ b/build-gcc.sh @@ -1,5 +1,7 @@ #!/usr/bin/env sh -mkdir -p build/gcc -gcc -O3 -o build/gcc/almost_pseudo_random src/main/c/almost_pseudo_random.c -lm -gcc -O3 -o build/gcc/java_2_times_faster_than_c src/main/c/java_2_times_faster_than_c.c -lm +mkdir -p build/clang +gcc -O3 -o build/clang/almost_pseudo_random src/main/c/almost_pseudo_random.c -lm +gcc -O3 -o build/clang/java_2_times_faster_than_c src/main/c/java_2_times_faster_than_c.c -lm +gcc -O3 -o build/clang/xorshift_rng src/main/c/xorshift_rng.c +gcc -O3 -o build/clang/java_2_times_faster_than_c_xorshift src/main/c/java_2_times_faster_than_c_xorshift.c diff --git a/build-rs.sh b/build-rs.sh index 1612307..6b252d6 100755 --- a/build-rs.sh +++ b/build-rs.sh @@ -2,5 +2,8 @@ mkdir -p build/rust rustc -O -o build/rust/almost_pseudo_random src/main/rust/almost_pseudo_random.rs +rustc -O -o build/rust/xorshift_rng src/main/rust/xorshift_rng.rs rustc -O -o build/rust/rust_safer src/main/rust/rust_safer.rs +rustc -O -o build/rust/rust_safer_xorshift src/main/rust/rust_safer_xorshift.rs +rustc -O -o build/rust/rust_raw_xorshift src/main/rust/rust_raw_xorshift.rs rustc -O -o build/rust/rust_raw src/main/rust/rust_raw.rs diff --git a/src/main/c/xorshift_rng.c b/src/main/c/xorshift_rng.c index 9675aed..3372d57 100644 --- a/src/main/c/xorshift_rng.c +++ b/src/main/c/xorshift_rng.c @@ -1,3 +1,22 @@ +/* + * Copyright 2021 Sam Leonard + * + * This file is part of java-2-times-faster-than-c. + * + * java-2-times-faster-than-c is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * java-2-times-faster-than-c is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with shader-web-background. If not, see . + */ + #include #include diff --git a/src/main/rust/rng.rs b/src/main/rust/rng.rs new file mode 100644 index 0000000..c86f29c --- /dev/null +++ b/src/main/rust/rng.rs @@ -0,0 +1,43 @@ +/* + * Copyright 2021 Sam Leonard + * + * This file is part of java-2-times-faster-than-c. + * + * java-2-times-faster-than-c is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * java-2-times-faster-than-c is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with shader-web-background. If not, see . + */ + +pub struct Xorshift64sRng { + a: u64 +} + +impl Xorshift64sRng { + pub fn new(a: u64) -> Self { + Self { a } + } + + pub fn get_rand(&mut self) -> f64 { + let mut x: u64 = self.a; /* The state must be seeded with a nonzero value. */ + x ^= x >> 12; // a + x ^= x << 25; // b + x ^= x >> 27; // c + self.a = x; + let rand_val: u64 = x * 0x2545F4914F6CDD1D_u64; + + // mix to a double + let a: u32 = (rand_val >> 32) as u32; + let b: u32 = (rand_val & 0xFFFFFFFF_u64) as u32; + + ((a >> 5) as f64 * 67108864.0 + (b >> 6) as f64) * (1.0 / 9007199254740991.0) + } +} diff --git a/src/main/rust/rust_raw_xorshift.rs b/src/main/rust/rust_raw_xorshift.rs new file mode 100644 index 0000000..6b23cc3 --- /dev/null +++ b/src/main/rust/rust_raw_xorshift.rs @@ -0,0 +1,119 @@ +/* + * Copyright 2021 Sam Leonard + * + * This file is part of java-2-times-faster-than-c. + * + * java-2-times-faster-than-c is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * java-2-times-faster-than-c is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with shader-web-background. If not, see . + */ + +mod rng; +use rng::Xorshift64sRng; + +use std::ptr; + +const MAX_PAYLOAD_SIZE: i32 = 50; +const INITIAL_NODE_COUNT: i32 = 10000; +const MUTATION_COUNT: i64 = 1000000; +const MAX_MUTATION_SIZE: i32 = 200; + +struct Node { + id: i64, + payload: Vec, + next: NodePointer, + previous: NodePointer, +} + +type NodePointer = *mut Node; + +fn main() { + let mut node_id: i64 = 0; + let mut rng = Xorshift64sRng::new(42); + + let mut head = Node::new(node_id, &mut rng); node_id += 1; + + // hell yeah who needs safety when we have pointers, YEE HAWWW + unsafe { + Node::join(head, Node::new(node_id, &mut rng)); node_id += 1; + for _ in 2..INITIAL_NODE_COUNT { + Node::insert(head, Node::new(node_id, &mut rng)); node_id += 1; + } + let mut node_count: i64 = INITIAL_NODE_COUNT as i64; + for _ in 0..MUTATION_COUNT { + let mut delete_count = (rng.get_rand() * MAX_MUTATION_SIZE as f64) as i32; + if delete_count > (node_count - 2) as i32 { + delete_count = (node_count - 2) as i32; + } + for _ in 0..delete_count { + let to_delete = head; + head = (*head).previous; + Node::delete(to_delete); + } + node_count -= delete_count as i64; + let insert_count = (rng.get_rand() * MAX_MUTATION_SIZE as f64) as i32; + for _ in 0..insert_count { + Node::insert(head, Node::new(node_id, &mut rng)); node_id += 1; + head = (*head).next; + } + node_count += insert_count as i64; + } + let mut checksum: i64 = 0; + let mut traveler = head; + loop { + checksum += (*traveler).id as i64 + (*traveler).payload.len() as i64; + if let Some(val) = (*traveler).payload.first() { + checksum += *val as i64; + } + if let Some(val) = (*traveler).payload.last() { + checksum += *val as i64; + } + traveler = (*traveler).next; + if traveler == head { break }; + } + println!("node count: {}", node_count); + println!("checksum: {}", checksum); + } +} + +impl Node { + fn new(id: i64, rng: &mut Xorshift64sRng) -> NodePointer { + Box::into_raw(Box::new(Self{ + id, + payload: (0..(rng.get_rand() * MAX_PAYLOAD_SIZE as f64) as i8).collect(), + next: ptr::null_mut(), + previous: ptr::null_mut(), + })) + } + + unsafe fn join(alfa: NodePointer, beta: NodePointer) { + (*alfa).previous = beta; + (*alfa).next = beta; + (*beta).previous = alfa; + (*beta).next = alfa; + } + + unsafe fn delete(node: NodePointer) { + (*(*node).next).previous = (*node).previous; + (*(*node).previous).next = (*node).next; + + // let the created box do the deallocation when it goes out of scope + Box::from_raw(node); + } + + unsafe fn insert(previous: NodePointer, node: NodePointer) { + (*node).next = (*previous).next; + (*node).previous = previous; + (*(*previous).next).previous = node; + (*previous).next = node; + } +} diff --git a/src/main/rust/rust_safer_xorshift.rs b/src/main/rust/rust_safer_xorshift.rs new file mode 100644 index 0000000..15ac762 --- /dev/null +++ b/src/main/rust/rust_safer_xorshift.rs @@ -0,0 +1,125 @@ +/* + * Copyright 2021 Sam Leonard + * + * This file is part of java-2-times-faster-than-c. + * + * java-2-times-faster-than-c is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * java-2-times-faster-than-c is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with shader-web-background. If not, see . + */ + +mod rng; +use rng::Xorshift64sRng; + +use std::ptr; + +const MAX_PAYLOAD_SIZE: i32 = 50; +const INITIAL_NODE_COUNT: i32 = 10000; +const MUTATION_COUNT: i64 = 1000000; +const MAX_MUTATION_SIZE: i32 = 200; + +struct Node { + id: i64, + payload: Vec, + next: Option, + previous: Option, +} + +type NodePointer = ptr::NonNull; + +fn main() { + let mut node_id: i64 = 0; + let mut rng = Xorshift64sRng::new(42); + + let mut head = Node::new(node_id, &mut rng); node_id += 1; + + // hell yeah who needs safety when we have pointers, YEE HAWWW + unsafe { + Node::join(head, Node::new(node_id, &mut rng)); node_id += 1; + for _ in 2..INITIAL_NODE_COUNT { + Node::insert(head, Node::new(node_id, &mut rng)); node_id += 1; + } + let mut node_count: i64 = INITIAL_NODE_COUNT as i64; + for _ in 0..MUTATION_COUNT { + let mut delete_count = (rng.get_rand() * MAX_MUTATION_SIZE as f64) as i32; + if delete_count > (node_count - 2) as i32 { + delete_count = (node_count - 2) as i32; + } + for _ in 0..delete_count { + let to_delete = head; + head = (*head.as_ptr()).previous.expect("Head has empty previous node."); + Node::delete(to_delete); + } + node_count -= delete_count as i64; + let insert_count = (rng.get_rand() * MAX_MUTATION_SIZE as f64) as i32; + for _ in 0..insert_count { + Node::insert(head, Node::new(node_id, &mut rng)); node_id += 1; + head = (*head.as_ptr()).next.expect("Head has empty next node."); + } + node_count += insert_count as i64; + } + let mut checksum: i64 = 0; + let mut traveler = head; + loop { + checksum += (*traveler.as_ptr()).id as i64 + (*traveler.as_ptr()).payload.len() as i64; + if let Some(val) = (*traveler.as_ptr()).payload.get(0) { + checksum += *val as i64; + } + if let Some(val) = (*traveler.as_ptr()).payload.last() { + checksum += *val as i64; + } + traveler = (*traveler.as_ptr()).next.expect("Traveler has an empty next pointer."); + if traveler == head { break }; + } + println!("node count: {}", node_count); + println!("checksum: {}", checksum); + } +} + +impl Node { + fn new(id: i64, rng: &mut Xorshift64sRng) -> NodePointer { + NodePointer::new( + Box::into_raw(Box::new(Self{ + id, + payload: (0..(rng.get_rand() * MAX_PAYLOAD_SIZE as f64) as i8).collect(), + next: None, + previous: None, + })) + ).expect("Failed to Allocate node.") + } + + unsafe fn join(alfa: NodePointer, beta: NodePointer) { + (*alfa.as_ptr()).previous = Some(beta); + (*alfa.as_ptr()).next = Some(beta); + (*beta.as_ptr()).previous = Some(alfa); + (*beta.as_ptr()).next = Some(alfa); + } + + unsafe fn delete(node: NodePointer) { + let node_next: NodePointer = (*node.as_ptr()).next.expect("Node to delete has empty next pointer."); + let node_prev: NodePointer = (*node.as_ptr()).previous.expect("Node to delete has empty previous pointer."); + + (*node_next.as_ptr()).previous = Some(node_prev); + (*node_prev.as_ptr()).next = Some(node_next); + + // let the created box do the deallocation when it goes out of scope + Box::from_raw(node.as_ptr()); + } + + unsafe fn insert(previous: NodePointer, node: NodePointer) { + (*node.as_ptr()).next = (*previous.as_ptr()).next; + (*node.as_ptr()).previous = Some(previous); + let prev_next = (*previous.as_ptr()).next.expect("Empty next pointer on previous node in insert."); + (*prev_next.as_ptr()).previous = Some(node); + (*previous.as_ptr()).next = Some(node); + } +} diff --git a/src/main/rust/xorshift_rng.rs b/src/main/rust/xorshift_rng.rs new file mode 100644 index 0000000..a228854 --- /dev/null +++ b/src/main/rust/xorshift_rng.rs @@ -0,0 +1,15 @@ +const ITERATION_COUNT: usize = 1000000000; + +mod rng; +use rng::Xorshift64sRng; + +fn main() { + let mut rng = Xorshift64sRng::new(42); + + let checksum = std::iter::repeat_with(|| rng.get_rand()) + .take(ITERATION_COUNT) + .sum::(); + + println!("checksum: {}", checksum); +} + From 324df9721b4a00ceb77e88b22f3d9e38ba9d3b40 Mon Sep 17 00:00:00 2001 From: Sam Date: Fri, 5 Feb 2021 17:48:08 +0000 Subject: [PATCH 3/8] Updated licenses and added go xorshift versions. --- build-go.sh | 4 +- .../c/java_2_times_faster_than_c_xorshift.c | 1 + src/main/go/java_faster_than_go_xorshift.go | 168 ++++++++++++++++++ src/main/go/xorshift_rng.go | 61 +++++++ .../Java2TimesFasterThanCXORShift.java | 1 + .../com/xemantic/test/howfast/XORShift.java | 2 +- 6 files changed, 235 insertions(+), 2 deletions(-) create mode 100644 src/main/go/java_faster_than_go_xorshift.go create mode 100644 src/main/go/xorshift_rng.go diff --git a/build-go.sh b/build-go.sh index 52d4bc2..edfb30d 100755 --- a/build-go.sh +++ b/build-go.sh @@ -2,4 +2,6 @@ mkdir -p build/go go build -o ./build/go/java_faster_than_go ./src/main/go/java_faster_than_go.go -go build -o ./build/go/almost_pseudo_random ./src/main/go/almost_pseudo_random.go \ No newline at end of file +go build -o ./build/go/almost_pseudo_random ./src/main/go/almost_pseudo_random.go +go build -o ./build/go/xorshift_rng ./src/main/go/xorshift_rng.go +go build -o ./build/go/java_faster_than_go_xorshift ./src/main/go/java_faster_than_go_xorshift.go diff --git a/src/main/c/java_2_times_faster_than_c_xorshift.c b/src/main/c/java_2_times_faster_than_c_xorshift.c index 6703138..3bbcf2d 100644 --- a/src/main/c/java_2_times_faster_than_c_xorshift.c +++ b/src/main/c/java_2_times_faster_than_c_xorshift.c @@ -1,5 +1,6 @@ /* * Copyright 2021 Kazimierz Pogoda + * Copyright 2021 Sam Leonard * * This file is part of java-2-times-faster-than-c. * diff --git a/src/main/go/java_faster_than_go_xorshift.go b/src/main/go/java_faster_than_go_xorshift.go new file mode 100644 index 0000000..6d3c688 --- /dev/null +++ b/src/main/go/java_faster_than_go_xorshift.go @@ -0,0 +1,168 @@ +/* + * Copyright 2021 Elad Hirsch + * Copyright 2021 Kazimierz Pogoda + * + * This file is part of java-2-times-faster-than-c. + * + * java-2-times-faster-than-c is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * java-2-times-faster-than-c is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with shader-web-background. If not, see . + */ + +package main + +import ( + "flag" + _ "fmt" + "log" + "os" + "runtime/pprof" +) + +const MaxPayloadSize int = 50 +const InitialNodeCount int = 10000 +const MutationCount int64 = 1000000 +const MaxMutationSize int = 200 + +type xorshift64s_rng struct { + a uint64; +}; + +func (state * xorshift64s_rng) get_rand() float64 { + var x = state.a; /* The state must be seeded with a nonzero value. */ + x ^= x >> 12; // a + x ^= x << 25; // b + x ^= x >> 27; // c + state.a = x; + var rand_val = x * uint64(0x2545F4914F6CDD1D); + + // mix to a double + var a = rand_val >> 32; + var b = rand_val & 0xFFFFFFFF; + + return (float64(a >> 5) * 67108864.0 + float64(b >> 6)) * (1.0 / 9007199254740991.0); +} + +func new_rng(a uint64) *xorshift64s_rng { + return &xorshift64s_rng { + a: a, + }; +} + +type Node struct { + id int64 + prev *Node + next *Node + payload []byte +} + +func (node *Node) insert(newNode *Node) { + newNode.next = node.next + newNode.prev = node + node.next.prev = newNode + node.next = newNode +} + +func (node *Node) delete() { + node.next.prev = node.prev + node.prev.next = node.next +} + +func (node *Node) join(newNode *Node) { + node.prev = newNode + node.next = newNode + newNode.prev = node + newNode.next = node +} + +func createNode(id int, rng *xorshift64s_rng) *Node { + size := int(rng.get_rand() * float64(MaxPayloadSize)) + data := make([]byte, size); + for i := 0; i < size; i++ { + data[i] = byte(i); + } + return &Node{ + id: int64(id), + payload: data, + } +} + +var cpuProfile = flag.String("cpuprofile", "", "write cpu profile to `file`") + +func main() { + flag.Parse() + + if *cpuProfile != "" { + f, err := os.Create(*cpuProfile) + if err != nil { + log.Fatal("could not create CPU profile: ", err) + } + defer f.Close() + if err := pprof.StartCPUProfile(f); err != nil { + log.Fatal("could not start CPU profile: ", err) + } + defer pprof.StopCPUProfile() + } + + nodeId := 0 + rng := new_rng(42); + head := createNode(nodeId, rng) + nodeId++ + head.join(createNode(nodeId, rng)) + nodeId++ + + for i := 2; i < InitialNodeCount; i++ { + head.insert(createNode(nodeId, rng)) + nodeId++ + } + nodeCount := InitialNodeCount + + for i := int64(0); i < MutationCount; i++ { + deleteCount := int(rng.get_rand() * float64(MaxMutationSize)) + if deleteCount > (nodeCount -2) { + deleteCount = nodeCount - 2 + } + + for j := 0; j < deleteCount; j++ { + toDelete := head + head = head.prev + toDelete.delete() + } + + nodeCount -= deleteCount + insertCount := int(rng.get_rand() * float64(MaxMutationSize)) + + for j := 0; j < insertCount; j++ { + head.insert(createNode(nodeId, rng)) + nodeId++ + head = head.next + } + nodeCount += insertCount + } + + var checksum int64 = 0 + traveler := head + + for { + checksum += traveler.id + int64(len(traveler.payload)) + if len(traveler.payload) > 0 { + checksum += int64(int8(traveler.payload[0])) + } + traveler = traveler.next + if traveler == head { + break + } + } + + println("node count:" ,nodeCount) + println("checksum: ", checksum) +} diff --git a/src/main/go/xorshift_rng.go b/src/main/go/xorshift_rng.go new file mode 100644 index 0000000..194555c --- /dev/null +++ b/src/main/go/xorshift_rng.go @@ -0,0 +1,61 @@ +/* + * Copyright 2021 Sam Leonard + * + * This file is part of java-2-times-faster-than-c. + * + * java-2-times-faster-than-c is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * java-2-times-faster-than-c is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with shader-web-background. If not, see . + */ + +package main + +import ( + "fmt" +) + +const IterationCount int64 = 1000000000 + +type xorshift64s_rng struct { + a uint64; +}; + +func (state * xorshift64s_rng) get_rand() float64 { + var x = state.a; /* The state must be seeded with a nonzero value. */ + x ^= x >> 12; // a + x ^= x << 25; // b + x ^= x >> 27; // c + state.a = x; + var rand_val = x * uint64(0x2545F4914F6CDD1D); + + // mix to a double + var a = rand_val >> 32; + var b = rand_val & 0xFFFFFFFF; + + return (float64(a >> 5) * 67108864.0 + float64(b >> 6)) * (1.0 / 9007199254740991.0); +} + +func new_rng(a uint64) *xorshift64s_rng { + return &xorshift64s_rng { + a: a, + }; +} + +func main() { + var rng = new_rng(42); + + var checksum float64 = 0 + for i := int64(0); i < IterationCount; i++ { + checksum += rng.get_rand(); + } + fmt.Printf("checksum: %g\n", checksum) +} diff --git a/src/main/java/com/xemantic/test/howfast/Java2TimesFasterThanCXORShift.java b/src/main/java/com/xemantic/test/howfast/Java2TimesFasterThanCXORShift.java index a6fce28..3d8a834 100644 --- a/src/main/java/com/xemantic/test/howfast/Java2TimesFasterThanCXORShift.java +++ b/src/main/java/com/xemantic/test/howfast/Java2TimesFasterThanCXORShift.java @@ -1,5 +1,6 @@ /* * Copyright 2021 Kazimierz Pogoda + * Copyright 2021 Sam Leonard * * This file is part of java-2-times-faster-than-c. * diff --git a/src/main/java/com/xemantic/test/howfast/XORShift.java b/src/main/java/com/xemantic/test/howfast/XORShift.java index 347292e..66a1f48 100644 --- a/src/main/java/com/xemantic/test/howfast/XORShift.java +++ b/src/main/java/com/xemantic/test/howfast/XORShift.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 Kazimierz Pogoda + * Copyright 2021 Sam Leonard * * This file is part of java-2-times-faster-than-c. * From 1a7ee54a7011b15a11a531ddac71d97d31ab0cf0 Mon Sep 17 00:00:00 2001 From: Sam Date: Fri, 5 Feb 2021 20:52:44 +0000 Subject: [PATCH 4/8] Fixed build-gcc.sh --- build-gcc.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/build-gcc.sh b/build-gcc.sh index 2343e79..f890eea 100755 --- a/build-gcc.sh +++ b/build-gcc.sh @@ -1,7 +1,7 @@ #!/usr/bin/env sh -mkdir -p build/clang -gcc -O3 -o build/clang/almost_pseudo_random src/main/c/almost_pseudo_random.c -lm -gcc -O3 -o build/clang/java_2_times_faster_than_c src/main/c/java_2_times_faster_than_c.c -lm -gcc -O3 -o build/clang/xorshift_rng src/main/c/xorshift_rng.c -gcc -O3 -o build/clang/java_2_times_faster_than_c_xorshift src/main/c/java_2_times_faster_than_c_xorshift.c +mkdir -p build/gcc +gcc -O3 -o build/gcc/almost_pseudo_random src/main/c/almost_pseudo_random.c -lm +gcc -O3 -o build/gcc/java_2_times_faster_than_c src/main/c/java_2_times_faster_than_c.c -lm +gcc -O3 -o build/gcc/xorshift_rng src/main/c/xorshift_rng.c +gcc -O3 -o build/gcc/java_2_times_faster_than_c_xorshift src/main/c/java_2_times_faster_than_c_xorshift.c From 8a762f590c2321761ba77e288902df44a9805951 Mon Sep 17 00:00:00 2001 From: Sam Date: Sat, 6 Feb 2021 13:06:54 +0000 Subject: [PATCH 5/8] Move rust over to cargo. --- .gitignore | 5 ++++ build-rs.sh | 12 ++++----- src/main/c/almost_pseudo_random.c | 5 +++- src/main/rust/.gitignore | 2 ++ src/main/rust/Cargo.toml | 9 +++++++ .../{ => src/bin}/almost_pseudo_random.rs | 0 src/main/rust/{ => src/bin}/rust_raw.rs | 0 .../rust/{ => src/bin}/rust_raw_xorshift.rs | 4 +-- src/main/rust/{ => src/bin}/rust_safer.rs | 0 .../rust/{ => src/bin}/rust_safer_xorshift.rs | 4 +-- .../rust/{rng.rs => src/bin/xorshift_rng.rs} | 25 ++++++++++++++++--- src/main/rust/xorshift_rng.rs | 15 ----------- 12 files changed, 51 insertions(+), 30 deletions(-) create mode 100644 src/main/rust/.gitignore create mode 100644 src/main/rust/Cargo.toml rename src/main/rust/{ => src/bin}/almost_pseudo_random.rs (100%) rename src/main/rust/{ => src/bin}/rust_raw.rs (100%) rename src/main/rust/{ => src/bin}/rust_raw_xorshift.rs (98%) rename src/main/rust/{ => src/bin}/rust_safer.rs (100%) rename src/main/rust/{ => src/bin}/rust_safer_xorshift.rs (98%) rename src/main/rust/{rng.rs => src/bin/xorshift_rng.rs} (64%) delete mode 100644 src/main/rust/xorshift_rng.rs diff --git a/.gitignore b/.gitignore index 1e5a5e5..5aa07fd 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,8 @@ # csharp /bin /obj + + +# Added by cargo + +/target diff --git a/build-rs.sh b/build-rs.sh index 6b252d6..8b6bb24 100755 --- a/build-rs.sh +++ b/build-rs.sh @@ -1,9 +1,9 @@ #!/usr/bin/env sh mkdir -p build/rust -rustc -O -o build/rust/almost_pseudo_random src/main/rust/almost_pseudo_random.rs -rustc -O -o build/rust/xorshift_rng src/main/rust/xorshift_rng.rs -rustc -O -o build/rust/rust_safer src/main/rust/rust_safer.rs -rustc -O -o build/rust/rust_safer_xorshift src/main/rust/rust_safer_xorshift.rs -rustc -O -o build/rust/rust_raw_xorshift src/main/rust/rust_raw_xorshift.rs -rustc -O -o build/rust/rust_raw src/main/rust/rust_raw.rs +cargo build --release --manifest-path src/main/rust/Cargo.toml +find src/main/rust/target/release \ + -maxdepth 1 \ + -executable \ + -type f \ + -exec cp -f {} build/rust \; diff --git a/src/main/c/almost_pseudo_random.c b/src/main/c/almost_pseudo_random.c index 68e52f2..3297ae4 100644 --- a/src/main/c/almost_pseudo_random.c +++ b/src/main/c/almost_pseudo_random.c @@ -1,5 +1,6 @@ /* * Copyright 2021 Kazimierz Pogoda + * Copyright 2021 Sam Leonard * * This file is part of java-2-times-faster-than-c. * @@ -26,10 +27,12 @@ double almost_pseudo_random(long ordinal) { return fmod(sin(((double) ordinal) * 100000.0) + 1.0, 1.0); } -void main() { +int main() { double checksum = 0; for (long i = 0; i < ITERATION_COUNT; i++) { checksum += almost_pseudo_random(i); } printf("checksum: %f\n", checksum); + + return 0; } diff --git a/src/main/rust/.gitignore b/src/main/rust/.gitignore new file mode 100644 index 0000000..a9d37c5 --- /dev/null +++ b/src/main/rust/.gitignore @@ -0,0 +1,2 @@ +target +Cargo.lock diff --git a/src/main/rust/Cargo.toml b/src/main/rust/Cargo.toml new file mode 100644 index 0000000..7175a24 --- /dev/null +++ b/src/main/rust/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "rust" +version = "0.1.0" +authors = ["Sam "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/main/rust/almost_pseudo_random.rs b/src/main/rust/src/bin/almost_pseudo_random.rs similarity index 100% rename from src/main/rust/almost_pseudo_random.rs rename to src/main/rust/src/bin/almost_pseudo_random.rs diff --git a/src/main/rust/rust_raw.rs b/src/main/rust/src/bin/rust_raw.rs similarity index 100% rename from src/main/rust/rust_raw.rs rename to src/main/rust/src/bin/rust_raw.rs diff --git a/src/main/rust/rust_raw_xorshift.rs b/src/main/rust/src/bin/rust_raw_xorshift.rs similarity index 98% rename from src/main/rust/rust_raw_xorshift.rs rename to src/main/rust/src/bin/rust_raw_xorshift.rs index 6b23cc3..d50678b 100644 --- a/src/main/rust/rust_raw_xorshift.rs +++ b/src/main/rust/src/bin/rust_raw_xorshift.rs @@ -17,8 +17,8 @@ * along with shader-web-background. If not, see . */ -mod rng; -use rng::Xorshift64sRng; +mod xorshift_rng; +use xorshift_rng::Xorshift64sRng; use std::ptr; diff --git a/src/main/rust/rust_safer.rs b/src/main/rust/src/bin/rust_safer.rs similarity index 100% rename from src/main/rust/rust_safer.rs rename to src/main/rust/src/bin/rust_safer.rs diff --git a/src/main/rust/rust_safer_xorshift.rs b/src/main/rust/src/bin/rust_safer_xorshift.rs similarity index 98% rename from src/main/rust/rust_safer_xorshift.rs rename to src/main/rust/src/bin/rust_safer_xorshift.rs index 15ac762..725d0c5 100644 --- a/src/main/rust/rust_safer_xorshift.rs +++ b/src/main/rust/src/bin/rust_safer_xorshift.rs @@ -17,8 +17,8 @@ * along with shader-web-background. If not, see . */ -mod rng; -use rng::Xorshift64sRng; +mod xorshift_rng; +use xorshift_rng::Xorshift64sRng; use std::ptr; diff --git a/src/main/rust/rng.rs b/src/main/rust/src/bin/xorshift_rng.rs similarity index 64% rename from src/main/rust/rng.rs rename to src/main/rust/src/bin/xorshift_rng.rs index c86f29c..99e5b63 100644 --- a/src/main/rust/rng.rs +++ b/src/main/rust/src/bin/xorshift_rng.rs @@ -17,26 +17,43 @@ * along with shader-web-background. If not, see . */ +// marks the function so that cargo doesn't complain that we don't +// use it when we import it into other modules +#[allow(dead_code)] +fn main() { + let iteration_count = 1000000000; + + let mut rng = Xorshift64sRng::new(42); + + let checksum = std::iter::repeat_with(|| rng.get_rand()) + .take(iteration_count) + .sum::(); + + println!("checksum: {}", checksum); +} + pub struct Xorshift64sRng { a: u64 } impl Xorshift64sRng { pub fn new(a: u64) -> Self { + assert!(a != 0, "must be seeded with a non-zero value"); + Self { a } } pub fn get_rand(&mut self) -> f64 { - let mut x: u64 = self.a; /* The state must be seeded with a nonzero value. */ + let mut x: u64 = self.a; x ^= x >> 12; // a x ^= x << 25; // b x ^= x >> 27; // c self.a = x; - let rand_val: u64 = x * 0x2545F4914F6CDD1D_u64; + let rand_val: u64 = x.wrapping_mul(0x2545F4914F6CDD1D_u64); // mix to a double - let a: u32 = (rand_val >> 32) as u32; - let b: u32 = (rand_val & 0xFFFFFFFF_u64) as u32; + let a = (rand_val >> 32) as u32; + let b = rand_val as u32; ((a >> 5) as f64 * 67108864.0 + (b >> 6) as f64) * (1.0 / 9007199254740991.0) } diff --git a/src/main/rust/xorshift_rng.rs b/src/main/rust/xorshift_rng.rs deleted file mode 100644 index a228854..0000000 --- a/src/main/rust/xorshift_rng.rs +++ /dev/null @@ -1,15 +0,0 @@ -const ITERATION_COUNT: usize = 1000000000; - -mod rng; -use rng::Xorshift64sRng; - -fn main() { - let mut rng = Xorshift64sRng::new(42); - - let checksum = std::iter::repeat_with(|| rng.get_rand()) - .take(ITERATION_COUNT) - .sum::(); - - println!("checksum: {}", checksum); -} - From 1e87b1fc6806bb7fdf93b5cae2e159eb26f03682 Mon Sep 17 00:00:00 2001 From: Sam Date: Thu, 18 Feb 2021 01:42:19 +0000 Subject: [PATCH 6/8] Removed extra xorshift versions, so all now use xorshift RNG. --- build-clang.sh | 4 +- build-gcc.sh | 4 +- build-rs.sh => build-rust.sh | 0 src/main/c/almost_pseudo_random.c | 38 ---- src/main/c/java_2_times_faster_than_c.c | 44 +++-- .../c/java_2_times_faster_than_c_xorshift.c | 136 -------------- src/main/go/almost_pseudo_random.go | 36 ---- src/main/go/java_faster_than_go.go | 51 ++++-- src/main/go/java_faster_than_go_xorshift.go | 168 ------------------ .../test/howfast/AlmostPseudoRandom.java | 38 ---- .../test/howfast/Java2TimesFasterThanC.java | 23 ++- .../Java2TimesFasterThanCXORShift.java | 111 ------------ src/main/rust/src/bin/almost_pseudo_random.rs | 31 ---- src/main/rust/src/bin/rust_raw.rs | 25 ++- src/main/rust/src/bin/rust_raw_xorshift.rs | 119 ------------- src/main/rust/src/bin/rust_safer.rs | 27 ++- src/main/rust/src/bin/rust_safer_xorshift.rs | 125 ------------- 17 files changed, 102 insertions(+), 878 deletions(-) rename build-rs.sh => build-rust.sh (100%) delete mode 100644 src/main/c/almost_pseudo_random.c delete mode 100644 src/main/c/java_2_times_faster_than_c_xorshift.c delete mode 100644 src/main/go/almost_pseudo_random.go delete mode 100644 src/main/go/java_faster_than_go_xorshift.go delete mode 100644 src/main/java/com/xemantic/test/howfast/AlmostPseudoRandom.java delete mode 100644 src/main/java/com/xemantic/test/howfast/Java2TimesFasterThanCXORShift.java delete mode 100644 src/main/rust/src/bin/almost_pseudo_random.rs delete mode 100644 src/main/rust/src/bin/rust_raw_xorshift.rs delete mode 100644 src/main/rust/src/bin/rust_safer_xorshift.rs diff --git a/build-clang.sh b/build-clang.sh index ca38ff7..c077909 100755 --- a/build-clang.sh +++ b/build-clang.sh @@ -1,7 +1,5 @@ #!/usr/bin/env sh mkdir -p build/clang -clang -O3 -o build/clang/almost_pseudo_random src/main/c/almost_pseudo_random.c -lm -clang -O3 -o build/clang/java_2_times_faster_than_c src/main/c/java_2_times_faster_than_c.c -lm clang -O3 -o build/clang/xorshift_rng src/main/c/xorshift_rng.c -clang -O3 -o build/clang/java_2_times_faster_than_c_xorshift src/main/c/java_2_times_faster_than_c_xorshift.c +clang -O3 -o build/clang/java_2_times_faster_than_c src/main/c/java_2_times_faster_than_c.c -lm diff --git a/build-gcc.sh b/build-gcc.sh index f890eea..2c08c51 100755 --- a/build-gcc.sh +++ b/build-gcc.sh @@ -1,7 +1,5 @@ #!/usr/bin/env sh mkdir -p build/gcc -gcc -O3 -o build/gcc/almost_pseudo_random src/main/c/almost_pseudo_random.c -lm -gcc -O3 -o build/gcc/java_2_times_faster_than_c src/main/c/java_2_times_faster_than_c.c -lm gcc -O3 -o build/gcc/xorshift_rng src/main/c/xorshift_rng.c -gcc -O3 -o build/gcc/java_2_times_faster_than_c_xorshift src/main/c/java_2_times_faster_than_c_xorshift.c +gcc -O3 -o build/gcc/java_2_times_faster_than_c src/main/c/java_2_times_faster_than_c.c -lm diff --git a/build-rs.sh b/build-rust.sh similarity index 100% rename from build-rs.sh rename to build-rust.sh diff --git a/src/main/c/almost_pseudo_random.c b/src/main/c/almost_pseudo_random.c deleted file mode 100644 index 3297ae4..0000000 --- a/src/main/c/almost_pseudo_random.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2021 Kazimierz Pogoda - * Copyright 2021 Sam Leonard - * - * This file is part of java-2-times-faster-than-c. - * - * java-2-times-faster-than-c is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * java-2-times-faster-than-c is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with shader-web-background. If not, see . - */ - -#include -#include - -const long ITERATION_COUNT = 1000000000L; - -double almost_pseudo_random(long ordinal) { - return fmod(sin(((double) ordinal) * 100000.0) + 1.0, 1.0); -} - -int main() { - double checksum = 0; - for (long i = 0; i < ITERATION_COUNT; i++) { - checksum += almost_pseudo_random(i); - } - printf("checksum: %f\n", checksum); - - return 0; -} diff --git a/src/main/c/java_2_times_faster_than_c.c b/src/main/c/java_2_times_faster_than_c.c index 966281c..3bbcf2d 100644 --- a/src/main/c/java_2_times_faster_than_c.c +++ b/src/main/c/java_2_times_faster_than_c.c @@ -1,5 +1,6 @@ /* * Copyright 2021 Kazimierz Pogoda + * Copyright 2021 Sam Leonard * * This file is part of java-2-times-faster-than-c. * @@ -18,6 +19,7 @@ */ #include +#include #include #include @@ -26,6 +28,24 @@ const int INITIAL_NODE_COUNT = 10000; const long MUTATION_COUNT = 1000000L; const int MAX_MUTATION_SIZE = 200; +struct xorshift64s_state { + uint64_t a; +}; + +double xorshift64s(struct xorshift64s_state *state) { + uint64_t x = state->a; /* The state must be seeded with a nonzero value. */ + x ^= x >> 12; // a + x ^= x << 25; // b + x ^= x >> 27; // c + state->a = x; + uint64_t rand_val = x * UINT64_C(0x2545F4914F6CDD1D); + + // mix to a double + uint32_t a = rand_val >> 32; + uint32_t b = rand_val & 0xFFFFFFFF; + return ((a >> 5) * 67108864.0 + (b >> 6)) * (1.0 / 9007199254740991.0); +} + typedef struct Node Node; struct Node { @@ -36,12 +56,8 @@ struct Node { Node *next; } NodeDef; -double almost_pseudo_random(long ordinal) { - return fmod((sin(((double) ordinal) * 100000.0) + 1.0), 1.0); -} - -Node *new_node(long id) { - int size = (int) (almost_pseudo_random(id) * MAX_PAYLOAD_SIZE); +Node *new_node(long id, struct xorshift64s_state * rng_state) { + int size = (int) (xorshift64s(rng_state) * MAX_PAYLOAD_SIZE); int charId = (char) id; Node *node = malloc(sizeof(NodeDef)); node->id = id; @@ -77,15 +93,17 @@ void insert(Node *previous, Node *node) { int main() { long node_id = 0; - long mutation_seq = 0; - Node *head = new_node(node_id++); - join(head, new_node(node_id++)); + struct xorshift64s_state rng_state = { + .a = 42, + }; + Node *head = new_node(node_id++, &rng_state); + join(head, new_node(node_id++, &rng_state)); for (int i = 2; i < INITIAL_NODE_COUNT; i++) { - insert(head, new_node(node_id++)); + insert(head, new_node(node_id++, &rng_state)); } long node_count = INITIAL_NODE_COUNT; for (long i = 0; i < MUTATION_COUNT; i++) { - int delete_count = (int) (almost_pseudo_random(mutation_seq++) * (double) MAX_MUTATION_SIZE); + int delete_count = (int) (xorshift64s(&rng_state) * (double) MAX_MUTATION_SIZE); if (delete_count > (node_count - 2)) { delete_count = (int) node_count - 2; } @@ -95,9 +113,9 @@ int main() { delete(to_delete); } node_count -= delete_count; - int insert_count = (int) (almost_pseudo_random(mutation_seq++) * (double) MAX_MUTATION_SIZE); + int insert_count = (int) (xorshift64s(&rng_state) * (double) MAX_MUTATION_SIZE); for (int j = 0; j < insert_count; j++) { - insert(head, new_node(node_id++)); + insert(head, new_node(node_id++, &rng_state)); head = head->next; } node_count += insert_count; diff --git a/src/main/c/java_2_times_faster_than_c_xorshift.c b/src/main/c/java_2_times_faster_than_c_xorshift.c deleted file mode 100644 index 3bbcf2d..0000000 --- a/src/main/c/java_2_times_faster_than_c_xorshift.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2021 Kazimierz Pogoda - * Copyright 2021 Sam Leonard - * - * This file is part of java-2-times-faster-than-c. - * - * java-2-times-faster-than-c is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * java-2-times-faster-than-c is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with shader-web-background. If not, see . - */ - -#include -#include -#include -#include - -const int MAX_PAYLOAD_SIZE = 50; -const int INITIAL_NODE_COUNT = 10000; -const long MUTATION_COUNT = 1000000L; -const int MAX_MUTATION_SIZE = 200; - -struct xorshift64s_state { - uint64_t a; -}; - -double xorshift64s(struct xorshift64s_state *state) { - uint64_t x = state->a; /* The state must be seeded with a nonzero value. */ - x ^= x >> 12; // a - x ^= x << 25; // b - x ^= x >> 27; // c - state->a = x; - uint64_t rand_val = x * UINT64_C(0x2545F4914F6CDD1D); - - // mix to a double - uint32_t a = rand_val >> 32; - uint32_t b = rand_val & 0xFFFFFFFF; - return ((a >> 5) * 67108864.0 + (b >> 6)) * (1.0 / 9007199254740991.0); -} - -typedef struct Node Node; - -struct Node { - long id; - int size; - char *payload; - Node *previous; - Node *next; -} NodeDef; - -Node *new_node(long id, struct xorshift64s_state * rng_state) { - int size = (int) (xorshift64s(rng_state) * MAX_PAYLOAD_SIZE); - int charId = (char) id; - Node *node = malloc(sizeof(NodeDef)); - node->id = id; - node->size = size; - char *payload = malloc(sizeof(char) * size); - for (int i = 0; i < size; i++) { - payload[i] = (char) i; - } - node->payload = payload; - return node; -} - -void join(Node *alfa, Node *beta) { - alfa->previous = beta; - alfa->next = beta; - beta->previous = alfa; - beta->next = alfa; -} - -void delete(Node *node) { - node->next->previous = node->previous; - node->previous->next = node->next; - free(node->payload); - free(node); -} - -void insert(Node *previous, Node *node) { - node->next = previous->next; - node->previous = previous; - previous->next->previous = node; - previous->next = node; -} - -int main() { - long node_id = 0; - struct xorshift64s_state rng_state = { - .a = 42, - }; - Node *head = new_node(node_id++, &rng_state); - join(head, new_node(node_id++, &rng_state)); - for (int i = 2; i < INITIAL_NODE_COUNT; i++) { - insert(head, new_node(node_id++, &rng_state)); - } - long node_count = INITIAL_NODE_COUNT; - for (long i = 0; i < MUTATION_COUNT; i++) { - int delete_count = (int) (xorshift64s(&rng_state) * (double) MAX_MUTATION_SIZE); - if (delete_count > (node_count - 2)) { - delete_count = (int) node_count - 2; - } - for (int j = 0; j < delete_count; j++) { - Node *to_delete = head; - head = head->previous; - delete(to_delete); - } - node_count -= delete_count; - int insert_count = (int) (xorshift64s(&rng_state) * (double) MAX_MUTATION_SIZE); - for (int j = 0; j < insert_count; j++) { - insert(head, new_node(node_id++, &rng_state)); - head = head->next; - } - node_count += insert_count; - } - long checksum = 0; - Node *traveler = head; - do { - checksum += traveler->id + traveler->size; - if (traveler->size > 0) { - checksum += traveler->payload[0]; - checksum += traveler->payload[traveler->size - 1]; - } - } while ( - (traveler = traveler->next) != head - ); - printf("node count: %lu\n", node_count); - printf("checksum: %lu\n", checksum); -} diff --git a/src/main/go/almost_pseudo_random.go b/src/main/go/almost_pseudo_random.go deleted file mode 100644 index f63cf5a..0000000 --- a/src/main/go/almost_pseudo_random.go +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2021 Elad Hirsch - * Copyright 2021 Kazimierz Pogoda - * - * This file is part of java-2-times-faster-than-c. - * - * java-2-times-faster-than-c is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * java-2-times-faster-than-c is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with shader-web-background. If not, see . - */ - -package main - -import ( - "math" - "fmt" -) - -const IterationCount int64 = 1000000000 - -func main() { - var checksum float64 = 0 - for i := int64(0); i < IterationCount; i++ { - checksum += math.Mod(math.Sin(float64(i) * 100000.0) + 1.0, 1.0) - } - fmt.Printf("checksum: %g\n", checksum) -} diff --git a/src/main/go/java_faster_than_go.go b/src/main/go/java_faster_than_go.go index 69d56fd..6d3c688 100644 --- a/src/main/go/java_faster_than_go.go +++ b/src/main/go/java_faster_than_go.go @@ -24,7 +24,6 @@ import ( "flag" _ "fmt" "log" - "math" "os" "runtime/pprof" ) @@ -34,6 +33,31 @@ const InitialNodeCount int = 10000 const MutationCount int64 = 1000000 const MaxMutationSize int = 200 +type xorshift64s_rng struct { + a uint64; +}; + +func (state * xorshift64s_rng) get_rand() float64 { + var x = state.a; /* The state must be seeded with a nonzero value. */ + x ^= x >> 12; // a + x ^= x << 25; // b + x ^= x >> 27; // c + state.a = x; + var rand_val = x * uint64(0x2545F4914F6CDD1D); + + // mix to a double + var a = rand_val >> 32; + var b = rand_val & 0xFFFFFFFF; + + return (float64(a >> 5) * 67108864.0 + float64(b >> 6)) * (1.0 / 9007199254740991.0); +} + +func new_rng(a uint64) *xorshift64s_rng { + return &xorshift64s_rng { + a: a, + }; +} + type Node struct { id int64 prev *Node @@ -60,8 +84,8 @@ func (node *Node) join(newNode *Node) { newNode.next = node } -func createNode(id int) *Node { - size := int(almostPseudoRandom(int64(id)) * float64(MaxPayloadSize)) +func createNode(id int, rng *xorshift64s_rng) *Node { + size := int(rng.get_rand() * float64(MaxPayloadSize)) data := make([]byte, size); for i := 0; i < size; i++ { data[i] = byte(i); @@ -72,11 +96,6 @@ func createNode(id int) *Node { } } -func almostPseudoRandom(ordinal int64) float64 { - return math.Mod(math.Sin(float64(ordinal) * 100000.0) + 1.0, 1.0) -} - - var cpuProfile = flag.String("cpuprofile", "", "write cpu profile to `file`") func main() { @@ -95,21 +114,20 @@ func main() { } nodeId := 0 - mutationSeq := 0 - head := createNode(nodeId) + rng := new_rng(42); + head := createNode(nodeId, rng) nodeId++ - head.join(createNode(nodeId)) + head.join(createNode(nodeId, rng)) nodeId++ for i := 2; i < InitialNodeCount; i++ { - head.insert(createNode(nodeId)) + head.insert(createNode(nodeId, rng)) nodeId++ } nodeCount := InitialNodeCount for i := int64(0); i < MutationCount; i++ { - deleteCount := int(almostPseudoRandom(int64(mutationSeq)) * float64(MaxMutationSize)) - mutationSeq++ + deleteCount := int(rng.get_rand() * float64(MaxMutationSize)) if deleteCount > (nodeCount -2) { deleteCount = nodeCount - 2 } @@ -121,11 +139,10 @@ func main() { } nodeCount -= deleteCount - insertCount := int(almostPseudoRandom(int64(mutationSeq)) * float64(MaxMutationSize)) - mutationSeq++ + insertCount := int(rng.get_rand() * float64(MaxMutationSize)) for j := 0; j < insertCount; j++ { - head.insert(createNode(nodeId)) + head.insert(createNode(nodeId, rng)) nodeId++ head = head.next } diff --git a/src/main/go/java_faster_than_go_xorshift.go b/src/main/go/java_faster_than_go_xorshift.go deleted file mode 100644 index 6d3c688..0000000 --- a/src/main/go/java_faster_than_go_xorshift.go +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2021 Elad Hirsch - * Copyright 2021 Kazimierz Pogoda - * - * This file is part of java-2-times-faster-than-c. - * - * java-2-times-faster-than-c is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * java-2-times-faster-than-c is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with shader-web-background. If not, see . - */ - -package main - -import ( - "flag" - _ "fmt" - "log" - "os" - "runtime/pprof" -) - -const MaxPayloadSize int = 50 -const InitialNodeCount int = 10000 -const MutationCount int64 = 1000000 -const MaxMutationSize int = 200 - -type xorshift64s_rng struct { - a uint64; -}; - -func (state * xorshift64s_rng) get_rand() float64 { - var x = state.a; /* The state must be seeded with a nonzero value. */ - x ^= x >> 12; // a - x ^= x << 25; // b - x ^= x >> 27; // c - state.a = x; - var rand_val = x * uint64(0x2545F4914F6CDD1D); - - // mix to a double - var a = rand_val >> 32; - var b = rand_val & 0xFFFFFFFF; - - return (float64(a >> 5) * 67108864.0 + float64(b >> 6)) * (1.0 / 9007199254740991.0); -} - -func new_rng(a uint64) *xorshift64s_rng { - return &xorshift64s_rng { - a: a, - }; -} - -type Node struct { - id int64 - prev *Node - next *Node - payload []byte -} - -func (node *Node) insert(newNode *Node) { - newNode.next = node.next - newNode.prev = node - node.next.prev = newNode - node.next = newNode -} - -func (node *Node) delete() { - node.next.prev = node.prev - node.prev.next = node.next -} - -func (node *Node) join(newNode *Node) { - node.prev = newNode - node.next = newNode - newNode.prev = node - newNode.next = node -} - -func createNode(id int, rng *xorshift64s_rng) *Node { - size := int(rng.get_rand() * float64(MaxPayloadSize)) - data := make([]byte, size); - for i := 0; i < size; i++ { - data[i] = byte(i); - } - return &Node{ - id: int64(id), - payload: data, - } -} - -var cpuProfile = flag.String("cpuprofile", "", "write cpu profile to `file`") - -func main() { - flag.Parse() - - if *cpuProfile != "" { - f, err := os.Create(*cpuProfile) - if err != nil { - log.Fatal("could not create CPU profile: ", err) - } - defer f.Close() - if err := pprof.StartCPUProfile(f); err != nil { - log.Fatal("could not start CPU profile: ", err) - } - defer pprof.StopCPUProfile() - } - - nodeId := 0 - rng := new_rng(42); - head := createNode(nodeId, rng) - nodeId++ - head.join(createNode(nodeId, rng)) - nodeId++ - - for i := 2; i < InitialNodeCount; i++ { - head.insert(createNode(nodeId, rng)) - nodeId++ - } - nodeCount := InitialNodeCount - - for i := int64(0); i < MutationCount; i++ { - deleteCount := int(rng.get_rand() * float64(MaxMutationSize)) - if deleteCount > (nodeCount -2) { - deleteCount = nodeCount - 2 - } - - for j := 0; j < deleteCount; j++ { - toDelete := head - head = head.prev - toDelete.delete() - } - - nodeCount -= deleteCount - insertCount := int(rng.get_rand() * float64(MaxMutationSize)) - - for j := 0; j < insertCount; j++ { - head.insert(createNode(nodeId, rng)) - nodeId++ - head = head.next - } - nodeCount += insertCount - } - - var checksum int64 = 0 - traveler := head - - for { - checksum += traveler.id + int64(len(traveler.payload)) - if len(traveler.payload) > 0 { - checksum += int64(int8(traveler.payload[0])) - } - traveler = traveler.next - if traveler == head { - break - } - } - - println("node count:" ,nodeCount) - println("checksum: ", checksum) -} diff --git a/src/main/java/com/xemantic/test/howfast/AlmostPseudoRandom.java b/src/main/java/com/xemantic/test/howfast/AlmostPseudoRandom.java deleted file mode 100644 index 0817583..0000000 --- a/src/main/java/com/xemantic/test/howfast/AlmostPseudoRandom.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2021 Kazimierz Pogoda - * - * This file is part of java-2-times-faster-than-c. - * - * java-2-times-faster-than-c is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * java-2-times-faster-than-c is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with shader-web-background. If not, see . - */ - -package com.xemantic.test.howfast; - -public class AlmostPseudoRandom { - - private static final long ITERATION_COUNT = 1000000000L; - - private static double almostPseudoRandom(long ordinal) { - return (Math.sin(((double) ordinal) * 100000.0) + 1.0) % 1.0; - } - - public static void main(String[] args) { - double checksum = 0; - for (long i = 0; i < ITERATION_COUNT; i++) { - checksum += almostPseudoRandom(i); - } - System.out.println("checksum: " + checksum); - } - -} diff --git a/src/main/java/com/xemantic/test/howfast/Java2TimesFasterThanC.java b/src/main/java/com/xemantic/test/howfast/Java2TimesFasterThanC.java index 00e3f36..cae8a14 100644 --- a/src/main/java/com/xemantic/test/howfast/Java2TimesFasterThanC.java +++ b/src/main/java/com/xemantic/test/howfast/Java2TimesFasterThanC.java @@ -1,5 +1,6 @@ /* * Copyright 2021 Kazimierz Pogoda + * Copyright 2021 Sam Leonard * * This file is part of java-2-times-faster-than-c. * @@ -33,9 +34,9 @@ private static class Node { private Node previous; private Node next; - private Node(long id) { + private Node(long id, xorshift64s_rng rng) { this.id = id; - int size = (int) (almostPseudoRandom(id) * (double) MAX_PAYLOAD_SIZE); + int size = (int) (rng.get_rand() * (double) MAX_PAYLOAD_SIZE); byte[] data = new byte[size]; for (int i = 0; i < size; i++) { data[i] = (byte) i; @@ -65,21 +66,17 @@ void insert(Node node) { } - private static double almostPseudoRandom(long ordinal) { - return (Math.sin(((double) ordinal) * 100000.0) + 1.0) % 1.0; - } - public static void main(String[] args) { long nodeId = 0; - long mutationSeq = 0; - Node head = new Node(nodeId++); - head.join(new Node(nodeId++)); + xorshift64s_rng rng = new xorshift64s_rng(42); + Node head = new Node(nodeId++, rng); + head.join(new Node(nodeId++, rng)); for (int i = 2; i < INITIAL_NODE_COUNT; i++) { - head.insert(new Node(nodeId++)); + head.insert(new Node(nodeId++, rng)); } long nodeCount = INITIAL_NODE_COUNT; for (long i = 0; i < MUTATION_COUNT; i++) { - int deleteCount = (int) (almostPseudoRandom(mutationSeq++) * (double) MAX_MUTATION_SIZE); + int deleteCount = (int) (rng.get_rand() * (double) MAX_MUTATION_SIZE); if (deleteCount > (nodeCount - 2)) { deleteCount = (int) nodeCount - 2; } @@ -89,9 +86,9 @@ public static void main(String[] args) { toDelete.delete(); } nodeCount -= deleteCount; - int insertCount = (int) (almostPseudoRandom(mutationSeq++) * (double) MAX_MUTATION_SIZE); + int insertCount = (int) (rng.get_rand() * (double) MAX_MUTATION_SIZE); for (int j = 0; j < insertCount; j++) { - head.insert(new Node(nodeId++)); + head.insert(new Node(nodeId++, rng)); head = head.next; } nodeCount += insertCount; diff --git a/src/main/java/com/xemantic/test/howfast/Java2TimesFasterThanCXORShift.java b/src/main/java/com/xemantic/test/howfast/Java2TimesFasterThanCXORShift.java deleted file mode 100644 index 3d8a834..0000000 --- a/src/main/java/com/xemantic/test/howfast/Java2TimesFasterThanCXORShift.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2021 Kazimierz Pogoda - * Copyright 2021 Sam Leonard - * - * This file is part of java-2-times-faster-than-c. - * - * java-2-times-faster-than-c is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * java-2-times-faster-than-c is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with shader-web-background. If not, see . - */ - -package com.xemantic.test.howfast; - -public class Java2TimesFasterThanCXORShift { - - private static final int MAX_PAYLOAD_SIZE = 50; - private static final int INITIAL_NODE_COUNT = 10000; - private static final long MUTATION_COUNT = 1000000L; - private static final int MAX_MUTATION_SIZE = 200; - - private static class Node { - - private long id; - private byte[] payload; - private Node previous; - private Node next; - - private Node(long id, xorshift64s_rng rng) { - this.id = id; - int size = (int) (rng.get_rand() * (double) MAX_PAYLOAD_SIZE); - byte[] data = new byte[size]; - for (int i = 0; i < size; i++) { - data[i] = (byte) i; - } - payload = data; - } - - void join(Node node) { - previous = node; - next = node; - node.previous = this; - node.next = this; - } - - void delete() { - next.previous = previous; - previous.next = next; - // free memory (which is explicit in C and implicit in Java) - } - - void insert(Node node) { - node.next = next; - node.previous = this; - next.previous = node; - next = node; - } - - } - - public static void main(String[] args) { - long nodeId = 0; - xorshift64s_rng rng = new xorshift64s_rng(42); - Node head = new Node(nodeId++, rng); - head.join(new Node(nodeId++, rng)); - for (int i = 2; i < INITIAL_NODE_COUNT; i++) { - head.insert(new Node(nodeId++, rng)); - } - long nodeCount = INITIAL_NODE_COUNT; - for (long i = 0; i < MUTATION_COUNT; i++) { - int deleteCount = (int) (rng.get_rand() * (double) MAX_MUTATION_SIZE); - if (deleteCount > (nodeCount - 2)) { - deleteCount = (int) nodeCount - 2; - } - for (int j = 0; j < deleteCount; j++) { - Node toDelete = head; - head = head.previous; - toDelete.delete(); - } - nodeCount -= deleteCount; - int insertCount = (int) (rng.get_rand() * (double) MAX_MUTATION_SIZE); - for (int j = 0; j < insertCount; j++) { - head.insert(new Node(nodeId++, rng)); - head = head.next; - } - nodeCount += insertCount; - } - long checksum = 0; - Node traveler = head; - do { - checksum += traveler.id + traveler.payload.length; - if (traveler.payload.length > 0) { - checksum += traveler.payload[0]; - checksum += traveler.payload[traveler.payload.length - 1]; - } - } while ( - (traveler = traveler.next) != head - ); - System.out.println("node count: " + nodeCount); - System.out.println("checksum: " + checksum); - } - -} diff --git a/src/main/rust/src/bin/almost_pseudo_random.rs b/src/main/rust/src/bin/almost_pseudo_random.rs deleted file mode 100644 index de61da4..0000000 --- a/src/main/rust/src/bin/almost_pseudo_random.rs +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2021 Sam Leonard - * - * This file is part of java-2-times-faster-than-c. - * - * java-2-times-faster-than-c is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * java-2-times-faster-than-c is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with shader-web-background. If not, see . - */ -const ITERATION_COUNT: i64 = 1000000000; - -fn almost_pseudo_random(ordinal: i64) -> f64 { - ((ordinal as f64 * 100000.0).sin() + 1.0) % 1.0 -} - -fn main() { - let checksum: f64 = (0..ITERATION_COUNT) - .map(almost_pseudo_random) - .sum(); - - println!("checksum: {}", checksum); -} diff --git a/src/main/rust/src/bin/rust_raw.rs b/src/main/rust/src/bin/rust_raw.rs index de95221..d50678b 100644 --- a/src/main/rust/src/bin/rust_raw.rs +++ b/src/main/rust/src/bin/rust_raw.rs @@ -17,6 +17,9 @@ * along with shader-web-background. If not, see . */ +mod xorshift_rng; +use xorshift_rng::Xorshift64sRng; + use std::ptr; const MAX_PAYLOAD_SIZE: i32 = 50; @@ -33,25 +36,21 @@ struct Node { type NodePointer = *mut Node; -fn almost_pseudo_random(ordinal: i64) -> f64 { - ((ordinal as f64 * 100000.0).sin() + 1.0) % 1.0 -} - fn main() { let mut node_id: i64 = 0; - let mut mutation_seq: i64 = 0; + let mut rng = Xorshift64sRng::new(42); - let mut head = Node::new(node_id); node_id += 1; + let mut head = Node::new(node_id, &mut rng); node_id += 1; // hell yeah who needs safety when we have pointers, YEE HAWWW unsafe { - Node::join(head, Node::new(node_id)); node_id += 1; + Node::join(head, Node::new(node_id, &mut rng)); node_id += 1; for _ in 2..INITIAL_NODE_COUNT { - Node::insert(head, Node::new(node_id)); node_id += 1; + Node::insert(head, Node::new(node_id, &mut rng)); node_id += 1; } let mut node_count: i64 = INITIAL_NODE_COUNT as i64; for _ in 0..MUTATION_COUNT { - let mut delete_count = (almost_pseudo_random(mutation_seq) * MAX_MUTATION_SIZE as f64) as i32; mutation_seq += 1; + let mut delete_count = (rng.get_rand() * MAX_MUTATION_SIZE as f64) as i32; if delete_count > (node_count - 2) as i32 { delete_count = (node_count - 2) as i32; } @@ -61,9 +60,9 @@ fn main() { Node::delete(to_delete); } node_count -= delete_count as i64; - let insert_count = (almost_pseudo_random(mutation_seq) * MAX_MUTATION_SIZE as f64) as i32; mutation_seq += 1; + let insert_count = (rng.get_rand() * MAX_MUTATION_SIZE as f64) as i32; for _ in 0..insert_count { - Node::insert(head, Node::new(node_id)); node_id += 1; + Node::insert(head, Node::new(node_id, &mut rng)); node_id += 1; head = (*head).next; } node_count += insert_count as i64; @@ -87,10 +86,10 @@ fn main() { } impl Node { - fn new(id: i64) -> NodePointer { + fn new(id: i64, rng: &mut Xorshift64sRng) -> NodePointer { Box::into_raw(Box::new(Self{ id, - payload: (0..(almost_pseudo_random(id) * MAX_PAYLOAD_SIZE as f64) as i8).collect(), + payload: (0..(rng.get_rand() * MAX_PAYLOAD_SIZE as f64) as i8).collect(), next: ptr::null_mut(), previous: ptr::null_mut(), })) diff --git a/src/main/rust/src/bin/rust_raw_xorshift.rs b/src/main/rust/src/bin/rust_raw_xorshift.rs deleted file mode 100644 index d50678b..0000000 --- a/src/main/rust/src/bin/rust_raw_xorshift.rs +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2021 Sam Leonard - * - * This file is part of java-2-times-faster-than-c. - * - * java-2-times-faster-than-c is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * java-2-times-faster-than-c is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with shader-web-background. If not, see . - */ - -mod xorshift_rng; -use xorshift_rng::Xorshift64sRng; - -use std::ptr; - -const MAX_PAYLOAD_SIZE: i32 = 50; -const INITIAL_NODE_COUNT: i32 = 10000; -const MUTATION_COUNT: i64 = 1000000; -const MAX_MUTATION_SIZE: i32 = 200; - -struct Node { - id: i64, - payload: Vec, - next: NodePointer, - previous: NodePointer, -} - -type NodePointer = *mut Node; - -fn main() { - let mut node_id: i64 = 0; - let mut rng = Xorshift64sRng::new(42); - - let mut head = Node::new(node_id, &mut rng); node_id += 1; - - // hell yeah who needs safety when we have pointers, YEE HAWWW - unsafe { - Node::join(head, Node::new(node_id, &mut rng)); node_id += 1; - for _ in 2..INITIAL_NODE_COUNT { - Node::insert(head, Node::new(node_id, &mut rng)); node_id += 1; - } - let mut node_count: i64 = INITIAL_NODE_COUNT as i64; - for _ in 0..MUTATION_COUNT { - let mut delete_count = (rng.get_rand() * MAX_MUTATION_SIZE as f64) as i32; - if delete_count > (node_count - 2) as i32 { - delete_count = (node_count - 2) as i32; - } - for _ in 0..delete_count { - let to_delete = head; - head = (*head).previous; - Node::delete(to_delete); - } - node_count -= delete_count as i64; - let insert_count = (rng.get_rand() * MAX_MUTATION_SIZE as f64) as i32; - for _ in 0..insert_count { - Node::insert(head, Node::new(node_id, &mut rng)); node_id += 1; - head = (*head).next; - } - node_count += insert_count as i64; - } - let mut checksum: i64 = 0; - let mut traveler = head; - loop { - checksum += (*traveler).id as i64 + (*traveler).payload.len() as i64; - if let Some(val) = (*traveler).payload.first() { - checksum += *val as i64; - } - if let Some(val) = (*traveler).payload.last() { - checksum += *val as i64; - } - traveler = (*traveler).next; - if traveler == head { break }; - } - println!("node count: {}", node_count); - println!("checksum: {}", checksum); - } -} - -impl Node { - fn new(id: i64, rng: &mut Xorshift64sRng) -> NodePointer { - Box::into_raw(Box::new(Self{ - id, - payload: (0..(rng.get_rand() * MAX_PAYLOAD_SIZE as f64) as i8).collect(), - next: ptr::null_mut(), - previous: ptr::null_mut(), - })) - } - - unsafe fn join(alfa: NodePointer, beta: NodePointer) { - (*alfa).previous = beta; - (*alfa).next = beta; - (*beta).previous = alfa; - (*beta).next = alfa; - } - - unsafe fn delete(node: NodePointer) { - (*(*node).next).previous = (*node).previous; - (*(*node).previous).next = (*node).next; - - // let the created box do the deallocation when it goes out of scope - Box::from_raw(node); - } - - unsafe fn insert(previous: NodePointer, node: NodePointer) { - (*node).next = (*previous).next; - (*node).previous = previous; - (*(*previous).next).previous = node; - (*previous).next = node; - } -} diff --git a/src/main/rust/src/bin/rust_safer.rs b/src/main/rust/src/bin/rust_safer.rs index a8b3b5a..7db27db 100644 --- a/src/main/rust/src/bin/rust_safer.rs +++ b/src/main/rust/src/bin/rust_safer.rs @@ -17,6 +17,9 @@ * along with shader-web-background. If not, see . */ +mod xorshift_rng; +use xorshift_rng::Xorshift64sRng; + use std::ptr; const MAX_PAYLOAD_SIZE: i32 = 50; @@ -33,25 +36,21 @@ struct Node { type NodePointer = ptr::NonNull; -fn almost_pseudo_random(ordinal: i64) -> f64 { - ((ordinal as f64 * 100000.0).sin() + 1.0) % 1.0 -} - fn main() { let mut node_id: i64 = 0; - let mut mutation_seq: i64 = 0; + let mut rng = Xorshift64sRng::new(42); - let mut head = Node::new(node_id); node_id += 1; + let mut head = Node::new(node_id, &mut rng); node_id += 1; // hell yeah who needs safety when we have pointers, YEE HAWWW unsafe { - Node::join(head, Node::new(node_id)); node_id += 1; + Node::join(head, Node::new(node_id, &mut rng)); node_id += 1; for _ in 2..INITIAL_NODE_COUNT { - Node::insert(head, Node::new(node_id)); node_id += 1; + Node::insert(head, Node::new(node_id, &mut rng)); node_id += 1; } let mut node_count: i64 = INITIAL_NODE_COUNT as i64; for _ in 0..MUTATION_COUNT { - let mut delete_count = (almost_pseudo_random(mutation_seq) * MAX_MUTATION_SIZE as f64) as i32; mutation_seq += 1; + let mut delete_count = (rng.get_rand() * MAX_MUTATION_SIZE as f64) as i32; if delete_count > (node_count - 2) as i32 { delete_count = (node_count - 2) as i32; } @@ -61,9 +60,9 @@ fn main() { Node::delete(to_delete); } node_count -= delete_count as i64; - let insert_count = (almost_pseudo_random(mutation_seq) * MAX_MUTATION_SIZE as f64) as i32; mutation_seq += 1; + let insert_count = (rng.get_rand() * MAX_MUTATION_SIZE as f64) as i32; for _ in 0..insert_count { - Node::insert(head, Node::new(node_id)); node_id += 1; + Node::insert(head, Node::new(node_id, &mut rng)); node_id += 1; head = (*head.as_ptr()).next.expect("Head has empty next node."); } node_count += insert_count as i64; @@ -72,7 +71,7 @@ fn main() { let mut traveler = head; loop { checksum += (*traveler.as_ptr()).id as i64 + (*traveler.as_ptr()).payload.len() as i64; - if let Some(val) = (*traveler.as_ptr()).payload.get(0) { + if let Some(val) = (*traveler.as_ptr()).payload.first() { checksum += *val as i64; } if let Some(val) = (*traveler.as_ptr()).payload.last() { @@ -87,11 +86,11 @@ fn main() { } impl Node { - fn new(id: i64) -> NodePointer { + fn new(id: i64, rng: &mut Xorshift64sRng) -> NodePointer { NodePointer::new( Box::into_raw(Box::new(Self{ id, - payload: (0..(almost_pseudo_random(id) * MAX_PAYLOAD_SIZE as f64) as i8).collect(), + payload: (0..(rng.get_rand() * MAX_PAYLOAD_SIZE as f64) as i8).collect(), next: None, previous: None, })) diff --git a/src/main/rust/src/bin/rust_safer_xorshift.rs b/src/main/rust/src/bin/rust_safer_xorshift.rs deleted file mode 100644 index 725d0c5..0000000 --- a/src/main/rust/src/bin/rust_safer_xorshift.rs +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2021 Sam Leonard - * - * This file is part of java-2-times-faster-than-c. - * - * java-2-times-faster-than-c is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * java-2-times-faster-than-c is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with shader-web-background. If not, see . - */ - -mod xorshift_rng; -use xorshift_rng::Xorshift64sRng; - -use std::ptr; - -const MAX_PAYLOAD_SIZE: i32 = 50; -const INITIAL_NODE_COUNT: i32 = 10000; -const MUTATION_COUNT: i64 = 1000000; -const MAX_MUTATION_SIZE: i32 = 200; - -struct Node { - id: i64, - payload: Vec, - next: Option, - previous: Option, -} - -type NodePointer = ptr::NonNull; - -fn main() { - let mut node_id: i64 = 0; - let mut rng = Xorshift64sRng::new(42); - - let mut head = Node::new(node_id, &mut rng); node_id += 1; - - // hell yeah who needs safety when we have pointers, YEE HAWWW - unsafe { - Node::join(head, Node::new(node_id, &mut rng)); node_id += 1; - for _ in 2..INITIAL_NODE_COUNT { - Node::insert(head, Node::new(node_id, &mut rng)); node_id += 1; - } - let mut node_count: i64 = INITIAL_NODE_COUNT as i64; - for _ in 0..MUTATION_COUNT { - let mut delete_count = (rng.get_rand() * MAX_MUTATION_SIZE as f64) as i32; - if delete_count > (node_count - 2) as i32 { - delete_count = (node_count - 2) as i32; - } - for _ in 0..delete_count { - let to_delete = head; - head = (*head.as_ptr()).previous.expect("Head has empty previous node."); - Node::delete(to_delete); - } - node_count -= delete_count as i64; - let insert_count = (rng.get_rand() * MAX_MUTATION_SIZE as f64) as i32; - for _ in 0..insert_count { - Node::insert(head, Node::new(node_id, &mut rng)); node_id += 1; - head = (*head.as_ptr()).next.expect("Head has empty next node."); - } - node_count += insert_count as i64; - } - let mut checksum: i64 = 0; - let mut traveler = head; - loop { - checksum += (*traveler.as_ptr()).id as i64 + (*traveler.as_ptr()).payload.len() as i64; - if let Some(val) = (*traveler.as_ptr()).payload.get(0) { - checksum += *val as i64; - } - if let Some(val) = (*traveler.as_ptr()).payload.last() { - checksum += *val as i64; - } - traveler = (*traveler.as_ptr()).next.expect("Traveler has an empty next pointer."); - if traveler == head { break }; - } - println!("node count: {}", node_count); - println!("checksum: {}", checksum); - } -} - -impl Node { - fn new(id: i64, rng: &mut Xorshift64sRng) -> NodePointer { - NodePointer::new( - Box::into_raw(Box::new(Self{ - id, - payload: (0..(rng.get_rand() * MAX_PAYLOAD_SIZE as f64) as i8).collect(), - next: None, - previous: None, - })) - ).expect("Failed to Allocate node.") - } - - unsafe fn join(alfa: NodePointer, beta: NodePointer) { - (*alfa.as_ptr()).previous = Some(beta); - (*alfa.as_ptr()).next = Some(beta); - (*beta.as_ptr()).previous = Some(alfa); - (*beta.as_ptr()).next = Some(alfa); - } - - unsafe fn delete(node: NodePointer) { - let node_next: NodePointer = (*node.as_ptr()).next.expect("Node to delete has empty next pointer."); - let node_prev: NodePointer = (*node.as_ptr()).previous.expect("Node to delete has empty previous pointer."); - - (*node_next.as_ptr()).previous = Some(node_prev); - (*node_prev.as_ptr()).next = Some(node_next); - - // let the created box do the deallocation when it goes out of scope - Box::from_raw(node.as_ptr()); - } - - unsafe fn insert(previous: NodePointer, node: NodePointer) { - (*node.as_ptr()).next = (*previous.as_ptr()).next; - (*node.as_ptr()).previous = Some(previous); - let prev_next = (*previous.as_ptr()).next.expect("Empty next pointer on previous node in insert."); - (*prev_next.as_ptr()).previous = Some(node); - (*previous.as_ptr()).next = Some(node); - } -} From 416b212e82b4d1abfa61715485d5e20fb7a24944 Mon Sep 17 00:00:00 2001 From: Sam Date: Sun, 21 Mar 2021 01:31:06 +0000 Subject: [PATCH 7/8] Added csharp and kotlin and made some other changes. --- build-clang.sh | 4 +- build-csharp.sh | 3 +- build-gcc.sh | 4 +- build-go.sh | 2 - build.gradle.kts | 8 ++-- src/main/csharp/.gitignore | 4 +- .../{ => java-faster-csharp}/Program.cs | 27 +++++------ .../java-faster-csharp.csproj | 13 ++++++ src/main/csharp/xorshift_rng/Program.cs | 22 +++++++++ .../csharp/xorshift_rng/XorShift64SRng.cs | 32 +++++++++++++ .../xorshift_rng.csproj} | 0 src/main/go/java_faster_than_go.go | 46 +++++++++---------- src/main/go/xorshift_rng.go | 45 +++++++++--------- .../test/howfast/Java2TimesFasterThanC.java | 11 ++--- .../com/xemantic/test/howfast/XORShift.java | 16 +++---- src/main/kotlin/KotlinAsFastAsJava.kt | 28 ++++------- .../{AlmostPseudoRandom.kt => XorShift.kt} | 28 +++++++++-- 17 files changed, 184 insertions(+), 109 deletions(-) rename src/main/csharp/{ => java-faster-csharp}/Program.cs (80%) create mode 100644 src/main/csharp/java-faster-csharp/java-faster-csharp.csproj create mode 100644 src/main/csharp/xorshift_rng/Program.cs create mode 100644 src/main/csharp/xorshift_rng/XorShift64SRng.cs rename src/main/csharp/{java-4-times-faster-than-c-sharp.csproj => xorshift_rng/xorshift_rng.csproj} (100%) rename src/main/kotlin/{AlmostPseudoRandom.kt => XorShift.kt} (60%) diff --git a/build-clang.sh b/build-clang.sh index c077909..a627833 100755 --- a/build-clang.sh +++ b/build-clang.sh @@ -1,5 +1,5 @@ #!/usr/bin/env sh mkdir -p build/clang -clang -O3 -o build/clang/xorshift_rng src/main/c/xorshift_rng.c -clang -O3 -o build/clang/java_2_times_faster_than_c src/main/c/java_2_times_faster_than_c.c -lm +clang -O3 -march=native -o build/clang/xorshift_rng src/main/c/xorshift_rng.c +clang -O3 -march=native -o build/clang/java_2_times_faster_than_c src/main/c/java_2_times_faster_than_c.c -lm diff --git a/build-csharp.sh b/build-csharp.sh index 0a59df7..f548f38 100755 --- a/build-csharp.sh +++ b/build-csharp.sh @@ -1,4 +1,5 @@ #!/usr/bin/env sh mkdir -p build/csharp -dotnet publish -c Release -o ./build/csharp ./src/main/csharp/java-4-times-faster-than-c-sharp.csproj +dotnet publish -c Release -o ./build/csharp ./src/main/csharp/java-faster-csharp/java-faster-csharp.csproj +dotnet publish -c Release -o ./build/csharp ./src/main/csharp/xorshift_rng/xorshift_rng.csproj diff --git a/build-gcc.sh b/build-gcc.sh index 2c08c51..884b313 100755 --- a/build-gcc.sh +++ b/build-gcc.sh @@ -1,5 +1,5 @@ #!/usr/bin/env sh mkdir -p build/gcc -gcc -O3 -o build/gcc/xorshift_rng src/main/c/xorshift_rng.c -gcc -O3 -o build/gcc/java_2_times_faster_than_c src/main/c/java_2_times_faster_than_c.c -lm +gcc -O3 -march=native -o build/gcc/xorshift_rng src/main/c/xorshift_rng.c +gcc -O3 -march=native -o build/gcc/java_2_times_faster_than_c src/main/c/java_2_times_faster_than_c.c -lm diff --git a/build-go.sh b/build-go.sh index edfb30d..52887f2 100755 --- a/build-go.sh +++ b/build-go.sh @@ -2,6 +2,4 @@ mkdir -p build/go go build -o ./build/go/java_faster_than_go ./src/main/go/java_faster_than_go.go -go build -o ./build/go/almost_pseudo_random ./src/main/go/almost_pseudo_random.go go build -o ./build/go/xorshift_rng ./src/main/go/xorshift_rng.go -go build -o ./build/go/java_faster_than_go_xorshift ./src/main/go/java_faster_than_go_xorshift.go diff --git a/build.gradle.kts b/build.gradle.kts index 6907970..91b4b1b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,8 +8,8 @@ group = "com.xemantic.test" version = "1.0-SNAPSHOT" java { - sourceCompatibility = JavaVersion.VERSION_15 - targetCompatibility = JavaVersion.VERSION_15 + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 } dependencies { implementation(kotlin("stdlib-jdk8")) @@ -20,9 +20,9 @@ repositories { } val compileKotlin: KotlinCompile by tasks compileKotlin.kotlinOptions { - jvmTarget = "15" + jvmTarget = "11" } val compileTestKotlin: KotlinCompile by tasks compileTestKotlin.kotlinOptions { - jvmTarget = "15" + jvmTarget = "11" } diff --git a/src/main/csharp/.gitignore b/src/main/csharp/.gitignore index 4c7473d..cd42ee3 100644 --- a/src/main/csharp/.gitignore +++ b/src/main/csharp/.gitignore @@ -1,2 +1,2 @@ -/bin -/obj +bin/ +obj/ diff --git a/src/main/csharp/Program.cs b/src/main/csharp/java-faster-csharp/Program.cs similarity index 80% rename from src/main/csharp/Program.cs rename to src/main/csharp/java-faster-csharp/Program.cs index fa25605..35d05f2 100644 --- a/src/main/csharp/Program.cs +++ b/src/main/csharp/java-faster-csharp/Program.cs @@ -1,11 +1,11 @@ using System; using System.Linq; +using XorShift; namespace csharp { static class Program { - private const int MaxPayloadSize = 50; private const int InitialNodeCount = 10000; private const long MutationCount = 1000000L; @@ -18,10 +18,10 @@ class Node public long Id { get; } public byte[] Payload { get; } - public Node(long id) + public Node(long id, XorShift64SRng rng) { Id = id; - int size = (int) (AlmostPseudoRandom(id) * (double) MaxPayloadSize); + int size = (int) (rng.getRand() * (double) MaxPayloadSize); byte[] data = new byte[size]; for (int i = 0; i < size; i++) { @@ -58,26 +58,21 @@ public void Insert(Node node) } } - private static double AlmostPseudoRandom(long ordinal) - { - return (Math.Sin(((double) ordinal) * 100000.0) + 1.0) % 1.0; - } - static void Main(string[] args) { long nodeId = 0; - long mutationSeq = 0; - var head = new Node(nodeId++); - head.Join(new Node(nodeId++)); + XorShift64SRng rng = new XorShift64SRng(42); + var head = new Node(nodeId++, rng); + head.Join(new Node(nodeId++, rng)); for (var i = 2; i < InitialNodeCount; i++) { - head.Insert(new Node(nodeId++)); + head.Insert(new Node(nodeId++, rng)); } long nodeCount = InitialNodeCount; for (long i = 0; i < MutationCount; i++) { - var deleteCount = (int) (AlmostPseudoRandom(mutationSeq++) * (double) MaxMutationSize); + var deleteCount = (int) (rng.getRand() * (double) MaxMutationSize); if (deleteCount > (nodeCount - 2)) { deleteCount = (int) nodeCount - 2; @@ -91,10 +86,10 @@ static void Main(string[] args) } nodeCount -= deleteCount; - var insertCount = (int) (AlmostPseudoRandom(mutationSeq++) * (double) MaxMutationSize); + var insertCount = (int) (rng.getRand() * (double) MaxMutationSize); for (int j = 0; j < insertCount; j++) { - head.Insert(new Node(nodeId++)); + head.Insert(new Node(nodeId++, rng)); head = head.Next; } @@ -119,4 +114,4 @@ static void Main(string[] args) Console.WriteLine("checksum: " + checksum); } } -} \ No newline at end of file +} diff --git a/src/main/csharp/java-faster-csharp/java-faster-csharp.csproj b/src/main/csharp/java-faster-csharp/java-faster-csharp.csproj new file mode 100644 index 0000000..1548d51 --- /dev/null +++ b/src/main/csharp/java-faster-csharp/java-faster-csharp.csproj @@ -0,0 +1,13 @@ + + + + + + + + Exe + net5.0 + csharp + + + diff --git a/src/main/csharp/xorshift_rng/Program.cs b/src/main/csharp/xorshift_rng/Program.cs new file mode 100644 index 0000000..051304d --- /dev/null +++ b/src/main/csharp/xorshift_rng/Program.cs @@ -0,0 +1,22 @@ +using System; +using System.Linq; + +namespace XorShift +{ + static class Program + { + private const ulong ITERATION_COUNT = 1000000000L; + + static void Main(string[] args) + { + double checksum = 0; + XorShift64SRng rng = new XorShift64SRng(42); + for (uint i = 0; i < ITERATION_COUNT; i++) + { + checksum += rng.getRand(); + } + + Console.WriteLine($"checksum: {checksum}"); + } + } +} diff --git a/src/main/csharp/xorshift_rng/XorShift64SRng.cs b/src/main/csharp/xorshift_rng/XorShift64SRng.cs new file mode 100644 index 0000000..2a4461f --- /dev/null +++ b/src/main/csharp/xorshift_rng/XorShift64SRng.cs @@ -0,0 +1,32 @@ +using System; +using System.Linq; + +namespace XorShift +{ + public class XorShift64SRng + { + private ulong State; + + public XorShift64SRng(ulong state) + { + State = state; + } + + public double getRand() + { + ulong x = State; + x ^= x >> 12; // a + x ^= x << 25; // b + x ^= x >> 27; // c + State = x; + + ulong rand_val = x * 0x2545F4914F6CDD1DL; + + // mix to a double + uint a = (uint) (rand_val >> 32); + uint b = (uint) rand_val; + + return ((double) (a >> 5) * 67108864.0 + (double) (b >> 6)) * (1.0 / 9007199254740991.0); + } + } +} diff --git a/src/main/csharp/java-4-times-faster-than-c-sharp.csproj b/src/main/csharp/xorshift_rng/xorshift_rng.csproj similarity index 100% rename from src/main/csharp/java-4-times-faster-than-c-sharp.csproj rename to src/main/csharp/xorshift_rng/xorshift_rng.csproj diff --git a/src/main/go/java_faster_than_go.go b/src/main/go/java_faster_than_go.go index 6d3c688..3f52dd6 100644 --- a/src/main/go/java_faster_than_go.go +++ b/src/main/go/java_faster_than_go.go @@ -33,29 +33,29 @@ const InitialNodeCount int = 10000 const MutationCount int64 = 1000000 const MaxMutationSize int = 200 -type xorshift64s_rng struct { - a uint64; -}; - -func (state * xorshift64s_rng) get_rand() float64 { - var x = state.a; /* The state must be seeded with a nonzero value. */ - x ^= x >> 12; // a - x ^= x << 25; // b - x ^= x >> 27; // c - state.a = x; - var rand_val = x * uint64(0x2545F4914F6CDD1D); +type xorshift64sRng struct { + a uint64 +} + +func (state *xorshift64sRng) getRand() float64 { + var x = state.a /* The state must be seeded with a nonzero value. */ + x ^= x >> 12 // a + x ^= x << 25 // b + x ^= x >> 27 // c + state.a = x + var randVal = x * uint64(0x2545F4914F6CDD1D) // mix to a double - var a = rand_val >> 32; - var b = rand_val & 0xFFFFFFFF; + var a = randVal >> 32 + var b = randVal & 0xFFFFFFFF - return (float64(a >> 5) * 67108864.0 + float64(b >> 6)) * (1.0 / 9007199254740991.0); + return (float64(a>>5)*67108864.0 + float64(b>>6)) * (1.0 / 9007199254740991.0) } -func new_rng(a uint64) *xorshift64s_rng { - return &xorshift64s_rng { - a: a, - }; +func newRng(a uint64) *xorshift64sRng { + return &xorshift64sRng{ + a: a, + } } type Node struct { @@ -84,8 +84,8 @@ func (node *Node) join(newNode *Node) { newNode.next = node } -func createNode(id int, rng *xorshift64s_rng) *Node { - size := int(rng.get_rand() * float64(MaxPayloadSize)) +func createNode(id int, rng *xorshift64sRng) *Node { + size := int(rng.getRand() * float64(MaxPayloadSize)) data := make([]byte, size); for i := 0; i < size; i++ { data[i] = byte(i); @@ -114,7 +114,7 @@ func main() { } nodeId := 0 - rng := new_rng(42); + rng := newRng(42); head := createNode(nodeId, rng) nodeId++ head.join(createNode(nodeId, rng)) @@ -127,7 +127,7 @@ func main() { nodeCount := InitialNodeCount for i := int64(0); i < MutationCount; i++ { - deleteCount := int(rng.get_rand() * float64(MaxMutationSize)) + deleteCount := int(rng.getRand() * float64(MaxMutationSize)) if deleteCount > (nodeCount -2) { deleteCount = nodeCount - 2 } @@ -139,7 +139,7 @@ func main() { } nodeCount -= deleteCount - insertCount := int(rng.get_rand() * float64(MaxMutationSize)) + insertCount := int(rng.getRand() * float64(MaxMutationSize)) for j := 0; j < insertCount; j++ { head.insert(createNode(nodeId, rng)) diff --git a/src/main/go/xorshift_rng.go b/src/main/go/xorshift_rng.go index 194555c..ddd684c 100644 --- a/src/main/go/xorshift_rng.go +++ b/src/main/go/xorshift_rng.go @@ -23,39 +23,40 @@ import ( "fmt" ) -const IterationCount int64 = 1000000000 +const iterationCount int64 = 1000000000 -type xorshift64s_rng struct { - a uint64; -}; +type xorshift64sRng struct { + a uint64 +} -func (state * xorshift64s_rng) get_rand() float64 { - var x = state.a; /* The state must be seeded with a nonzero value. */ - x ^= x >> 12; // a - x ^= x << 25; // b - x ^= x >> 27; // c - state.a = x; - var rand_val = x * uint64(0x2545F4914F6CDD1D); +func (state *xorshift64sRng) getRand() float64 { + var x = state.a /* The state must be seeded with a nonzero value. */ + x ^= x >> 12 // a + x ^= x << 25 // b + x ^= x >> 27 // c + state.a = x + var randVal = x * uint64(0x2545F4914F6CDD1D) // mix to a double - var a = rand_val >> 32; - var b = rand_val & 0xFFFFFFFF; + var a = randVal >> 32 + var b = randVal & 0xFFFFFFFF - return (float64(a >> 5) * 67108864.0 + float64(b >> 6)) * (1.0 / 9007199254740991.0); + return (float64(a>>5)*67108864.0 + float64(b>>6)) * (1.0 / 9007199254740991.0) } -func new_rng(a uint64) *xorshift64s_rng { - return &xorshift64s_rng { - a: a, - }; +func newRng(a uint64) *xorshift64sRng { + return &xorshift64sRng{ + a: a, + } } func main() { - var rng = new_rng(42); + var rng = newRng(42) var checksum float64 = 0 - for i := int64(0); i < IterationCount; i++ { - checksum += rng.get_rand(); + for i := int64(0); i < iterationCount; i++ { + checksum += rng.getRand() } - fmt.Printf("checksum: %g\n", checksum) + + fmt.Println("checksum:", checksum) } diff --git a/src/main/java/com/xemantic/test/howfast/Java2TimesFasterThanC.java b/src/main/java/com/xemantic/test/howfast/Java2TimesFasterThanC.java index cae8a14..22c6b52 100644 --- a/src/main/java/com/xemantic/test/howfast/Java2TimesFasterThanC.java +++ b/src/main/java/com/xemantic/test/howfast/Java2TimesFasterThanC.java @@ -34,9 +34,9 @@ private static class Node { private Node previous; private Node next; - private Node(long id, xorshift64s_rng rng) { + private Node(long id, xorshift64SRng rng) { this.id = id; - int size = (int) (rng.get_rand() * (double) MAX_PAYLOAD_SIZE); + int size = (int) (rng.getRand() * (double) MAX_PAYLOAD_SIZE); byte[] data = new byte[size]; for (int i = 0; i < size; i++) { data[i] = (byte) i; @@ -68,7 +68,7 @@ void insert(Node node) { public static void main(String[] args) { long nodeId = 0; - xorshift64s_rng rng = new xorshift64s_rng(42); + xorshift64SRng rng = new xorshift64SRng(42); Node head = new Node(nodeId++, rng); head.join(new Node(nodeId++, rng)); for (int i = 2; i < INITIAL_NODE_COUNT; i++) { @@ -76,7 +76,7 @@ public static void main(String[] args) { } long nodeCount = INITIAL_NODE_COUNT; for (long i = 0; i < MUTATION_COUNT; i++) { - int deleteCount = (int) (rng.get_rand() * (double) MAX_MUTATION_SIZE); + int deleteCount = (int) (rng.getRand() * (double) MAX_MUTATION_SIZE); if (deleteCount > (nodeCount - 2)) { deleteCount = (int) nodeCount - 2; } @@ -86,7 +86,7 @@ public static void main(String[] args) { toDelete.delete(); } nodeCount -= deleteCount; - int insertCount = (int) (rng.get_rand() * (double) MAX_MUTATION_SIZE); + int insertCount = (int) (rng.getRand() * (double) MAX_MUTATION_SIZE); for (int j = 0; j < insertCount; j++) { head.insert(new Node(nodeId++, rng)); head = head.next; @@ -107,5 +107,4 @@ public static void main(String[] args) { System.out.println("node count: " + nodeCount); System.out.println("checksum: " + checksum); } - } diff --git a/src/main/java/com/xemantic/test/howfast/XORShift.java b/src/main/java/com/xemantic/test/howfast/XORShift.java index 66a1f48..f2ab36e 100644 --- a/src/main/java/com/xemantic/test/howfast/XORShift.java +++ b/src/main/java/com/xemantic/test/howfast/XORShift.java @@ -19,25 +19,25 @@ package com.xemantic.test.howfast; -class xorshift64s_rng { +class xorshift64SRng { private long state; - xorshift64s_rng(long state) { + xorshift64SRng(long state) { this.state = state; } - double get_rand() { + double getRand() { long x = this.state; /* The state must be seeded with a nonzero value. */ x ^= x >>> 12; // a x ^= x << 25; // b x ^= x >>> 27; // c this.state = x; - long rand_val = x * 0x2545F4914F6CDD1DL; + long randVal = x * 0x2545F4914F6CDD1DL; // mix to a double - long a = (rand_val >>> 32) & 0xFFFFFFFFL; - long b = rand_val & 0xFFFFFFFFL; + long a = (randVal >>> 32) & 0xFFFFFFFFL; + long b = randVal & 0xFFFFFFFFL; return ((a >> 5) * 67108864.0 + (b >> 6)) * (1.0 / 9007199254740991.0); } @@ -48,11 +48,11 @@ public class XORShift { private static final long ITERATION_COUNT = 1000000000L; public static void main(String[] args) { - xorshift64s_rng rng = new xorshift64s_rng(42); + xorshift64SRng rng = new xorshift64SRng(42); double checksum = 0; for (long i = 0; i < ITERATION_COUNT; i++) { - checksum += rng.get_rand(); + checksum += rng.getRand(); } System.out.println("checksum: " + checksum); } diff --git a/src/main/kotlin/KotlinAsFastAsJava.kt b/src/main/kotlin/KotlinAsFastAsJava.kt index fac684e..538e446 100644 --- a/src/main/kotlin/KotlinAsFastAsJava.kt +++ b/src/main/kotlin/KotlinAsFastAsJava.kt @@ -26,14 +26,11 @@ private const val INITIAL_NODE_COUNT = 10000 private const val MUTATION_COUNT = 1000000L private const val MAX_MUTATION_SIZE = 200 -private fun almostPseudoRandom(ordinal: Long) = - (sin(ordinal.toDouble() * 100000.0) + 1.0) % 1.0 - -private class Node(val id: Long) { +private class Node(val id: Long, rng: XorShift64SRng) { var previous: Node? = null var next: Node? = null val payload: ByteArray = ByteArray( - (almostPseudoRandom(id) * MAX_PAYLOAD_SIZE).toInt() + (rng.getRand() * MAX_PAYLOAD_SIZE).toInt() ) init { @@ -61,22 +58,19 @@ private class Node(val id: Long) { next?.previous = node next = node } - } fun main() { + var rng = XorShift64SRng(42UL) var nodeId: Long = 0 - var mutationSeq: Long = 0 - var head = Node(nodeId++) - head.join(Node(nodeId++)) + var head = Node(nodeId++, rng) + head.join(Node(nodeId++, rng)) for (i in 2 until INITIAL_NODE_COUNT) { - head.insert(Node(nodeId++)) + head.insert(Node(nodeId++, rng)) } var nodeCount = INITIAL_NODE_COUNT.toLong() for (i in 0 until MUTATION_COUNT) { - var deleteCount = - (almostPseudoRandom(mutationSeq++) - * MAX_MUTATION_SIZE.toDouble()).toInt() + var deleteCount = (rng.getRand() * MAX_MUTATION_SIZE.toDouble()).toInt() if (deleteCount > nodeCount - 2) { deleteCount = nodeCount.toInt() - 2 } @@ -86,11 +80,9 @@ fun main() { toDelete.delete() } nodeCount -= deleteCount.toLong() - val insertCount = - (almostPseudoRandom(mutationSeq++) - * MAX_MUTATION_SIZE.toDouble()).toInt() + val insertCount = (rng.getRand() * MAX_MUTATION_SIZE.toDouble()).toInt() for (j in 0 until insertCount) { - head.insert(Node(nodeId++)) + head.insert(Node(nodeId++, rng)) head = head.next!! } nodeCount += insertCount.toLong() @@ -106,4 +98,4 @@ fun main() { } while (traveler.next.also { traveler = it!! } !== head) println("node count: $nodeCount") println("checksum: $checksum") -} +} \ No newline at end of file diff --git a/src/main/kotlin/AlmostPseudoRandom.kt b/src/main/kotlin/XorShift.kt similarity index 60% rename from src/main/kotlin/AlmostPseudoRandom.kt rename to src/main/kotlin/XorShift.kt index 67192fd..8174818 100644 --- a/src/main/kotlin/AlmostPseudoRandom.kt +++ b/src/main/kotlin/XorShift.kt @@ -23,12 +23,34 @@ import kotlin.math.sin const val ITERATION_COUNT = 1000000000L +@ExperimentalUnsignedTypes +class XorShift64SRng(var state: ULong) { + init { + assert(state != 0UL) + } + + fun getRand(): Double { + var x: ULong = state /* The state must be seeded with a nonzero value. */ + x = x xor (x shr 12) // a + x = x xor (x shl 25) // b + x = x xor (x shr 27) // c + + state = x + val rand_val: ULong = x * 0x2545F4914F6CDD1DUL; + + // mix to a double + val a = (rand_val shr 32).toUInt() + val b = (rand_val and 0xFFFFFFFFU).toUInt() + + return ((a shr 5).toDouble() * 67108864.0 + (b shr 6).toDouble()) * (1.0 / 9007199254740991.0) + } +} + fun main() { - fun almostPseudoRandom(ordinal: Long) = - (sin(ordinal.toDouble() * 100000.0) + 1.0) % 1.0 + var rng = XorShift64SRng(42UL); var checksum = 0.0 for (i in 0 until ITERATION_COUNT) { - checksum += almostPseudoRandom(i) + checksum += rng.getRand() } println("checksum: $checksum") } From 64119fc30531c987c5e68c7209f6c07d7b134cf2 Mon Sep 17 00:00:00 2001 From: Sam Date: Sun, 21 Mar 2021 13:12:17 +0000 Subject: [PATCH 8/8] Added javascript version. --- build.gradle.kts | 8 ++--- src/main/html/xorshift_rng.html | 32 +++++++++++++++++++ ...lmost_pseudo_random.js => xorshift_rng.js} | 27 +++++++++++++--- 3 files changed, 59 insertions(+), 8 deletions(-) create mode 100644 src/main/html/xorshift_rng.html rename src/main/javascript/{almost_pseudo_random.js => xorshift_rng.js} (52%) diff --git a/build.gradle.kts b/build.gradle.kts index 91b4b1b..6907970 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,8 +8,8 @@ group = "com.xemantic.test" version = "1.0-SNAPSHOT" java { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 + sourceCompatibility = JavaVersion.VERSION_15 + targetCompatibility = JavaVersion.VERSION_15 } dependencies { implementation(kotlin("stdlib-jdk8")) @@ -20,9 +20,9 @@ repositories { } val compileKotlin: KotlinCompile by tasks compileKotlin.kotlinOptions { - jvmTarget = "11" + jvmTarget = "15" } val compileTestKotlin: KotlinCompile by tasks compileTestKotlin.kotlinOptions { - jvmTarget = "11" + jvmTarget = "15" } diff --git a/src/main/html/xorshift_rng.html b/src/main/html/xorshift_rng.html new file mode 100644 index 0000000..2954ca6 --- /dev/null +++ b/src/main/html/xorshift_rng.html @@ -0,0 +1,32 @@ + + + + + + + Almost pseudo random test + + + + + + diff --git a/src/main/javascript/almost_pseudo_random.js b/src/main/javascript/xorshift_rng.js similarity index 52% rename from src/main/javascript/almost_pseudo_random.js rename to src/main/javascript/xorshift_rng.js index bfe30a7..9ea238e 100644 --- a/src/main/javascript/almost_pseudo_random.js +++ b/src/main/javascript/xorshift_rng.js @@ -14,18 +14,37 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with shader-web-background. If not, see . + * alet with shader-web-background. If not, see . */ const ITERATION_COUNT = 1000000000; -function almostPseudoRandom(ordinal) { - return (Math.sin(ordinal * 100000.0) + 1.0) % 1.0; +class XorShift64SRng { + constructor(state) { + this.state = state; + } + + getRand() { + let x = this.state; /* The state must be seeded with a nonzero value. */ + x ^= x >> 12n; // a + x ^= BigInt.asUintN(64, x << 25n); // b + x ^= x >> 27n; // c + this.state = x; + + let randVal = BigInt.asUintN(64, x * 0x2545F4914F6CDD1Dn); + + // mix to a double + let a = BigInt.asUintN(32, randVal >> 32n); + let b = BigInt.asUintN(32, randVal); + + return (Number(a >> 5n) * 67108864.0 + Number(b >> 6n)) * (1.0 / 9007199254740991.0); + } } +let rng = new XorShift64SRng(42n); let checksum = 0; for (let i = 0; i < ITERATION_COUNT; i++) { - checksum += almostPseudoRandom(i); + checksum += rng.getRand(); } console.log("checksum: " + checksum);