why the fuck didn't I start earlier
This commit is contained in:
parent
9941175a3c
commit
965bb36b0b
31 changed files with 2105 additions and 15 deletions
3
lab4/zad4/.gitignore
vendored
Normal file
3
lab4/zad4/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
target
|
||||||
|
results
|
||||||
|
plots
|
285
lab4/zad4/Cargo.lock
generated
Normal file
285
lab4/zad4/Cargo.lock
generated
Normal file
|
@ -0,0 +1,285 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-deque"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-epoch"
|
||||||
|
version = "0.9.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.8.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dashmap"
|
||||||
|
version = "5.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"hashbrown",
|
||||||
|
"lock_api",
|
||||||
|
"once_cell",
|
||||||
|
"parking_lot_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.14.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.155"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libgen"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"rand",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libtree"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.19.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.9.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall",
|
||||||
|
"smallvec",
|
||||||
|
"windows-targets",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon"
|
||||||
|
version = "1.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
"rayon-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon-core"
|
||||||
|
version = "1.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-deque",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smallvec"
|
||||||
|
version = "1.13.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm",
|
||||||
|
"windows_aarch64_msvc",
|
||||||
|
"windows_i686_gnu",
|
||||||
|
"windows_i686_gnullvm",
|
||||||
|
"windows_i686_msvc",
|
||||||
|
"windows_x86_64_gnu",
|
||||||
|
"windows_x86_64_gnullvm",
|
||||||
|
"windows_x86_64_msvc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnullvm"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zad4"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"dashmap",
|
||||||
|
"libgen",
|
||||||
|
"libtree",
|
||||||
|
"rayon",
|
||||||
|
]
|
10
lab4/zad4/Cargo.toml
Normal file
10
lab4/zad4/Cargo.toml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[package]
|
||||||
|
name = "zad4"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
libtree = { path = "../../libtree" }
|
||||||
|
libgen = { path = "../../libgen" }
|
||||||
|
rayon = "1.10.0"
|
||||||
|
dashmap = "5.5.3"
|
14
lab4/zad4/gnuplot/asc_comp.gp
Normal file
14
lab4/zad4/gnuplot/asc_comp.gp
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
set title "Insert n asc, delete n rand - Comp, n ∈ {10000, 20000, ..., 100000}"
|
||||||
|
set style data lines
|
||||||
|
|
||||||
|
set xlabel "n"
|
||||||
|
set ylabel "comparisons"
|
||||||
|
set term pdfcairo font "JetBrainsMono-NF,12"
|
||||||
|
|
||||||
|
plot "./results/asc_comp" \
|
||||||
|
using 1:2 t "Average", \
|
||||||
|
"" using 1:3 t "Max", \
|
||||||
|
|
||||||
|
set terminal pdf
|
||||||
|
|
||||||
|
# vim: ft=gnuplot
|
14
lab4/zad4/gnuplot/asc_height.gp
Normal file
14
lab4/zad4/gnuplot/asc_height.gp
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
set title "Insert n asc, delete n rand - Height, n ∈ {10000, 20000, ..., 100000}"
|
||||||
|
set style data lines
|
||||||
|
|
||||||
|
set xlabel "n"
|
||||||
|
set ylabel "height"
|
||||||
|
set term pdfcairo font "JetBrainsMono-NF,12"
|
||||||
|
|
||||||
|
plot "./results/asc_height" \
|
||||||
|
using 1:2 t "Average", \
|
||||||
|
"" using 1:3 t "Max", \
|
||||||
|
|
||||||
|
set terminal pdf
|
||||||
|
|
||||||
|
# vim: ft=gnuplot
|
14
lab4/zad4/gnuplot/asc_read.gp
Normal file
14
lab4/zad4/gnuplot/asc_read.gp
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
set title "Insert n asc, delete n rand - Reads, n ∈ {10000, 20000, ..., 100000}"
|
||||||
|
set style data lines
|
||||||
|
|
||||||
|
set xlabel "n"
|
||||||
|
set ylabel "reads"
|
||||||
|
set term pdfcairo font "JetBrainsMono-NF,12"
|
||||||
|
|
||||||
|
plot "./results/asc_read" \
|
||||||
|
using 1:2 t "Average", \
|
||||||
|
"" using 1:3 t "Max", \
|
||||||
|
|
||||||
|
set terminal pdf
|
||||||
|
|
||||||
|
# vim: ft=gnuplot
|
14
lab4/zad4/gnuplot/asc_write.gp
Normal file
14
lab4/zad4/gnuplot/asc_write.gp
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
set title "Insert n asc, delete n rand - Writes, n ∈ {10000, 20000, ..., 100000}"
|
||||||
|
set style data lines
|
||||||
|
|
||||||
|
set xlabel "n"
|
||||||
|
set ylabel "writes"
|
||||||
|
set term pdfcairo font "JetBrainsMono-NF,12"
|
||||||
|
|
||||||
|
plot "./results/asc_write" \
|
||||||
|
using 1:2 t "Average", \
|
||||||
|
"" using 1:3 t "Max", \
|
||||||
|
|
||||||
|
set terminal pdf
|
||||||
|
|
||||||
|
# vim: ft=gnuplot
|
14
lab4/zad4/gnuplot/rand_comp.gp
Normal file
14
lab4/zad4/gnuplot/rand_comp.gp
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
set title "Insert n rand, delete n rand - Comp, n ∈ {10000, 20000, ..., 100000}"
|
||||||
|
set style data lines
|
||||||
|
|
||||||
|
set xlabel "n"
|
||||||
|
set ylabel "comparisons"
|
||||||
|
set term pdfcairo font "JetBrainsMono-NF,12"
|
||||||
|
|
||||||
|
plot "./results/rand_comp" \
|
||||||
|
using 1:2 t "Average", \
|
||||||
|
"" using 1:3 t "Max", \
|
||||||
|
|
||||||
|
set terminal pdf
|
||||||
|
|
||||||
|
# vim: ft=gnuplot
|
14
lab4/zad4/gnuplot/rand_height.gp
Normal file
14
lab4/zad4/gnuplot/rand_height.gp
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
set title "Insert n rand, delete n rand - height, n ∈ {10000, 20000, ..., 100000}"
|
||||||
|
set style data lines
|
||||||
|
|
||||||
|
set xlabel "n"
|
||||||
|
set ylabel "height"
|
||||||
|
set term pdfcairo font "JetBrainsMono-NF,12"
|
||||||
|
|
||||||
|
plot "./results/rand_height" \
|
||||||
|
using 1:2 t "Average", \
|
||||||
|
"" using 1:3 t "Max", \
|
||||||
|
|
||||||
|
set terminal pdf
|
||||||
|
|
||||||
|
# vim: ft=gnuplot
|
14
lab4/zad4/gnuplot/rand_read.gp
Normal file
14
lab4/zad4/gnuplot/rand_read.gp
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
set title "Insert n rand, delete n rand - Reads, n ∈ {10000, 20000, ..., 100000}"
|
||||||
|
set style data lines
|
||||||
|
|
||||||
|
set xlabel "n"
|
||||||
|
set ylabel "reads"
|
||||||
|
set term pdfcairo font "JetBrainsMono-NF,12"
|
||||||
|
|
||||||
|
plot "./results/rand_read" \
|
||||||
|
using 1:2 t "Average", \
|
||||||
|
"" using 1:3 t "Max", \
|
||||||
|
|
||||||
|
set terminal pdf
|
||||||
|
|
||||||
|
# vim: ft=gnuplot
|
14
lab4/zad4/gnuplot/rand_write.gp
Normal file
14
lab4/zad4/gnuplot/rand_write.gp
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
set title "Insert n rand, delete n rand - Writes, n ∈ {10000, 20000, ..., 100000}"
|
||||||
|
set style data lines
|
||||||
|
|
||||||
|
set xlabel "n"
|
||||||
|
set ylabel "writes"
|
||||||
|
set term pdfcairo font "JetBrainsMono-NF,12"
|
||||||
|
|
||||||
|
plot "./results/rand_write" \
|
||||||
|
using 1:2 t "Average", \
|
||||||
|
"" using 1:3 t "Max", \
|
||||||
|
|
||||||
|
set terminal pdf
|
||||||
|
|
||||||
|
# vim: ft=gnuplot
|
286
lab4/zad4/src/main.rs
Normal file
286
lab4/zad4/src/main.rs
Normal file
|
@ -0,0 +1,286 @@
|
||||||
|
use std::{fs::{self, OpenOptions}, io::{self, Write}, sync::Arc};
|
||||||
|
|
||||||
|
use dashmap::DashMap;
|
||||||
|
use libgen::{gen_asc, gen_rand};
|
||||||
|
use rayon::{current_thread_index, iter::{IntoParallelIterator, ParallelIterator}};
|
||||||
|
use libtree::{RedBlackTree, Stats};
|
||||||
|
|
||||||
|
fn comp_avg(results_map: &DashMap<u64, Vec<Stats>>) -> DashMap<u64, f64> {
|
||||||
|
results_map.iter()
|
||||||
|
.map(|ref_multi| {
|
||||||
|
let (i, results) = ref_multi.pair();
|
||||||
|
(*i, (results.iter()
|
||||||
|
.map(|res| res.comparisons)
|
||||||
|
.sum::<u64>() as f64 / results.len() as f64))
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn comp_max(results_map: &DashMap<u64, Vec<Stats>>) -> DashMap<u64, u64> {
|
||||||
|
results_map.iter()
|
||||||
|
.map(|ref_multi| {
|
||||||
|
let (i, results) = ref_multi.pair();
|
||||||
|
(*i, results.iter()
|
||||||
|
.map(|s| s.comparisons)
|
||||||
|
.max()
|
||||||
|
.unwrap())
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_avg(results_map: &DashMap<u64, Vec<Stats>>) -> DashMap<u64, f64> {
|
||||||
|
results_map.iter()
|
||||||
|
.map(|ref_multi| {
|
||||||
|
let (i, results) = ref_multi.pair();
|
||||||
|
(*i, (results.iter()
|
||||||
|
.map(|res| res.reads)
|
||||||
|
.sum::<u64>() as f64 / results.len() as f64))
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_max(results_map: &DashMap<u64, Vec<Stats>>) -> DashMap<u64, u64> {
|
||||||
|
results_map.iter()
|
||||||
|
.map(|ref_multi| {
|
||||||
|
let (i, results) = ref_multi.pair();
|
||||||
|
(*i, results.iter()
|
||||||
|
.map(|s| s.reads)
|
||||||
|
.max()
|
||||||
|
.unwrap())
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_avg(results_map: &DashMap<u64, Vec<Stats>>) -> DashMap<u64, f64> {
|
||||||
|
results_map.iter()
|
||||||
|
.map(|ref_multi| {
|
||||||
|
let (i, results) = ref_multi.pair();
|
||||||
|
(*i, (results.iter()
|
||||||
|
.map(|res| res.writes)
|
||||||
|
.sum::<u64>() as f64 / results.len() as f64))
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_max(results_map: &DashMap<u64, Vec<Stats>>) -> DashMap<u64, u64> {
|
||||||
|
results_map.iter()
|
||||||
|
.map(|ref_multi| {
|
||||||
|
let (i, results) = ref_multi.pair();
|
||||||
|
(*i, results.iter()
|
||||||
|
.map(|s| s.writes)
|
||||||
|
.max()
|
||||||
|
.unwrap())
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> io::Result<()> {
|
||||||
|
|
||||||
|
let m = 20;
|
||||||
|
|
||||||
|
let asc_results: Arc<DashMap<u64, Vec<Stats>>> = Arc::new(DashMap::new());
|
||||||
|
let asc_heights: Arc<DashMap<u64, Vec<usize>>> = Arc::new(DashMap::new());
|
||||||
|
let rand_results: Arc<DashMap<u64, Vec<Stats>>> = Arc::new(DashMap::new());
|
||||||
|
let rand_heights: Arc<DashMap<u64, Vec<usize>>> = Arc::new(DashMap::new());
|
||||||
|
|
||||||
|
let asc_results_clone = Arc::clone(&asc_results);
|
||||||
|
let asc_heights_clone = Arc::clone(&asc_heights);
|
||||||
|
let rand_results_clone = Arc::clone(&rand_results);
|
||||||
|
let rand_heights_clone = Arc::clone(&rand_heights);
|
||||||
|
|
||||||
|
(10000u64..=100000u64).step_by(10000).collect::<Vec<_>>().into_par_iter().for_each(move |n| {
|
||||||
|
if asc_results_clone.get(&n).is_some() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if asc_heights_clone.get(&n).is_some() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if rand_results_clone.get(&n).is_some() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if rand_heights_clone.get(&n).is_some() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
println!("{thread}: starting n: {n}", thread = current_thread_index().unwrap());
|
||||||
|
|
||||||
|
asc_results_clone.insert(n, vec![]);
|
||||||
|
asc_heights_clone.insert(n, vec![]);
|
||||||
|
rand_results_clone.insert(n, vec![]);
|
||||||
|
rand_heights_clone.insert(n, vec![]);
|
||||||
|
|
||||||
|
(1..=m).into_par_iter().for_each(|k| {
|
||||||
|
println!("{thread}: starting iteration {k}/{m} for n: {n}", thread = current_thread_index().unwrap());
|
||||||
|
let mut asc = RedBlackTree::new(n as usize);
|
||||||
|
|
||||||
|
for i in gen_asc(n) {
|
||||||
|
asc.insert(i);
|
||||||
|
asc_results_clone.get_mut(&n).unwrap().push(asc.stats.clone());
|
||||||
|
asc.reset_stats();
|
||||||
|
asc_heights_clone.get_mut(&n).unwrap().push(asc.height());
|
||||||
|
}
|
||||||
|
for i in gen_rand(n) {
|
||||||
|
asc.delete(i);
|
||||||
|
asc_results_clone.get_mut(&n).unwrap().push(asc.stats.clone());
|
||||||
|
asc.reset_stats();
|
||||||
|
asc_heights_clone.get_mut(&n).unwrap().push(asc.height());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut rand = RedBlackTree::new(n as usize);
|
||||||
|
|
||||||
|
for i in gen_rand(n) {
|
||||||
|
rand.insert(i);
|
||||||
|
rand_results_clone.get_mut(&n).unwrap().push(rand.stats.clone());
|
||||||
|
rand.reset_stats();
|
||||||
|
rand_heights_clone.get_mut(&n).unwrap().push(rand.height());
|
||||||
|
}
|
||||||
|
for i in gen_rand(n) {
|
||||||
|
rand.delete(i);
|
||||||
|
rand_results_clone.get_mut(&n).unwrap().push(rand.stats.clone());
|
||||||
|
rand.reset_stats();
|
||||||
|
rand_heights_clone.get_mut(&n).unwrap().push(rand.height());
|
||||||
|
}
|
||||||
|
|
||||||
|
rand_results_clone.get_mut(&n).unwrap().push(rand.stats.clone());
|
||||||
|
println!("{thread}: finished iteration {k}/{m} for n: {n}", thread = current_thread_index().unwrap());
|
||||||
|
});
|
||||||
|
println!("{thread}: finished n: {n}", thread = current_thread_index().unwrap());
|
||||||
|
});
|
||||||
|
|
||||||
|
let asc_comp_averages = comp_avg(&asc_results);
|
||||||
|
let asc_read_averages = read_avg(&asc_results);
|
||||||
|
let asc_write_averages = write_avg(&asc_results);
|
||||||
|
|
||||||
|
let asc_height_averages: DashMap<_, _> = asc_heights.iter()
|
||||||
|
.map(|ref_multi| {
|
||||||
|
let (i, results) = ref_multi.pair();
|
||||||
|
(*i, results.iter().sum::<usize>() as f64 / results.len() as f64)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let asc_comp_max = comp_max(&asc_results);
|
||||||
|
let asc_read_max = read_max(&asc_results);
|
||||||
|
let asc_write_max = write_max(&asc_results);
|
||||||
|
|
||||||
|
let asc_height_max: DashMap<_, _> = asc_heights.iter()
|
||||||
|
.map(|ref_multi| {
|
||||||
|
let (i, results) = ref_multi.pair();
|
||||||
|
(*i, *results.iter().max().unwrap())
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let rand_comp_averages = comp_avg(&rand_results);
|
||||||
|
let rand_read_averages = read_avg(&rand_results);
|
||||||
|
let rand_write_averages = write_avg(&rand_results);
|
||||||
|
|
||||||
|
let rand_height_averages: DashMap<_, _> = rand_heights.iter()
|
||||||
|
.map(|ref_multi| {
|
||||||
|
let (i, results) = ref_multi.pair();
|
||||||
|
(*i, results.iter().sum::<usize>() as f64 / results.len() as f64)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let rand_comp_max = comp_max(&rand_results);
|
||||||
|
let rand_read_max = read_max(&rand_results);
|
||||||
|
let rand_write_max = write_max(&rand_results);
|
||||||
|
|
||||||
|
let rand_height_max: DashMap<_, _> = rand_heights.iter()
|
||||||
|
.map(|ref_multi| {
|
||||||
|
let (i, results) = ref_multi.pair();
|
||||||
|
(*i, *results.iter().max().unwrap())
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
_ = fs::create_dir_all("./results");
|
||||||
|
|
||||||
|
let mut asc_comp_file = OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.write(true)
|
||||||
|
.truncate(true)
|
||||||
|
.open("./results/asc_comp")?;
|
||||||
|
|
||||||
|
let mut asc_read_file = OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.write(true)
|
||||||
|
.truncate(true)
|
||||||
|
.open("./results/asc_read")?;
|
||||||
|
|
||||||
|
let mut asc_write_file = OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.write(true)
|
||||||
|
.truncate(true)
|
||||||
|
.open("./results/asc_write")?;
|
||||||
|
|
||||||
|
let mut asc_height_file = OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.write(true)
|
||||||
|
.truncate(true)
|
||||||
|
.open("./results/asc_height")?;
|
||||||
|
|
||||||
|
let mut rand_comp_file = OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.write(true)
|
||||||
|
.truncate(true)
|
||||||
|
.open("./results/rand_comp")?;
|
||||||
|
|
||||||
|
let mut rand_read_file = OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.write(true)
|
||||||
|
.truncate(true)
|
||||||
|
.open("./results/rand_read")?;
|
||||||
|
|
||||||
|
let mut rand_write_file = OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.write(true)
|
||||||
|
.truncate(true)
|
||||||
|
.open("./results/rand_write")?;
|
||||||
|
|
||||||
|
let mut rand_height_file = OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.write(true)
|
||||||
|
.truncate(true)
|
||||||
|
.open("./results/rand_height")?;
|
||||||
|
|
||||||
|
for n in (10000u64..=100000u64).step_by(10000) {
|
||||||
|
writeln!(asc_comp_file, "{n} {} {}",
|
||||||
|
asc_comp_averages.get(&n).unwrap().value(),
|
||||||
|
asc_comp_max.get(&n).unwrap().value(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
writeln!(asc_read_file, "{n} {} {}",
|
||||||
|
asc_read_averages.get(&n).unwrap().value(),
|
||||||
|
asc_read_max.get(&n).unwrap().value(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
writeln!(asc_write_file, "{n} {} {}",
|
||||||
|
asc_write_averages.get(&n).unwrap().value(),
|
||||||
|
asc_write_max.get(&n).unwrap().value(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
writeln!(asc_height_file, "{n} {} {}",
|
||||||
|
asc_height_averages.get(&n).unwrap().value(),
|
||||||
|
asc_height_max.get(&n).unwrap().value(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
writeln!(rand_comp_file, "{n} {} {}",
|
||||||
|
rand_comp_averages.get(&n).unwrap().value(),
|
||||||
|
rand_comp_max.get(&n).unwrap().value(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
writeln!(rand_read_file, "{n} {} {}",
|
||||||
|
rand_read_averages.get(&n).unwrap().value(),
|
||||||
|
rand_read_max.get(&n).unwrap().value(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
writeln!(rand_write_file, "{n} {} {}",
|
||||||
|
rand_write_averages.get(&n).unwrap().value(),
|
||||||
|
rand_write_max.get(&n).unwrap().value(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
writeln!(rand_height_file, "{n} {} {}",
|
||||||
|
rand_height_averages.get(&n).unwrap().value(),
|
||||||
|
rand_height_max.get(&n).unwrap().value(),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
1
lab4/zad5/.gitignore
vendored
Normal file
1
lab4/zad5/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
target
|
87
lab4/zad5/Cargo.lock
generated
Normal file
87
lab4/zad5/Cargo.lock
generated
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.155"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libgen"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"rand",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libtree"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zad5"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"libgen",
|
||||||
|
"libtree",
|
||||||
|
]
|
8
lab4/zad5/Cargo.toml
Normal file
8
lab4/zad5/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[package]
|
||||||
|
name = "zad5"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
libgen = { path = "../../libgen" }
|
||||||
|
libtree = { path = "../../libtree" }
|
34
lab4/zad5/src/main.rs
Normal file
34
lab4/zad5/src/main.rs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
use libgen::{gen_asc, gen_rand};
|
||||||
|
use libtree::SplayTree;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("1. insert 50 ascending; delete 50 random");
|
||||||
|
let mut tree1 = SplayTree::new(50);
|
||||||
|
|
||||||
|
for i in gen_asc(50) {
|
||||||
|
println!("insert {i}");
|
||||||
|
tree1.insert(i);
|
||||||
|
println!("{}", tree1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in gen_rand(50) {
|
||||||
|
println!("delete {i}");
|
||||||
|
tree1.delete(i);
|
||||||
|
println!("{}", tree1);
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("2. insert 50 random; delete 50 random");
|
||||||
|
let mut tree2 = SplayTree::new(50);
|
||||||
|
|
||||||
|
for i in gen_rand(50) {
|
||||||
|
println!("insert {i}");
|
||||||
|
tree2.insert(i);
|
||||||
|
println!("{}", tree2);
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in gen_rand(50) {
|
||||||
|
println!("delete {i}");
|
||||||
|
tree2.delete(i);
|
||||||
|
println!("{}", tree2);
|
||||||
|
}
|
||||||
|
}
|
3
lab4/zad6/.gitignore
vendored
Normal file
3
lab4/zad6/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
target
|
||||||
|
results
|
||||||
|
plots
|
285
lab4/zad6/Cargo.lock
generated
Normal file
285
lab4/zad6/Cargo.lock
generated
Normal file
|
@ -0,0 +1,285 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-deque"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-epoch"
|
||||||
|
version = "0.9.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.8.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dashmap"
|
||||||
|
version = "5.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"hashbrown",
|
||||||
|
"lock_api",
|
||||||
|
"once_cell",
|
||||||
|
"parking_lot_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.14.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.155"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libgen"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"rand",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libtree"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.19.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.9.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall",
|
||||||
|
"smallvec",
|
||||||
|
"windows-targets",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon"
|
||||||
|
version = "1.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
"rayon-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon-core"
|
||||||
|
version = "1.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-deque",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smallvec"
|
||||||
|
version = "1.13.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm",
|
||||||
|
"windows_aarch64_msvc",
|
||||||
|
"windows_i686_gnu",
|
||||||
|
"windows_i686_gnullvm",
|
||||||
|
"windows_i686_msvc",
|
||||||
|
"windows_x86_64_gnu",
|
||||||
|
"windows_x86_64_gnullvm",
|
||||||
|
"windows_x86_64_msvc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnullvm"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zad4"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"dashmap",
|
||||||
|
"libgen",
|
||||||
|
"libtree",
|
||||||
|
"rayon",
|
||||||
|
]
|
10
lab4/zad6/Cargo.toml
Normal file
10
lab4/zad6/Cargo.toml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[package]
|
||||||
|
name = "zad4"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
libtree = { path = "../../libtree" }
|
||||||
|
libgen = { path = "../../libgen" }
|
||||||
|
rayon = "1.10.0"
|
||||||
|
dashmap = "5.5.3"
|
14
lab4/zad6/gnuplot/asc_comp.gp
Normal file
14
lab4/zad6/gnuplot/asc_comp.gp
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
set title "Insert n asc, delete n rand - Comp, n ∈ {10000, 20000, ..., 100000}"
|
||||||
|
set style data lines
|
||||||
|
|
||||||
|
set xlabel "n"
|
||||||
|
set ylabel "comparisons"
|
||||||
|
set term pdfcairo font "JetBrainsMono-NF,12"
|
||||||
|
|
||||||
|
plot "./results/asc_comp" \
|
||||||
|
using 1:2 t "Average", \
|
||||||
|
"" using 1:3 t "Max", \
|
||||||
|
|
||||||
|
set terminal pdf
|
||||||
|
|
||||||
|
# vim: ft=gnuplot
|
14
lab4/zad6/gnuplot/asc_height.gp
Normal file
14
lab4/zad6/gnuplot/asc_height.gp
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
set title "Insert n asc, delete n rand - Height, n ∈ {10000, 20000, ..., 100000}"
|
||||||
|
set style data lines
|
||||||
|
|
||||||
|
set xlabel "n"
|
||||||
|
set ylabel "height"
|
||||||
|
set term pdfcairo font "JetBrainsMono-NF,12"
|
||||||
|
|
||||||
|
plot "./results/asc_height" \
|
||||||
|
using 1:2 t "Average", \
|
||||||
|
"" using 1:3 t "Max", \
|
||||||
|
|
||||||
|
set terminal pdf
|
||||||
|
|
||||||
|
# vim: ft=gnuplot
|
14
lab4/zad6/gnuplot/asc_read.gp
Normal file
14
lab4/zad6/gnuplot/asc_read.gp
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
set title "Insert n asc, delete n rand - Reads, n ∈ {10000, 20000, ..., 100000}"
|
||||||
|
set style data lines
|
||||||
|
|
||||||
|
set xlabel "n"
|
||||||
|
set ylabel "reads"
|
||||||
|
set term pdfcairo font "JetBrainsMono-NF,12"
|
||||||
|
|
||||||
|
plot "./results/asc_read" \
|
||||||
|
using 1:2 t "Average", \
|
||||||
|
"" using 1:3 t "Max", \
|
||||||
|
|
||||||
|
set terminal pdf
|
||||||
|
|
||||||
|
# vim: ft=gnuplot
|
14
lab4/zad6/gnuplot/asc_write.gp
Normal file
14
lab4/zad6/gnuplot/asc_write.gp
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
set title "Insert n asc, delete n rand - Writes, n ∈ {10000, 20000, ..., 100000}"
|
||||||
|
set style data lines
|
||||||
|
|
||||||
|
set xlabel "n"
|
||||||
|
set ylabel "writes"
|
||||||
|
set term pdfcairo font "JetBrainsMono-NF,12"
|
||||||
|
|
||||||
|
plot "./results/asc_write" \
|
||||||
|
using 1:2 t "Average", \
|
||||||
|
"" using 1:3 t "Max", \
|
||||||
|
|
||||||
|
set terminal pdf
|
||||||
|
|
||||||
|
# vim: ft=gnuplot
|
14
lab4/zad6/gnuplot/rand_comp.gp
Normal file
14
lab4/zad6/gnuplot/rand_comp.gp
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
set title "Insert n rand, delete n rand - Comp, n ∈ {10000, 20000, ..., 100000}"
|
||||||
|
set style data lines
|
||||||
|
|
||||||
|
set xlabel "n"
|
||||||
|
set ylabel "comparisons"
|
||||||
|
set term pdfcairo font "JetBrainsMono-NF,12"
|
||||||
|
|
||||||
|
plot "./results/rand_comp" \
|
||||||
|
using 1:2 t "Average", \
|
||||||
|
"" using 1:3 t "Max", \
|
||||||
|
|
||||||
|
set terminal pdf
|
||||||
|
|
||||||
|
# vim: ft=gnuplot
|
14
lab4/zad6/gnuplot/rand_height.gp
Normal file
14
lab4/zad6/gnuplot/rand_height.gp
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
set title "Insert n rand, delete n rand - height, n ∈ {10000, 20000, ..., 100000}"
|
||||||
|
set style data lines
|
||||||
|
|
||||||
|
set xlabel "n"
|
||||||
|
set ylabel "height"
|
||||||
|
set term pdfcairo font "JetBrainsMono-NF,12"
|
||||||
|
|
||||||
|
plot "./results/rand_height" \
|
||||||
|
using 1:2 t "Average", \
|
||||||
|
"" using 1:3 t "Max", \
|
||||||
|
|
||||||
|
set terminal pdf
|
||||||
|
|
||||||
|
# vim: ft=gnuplot
|
14
lab4/zad6/gnuplot/rand_read.gp
Normal file
14
lab4/zad6/gnuplot/rand_read.gp
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
set title "Insert n rand, delete n rand - Reads, n ∈ {10000, 20000, ..., 100000}"
|
||||||
|
set style data lines
|
||||||
|
|
||||||
|
set xlabel "n"
|
||||||
|
set ylabel "reads"
|
||||||
|
set term pdfcairo font "JetBrainsMono-NF,12"
|
||||||
|
|
||||||
|
plot "./results/rand_read" \
|
||||||
|
using 1:2 t "Average", \
|
||||||
|
"" using 1:3 t "Max", \
|
||||||
|
|
||||||
|
set terminal pdf
|
||||||
|
|
||||||
|
# vim: ft=gnuplot
|
14
lab4/zad6/gnuplot/rand_write.gp
Normal file
14
lab4/zad6/gnuplot/rand_write.gp
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
set title "Insert n rand, delete n rand - Writes, n ∈ {10000, 20000, ..., 100000}"
|
||||||
|
set style data lines
|
||||||
|
|
||||||
|
set xlabel "n"
|
||||||
|
set ylabel "writes"
|
||||||
|
set term pdfcairo font "JetBrainsMono-NF,12"
|
||||||
|
|
||||||
|
plot "./results/rand_write" \
|
||||||
|
using 1:2 t "Average", \
|
||||||
|
"" using 1:3 t "Max", \
|
||||||
|
|
||||||
|
set terminal pdf
|
||||||
|
|
||||||
|
# vim: ft=gnuplot
|
286
lab4/zad6/src/main.rs
Normal file
286
lab4/zad6/src/main.rs
Normal file
|
@ -0,0 +1,286 @@
|
||||||
|
use std::{fs::{self, OpenOptions}, io::{self, Write}, sync::Arc};
|
||||||
|
|
||||||
|
use dashmap::DashMap;
|
||||||
|
use libgen::{gen_asc, gen_rand};
|
||||||
|
use rayon::{current_thread_index, iter::{IntoParallelIterator, ParallelIterator}};
|
||||||
|
use libtree::{SplayTree, Stats};
|
||||||
|
|
||||||
|
fn comp_avg(results_map: &DashMap<u64, Vec<Stats>>) -> DashMap<u64, f64> {
|
||||||
|
results_map.iter()
|
||||||
|
.map(|ref_multi| {
|
||||||
|
let (i, results) = ref_multi.pair();
|
||||||
|
(*i, (results.iter()
|
||||||
|
.map(|res| res.comparisons)
|
||||||
|
.sum::<u64>() as f64 / results.len() as f64))
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn comp_max(results_map: &DashMap<u64, Vec<Stats>>) -> DashMap<u64, u64> {
|
||||||
|
results_map.iter()
|
||||||
|
.map(|ref_multi| {
|
||||||
|
let (i, results) = ref_multi.pair();
|
||||||
|
(*i, results.iter()
|
||||||
|
.map(|s| s.comparisons)
|
||||||
|
.max()
|
||||||
|
.unwrap())
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_avg(results_map: &DashMap<u64, Vec<Stats>>) -> DashMap<u64, f64> {
|
||||||
|
results_map.iter()
|
||||||
|
.map(|ref_multi| {
|
||||||
|
let (i, results) = ref_multi.pair();
|
||||||
|
(*i, (results.iter()
|
||||||
|
.map(|res| res.reads)
|
||||||
|
.sum::<u64>() as f64 / results.len() as f64))
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_max(results_map: &DashMap<u64, Vec<Stats>>) -> DashMap<u64, u64> {
|
||||||
|
results_map.iter()
|
||||||
|
.map(|ref_multi| {
|
||||||
|
let (i, results) = ref_multi.pair();
|
||||||
|
(*i, results.iter()
|
||||||
|
.map(|s| s.reads)
|
||||||
|
.max()
|
||||||
|
.unwrap())
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_avg(results_map: &DashMap<u64, Vec<Stats>>) -> DashMap<u64, f64> {
|
||||||
|
results_map.iter()
|
||||||
|
.map(|ref_multi| {
|
||||||
|
let (i, results) = ref_multi.pair();
|
||||||
|
(*i, (results.iter()
|
||||||
|
.map(|res| res.writes)
|
||||||
|
.sum::<u64>() as f64 / results.len() as f64))
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_max(results_map: &DashMap<u64, Vec<Stats>>) -> DashMap<u64, u64> {
|
||||||
|
results_map.iter()
|
||||||
|
.map(|ref_multi| {
|
||||||
|
let (i, results) = ref_multi.pair();
|
||||||
|
(*i, results.iter()
|
||||||
|
.map(|s| s.writes)
|
||||||
|
.max()
|
||||||
|
.unwrap())
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> io::Result<()> {
|
||||||
|
|
||||||
|
let m = 20;
|
||||||
|
|
||||||
|
let asc_results: Arc<DashMap<u64, Vec<Stats>>> = Arc::new(DashMap::new());
|
||||||
|
let asc_heights: Arc<DashMap<u64, Vec<usize>>> = Arc::new(DashMap::new());
|
||||||
|
let rand_results: Arc<DashMap<u64, Vec<Stats>>> = Arc::new(DashMap::new());
|
||||||
|
let rand_heights: Arc<DashMap<u64, Vec<usize>>> = Arc::new(DashMap::new());
|
||||||
|
|
||||||
|
let asc_results_clone = Arc::clone(&asc_results);
|
||||||
|
let asc_heights_clone = Arc::clone(&asc_heights);
|
||||||
|
let rand_results_clone = Arc::clone(&rand_results);
|
||||||
|
let rand_heights_clone = Arc::clone(&rand_heights);
|
||||||
|
|
||||||
|
(10000u64..=100000u64).step_by(10000).collect::<Vec<_>>().into_par_iter().for_each(move |n| {
|
||||||
|
if asc_results_clone.get(&n).is_some() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if asc_heights_clone.get(&n).is_some() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if rand_results_clone.get(&n).is_some() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if rand_heights_clone.get(&n).is_some() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
println!("{thread}: starting n: {n}", thread = current_thread_index().unwrap());
|
||||||
|
|
||||||
|
asc_results_clone.insert(n, vec![]);
|
||||||
|
asc_heights_clone.insert(n, vec![]);
|
||||||
|
rand_results_clone.insert(n, vec![]);
|
||||||
|
rand_heights_clone.insert(n, vec![]);
|
||||||
|
|
||||||
|
(1..=m).into_par_iter().for_each(|k| {
|
||||||
|
println!("{thread}: starting iteration {k}/{m} for n: {n}", thread = current_thread_index().unwrap());
|
||||||
|
let mut asc = SplayTree::new(n as usize);
|
||||||
|
|
||||||
|
for i in gen_asc(n) {
|
||||||
|
asc.insert(i);
|
||||||
|
asc_results_clone.get_mut(&n).unwrap().push(asc.stats.clone());
|
||||||
|
asc.reset_stats();
|
||||||
|
asc_heights_clone.get_mut(&n).unwrap().push(asc.height());
|
||||||
|
}
|
||||||
|
for i in gen_rand(n) {
|
||||||
|
asc.delete(i);
|
||||||
|
asc_results_clone.get_mut(&n).unwrap().push(asc.stats.clone());
|
||||||
|
asc.reset_stats();
|
||||||
|
asc_heights_clone.get_mut(&n).unwrap().push(asc.height());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut rand = SplayTree::new(n as usize);
|
||||||
|
|
||||||
|
for i in gen_rand(n) {
|
||||||
|
rand.insert(i);
|
||||||
|
rand_results_clone.get_mut(&n).unwrap().push(rand.stats.clone());
|
||||||
|
rand.reset_stats();
|
||||||
|
rand_heights_clone.get_mut(&n).unwrap().push(rand.height());
|
||||||
|
}
|
||||||
|
for i in gen_rand(n) {
|
||||||
|
rand.delete(i);
|
||||||
|
rand_results_clone.get_mut(&n).unwrap().push(rand.stats.clone());
|
||||||
|
rand.reset_stats();
|
||||||
|
rand_heights_clone.get_mut(&n).unwrap().push(rand.height());
|
||||||
|
}
|
||||||
|
|
||||||
|
rand_results_clone.get_mut(&n).unwrap().push(rand.stats.clone());
|
||||||
|
println!("{thread}: finished iteration {k}/{m} for n: {n}", thread = current_thread_index().unwrap());
|
||||||
|
});
|
||||||
|
println!("{thread}: finished n: {n}", thread = current_thread_index().unwrap());
|
||||||
|
});
|
||||||
|
|
||||||
|
let asc_comp_averages = comp_avg(&asc_results);
|
||||||
|
let asc_read_averages = read_avg(&asc_results);
|
||||||
|
let asc_write_averages = write_avg(&asc_results);
|
||||||
|
|
||||||
|
let asc_height_averages: DashMap<_, _> = asc_heights.iter()
|
||||||
|
.map(|ref_multi| {
|
||||||
|
let (i, results) = ref_multi.pair();
|
||||||
|
(*i, results.iter().sum::<usize>() as f64 / results.len() as f64)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let asc_comp_max = comp_max(&asc_results);
|
||||||
|
let asc_read_max = read_max(&asc_results);
|
||||||
|
let asc_write_max = write_max(&asc_results);
|
||||||
|
|
||||||
|
let asc_height_max: DashMap<_, _> = asc_heights.iter()
|
||||||
|
.map(|ref_multi| {
|
||||||
|
let (i, results) = ref_multi.pair();
|
||||||
|
(*i, *results.iter().max().unwrap())
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let rand_comp_averages = comp_avg(&rand_results);
|
||||||
|
let rand_read_averages = read_avg(&rand_results);
|
||||||
|
let rand_write_averages = write_avg(&rand_results);
|
||||||
|
|
||||||
|
let rand_height_averages: DashMap<_, _> = rand_heights.iter()
|
||||||
|
.map(|ref_multi| {
|
||||||
|
let (i, results) = ref_multi.pair();
|
||||||
|
(*i, results.iter().sum::<usize>() as f64 / results.len() as f64)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let rand_comp_max = comp_max(&rand_results);
|
||||||
|
let rand_read_max = read_max(&rand_results);
|
||||||
|
let rand_write_max = write_max(&rand_results);
|
||||||
|
|
||||||
|
let rand_height_max: DashMap<_, _> = rand_heights.iter()
|
||||||
|
.map(|ref_multi| {
|
||||||
|
let (i, results) = ref_multi.pair();
|
||||||
|
(*i, *results.iter().max().unwrap())
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
_ = fs::create_dir_all("./results");
|
||||||
|
|
||||||
|
let mut asc_comp_file = OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.write(true)
|
||||||
|
.truncate(true)
|
||||||
|
.open("./results/asc_comp")?;
|
||||||
|
|
||||||
|
let mut asc_read_file = OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.write(true)
|
||||||
|
.truncate(true)
|
||||||
|
.open("./results/asc_read")?;
|
||||||
|
|
||||||
|
let mut asc_write_file = OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.write(true)
|
||||||
|
.truncate(true)
|
||||||
|
.open("./results/asc_write")?;
|
||||||
|
|
||||||
|
let mut asc_height_file = OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.write(true)
|
||||||
|
.truncate(true)
|
||||||
|
.open("./results/asc_height")?;
|
||||||
|
|
||||||
|
let mut rand_comp_file = OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.write(true)
|
||||||
|
.truncate(true)
|
||||||
|
.open("./results/rand_comp")?;
|
||||||
|
|
||||||
|
let mut rand_read_file = OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.write(true)
|
||||||
|
.truncate(true)
|
||||||
|
.open("./results/rand_read")?;
|
||||||
|
|
||||||
|
let mut rand_write_file = OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.write(true)
|
||||||
|
.truncate(true)
|
||||||
|
.open("./results/rand_write")?;
|
||||||
|
|
||||||
|
let mut rand_height_file = OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.write(true)
|
||||||
|
.truncate(true)
|
||||||
|
.open("./results/rand_height")?;
|
||||||
|
|
||||||
|
for n in (10000u64..=100000u64).step_by(10000) {
|
||||||
|
writeln!(asc_comp_file, "{n} {} {}",
|
||||||
|
asc_comp_averages.get(&n).unwrap().value(),
|
||||||
|
asc_comp_max.get(&n).unwrap().value(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
writeln!(asc_read_file, "{n} {} {}",
|
||||||
|
asc_read_averages.get(&n).unwrap().value(),
|
||||||
|
asc_read_max.get(&n).unwrap().value(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
writeln!(asc_write_file, "{n} {} {}",
|
||||||
|
asc_write_averages.get(&n).unwrap().value(),
|
||||||
|
asc_write_max.get(&n).unwrap().value(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
writeln!(asc_height_file, "{n} {} {}",
|
||||||
|
asc_height_averages.get(&n).unwrap().value(),
|
||||||
|
asc_height_max.get(&n).unwrap().value(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
writeln!(rand_comp_file, "{n} {} {}",
|
||||||
|
rand_comp_averages.get(&n).unwrap().value(),
|
||||||
|
rand_comp_max.get(&n).unwrap().value(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
writeln!(rand_read_file, "{n} {} {}",
|
||||||
|
rand_read_averages.get(&n).unwrap().value(),
|
||||||
|
rand_read_max.get(&n).unwrap().value(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
writeln!(rand_write_file, "{n} {} {}",
|
||||||
|
rand_write_averages.get(&n).unwrap().value(),
|
||||||
|
rand_write_max.get(&n).unwrap().value(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
writeln!(rand_height_file, "{n} {} {}",
|
||||||
|
rand_height_averages.get(&n).unwrap().value(),
|
||||||
|
rand_height_max.get(&n).unwrap().value(),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -1,8 +1,10 @@
|
||||||
mod binary_search_tree;
|
mod binary_search_tree;
|
||||||
mod red_black_tree;
|
mod red_black_tree;
|
||||||
|
mod splay_tree;
|
||||||
|
|
||||||
pub use binary_search_tree::*;
|
pub use binary_search_tree::*;
|
||||||
pub use red_black_tree::*;
|
pub use red_black_tree::*;
|
||||||
|
pub use splay_tree::*;
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct Stats {
|
pub struct Stats {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use std::{cmp::Ordering, fmt::Display, ptr};
|
use std::{cmp::Ordering, fmt::Display, ptr};
|
||||||
|
|
||||||
|
use crate::Stats;
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq)]
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
pub enum Colour { Red, Black }
|
pub enum Colour { Red, Black }
|
||||||
|
|
||||||
|
@ -53,6 +55,22 @@ impl RBT {
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn height(&self) -> usize {
|
||||||
|
if self.is_null() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
match (self.left().is_null(), self.right().is_null()) {
|
||||||
|
(true, true) =>
|
||||||
|
1,
|
||||||
|
(true, false) =>
|
||||||
|
1 + self.right().height(),
|
||||||
|
(false, true) =>
|
||||||
|
1 + self.left().height(),
|
||||||
|
(false, false) =>
|
||||||
|
1 + (self.left().height()).max(self.right().height()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn deep_clone(&self) -> Self {
|
unsafe fn deep_clone(&self) -> Self {
|
||||||
let mut node = Self::new((*self.0).key);
|
let mut node = Self::new((*self.0).key);
|
||||||
if !self.left().is_null() {
|
if !self.left().is_null() {
|
||||||
|
@ -71,7 +89,8 @@ impl RBT {
|
||||||
while !temp.left().is_null() {
|
while !temp.left().is_null() {
|
||||||
temp = temp.left();
|
temp = temp.left();
|
||||||
}
|
}
|
||||||
return temp;
|
|
||||||
|
temp
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_colour(&mut self, colour: Colour) {
|
fn set_colour(&mut self, colour: Colour) {
|
||||||
|
@ -195,6 +214,7 @@ pub struct RedBlackTree {
|
||||||
root: RBT,
|
root: RBT,
|
||||||
pub size: usize,
|
pub size: usize,
|
||||||
print_capacity: usize,
|
print_capacity: usize,
|
||||||
|
pub stats: Stats,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for RedBlackTree {
|
impl Clone for RedBlackTree {
|
||||||
|
@ -214,51 +234,89 @@ impl RedBlackTree {
|
||||||
root: RBT::null(),
|
root: RBT::null(),
|
||||||
size: 0,
|
size: 0,
|
||||||
print_capacity,
|
print_capacity,
|
||||||
|
stats: Stats::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn height(&self) -> usize {
|
||||||
|
match &self.root.is_null() {
|
||||||
|
false => self.root.height(),
|
||||||
|
true => 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn rotate_left(&mut self, mut node: RBT) {
|
unsafe fn rotate_left(&mut self, mut node: RBT) {
|
||||||
let mut right = node.right();
|
let mut right = node.right();
|
||||||
node.set_right(right.left());
|
node.set_right(right.left());
|
||||||
|
self.stats.writes += 1;
|
||||||
|
self.stats.reads += 2;
|
||||||
|
|
||||||
|
self.stats.reads += 1;
|
||||||
if !right.left().is_null() {
|
if !right.left().is_null() {
|
||||||
right.left().set_parent(node.clone());
|
right.left().set_parent(node);
|
||||||
|
self.stats.writes += 1;
|
||||||
|
self.stats.reads += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
right.set_parent(node.parent());
|
right.set_parent(node.parent());
|
||||||
|
self.stats.writes += 1;
|
||||||
|
self.stats.reads += 1;
|
||||||
|
|
||||||
|
self.stats.reads += 1;
|
||||||
if node == self.root {
|
if node == self.root {
|
||||||
self.root = right.clone();
|
self.root = right;
|
||||||
|
self.stats.writes += 1;
|
||||||
} else if node == node.parent().left() {
|
} else if node == node.parent().left() {
|
||||||
node.parent().set_left(right.clone());
|
node.parent().set_left(right);
|
||||||
|
self.stats.writes += 1;
|
||||||
|
self.stats.reads += 2;
|
||||||
} else if node == node.parent().right() {
|
} else if node == node.parent().right() {
|
||||||
node.parent().set_right(right.clone());
|
node.parent().set_right(right);
|
||||||
|
self.stats.writes += 1;
|
||||||
|
self.stats.reads += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
right.set_left(node.clone());
|
right.set_left(node);
|
||||||
node.set_parent(right.clone());
|
node.set_parent(right);
|
||||||
|
self.stats.writes += 2;
|
||||||
|
self.stats.reads += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn rotate_right(&mut self, mut node: RBT) {
|
unsafe fn rotate_right(&mut self, mut node: RBT) {
|
||||||
let mut left = node.left();
|
let mut left = node.left();
|
||||||
node.set_left(left.right());
|
node.set_left(left.right());
|
||||||
|
self.stats.writes += 1;
|
||||||
|
self.stats.reads += 2;
|
||||||
|
|
||||||
|
self.stats.reads += 1;
|
||||||
if !left.right().is_null() {
|
if !left.right().is_null() {
|
||||||
left.right().set_parent(node.clone());
|
left.right().set_parent(node);
|
||||||
|
self.stats.writes += 1;
|
||||||
|
self.stats.reads += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
left.set_parent(node.parent());
|
left.set_parent(node.parent());
|
||||||
|
self.stats.writes += 1;
|
||||||
|
self.stats.reads += 1;
|
||||||
|
|
||||||
|
self.stats.reads += 1;
|
||||||
if node == self.root {
|
if node == self.root {
|
||||||
self.root = left.clone();
|
self.root = left;
|
||||||
|
self.stats.writes += 1;
|
||||||
} else if node == node.parent().left() {
|
} else if node == node.parent().left() {
|
||||||
node.parent().set_left(left.clone());
|
node.parent().set_left(left);
|
||||||
|
self.stats.writes += 1;
|
||||||
|
self.stats.reads += 2;
|
||||||
} else if node == node.parent().right() {
|
} else if node == node.parent().right() {
|
||||||
node.parent().set_right(left.clone());
|
node.parent().set_right(left);
|
||||||
|
self.stats.writes += 1;
|
||||||
|
self.stats.reads += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
left.set_right(node.clone());
|
left.set_right(node);
|
||||||
node.set_parent(left.clone());
|
node.set_parent(left);
|
||||||
|
self.stats.writes += 2;
|
||||||
|
self.stats.reads += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn insert_fixup(&mut self, mut node: RBT) {
|
unsafe fn insert_fixup(&mut self, mut node: RBT) {
|
||||||
|
@ -267,11 +325,15 @@ impl RedBlackTree {
|
||||||
let mut parent;
|
let mut parent;
|
||||||
let mut grandparent;
|
let mut grandparent;
|
||||||
|
|
||||||
|
self.stats.reads += 1;
|
||||||
while node.parent().colour() == Red {
|
while node.parent().colour() == Red {
|
||||||
|
self.stats.reads += 2;
|
||||||
parent = node.parent();
|
parent = node.parent();
|
||||||
grandparent = parent.parent();
|
grandparent = parent.parent();
|
||||||
|
|
||||||
|
self.stats.reads += 1;
|
||||||
if parent == grandparent.left() {
|
if parent == grandparent.left() {
|
||||||
|
self.stats.reads += 1;
|
||||||
let mut uncle = grandparent.right();
|
let mut uncle = grandparent.right();
|
||||||
if !uncle.is_null() && uncle.colour() == Red {
|
if !uncle.is_null() && uncle.colour() == Red {
|
||||||
uncle.set_colour(Black);
|
uncle.set_colour(Black);
|
||||||
|
@ -279,6 +341,7 @@ impl RedBlackTree {
|
||||||
grandparent.set_colour(Red);
|
grandparent.set_colour(Red);
|
||||||
node = grandparent;
|
node = grandparent;
|
||||||
} else {
|
} else {
|
||||||
|
self.stats.reads += 1;
|
||||||
if parent.right() == node {
|
if parent.right() == node {
|
||||||
node = parent;
|
node = parent;
|
||||||
self.rotate_left(node);
|
self.rotate_left(node);
|
||||||
|
@ -290,12 +353,14 @@ impl RedBlackTree {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let mut uncle = grandparent.left();
|
let mut uncle = grandparent.left();
|
||||||
|
self.stats.reads += 1;
|
||||||
if !uncle.is_null() && uncle.colour() == Red {
|
if !uncle.is_null() && uncle.colour() == Red {
|
||||||
uncle.set_colour(Black);
|
uncle.set_colour(Black);
|
||||||
parent.set_colour(Black);
|
parent.set_colour(Black);
|
||||||
grandparent.set_colour(Red);
|
grandparent.set_colour(Red);
|
||||||
node = grandparent;
|
node = grandparent;
|
||||||
} else {
|
} else {
|
||||||
|
self.stats.reads += 1;
|
||||||
if parent.left() == node {
|
if parent.left() == node {
|
||||||
node = parent;
|
node = parent;
|
||||||
self.rotate_right(node);
|
self.rotate_right(node);
|
||||||
|
@ -318,25 +383,34 @@ impl RedBlackTree {
|
||||||
|
|
||||||
while !x.is_null() {
|
while !x.is_null() {
|
||||||
y = x;
|
y = x;
|
||||||
|
self.stats.comparisons += 1;
|
||||||
match node.cmp(&&mut x) {
|
match node.cmp(&&mut x) {
|
||||||
Ordering::Less => {
|
Ordering::Less => {
|
||||||
|
self.stats.reads += 1;
|
||||||
x = x.left();
|
x = x.left();
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
self.stats.reads += 1;
|
||||||
x = x.right();
|
x = x.right();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.stats.writes += 1;
|
||||||
node.set_parent(y);
|
node.set_parent(y);
|
||||||
|
|
||||||
if y.is_null() {
|
if y.is_null() {
|
||||||
|
self.stats.writes += 1;
|
||||||
self.root = node;
|
self.root = node;
|
||||||
} else {
|
} else {
|
||||||
|
self.stats.comparisons += 1;
|
||||||
match node.cmp(&&mut y) {
|
match node.cmp(&&mut y) {
|
||||||
Ordering::Less => {
|
Ordering::Less => {
|
||||||
|
self.stats.writes += 1;
|
||||||
y.set_left(node);
|
y.set_left(node);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
self.stats.writes += 1;
|
||||||
y.set_right(node);
|
y.set_right(node);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -346,18 +420,21 @@ impl RedBlackTree {
|
||||||
unsafe { self.insert_fixup(node); }
|
unsafe { self.insert_fixup(node); }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_node(&self, key: u64) -> RBT {
|
fn find_node(&mut self, key: u64) -> RBT {
|
||||||
if self.root.is_null() {
|
if self.root.is_null() {
|
||||||
return RBT::null();
|
return RBT::null();
|
||||||
}
|
}
|
||||||
|
self.stats.reads += 1;
|
||||||
let mut temp = &self.root;
|
let mut temp = &self.root;
|
||||||
unsafe {
|
unsafe {
|
||||||
loop {
|
loop {
|
||||||
|
self.stats.comparisons += 1;
|
||||||
let next = match key.cmp(&(*temp.0).key) {
|
let next = match key.cmp(&(*temp.0).key) {
|
||||||
Ordering::Less => &mut (*temp.0).left,
|
Ordering::Less => &mut (*temp.0).left,
|
||||||
Ordering::Greater => &mut (*temp.0).right,
|
Ordering::Greater => &mut (*temp.0).right,
|
||||||
Ordering::Equal => return *temp,
|
Ordering::Equal => return *temp,
|
||||||
};
|
};
|
||||||
|
self.stats.reads += 1;
|
||||||
if next.is_null() {
|
if next.is_null() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -372,60 +449,78 @@ impl RedBlackTree {
|
||||||
use Colour::*;
|
use Colour::*;
|
||||||
|
|
||||||
let mut other;
|
let mut other;
|
||||||
|
self.stats.reads += 1;
|
||||||
while node != self.root && node.colour() == Black {
|
while node != self.root && node.colour() == Black {
|
||||||
|
self.stats.reads += 1;
|
||||||
if parent.left() == node {
|
if parent.left() == node {
|
||||||
|
self.stats.reads += 1;
|
||||||
other = parent.right();
|
other = parent.right();
|
||||||
|
|
||||||
if other.colour() == Red {
|
if other.colour() == Red {
|
||||||
other.set_colour(Black);
|
other.set_colour(Black);
|
||||||
parent.set_colour(Red);
|
parent.set_colour(Red);
|
||||||
self.rotate_left(parent);
|
self.rotate_left(parent);
|
||||||
|
self.stats.reads += 1;
|
||||||
other = parent.right();
|
other = parent.right();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.stats.reads += 2;
|
||||||
if other.left().colour() == Black && other.right().colour() == Black {
|
if other.left().colour() == Black && other.right().colour() == Black {
|
||||||
other.set_colour(Red);
|
other.set_colour(Red);
|
||||||
node = parent;
|
node = parent;
|
||||||
|
self.stats.reads += 1;
|
||||||
parent = node.parent();
|
parent = node.parent();
|
||||||
} else {
|
} else {
|
||||||
|
self.stats.reads += 1;
|
||||||
if other.right().colour() == Black {
|
if other.right().colour() == Black {
|
||||||
|
self.stats.reads += 1;
|
||||||
other.left().set_colour(Black);
|
other.left().set_colour(Black);
|
||||||
other.set_colour(Red);
|
other.set_colour(Red);
|
||||||
self.rotate_right(other);
|
self.rotate_right(other);
|
||||||
|
self.stats.reads += 1;
|
||||||
other = parent.right();
|
other = parent.right();
|
||||||
}
|
}
|
||||||
|
|
||||||
other.set_colour(parent.colour());
|
other.set_colour(parent.colour());
|
||||||
parent.set_colour(Black);
|
parent.set_colour(Black);
|
||||||
|
self.stats.reads += 1;
|
||||||
other.right().set_colour(Black);
|
other.right().set_colour(Black);
|
||||||
self.rotate_left(parent);
|
self.rotate_left(parent);
|
||||||
node = self.root;
|
node = self.root;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
self.stats.reads += 1;
|
||||||
other = parent.left();
|
other = parent.left();
|
||||||
|
|
||||||
if other.colour() == Red {
|
if other.colour() == Red {
|
||||||
other.set_colour(Black);
|
other.set_colour(Black);
|
||||||
parent.set_colour(Red);
|
parent.set_colour(Red);
|
||||||
self.rotate_right(parent);
|
self.rotate_right(parent);
|
||||||
|
self.stats.reads += 1;
|
||||||
other = parent.left();
|
other = parent.left();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.stats.reads += 2;
|
||||||
if other.left().colour() == Black && other.right().colour() == Black {
|
if other.left().colour() == Black && other.right().colour() == Black {
|
||||||
other.set_colour(Red);
|
other.set_colour(Red);
|
||||||
node = parent;
|
node = parent;
|
||||||
|
self.stats.reads += 1;
|
||||||
parent = node.parent();
|
parent = node.parent();
|
||||||
} else {
|
} else {
|
||||||
|
self.stats.reads += 1;
|
||||||
if other.left().colour() == Black {
|
if other.left().colour() == Black {
|
||||||
|
self.stats.reads += 1;
|
||||||
other.right().set_colour(Black);
|
other.right().set_colour(Black);
|
||||||
other.set_colour(Red);
|
other.set_colour(Red);
|
||||||
self.rotate_left(other);
|
self.rotate_left(other);
|
||||||
|
self.stats.reads += 1;
|
||||||
other = parent.left();
|
other = parent.left();
|
||||||
}
|
}
|
||||||
|
|
||||||
other.set_colour(parent.colour());
|
other.set_colour(parent.colour());
|
||||||
parent.set_colour(Black);
|
parent.set_colour(Black);
|
||||||
|
self.stats.reads += 1;
|
||||||
other.left().set_colour(Black);
|
other.left().set_colour(Black);
|
||||||
self.rotate_right(parent);
|
self.rotate_right(parent);
|
||||||
node = self.root;
|
node = self.root;
|
||||||
|
@ -444,18 +539,25 @@ impl RedBlackTree {
|
||||||
|
|
||||||
self.size -= 1;
|
self.size -= 1;
|
||||||
|
|
||||||
|
self.stats.reads += 2;
|
||||||
if !node.left().is_null() && !node.right().is_null() {
|
if !node.left().is_null() && !node.right().is_null() {
|
||||||
|
self.stats.reads += 1;
|
||||||
let mut replace = node.right().minimum();
|
let mut replace = node.right().minimum();
|
||||||
if node == self.root {
|
if node == self.root {
|
||||||
self.root = replace;
|
self.root = replace;
|
||||||
} else {
|
} else {
|
||||||
if node.parent().left() == node {
|
if node.parent().left() == node {
|
||||||
|
self.stats.reads += 1;
|
||||||
|
self.stats.writes += 1;
|
||||||
node.parent().set_left(replace);
|
node.parent().set_left(replace);
|
||||||
} else {
|
} else {
|
||||||
|
self.stats.reads += 1;
|
||||||
|
self.stats.writes += 1;
|
||||||
node.parent().set_right(replace);
|
node.parent().set_right(replace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.stats.reads += 2;
|
||||||
child = replace.right();
|
child = replace.right();
|
||||||
parent = replace.parent();
|
parent = replace.parent();
|
||||||
color = replace.colour();
|
color = replace.colour();
|
||||||
|
@ -463,13 +565,18 @@ impl RedBlackTree {
|
||||||
parent = replace;
|
parent = replace;
|
||||||
} else {
|
} else {
|
||||||
if !child.is_null() {
|
if !child.is_null() {
|
||||||
|
self.stats.writes += 1;
|
||||||
child.set_parent(parent);
|
child.set_parent(parent);
|
||||||
}
|
}
|
||||||
|
self.stats.writes += 3;
|
||||||
|
self.stats.reads += 2;
|
||||||
parent.set_left(child);
|
parent.set_left(child);
|
||||||
replace.set_right(node.right());
|
replace.set_right(node.right());
|
||||||
node.right().set_parent(replace);
|
node.right().set_parent(replace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.stats.writes += 3;
|
||||||
|
self.stats.reads += 3;
|
||||||
replace.set_parent(node.parent());
|
replace.set_parent(node.parent());
|
||||||
replace.set_colour(node.colour());
|
replace.set_colour(node.colour());
|
||||||
replace.set_left(node.left());
|
replace.set_left(node.left());
|
||||||
|
@ -483,24 +590,32 @@ impl RedBlackTree {
|
||||||
return obj.key;
|
return obj.key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.stats.reads += 1;
|
||||||
if !node.left().is_null() {
|
if !node.left().is_null() {
|
||||||
|
self.stats.reads += 1;
|
||||||
child = node.left();
|
child = node.left();
|
||||||
} else {
|
} else {
|
||||||
|
self.stats.reads += 1;
|
||||||
child = node.right();
|
child = node.right();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.stats.reads += 1;
|
||||||
parent = node.parent();
|
parent = node.parent();
|
||||||
color = node.colour();
|
color = node.colour();
|
||||||
if !child.is_null() {
|
if !child.is_null() {
|
||||||
|
self.stats.writes += 1;
|
||||||
child.set_parent(parent);
|
child.set_parent(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.root == node {
|
if self.root == node {
|
||||||
self.root = child
|
self.root = child;
|
||||||
} else {
|
} else {
|
||||||
|
self.stats.reads += 1;
|
||||||
if parent.left() == node {
|
if parent.left() == node {
|
||||||
|
self.stats.writes += 1;
|
||||||
parent.set_left(child);
|
parent.set_left(child);
|
||||||
} else {
|
} else {
|
||||||
|
self.stats.writes += 1;
|
||||||
parent.set_right(child);
|
parent.set_right(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -525,6 +640,10 @@ impl RedBlackTree {
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn reset_stats(&mut self) {
|
||||||
|
self.stats = Stats::default();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for RedBlackTree {
|
impl Display for RedBlackTree {
|
||||||
|
|
447
libtree/src/splay_tree.rs
Normal file
447
libtree/src/splay_tree.rs
Normal file
|
@ -0,0 +1,447 @@
|
||||||
|
use core::fmt::Display;
|
||||||
|
use std::{cmp::Ordering, ptr};
|
||||||
|
use crate::Stats;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct SplayTreeNode {
|
||||||
|
pub key: u64,
|
||||||
|
pub left: ST,
|
||||||
|
pub right: ST,
|
||||||
|
pub parent: ST,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SplayTreeNode {
|
||||||
|
pub fn new(key: u64) -> Self {
|
||||||
|
Self {
|
||||||
|
key,
|
||||||
|
left: ST::null(),
|
||||||
|
right: ST::null(),
|
||||||
|
parent: ST::null(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ST(*mut SplayTreeNode);
|
||||||
|
|
||||||
|
|
||||||
|
impl Clone for ST {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self(self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Copy for ST {}
|
||||||
|
|
||||||
|
impl Ord for ST {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
unsafe { (*self.0).key.cmp(&(*other.0).key) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for ST {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
unsafe { Some((*self.0).key.cmp(&(*other.0).key)) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for ST {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.0 == other.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for ST {}
|
||||||
|
|
||||||
|
impl ST {
|
||||||
|
fn new(key: u64) -> Self {
|
||||||
|
Self(Box::into_raw(Box::new(SplayTreeNode {
|
||||||
|
key,
|
||||||
|
left: Self::null(),
|
||||||
|
right: Self::null(),
|
||||||
|
parent: Self::null(),
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn height(&self) -> usize {
|
||||||
|
if self.is_null() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
match (self.left().is_null(), self.right().is_null()) {
|
||||||
|
(true, true) =>
|
||||||
|
1,
|
||||||
|
(true, false) =>
|
||||||
|
1 + self.right().height(),
|
||||||
|
(false, true) =>
|
||||||
|
1 + self.left().height(),
|
||||||
|
(false, false) =>
|
||||||
|
1 + (self.left().height()).max(self.right().height()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn minimum(self) -> Self {
|
||||||
|
let mut temp = self.clone();
|
||||||
|
while !temp.left().is_null() {
|
||||||
|
temp = temp.left();
|
||||||
|
}
|
||||||
|
|
||||||
|
temp
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_parent(&mut self, parent: Self) {
|
||||||
|
if !self.is_null() {
|
||||||
|
unsafe { (*self.0).parent = parent; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_right(&mut self, right: Self) {
|
||||||
|
if !self.is_null() {
|
||||||
|
unsafe { (*self.0).right = right; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_left(&mut self, left: Self) {
|
||||||
|
if !self.is_null() {
|
||||||
|
unsafe { (*self.0).left = left; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parent(&self) -> Self {
|
||||||
|
match self.is_null() {
|
||||||
|
true => Self::null(),
|
||||||
|
false => unsafe { (*self.0).parent.clone() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn right(&self) -> Self {
|
||||||
|
match self.is_null() {
|
||||||
|
true => Self::null(),
|
||||||
|
false => unsafe { (*self.0).right.clone() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn left(&self) -> Self {
|
||||||
|
match self.is_null() {
|
||||||
|
true => Self::null(),
|
||||||
|
false => unsafe { (*self.0).left.clone() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn null() -> Self {
|
||||||
|
Self(ptr::null_mut())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_null(&self) -> bool {
|
||||||
|
self.0.is_null()
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://stackoverflow.com/a/66661638
|
||||||
|
fn replace_nth_char_ascii(s: &mut str, idx: usize, newchar: char) {
|
||||||
|
let s_bytes: &mut [u8] = unsafe { s.as_bytes_mut() };
|
||||||
|
assert!(idx < s_bytes.len());
|
||||||
|
assert!(s_bytes[idx].is_ascii());
|
||||||
|
assert!(newchar.is_ascii());
|
||||||
|
// we've made sure this is safe.
|
||||||
|
s_bytes[idx] = newchar as u8;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _print(&self, f: &mut std::fmt::Formatter<'_>, depth: usize, prefix: char, left_trace: &mut String, right_trace: &mut String) -> std::fmt::Result {
|
||||||
|
if self.is_null() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.left().is_null() {
|
||||||
|
self.left()._print(f, depth + 1, '/', left_trace, right_trace)?;
|
||||||
|
}
|
||||||
|
if prefix == '/' {
|
||||||
|
Self::replace_nth_char_ascii(left_trace, depth - 1, '|');
|
||||||
|
}
|
||||||
|
if prefix == '\\' {
|
||||||
|
Self::replace_nth_char_ascii(right_trace, depth - 1, ' ');
|
||||||
|
}
|
||||||
|
if depth == 0 {
|
||||||
|
write!(f, "-")?;
|
||||||
|
}
|
||||||
|
if depth > 0 {
|
||||||
|
write!(f, " ")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if depth > 0 {
|
||||||
|
for i in 0..(depth - 1) {
|
||||||
|
if left_trace.chars().nth(i).unwrap() == '|' || right_trace.chars().nth(i).unwrap() == '|' {
|
||||||
|
write!(f, "| ")?;
|
||||||
|
} else {
|
||||||
|
write!(f, " ")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
write!(f, "{}-", prefix)?;
|
||||||
|
}
|
||||||
|
writeln!(f, "[{}]", unsafe { (*self.0).key })?;
|
||||||
|
Self::replace_nth_char_ascii(left_trace, depth, ' ');
|
||||||
|
|
||||||
|
if !self.right().is_null() {
|
||||||
|
Self::replace_nth_char_ascii(right_trace, depth, '|');
|
||||||
|
self.right()._print(f, depth + 1, '\\', left_trace, right_trace)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SplayTree {
|
||||||
|
pub root: ST,
|
||||||
|
pub size: usize,
|
||||||
|
print_capacity: usize,
|
||||||
|
pub stats: Stats,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SplayTree {
|
||||||
|
pub fn new(print_capacity: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
root: ST::null(),
|
||||||
|
size: 0,
|
||||||
|
print_capacity,
|
||||||
|
stats: Stats::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn height(&self) -> usize {
|
||||||
|
match &self.root.is_null() {
|
||||||
|
false => self.root.height(),
|
||||||
|
true => 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn rotate_left(&mut self, mut node: ST) {
|
||||||
|
let mut right = node.right();
|
||||||
|
node.set_right(right.left());
|
||||||
|
self.stats.writes += 1;
|
||||||
|
self.stats.reads += 2;
|
||||||
|
|
||||||
|
self.stats.reads += 1;
|
||||||
|
if !right.left().is_null() {
|
||||||
|
right.left().set_parent(node);
|
||||||
|
self.stats.writes += 1;
|
||||||
|
self.stats.reads += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
right.set_parent(node.parent());
|
||||||
|
self.stats.writes += 1;
|
||||||
|
self.stats.reads += 1;
|
||||||
|
|
||||||
|
self.stats.reads += 1;
|
||||||
|
if node == self.root {
|
||||||
|
self.root = right;
|
||||||
|
self.stats.writes += 1;
|
||||||
|
} else if node == node.parent().left() {
|
||||||
|
node.parent().set_left(right);
|
||||||
|
self.stats.writes += 1;
|
||||||
|
self.stats.reads += 2;
|
||||||
|
} else if node == node.parent().right() {
|
||||||
|
node.parent().set_right(right);
|
||||||
|
self.stats.writes += 1;
|
||||||
|
self.stats.reads += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
right.set_left(node);
|
||||||
|
node.set_parent(right);
|
||||||
|
self.stats.writes += 2;
|
||||||
|
self.stats.reads += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn rotate_right(&mut self, mut node: ST) {
|
||||||
|
let mut left = node.left();
|
||||||
|
node.set_left(left.right());
|
||||||
|
self.stats.writes += 1;
|
||||||
|
self.stats.reads += 2;
|
||||||
|
|
||||||
|
self.stats.reads += 1;
|
||||||
|
if !left.right().is_null() {
|
||||||
|
left.right().set_parent(node);
|
||||||
|
self.stats.writes += 1;
|
||||||
|
self.stats.reads += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
left.set_parent(node.parent());
|
||||||
|
self.stats.writes += 1;
|
||||||
|
self.stats.reads += 1;
|
||||||
|
|
||||||
|
self.stats.reads += 1;
|
||||||
|
if node == self.root {
|
||||||
|
self.root = left;
|
||||||
|
self.stats.writes += 1;
|
||||||
|
} else if node == node.parent().left() {
|
||||||
|
node.parent().set_left(left);
|
||||||
|
self.stats.writes += 1;
|
||||||
|
self.stats.reads += 2;
|
||||||
|
} else if node == node.parent().right() {
|
||||||
|
node.parent().set_right(left);
|
||||||
|
self.stats.writes += 1;
|
||||||
|
self.stats.reads += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
left.set_right(node);
|
||||||
|
node.set_parent(left);
|
||||||
|
self.stats.writes += 2;
|
||||||
|
self.stats.reads += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn splay(&mut self, node: ST) {
|
||||||
|
while !node.parent().is_null() {
|
||||||
|
self.stats.reads += 1;
|
||||||
|
if node.parent() == self.root {
|
||||||
|
self.stats.reads += 1;
|
||||||
|
if node == node.parent().left() {
|
||||||
|
self.rotate_right(node.parent());
|
||||||
|
} else {
|
||||||
|
self.rotate_left(node.parent());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.stats.reads += 2;
|
||||||
|
let parent = node.parent();
|
||||||
|
let grandparent = node.parent().parent();
|
||||||
|
|
||||||
|
self.stats.reads += 4;
|
||||||
|
if node.parent().left() == node && parent.parent().left() == parent {
|
||||||
|
self.rotate_right(grandparent);
|
||||||
|
self.rotate_right(parent);
|
||||||
|
} else if node.parent().right() == node && parent.parent().right() == parent {
|
||||||
|
self.rotate_left(grandparent);
|
||||||
|
self.rotate_left(parent);
|
||||||
|
} else if node.parent().right() == node && parent.parent().left() == parent {
|
||||||
|
self.rotate_left(parent);
|
||||||
|
self.rotate_right(grandparent);
|
||||||
|
} else if node.parent().left() == node && parent.parent().right() == parent {
|
||||||
|
self.rotate_right(parent);
|
||||||
|
self.rotate_left(grandparent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert(&mut self, key: u64) {
|
||||||
|
self.size += 1;
|
||||||
|
|
||||||
|
let mut node = ST::new(key);
|
||||||
|
let mut new = ST::null();
|
||||||
|
let mut temp = self.root;
|
||||||
|
|
||||||
|
while !temp.is_null() {
|
||||||
|
new = temp;
|
||||||
|
|
||||||
|
self.stats.comparisons += 1;
|
||||||
|
self.stats.reads += 1;
|
||||||
|
if key < unsafe { (*temp.0).clone() }.key {
|
||||||
|
temp = temp.left()
|
||||||
|
} else {
|
||||||
|
temp = temp.right();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.stats.writes += 1;
|
||||||
|
node.set_parent(new);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.stats.writes += 2;
|
||||||
|
if new.is_null() {
|
||||||
|
self.root = node;
|
||||||
|
} else if key < unsafe { (*new.0).clone() }.key {
|
||||||
|
self.stats.comparisons += 1;
|
||||||
|
new.set_left(node);
|
||||||
|
} else {
|
||||||
|
new.set_right(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe { self.splay(node); }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn replace(&mut self, node: ST, mut with: ST) {
|
||||||
|
if node.parent().is_null() {
|
||||||
|
self.stats.reads += 1;
|
||||||
|
self.stats.writes += 1;
|
||||||
|
self.root = with;
|
||||||
|
} else if node == node.parent().left() {
|
||||||
|
self.stats.reads += 1;
|
||||||
|
node.parent().set_left(with);
|
||||||
|
} else {
|
||||||
|
self.stats.reads += 1;
|
||||||
|
node.parent().set_right(with);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !with.is_null() {
|
||||||
|
self.stats.reads += 1;
|
||||||
|
self.stats.writes += 1;
|
||||||
|
with.set_parent(node.parent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_node(&mut self, key: u64) -> ST {
|
||||||
|
if self.root.is_null() {
|
||||||
|
return ST::null();
|
||||||
|
}
|
||||||
|
self.stats.reads += 1;
|
||||||
|
let mut temp = &self.root;
|
||||||
|
unsafe {
|
||||||
|
loop {
|
||||||
|
let next = match key.cmp(&(*temp.0).key) {
|
||||||
|
Ordering::Less => &mut (*temp.0).left,
|
||||||
|
Ordering::Greater => &mut (*temp.0).right,
|
||||||
|
Ordering::Equal => return *temp,
|
||||||
|
};
|
||||||
|
self.stats.reads += 1;
|
||||||
|
if next.is_null() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
temp = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ST::null()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn delete(&mut self, key: u64) -> bool {
|
||||||
|
let node = self.find_node(key);
|
||||||
|
|
||||||
|
if node.is_null() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe { self.splay(node); }
|
||||||
|
|
||||||
|
if node.left().is_null() {
|
||||||
|
self.stats.reads += 2;
|
||||||
|
self.replace(node, node.right());
|
||||||
|
} else if node.right().is_null() {
|
||||||
|
self.stats.reads += 2;
|
||||||
|
self.replace(node, node.left());
|
||||||
|
} else {
|
||||||
|
let mut temp = node.right().minimum();
|
||||||
|
|
||||||
|
self.stats.reads += 1;
|
||||||
|
if temp.parent() != node {
|
||||||
|
self.stats.reads += 2;
|
||||||
|
self.stats.writes += 2;
|
||||||
|
self.replace(temp, temp.right());
|
||||||
|
temp.set_right(node.right());
|
||||||
|
temp.right().set_parent(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.replace(node, temp);
|
||||||
|
self.stats.reads += 2;
|
||||||
|
self.stats.writes += 2;
|
||||||
|
temp.set_left(node.left());
|
||||||
|
temp.left().set_parent(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reset_stats(&mut self) {
|
||||||
|
self.stats = Stats::default();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for SplayTree {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
self.root._print(f, 0, '-', &mut " ".repeat(self.print_capacity), &mut " ".repeat(self.print_capacity))
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue