Create most naive starting solution (#22)
This commit is contained in:
102
Cargo.lock
generated
102
Cargo.lock
generated
@@ -126,7 +126,7 @@ dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.14",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -143,22 +143,22 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||
|
||||
[[package]]
|
||||
name = "const_panic"
|
||||
version = "0.2.7"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58baae561b85ca19b3122a9ddd35c8ec40c3bcd14fe89921824eae73f7baffbf"
|
||||
checksum = "6051f239ecec86fde3410901ab7860d458d160371533842974fc61f96d15879b"
|
||||
dependencies = [
|
||||
"konst_kernel",
|
||||
"typewit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_arbitrary"
|
||||
version = "1.3.0"
|
||||
version = "1.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3cdeb9ec472d588e539a818b2dee436825730da08ad0017c4b1a17676bdc8b7"
|
||||
checksum = "53e0efad4403bfc52dc201159c4b842a246a14b98c64b55dfd0f2d89729dfeb8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -212,6 +212,17 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "haversine-app"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"clap",
|
||||
"haversine",
|
||||
"json",
|
||||
"utf8-read",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
@@ -226,9 +237,9 @@ checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
|
||||
|
||||
[[package]]
|
||||
name = "io-lifetimes"
|
||||
version = "1.0.10"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
|
||||
checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
@@ -257,23 +268,17 @@ checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
|
||||
name = "json"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "konst_kernel"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7771682454392dfe62a909aba2c6efc6674e2ad0b678fbc33b154e2e1bd59b89"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.141"
|
||||
version = "0.2.144"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5"
|
||||
checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.3.1"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f"
|
||||
checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
@@ -299,9 +304,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.17.1"
|
||||
version = "1.17.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
|
||||
checksum = "9670a07f94779e00908f3e686eab508878ebb390ba6e604d3a284c00e8d0487b"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
@@ -311,18 +316,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.56"
|
||||
version = "1.0.59"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
|
||||
checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.26"
|
||||
version = "1.0.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
|
||||
checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
@@ -359,9 +364,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.37.11"
|
||||
version = "0.37.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85597d61f83914ddeba6a47b3b8ffe7365107221c2e557ed94426489fefb5f77"
|
||||
checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
@@ -394,7 +399,7 @@ checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.14",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -408,6 +413,14 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sim-wrapper"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"sim_8086",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sim_8086"
|
||||
version = "0.1.0"
|
||||
@@ -426,9 +439,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
version = "2.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -436,21 +449,22 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.14"
|
||||
name = "typewit"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcf316d5356ed6847742d036f8a39c3b8435cac10bd528a4bd461928a6ab34d5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
checksum = "7c52b4cb7830f995903b2fcff3f523d21efc1c11f6c1596dd544b7925a64ff56"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.8"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
|
||||
checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
|
||||
|
||||
[[package]]
|
||||
name = "utf8-read"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb566ac06e11c3f13872ebcb0e72ea5f97f0f65a16f45048d0adea21edc28018"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
@@ -529,11 +543,3 @@ name = "windows_x86_64_msvc"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
|
||||
|
||||
[[package]]
|
||||
name = "wrapper"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"sim_8086",
|
||||
]
|
||||
|
@@ -1,10 +1,11 @@
|
||||
[workspace]
|
||||
members = [
|
||||
"sim_8086",
|
||||
"wrapper",
|
||||
"sim-wrapper",
|
||||
"generator",
|
||||
"haversine",
|
||||
"json"
|
||||
"json",
|
||||
"haversine-app"
|
||||
]
|
||||
|
||||
[profile.release]
|
||||
|
@@ -1,7 +1,8 @@
|
||||
# Performance-Aware Programming coursework
|
||||
|
||||
Me running through [Performance-Aware Programming](https://www.computerenhance.com) in Rust.
|
||||
There are *certainly* bugs in the code; I mostly just bashed it out without thinking very hard, and without testing it except by using Casey's provided tests.
|
||||
There are *certainly* bugs in the 8086 simulator code; I mostly just bashed it out without thinking very hard, and without testing it except by using Casey's provided tests.
|
||||
It does, however, conform to all Casey's provided test cases except the "completionist decode" one.
|
||||
|
||||
## Licensing
|
||||
|
||||
|
@@ -23,7 +23,7 @@
|
||||
crate2nix,
|
||||
...
|
||||
}: let
|
||||
name = "wrapper";
|
||||
name = "sim-wrapper";
|
||||
in
|
||||
utils.lib.eachDefaultSystem
|
||||
(
|
||||
|
@@ -7,7 +7,7 @@ use rand::rngs::StdRng;
|
||||
use rand::{Rng, SeedableRng};
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::fs::File;
|
||||
use std::io::{BufWriter, Read, Write};
|
||||
use std::io::{BufWriter, Write};
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@@ -71,10 +71,10 @@ fn write_answer(data: &HaversineData, binary_filename: &str) {
|
||||
let output_file = File::create(binary_filename).unwrap();
|
||||
let mut writer = BufWriter::new(output_file);
|
||||
|
||||
let mut expected_sum: f64 = 0.0;
|
||||
let mut expected_average: f64 = 0.0;
|
||||
|
||||
let mut buf = [0u8; 8];
|
||||
for point in &data.pairs {
|
||||
for (count, point) in data.pairs.iter().enumerate() {
|
||||
let distance = distance::naive(point, earth::RADIUS);
|
||||
LittleEndian::write_f64(&mut buf, distance);
|
||||
|
||||
@@ -83,12 +83,14 @@ fn write_answer(data: &HaversineData, binary_filename: &str) {
|
||||
panic!("Failed to write everything")
|
||||
}
|
||||
|
||||
expected_sum += distance;
|
||||
expected_average = ((1.0 - (1.0 / (count as f64 + 1.0))) * expected_average)
|
||||
+ (distance / (count as f64 + 1.0));
|
||||
}
|
||||
|
||||
println!("Expected sum: {}", expected_sum);
|
||||
// sic!
|
||||
println!("Expected sum: {}", expected_average);
|
||||
|
||||
LittleEndian::write_f64(&mut buf, expected_sum);
|
||||
LittleEndian::write_f64(&mut buf, expected_average);
|
||||
let written = writer.write(&buf).unwrap();
|
||||
if written < buf.len() {
|
||||
panic!("Failed to write everything")
|
||||
@@ -97,64 +99,38 @@ fn write_answer(data: &HaversineData, binary_filename: &str) {
|
||||
writer.flush().unwrap();
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn read_answer(binary_filename: &str) -> (Vec<f64>, f64) {
|
||||
let mut file = File::create(binary_filename).unwrap();
|
||||
let file_size = file.metadata().unwrap().len();
|
||||
if file_size % 8 != 0 {
|
||||
panic!(
|
||||
"Malformed input file of size {} is not a multiple of 8",
|
||||
file_size
|
||||
)
|
||||
}
|
||||
let num_floats = file_size / 8;
|
||||
assert_ne!(num_floats, 0, "Empty file");
|
||||
let num_bytes = num_floats - 1;
|
||||
|
||||
let mut data = Vec::with_capacity(num_bytes as usize);
|
||||
let mut buf = [0u8, 8];
|
||||
|
||||
for _ in 0..num_floats {
|
||||
let bytes_read = file.read(&mut buf).unwrap();
|
||||
if bytes_read < 8 {
|
||||
panic!("Not enough bytes read")
|
||||
}
|
||||
|
||||
data.push(LittleEndian::read_f64(&buf));
|
||||
}
|
||||
|
||||
let bytes_read = file.read(&mut buf).unwrap();
|
||||
if bytes_read < 8 {
|
||||
panic!("Not enough bytes read")
|
||||
}
|
||||
|
||||
(data, LittleEndian::read_f64(&buf))
|
||||
}
|
||||
|
||||
fn point_within(
|
||||
point: &CoordinatePair,
|
||||
cluster_centre_x: f64,
|
||||
cluster_centre_y: f64,
|
||||
cluster_radius: f64,
|
||||
) -> bool {
|
||||
let mut distance = CoordinatePair {
|
||||
x0: point.x0,
|
||||
y0: point.y0,
|
||||
x1: cluster_centre_x,
|
||||
y1: cluster_centre_y,
|
||||
};
|
||||
if distance::naive(&distance, 1.0) > cluster_radius {
|
||||
return false;
|
||||
}
|
||||
|
||||
distance.x0 = point.x1;
|
||||
distance.y0 = point.y1;
|
||||
|
||||
distance::naive(&distance, 1.0) <= cluster_radius
|
||||
}
|
||||
|
||||
const CLUSTER_COUNT: usize = 20;
|
||||
|
||||
/// Returns the smaller one then the larger one.
|
||||
fn sample_two<R, D>(range: D, rng: &mut R) -> (f64, f64)
|
||||
where
|
||||
R: Rng,
|
||||
D: Distribution<f64>,
|
||||
{
|
||||
let x1 = range.sample(rng);
|
||||
let x2 = range.sample(rng);
|
||||
|
||||
if x1 < x2 {
|
||||
(x1, x2)
|
||||
} else {
|
||||
(x2, x1)
|
||||
}
|
||||
}
|
||||
|
||||
fn sample_point<R, D1, D2>(rng: &mut R, x_range: D1, y_range: D2) -> CoordinatePair
|
||||
where
|
||||
R: Rng,
|
||||
D1: Distribution<f64>,
|
||||
D2: Distribution<f64>,
|
||||
{
|
||||
CoordinatePair {
|
||||
x0: x_range.sample(rng),
|
||||
y0: y_range.sample(rng),
|
||||
x1: x_range.sample(rng),
|
||||
y1: y_range.sample(rng),
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args = Args::parse();
|
||||
println!("Method: {}", args.algorithm);
|
||||
@@ -170,13 +146,7 @@ fn main() {
|
||||
match args.algorithm {
|
||||
SelectionAlgorithm::Uniform => {
|
||||
for _ in 0usize..args.count {
|
||||
let point = CoordinatePair {
|
||||
x0: x_range.sample(&mut rng),
|
||||
y0: y_range.sample(&mut rng),
|
||||
x1: x_range.sample(&mut rng),
|
||||
y1: y_range.sample(&mut rng),
|
||||
};
|
||||
|
||||
let point = sample_point(&mut rng, x_range, y_range);
|
||||
v.push(point);
|
||||
}
|
||||
}
|
||||
@@ -189,29 +159,14 @@ fn main() {
|
||||
}
|
||||
|
||||
for _ in 0..CLUSTER_COUNT {
|
||||
// Uniformly sampling over lat/long pairs is dumb and biased towards the poles,
|
||||
// but :shrug: we'll just bias it away a bit by hand.
|
||||
let cluster_centre_x = x_range.sample(&mut rng);
|
||||
// Bias a bit away from the pole by shrinking it
|
||||
let cluster_centre_y = y_range.sample(&mut rng) * 0.9;
|
||||
let cluster_radius = rng.gen_range(0.1..0.4);
|
||||
let (min_x, max_x) = sample_two(x_range, &mut rng);
|
||||
let (min_y, max_y) = sample_two(y_range, &mut rng);
|
||||
|
||||
let x_range = rand::distributions::Uniform::from(min_x..max_x);
|
||||
let y_range = rand::distributions::Uniform::from(min_y..max_y);
|
||||
|
||||
for _ in 0..args.count / CLUSTER_COUNT {
|
||||
let mut point = CoordinatePair {
|
||||
x0: 0.0,
|
||||
y0: 0.0,
|
||||
x1: 0.0,
|
||||
// too big to ever be in the right place, so a suitable uninitialised value
|
||||
y1: 1000.0,
|
||||
};
|
||||
while !point_within(&point, cluster_centre_x, cluster_centre_y, cluster_radius)
|
||||
{
|
||||
point.x0 = x_range.sample(&mut rng);
|
||||
point.y0 = y_range.sample(&mut rng);
|
||||
point.x1 = x_range.sample(&mut rng);
|
||||
point.y1 = y_range.sample(&mut rng);
|
||||
}
|
||||
|
||||
let point = sample_point(&mut rng, x_range, y_range);
|
||||
v.push(point);
|
||||
}
|
||||
}
|
||||
|
13
haversine-app/Cargo.toml
Normal file
13
haversine-app/Cargo.toml
Normal file
@@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "haversine-app"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.3.1", features = [ "derive" ] }
|
||||
haversine = { path = "../haversine" }
|
||||
json = { path = "../json" }
|
||||
byteorder = "1.4.3"
|
||||
utf8-read = "0.4.0"
|
99
haversine-app/src/main.rs
Normal file
99
haversine-app/src/main.rs
Normal file
@@ -0,0 +1,99 @@
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use clap::Parser;
|
||||
use haversine::haversine::CoordinatePair;
|
||||
use haversine::{distance, earth};
|
||||
use json::json_object::JsonValue;
|
||||
use std::fs::File;
|
||||
use std::io::{BufReader, Read};
|
||||
use utf8_read::Reader;
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
struct Args {
|
||||
#[arg(value_name = "INPUT_JSON", required = true)]
|
||||
input_json: String,
|
||||
#[arg(value_name = "EXPECTED_F64", required = true)]
|
||||
expected: String,
|
||||
}
|
||||
|
||||
fn read_answer(binary_filename: &str) -> (Vec<f64>, f64) {
|
||||
let mut file = File::open(binary_filename).unwrap();
|
||||
let file_size = file.metadata().unwrap().len();
|
||||
if file_size % 8 != 0 {
|
||||
panic!(
|
||||
"Malformed input file of size {} is not a multiple of 8",
|
||||
file_size
|
||||
)
|
||||
}
|
||||
let num_floats = file_size / 8;
|
||||
assert_ne!(num_floats, 0, "Empty file");
|
||||
let num_floats = num_floats - 1;
|
||||
|
||||
let mut data = Vec::with_capacity(num_floats as usize);
|
||||
let mut buf = [0u8; 8];
|
||||
|
||||
for _ in 0..num_floats {
|
||||
let mut bytes_read = 0;
|
||||
while bytes_read < 8 {
|
||||
let new_bytes = file.read(&mut buf[bytes_read..]).unwrap();
|
||||
if new_bytes == 0 {
|
||||
panic!("Reached end of file");
|
||||
}
|
||||
bytes_read += new_bytes;
|
||||
}
|
||||
|
||||
data.push(LittleEndian::read_f64(&buf));
|
||||
}
|
||||
|
||||
let bytes_read = file.read(&mut buf).unwrap();
|
||||
if bytes_read < 8 {
|
||||
panic!("Not enough bytes read")
|
||||
}
|
||||
|
||||
(data, LittleEndian::read_f64(&buf))
|
||||
}
|
||||
|
||||
fn read_json(json_filename: &str) -> Vec<CoordinatePair> {
|
||||
let file = File::open(json_filename).unwrap();
|
||||
let reader = BufReader::new(file);
|
||||
let mut decoder = Reader::new(reader);
|
||||
match JsonValue::parse(&mut decoder.into_iter().map(|x| x.unwrap())).unwrap() {
|
||||
(JsonValue::Object(o), None) => {
|
||||
let a = o.values.get("pairs").unwrap().as_array();
|
||||
a.iter()
|
||||
.map(|o| {
|
||||
let o = o.as_object();
|
||||
CoordinatePair {
|
||||
x0: o.get("x0").unwrap().as_number(),
|
||||
y0: o.get("y0").unwrap().as_number(),
|
||||
x1: o.get("x1").unwrap().as_number(),
|
||||
y1: o.get("y1").unwrap().as_number(),
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
other => {
|
||||
panic!("Expected a JSON object, got: {:?}", other)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn haversine_sum(v: &[CoordinatePair]) -> f64 {
|
||||
let mut answer = 0.0_f64;
|
||||
for pair in v {
|
||||
answer += distance::naive(pair, earth::RADIUS);
|
||||
}
|
||||
answer / (v.len() as f64)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args = Args::parse();
|
||||
let input = read_json(&args.input_json);
|
||||
let (_expected_values, expected_sum) = read_answer(&args.expected);
|
||||
let actual_sum = haversine_sum(&input);
|
||||
println!("Pair count: {}", input.len());
|
||||
println!("Haversine sum: {}", actual_sum);
|
||||
|
||||
println!("Validation:");
|
||||
println!("Reference sum: {}", expected_sum);
|
||||
println!("Difference: {}", f64::abs(expected_sum - actual_sum));
|
||||
}
|
1
json/src/example.json
Normal file
1
json/src/example.json
Normal file
@@ -0,0 +1 @@
|
||||
{"pairs":[{"x0":22.477076634891404,"y0":1.96712597438826,"x1":64.3045066154957,"y1":-11.011501834694641},{"x0":-29.95327542455132,"y0":-16.17420677740482,"x1":-95.33727035262879,"y1":5.442724293569228},{"x0":176.9535218941732,"y0":-23.62633427891349,"x1":98.49393113007599,"y1":66.11720571650596},{"x0":84.10721569912283,"y0":-31.531857354540108,"x1":19.118449375424888,"y1":28.47444316116797},{"x0":-104.74547266971662,"y0":-44.6905221231317,"x1":-41.98223217669326,"y1":-0.8361930004999607},{"x0":-97.57786242745013,"y0":-7.555696001498205,"x1":-110.18578839345321,"y1":-45.82142186105271},{"x0":8.489029425696025,"y0":-19.661609891086545,"x1":32.6916569844426,"y1":-19.23122886972898},{"x0":-82.73889716232972,"y0":-3.4950910477402566,"x1":-61.08583995567845,"y1":-7.395573056242222},{"x0":-2.348717663153586,"y0":-18.777604624531843,"x1":145.1231894370418,"y1":-16.272245920530942},{"x0":-118.95284692848952,"y0":-38.240441628627764,"x1":-95.75644279084551,"y1":38.35221318654381},{"x0":143.2114792465152,"y0":7.237874212954941,"x1":143.10890111372015,"y1":3.0510375574127986},{"x0":-117.16427058103187,"y0":-19.328188969376868,"x1":-109.1457976040175,"y1":-42.77835599605936},{"x0":-76.39830609710457,"y0":58.00061923926861,"x1":-46.41076441053505,"y1":54.73539164184136},{"x0":-99.69233221681043,"y0":-16.03252235163597,"x1":-95.66539569227095,"y1":-18.54085071711185},{"x0":4.005958252988464,"y0":-15.08359144353581,"x1":2.868307430731619,"y1":35.954144546196765},{"x0":-105.22171195417796,"y0":44.664012522319325,"x1":-115.66595736862281,"y1":5.8518107376345085},{"x0":-45.56180924277177,"y0":5.185604480193316,"x1":-37.5672842051612,"y1":-6.723875513314969},{"x0":-81.211983455444,"y0":82.43176574614236,"x1":-89.23338448851845,"y1":82.57791072309365},{"x0":9.362158900743665,"y0":19.55481006439635,"x1":-43.13010547577467,"y1":8.122399345136628},{"x0":-7.901960753291205,"y0":-12.360772954348086,"x1":-7.911976757629197,"y1":-21.793505300605254}]}
|
@@ -143,23 +143,26 @@ where
|
||||
}
|
||||
};
|
||||
|
||||
if current != '0' {
|
||||
if ('1'..='9').contains(¤t) {
|
||||
integer_part = (current as u8 - b'0') as f64;
|
||||
loop {
|
||||
current = match iter.next() {
|
||||
None => return Ok((negative * integer_part, None)),
|
||||
Some(v) => v,
|
||||
};
|
||||
if current.is_ascii_digit() {
|
||||
integer_part = integer_part * 10.0 + ((current as u8 - b'0') as f64)
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Err(JsonNumberParseError::NonDigit(current));
|
||||
if current == '0' {
|
||||
current = match iter.next() {
|
||||
Some(v) => v,
|
||||
None => return Ok((negative * 0.0, None)),
|
||||
}
|
||||
} else if ('1'..='9').contains(¤t) {
|
||||
integer_part = (current as u8 - b'0') as f64;
|
||||
loop {
|
||||
current = match iter.next() {
|
||||
None => return Ok((negative * integer_part, None)),
|
||||
Some(v) => v,
|
||||
};
|
||||
if current.is_ascii_digit() {
|
||||
integer_part = integer_part * 10.0 + ((current as u8 - b'0') as f64)
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Err(JsonNumberParseError::NonDigit(current));
|
||||
}
|
||||
|
||||
// Parse fraction
|
||||
@@ -347,6 +350,27 @@ where
|
||||
}
|
||||
|
||||
impl JsonValue {
|
||||
pub fn as_number(&self) -> f64 {
|
||||
match self {
|
||||
JsonValue::Number(f) => *f,
|
||||
_ => panic!("Expected a number, got: {:?}", self),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_object(&self) -> &HashMap<String, JsonValue> {
|
||||
match self {
|
||||
JsonValue::Object(o) => &o.values,
|
||||
_ => panic!("Expected an object, got: {:?}", self),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_array(&self) -> &Vec<JsonValue> {
|
||||
match self {
|
||||
JsonValue::Array(a) => a,
|
||||
_ => panic!("Expected an array, got: {:?}", self),
|
||||
}
|
||||
}
|
||||
|
||||
/// Consumes the JSON value and leaves the iterator sitting on the first non-whitespace
|
||||
/// character after the JSON value. Returns that non-whitespace character in the Ok case.
|
||||
pub(crate) fn parse_iter<I>(
|
||||
@@ -861,4 +885,19 @@ mod test {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn negative_number() {
|
||||
let (parsed, remaining) = JsonValue::parse(&mut "-0.8".chars()).unwrap();
|
||||
assert_eq!(remaining, None);
|
||||
assert_eq!(parsed.as_number(), -0.8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn haversine_example() {
|
||||
let s = include_str!("example.json");
|
||||
let parsed = parse_object(&s);
|
||||
let o = parsed.values.get("pairs").unwrap().as_array();
|
||||
assert_eq!(o.len(), 20);
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "wrapper"
|
||||
name = "sim-wrapper"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
Reference in New Issue
Block a user