Struct Filter

Source
pub struct Filter<T> { /* private fields */ }
Expand description

An implementation of a median filter with linear complexity.

While the common naïve implementation of a median filter has a worst-case complexity of O(n^2) (due to having to sort the sliding window) the use of a combination of linked list and ring buffer allows for a worst-case complexity of O(n).

Implementations§

Source§

impl<T> Filter<T>
where T: Clone + PartialOrd,

Source

pub fn new(size: usize) -> Self

Creates a new median filter with a given window size.

Source

pub fn len(&self) -> usize

Returns the window size of the filter.

Source

pub fn is_empty(&self) -> usize

Returns true if the filter has a length of 0.

Source

pub fn median(&self) -> T

Returns the filter buffer’s current median value, panicking if empty.

Source

pub fn min(&self) -> T

Returns the filter buffer’s current min value, panicking if empty.

Source

pub fn max(&self) -> T

Returns the filter buffer’s current max value, panicking if empty.

Source

pub fn consume(&mut self, value: T) -> T

Applies a median filter to the consumed value.

§Implementation

The algorithm makes use of a ring buffer of the same size as its filter window. Inserting values into the ring buffer appends them to a linked list that is embedded inside said ring buffer (using relative integer jump offsets as links).

§Example

Given a sequence of values [3, 2, 4, 6, 5, 1] and a buffer of size 5, the buffer would be filled like this:

new(5)  consume(3)  consume(2)  consume(4)  consume(6)  consume(5)  consume(1)
▶︎[ ]      ▷[3]       ┌→[3]       ┌→[3]─┐     ┌→[3]─┐    ▶︎┌→[3]─┐      ▷[1]─┐
 [ ]      ▶︎[ ]      ▷└─[2]      ▷└─[2] │    ▷└─[2] │    ▷└─[2] │    ▶︎┌─[2]←┘
 [ ]       [ ]        ▶︎[ ]         [4]←┘     ┌─[4]←┘     ┌─[4]←┘     └→[4]─┐
 [ ]       [ ]         [ ]        ▶︎[ ]       └→[6]       │ [6]←┐     ┌→[6] │
 [ ]       [ ]         [ ]         [ ]        ▶︎[ ]       └→[5]─┘     └─[5]←┘
§Algorithm
  1. Remove node at current cursor (▶︎) from linked list, if it exists. (by re-wiring its predecessor to its successor).
  2. Initialize current and median index to first node of linked list ().
  3. Walk through linked list, searching for insertion point.
  4. Shift median index on every other hop (thus ending up in the list’s median).
  5. Insert value into ring buffer and linked list respectively.
  6. Update index to linked list’s first node, if necessary.
  7. Update ring buffer’s cursor.
  8. Return median value.

(Based on Phil Ekstrom, Embedded Systems Programming, November 2000.)

Trait Implementations§

Source§

impl<T: Clone> Clone for Filter<T>

Source§

fn clone(&self) -> Filter<T>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T: Debug> Debug for Filter<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<T> Freeze for Filter<T>

§

impl<T> RefUnwindSafe for Filter<T>
where T: RefUnwindSafe,

§

impl<T> Send for Filter<T>
where T: Send,

§

impl<T> Sync for Filter<T>
where T: Sync,

§

impl<T> Unpin for Filter<T>
where T: Unpin,

§

impl<T> UnwindSafe for Filter<T>
where T: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.