add StringInterner

main
_ 2023-10-02 12:27:25 -05:00
parent b9865b7174
commit 08bbb53900
3 changed files with 232 additions and 0 deletions

View File

@ -23,6 +23,7 @@ fn main () {
// Fastest on my system, at 83 ms
timer (|| n_body_2::<BTreeTable3> (100000), "BTreeTable3");
timer (|| n_body_2::<BTreeTable3> (500000), "BTreeTable3");
timer (|| n_body_3::<BTreeTable4> (500000), "BTreeTable4");
}
trait Table {
@ -444,3 +445,192 @@ fn n_body_2 <T: Default + Table2> (num_iters: usize) {
}
println! ("{:0.9}", energy (&bodies));
}
trait Table3 {
fn get (&self, key: u64) -> f64;
fn set (&mut self, key: u64, value: f64);
}
#[derive (Default)]
struct BTreeTable4 (BTreeMap <u64, f64>);
impl Table3 for BTreeTable4 {
fn get (&self, key: u64) -> f64 {
*self.0.get (&key).unwrap ()
}
fn set (&mut self, key: u64, value: f64) {
self.0.insert (key, value);
}
}
fn n_body_3 <T: Default + Table3> (num_iters: usize) {
const X: u64 = 1;
const Y: u64 = 2;
const Z: u64 = 3;
const VX: u64 = 4;
const VY: u64 = 5;
const VZ: u64 = 6;
const MASS: u64 = 7;
let days_per_year = 365.24;
let mut bodies = vec! [];
{
let mut t = T::default ();
t.set (X, 0.0);
t.set (Y, 0.0);
t.set (Z, 0.0);
t.set (VX, 0.0);
t.set (VY, 0.0);
t.set (VZ, 0.0);
t.set (MASS, SOLAR_MASS);
bodies.push (t);
}
{
let mut t = T::default ();
t.set (X, 4.84143144246472090e+00);
t.set (Y, -1.16032004402742839e+00);
t.set (Z, -1.03622044471123109e-01);
t.set (VX, 1.66007664274403694e-03 * days_per_year);
t.set (VY, 7.69901118419740425e-03 * days_per_year);
t.set (VZ, -6.90460016972063023e-05 * days_per_year);
t.set (MASS, 9.54791938424326609e-04 * SOLAR_MASS);
bodies.push (t);
}
{
let mut t = T::default ();
t.set (X, 8.34336671824457987e+00);
t.set (Y, 4.12479856412430479e+00);
t.set (Z, -4.03523417114321381e-01);
t.set (VX, -2.76742510726862411e-03 * days_per_year);
t.set (VY, 4.99852801234917238e-03 * days_per_year);
t.set (VZ, 2.30417297573763929e-05 * days_per_year);
t.set (MASS, 2.85885980666130812e-04 * SOLAR_MASS);
bodies.push (t);
}
{
let mut t = T::default ();
t.set (X, 1.28943695621391310e+01);
t.set (Y, -1.51111514016986312e+01);
t.set (Z, -2.23307578892655734e-01);
t.set (VX, 2.96460137564761618e-03 * days_per_year);
t.set (VY, 2.37847173959480950e-03 * days_per_year);
t.set (VZ, -2.96589568540237556e-05 * days_per_year);
t.set (MASS, 4.36624404335156298e-05 * SOLAR_MASS);
bodies.push (t);
}
{
let mut t = T::default ();
t.set (X, 1.53796971148509165e+01);
t.set (Y, -2.59193146099879641e+01);
t.set (Z, 1.79258772950371181e-01);
t.set (VX, 2.68067772490389322e-03 * days_per_year);
t.set (VY, 1.62824170038242295e-03 * days_per_year);
t.set (VZ, -9.51592254519715870e-05 * days_per_year);
t.set (MASS, 5.15138902046611451e-05 * SOLAR_MASS);
bodies.push (t);
}
fn advance <T: Table3> (bodies: &mut [T], dt: f64) {
let nbody = bodies.len ();
for i in 0..nbody {
let bix;
let biy;
let biz;
let bimass;
let mut bivx;
let mut bivy;
let mut bivz;
{
let bi = &mut bodies [i];
bix = bi.get (X);
biy = bi.get (Y);
biz = bi.get (Z);
bimass = bi.get (MASS);
bivx = bi.get (VX);
bivy = bi.get (VY);
bivz = bi.get (VZ);
}
for j in i + 1..nbody {
let bj = &mut bodies [j];
let dx = bix - bj.get (X);
let dy = biy - bj.get (Y);
let dz = biz - bj.get (Z);
let mut mag = (dx * dx + dy * dy + dz * dz).sqrt ();
mag = dt / (mag * mag * mag);
let mut bm = bj.get (MASS) * mag;
bivx -= dx * bm;
bivy -= dy * bm;
bivz -= dz * bm;
bm = bimass * mag;
bj.set (VX, bj.get (VX) + dx * bm);
bj.set (VY, bj.get (VY) + dy * bm);
bj.set (VZ, bj.get (VZ) + dz * bm);
}
let bi = &mut bodies [i];
bi.set (VX, bivx);
bi.set (VY, bivy);
bi.set (VZ, bivz);
bi.set (X, bix + dt * bivx);
bi.set (Y, biy + dt * bivy);
bi.set (Z, biz + dt * bivz);
}
}
fn energy <T: Table3> (bodies: &[T]) -> f64 {
let mut e = 0.0;
for (i, bi) in bodies.iter ().enumerate () {
let vx = bi.get (VX);
let vy = bi.get (VY);
let vz = bi.get (VZ);
let bim = bi.get (MASS);
e += 0.5 * bim * (vx * vx + vy * vy + vz * vz);
for j in i + 1..bodies.len () {
let bj = &bodies [j];
let dx = bi.get (X) - bj.get (X);
let dy = bi.get (Y) - bj.get (Y);
let dz = bi.get (Z) - bj.get (Z);
let distance = (dx * dx + dy * dy + dz * dz).sqrt ();
e -= (bim * bj.get (MASS)) / distance;
}
}
e
}
fn offset_momentum <T: Table3> (b: &mut [T]) {
let mut px = 0.0;
let mut py = 0.0;
let mut pz = 0.0;
for bi in b.iter () {
let bim = bi.get (MASS);
px += bi.get (VX) * bim;
py += bi.get (VY) * bim;
pz += bi.get (VZ) * bim;
}
let bimass = b [0].get (MASS);
b [0].set (VX, -px / bimass);
b [0].set (VY, -py / bimass);
b [0].set (VZ, -pz / bimass);
}
offset_momentum (&mut bodies);
println! ("{:0.9}", energy (&bodies));
for _ in 0..num_iters {
advance (&mut bodies, 0.01);
}
println! ("{:0.9}", energy (&bodies));
}

View File

@ -2,6 +2,7 @@ mod error;
mod instruction;
mod loader;
mod state;
mod string_interner;
mod value;
pub use error::Error as Error;

View File

@ -0,0 +1,41 @@
pub struct InternedString (i64);
#[derive (Default)]
pub struct Interner {
table: std::collections::BTreeMap <String, i64>,
counter: i64,
}
impl Interner {
pub fn intern (&mut self, s: &str) -> InternedString {
match self.table.get (s) {
Some (x) => InternedString (*x),
None => {
self.counter += 1;
if self.counter == i64::MAX {
panic! ("Out of IDs");
}
self.table.insert (s.to_string (), self.counter);
InternedString (self.counter)
}
}
}
}
#[cfg (test)]
mod tests {
use super::*;
#[test]
fn test () {
let mut interner = Interner::default ();
assert_eq! (interner.intern ("x").0, 1);
assert_eq! (interner.intern ("x").0, 1);
assert_eq! (interner.intern ("y").0, 2);
assert_eq! (interner.intern ("z").0, 3);
assert_eq! (interner.intern ("y").0, 2);
assert_eq! (interner.intern ("asdf").0, 4);
}
}