compress all values instead of just zeros

This commit is contained in:
MaxOhn
2023-02-14 08:59:47 +01:00
parent 7b87041f49
commit de342f5c3d
8 changed files with 129 additions and 133 deletions
+4 -4
View File
@@ -8,7 +8,7 @@ use crate::{
colours::{AlternatingMonoPattern, MonoStreak, RepeatingHitPatterns},
difficulty_object::{ObjectLists, TaikoDifficultyObject},
},
util::CompactZerosVec,
util::CompactVec,
};
use super::{Skill, StrainDecaySkill, StrainSkill};
@@ -18,7 +18,7 @@ pub(crate) struct Colour {
curr_strain: f64,
curr_section_peak: f64,
curr_section_end: f64,
pub(crate) strain_peaks: CompactZerosVec,
pub(crate) strain_peaks: CompactVec,
}
impl Colour {
@@ -27,7 +27,7 @@ impl Colour {
curr_strain: 0.0,
curr_section_peak: 0.0,
curr_section_end: 0.0,
strain_peaks: CompactZerosVec::new(),
strain_peaks: CompactVec::new(),
}
}
}
@@ -46,7 +46,7 @@ impl Skill for Colour {
impl StrainSkill for Colour {
#[inline]
fn strain_peaks_mut(&mut self) -> &mut CompactZerosVec {
fn strain_peaks_mut(&mut self) -> &mut CompactVec {
&mut self.strain_peaks
}
+4 -4
View File
@@ -2,7 +2,7 @@ use std::cmp::Ordering;
use crate::{
taiko::difficulty_object::{ObjectLists, TaikoDifficultyObject},
util::CompactZerosVec,
util::CompactVec,
};
use super::{colour::Colour, rhythm::Rhythm, stamina::Stamina, Skill, StrainSkill};
@@ -119,7 +119,7 @@ pub(crate) struct PeaksDifficultyValues {
}
pub(crate) struct PeaksRaw {
pub(crate) colour: CompactZerosVec,
pub(crate) rhythm: CompactZerosVec,
pub(crate) stamina: CompactZerosVec,
pub(crate) colour: CompactVec,
pub(crate) rhythm: CompactVec,
pub(crate) stamina: CompactVec,
}
+4 -4
View File
@@ -1,6 +1,6 @@
use crate::{
taiko::difficulty_object::{HitObjectRhythm, ObjectLists, TaikoDifficultyObject},
util::{CompactZerosVec, LimitedQueue},
util::{CompactVec, LimitedQueue},
};
use super::{Skill, StrainDecaySkill, StrainSkill};
@@ -17,7 +17,7 @@ pub(crate) struct Rhythm {
history: LimitedQueue<HistoryElement, HISTORY_MAX_LEN>,
curr_section_peak: f64,
curr_section_end: f64,
pub(crate) strain_peaks: CompactZerosVec,
pub(crate) strain_peaks: CompactVec,
}
impl Rhythm {
@@ -31,7 +31,7 @@ impl Rhythm {
history: LimitedQueue::new(),
curr_section_peak: 0.0,
curr_section_end: 0.0,
strain_peaks: CompactZerosVec::new(),
strain_peaks: CompactVec::new(),
}
}
@@ -113,7 +113,7 @@ impl Skill for Rhythm {
impl StrainSkill for Rhythm {
#[inline]
fn strain_peaks_mut(&mut self) -> &mut CompactZerosVec {
fn strain_peaks_mut(&mut self) -> &mut CompactVec {
&mut self.strain_peaks
}
+4 -4
View File
@@ -1,6 +1,6 @@
use crate::{
taiko::difficulty_object::{ObjectLists, TaikoDifficultyObject},
util::CompactZerosVec,
util::CompactVec,
};
use super::{Skill, StrainDecaySkill, StrainSkill};
@@ -10,7 +10,7 @@ pub(crate) struct Stamina {
curr_strain: f64,
curr_section_peak: f64,
curr_section_end: f64,
pub(crate) strain_peaks: CompactZerosVec,
pub(crate) strain_peaks: CompactVec,
}
impl Stamina {
@@ -19,7 +19,7 @@ impl Stamina {
curr_strain: 0.0,
curr_section_peak: 0.0,
curr_section_end: 0.0,
strain_peaks: CompactZerosVec::new(),
strain_peaks: CompactVec::new(),
}
}
}
@@ -38,7 +38,7 @@ impl Skill for Stamina {
impl StrainSkill for Stamina {
#[inline]
fn strain_peaks_mut(&mut self) -> &mut CompactZerosVec {
fn strain_peaks_mut(&mut self) -> &mut CompactVec {
&mut self.strain_peaks
}
+7 -5
View File
@@ -5,7 +5,7 @@ use crate::{
difficulty_object::{ObjectLists, TaikoDifficultyObject},
SECTION_LEN,
},
util::CompactZerosVec,
util::CompactVec,
};
pub(crate) trait Skill: Sized {
@@ -16,7 +16,7 @@ pub(crate) trait Skill: Sized {
pub(crate) trait StrainSkill: Skill {
const DECAY_WEIGHT: f64 = 0.9;
fn strain_peaks_mut(&mut self) -> &mut CompactZerosVec;
fn strain_peaks_mut(&mut self) -> &mut CompactVec;
fn curr_section_peak(&mut self) -> &mut f64;
fn curr_section_end(&mut self) -> &mut f64;
@@ -52,7 +52,7 @@ pub(crate) trait StrainSkill: Skill {
let remaining_iters = (remaining_time / SECTION_LEN).ceil();
*self.curr_section_end() += remaining_iters * SECTION_LEN;
self.strain_peaks_mut()
.push_n_zeros(remaining_iters as usize);
.push_n(0.0, remaining_iters as usize);
}
}
@@ -81,7 +81,9 @@ pub(crate) trait StrainSkill: Skill {
// * Sections with 0 strain are excluded to avoid worst-case time complexity of the following sort (e.g. /b/2351871).
// * These sections will not contribute to the difficulty.
let mut peaks = self.get_curr_strain_peaks().to_non_zeros();
let mut peaks = self.get_curr_strain_peaks();
peaks.retain(|peak| peak > 0.0);
let mut peaks = peaks.to_vec();
peaks.sort_unstable_by(|a, b| b.partial_cmp(a).unwrap_or(Ordering::Equal));
// * Difficulty is the weighted sum of the highest strains from every section.
@@ -95,7 +97,7 @@ pub(crate) trait StrainSkill: Skill {
}
#[inline]
fn get_curr_strain_peaks(mut self) -> CompactZerosVec {
fn get_curr_strain_peaks(mut self) -> CompactVec {
let curr_peak = *self.curr_section_peak();
let mut strain_peaks = mem::take(self.strain_peaks_mut());
strain_peaks.push(curr_peak);
+104
View File
@@ -0,0 +1,104 @@
use std::{
iter::{self, Copied},
slice,
};
#[derive(Clone, Debug, Default)]
pub(crate) struct CompactVec {
inner: Vec<Entry>,
len: usize,
}
impl CompactVec {
const ACCEPTABLE_DIFFERENCE: f64 = 1e-7;
pub(crate) fn new() -> Self {
Self::default()
}
pub(crate) fn push(&mut self, num: f64) {
self.push_n(num, 1)
}
pub(crate) fn push_n(&mut self, num: f64, n: usize) {
if let Some(last) = self
.inner
.last_mut()
.filter(|entry| (entry.value - num).abs() <= Self::ACCEPTABLE_DIFFERENCE)
{
last.count += n;
} else if n > 0 {
self.inner.push(Entry::new(num, n))
}
self.len += n;
}
pub(crate) fn retain<F>(&mut self, mut f: F)
where
F: FnMut(f64) -> bool,
{
self.inner.retain(|entry| f(entry.value))
}
pub(crate) fn iter(&self) -> Iter<'_> {
Iter::new(self)
}
pub(crate) fn to_vec(&self) -> Vec<f64> {
let mut nums = Vec::with_capacity(self.len);
for entry in self.inner.iter() {
nums.extend(iter::repeat(entry.value).take(entry.count));
}
nums
}
}
#[derive(Copy, Clone, Debug)]
struct Entry {
value: f64,
count: usize,
}
impl Entry {
fn new(value: f64, count: usize) -> Self {
Self { value, count }
}
}
pub(crate) struct Iter<'a> {
iter: Copied<slice::Iter<'a, Entry>>,
curr: Option<Entry>,
}
impl<'a> Iter<'a> {
fn new(compact_zeros: &'a CompactVec) -> Self {
let mut iter = compact_zeros.inner.iter().copied();
Self {
curr: iter.next(),
iter,
}
}
}
impl Iterator for Iter<'_> {
type Item = f64;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
loop {
let curr = self.curr.as_mut()?;
if curr.count == 0 {
self.curr = self.iter.next();
} else {
curr.count -= 1;
return Some(curr.value);
}
}
}
}
-110
View File
@@ -1,110 +0,0 @@
use std::{
iter::{self, Copied},
slice,
};
#[derive(Clone, Debug, Default)]
pub(crate) struct CompactZerosVec {
inner: Vec<Number>,
non_zero_count: usize,
}
impl CompactZerosVec {
pub(crate) fn new() -> Self {
Self::default()
}
pub(crate) fn push(&mut self, num: f64) {
if num.abs() > f64::EPSILON {
self.inner.push(Number::NonZero(num));
self.non_zero_count += 1;
} else {
self.push_n_zeros(1);
}
}
pub(crate) fn push_n_zeros(&mut self, n: usize) {
match self.inner.last_mut() {
Some(Number::NonZero(_)) | None => self.inner.push(Number::Zeros(n)),
Some(Number::Zeros(zeros)) => *zeros += n,
}
}
pub(crate) fn to_non_zeros(&self) -> Vec<f64> {
let mut non_zeros = Vec::with_capacity(self.non_zero_count);
let iter = self.inner.iter().filter_map(|num| match num {
Number::NonZero(n) => Some(*n),
Number::Zeros(_) => None,
});
non_zeros.extend(iter);
non_zeros
}
pub(crate) fn iter(&self) -> Iter<'_> {
Iter::new(self)
}
pub(crate) fn to_vec(&self) -> Vec<f64> {
let mut nums = Vec::with_capacity(self.inner.len() * 2);
for &num in self.inner.iter() {
match num {
Number::NonZero(num) => nums.push(num),
Number::Zeros(zeros) => nums.extend(iter::repeat(0.0).take(zeros)),
}
}
nums
}
}
#[derive(Copy, Clone, Debug)]
enum Number {
NonZero(f64),
Zeros(usize),
}
pub(crate) struct Iter<'a> {
iter: Copied<slice::Iter<'a, Number>>,
curr: Option<Number>,
}
impl<'a> Iter<'a> {
fn new(compact_zeros: &'a CompactZerosVec) -> Self {
let mut iter = compact_zeros.inner.iter().copied();
Self {
curr: iter.next(),
iter,
}
}
}
impl Iterator for Iter<'_> {
type Item = f64;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match self.curr.as_mut()? {
Number::NonZero(n) => {
let n = *n;
self.curr = self.iter.next();
Some(n)
}
Number::Zeros(zeros @ 1..) => {
*zeros -= 1;
Some(0.0)
}
Number::Zeros(_) => {
self.curr = self.iter.next();
self.next()
}
}
}
}
+2 -2
View File
@@ -1,5 +1,5 @@
mod byte_hasher;
mod compact_zeros;
mod compact_vec;
mod float_ext;
mod limited_queue;
mod sorted_vec;
@@ -8,6 +8,6 @@ mod tandem_sort;
pub use self::sorted_vec::SortedVec;
pub(crate) use self::{
byte_hasher::ByteHasher, compact_zeros::CompactZerosVec, float_ext::FloatExt,
byte_hasher::ByteHasher, compact_vec::CompactVec, float_ext::FloatExt,
limited_queue::LimitedQueue, tandem_sort::TandemSorter,
};