Skip to content

Commit

Permalink
improve internal sorting (#21)
Browse files Browse the repository at this point in the history
* improve internal sorting
* add setSearchMode()
* update readme
  • Loading branch information
RobTillaart authored Nov 6, 2022
1 parent 1f625f9 commit 7a10a4e
Show file tree
Hide file tree
Showing 12 changed files with 538 additions and 98 deletions.
16 changes: 16 additions & 0 deletions .arduino-ci.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
platforms:
rpipico:
board: rp2040:rp2040:rpipico
package: rp2040:rp2040
gcc:
features:
defines:
- ARDUINO_ARCH_RP2040
warnings:
flags:

packages:
rp2040:rp2040:
url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json

compile:
# Choosing to run compilation tests on 2 different Arduino platforms
platforms:
Expand All @@ -9,3 +24,4 @@ compile:
- esp32
- esp8266
- mega2560
- rpipico
110 changes: 110 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# Change Log RunningMedian

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).


## [0.3.7] - 2022-10-28
- Add RP2040 support to build-CI.
- Add CHANGELOG.md
- optimized binary insertion sort - see issue #20 (idea thanks to acicuc)
- add performance test sketch (to test sort efficiency)
- add setSearchMode() for selecting fastest median search mode.
EXPERIMENTAL, select between LINEAR or BINARY search.


## [0.3.6} - 2022-06-06
- bump version for platformio

## [0.3.5} - 2022-06-05
- configuration options,
- fixed static version not working

## [0.3.4} - 2021-12-28
- update library.json,
- update readme.md,
- license, minor edits

## [0.3.3} - 2021-01-22
- better insertionSort (+ clean up test code)

## [0.3.2} - 2021-01-21
- replaced bubbleSort by insertionSort
better performance for large arrays.

## [0.3.1} - 2021-01-16
- Changed size parameter to 255 max

## [0.3.0} - 2021-01-04
- malloc() memory as default storage

----

## [0.2.2] - 2021-01-03
- add Arduino-CI + unit tests

## [0.2.1] - 2020-06-19
- fix library.json

## [0.2.0] - 2020-04-16
- refactor.

----

## [0.1.15] - 2018-08-24
- make runningMedian Configurable #110

## [0.1.14] - 2017-07-26
- revert double to float - issue #33

## [0.1.13] - 2015-10-30
- fix getElement(n) - kudos to Gdunge

## [0.1.12] - 2015-07-12
- refactor constructor + const

## [0.1.11] - 2015-03-29
- undo 0.1.10 fix clear

## [0.1.10] - 2015-03-07
- fix clear

## [0.1.09] - 2014-11-25
- float to double (support ARM)

## [0.1.08] - 2013-10-20
- add getElement(),
- add getSottedElement()
- add predict()

## [0.1.07] - 2013-10-19
- add correct median if \_count is even.

## [0.1.06] - 2013-10-19
- faster sort,
- dynamic arrays,
- replaced sorted float array with indirection array

## [0.1.05] - 2013-10-18
- fixed bug in sort;
- removes default constructor;
- dynamic memory

## [0.1.04] - 2013-10-17
- added getAverage(uint8_t) - kudo's to Sembazuru

## [0.1.03] - 2013-09-30
- added \_sorted flag,
- minor refactor

## [0.1.02] - 2012-03-15
- added ??

## [0.1.01] - 2011-02-22
- added remarks from CodingBadly

## [0.1.00] - 2011-02-16
- initial version

65 changes: 44 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,15 @@ is performance wise O(100x) faster in sorting than 255 elements.
### Note: Configurable Options

There are several options that can be configured via defines at compile time, those being:
- RUNNING_MEDIAN_USE_MALLOC: bool
- true (default): Dynamic memory allocation is used for the buffer.
- false: Static buffers of size MEDIAN_MAX_SIZE are used.
- MEDIAN_MIN_SIZE: uint
- Dynamic / Static: The buffer stores at least this many items.
- MEDIAN_MAX_SIZE: uint
- Dynamic: Not used.
- Static: The buffer stores at most this many items.
- **RUNNING_MEDIAN_USE_MALLOC**: bool
- true (default): Dynamic memory allocation is used for the buffer.
- false: Static buffers of size MEDIAN_MAX_SIZE are used.
- **MEDIAN_MIN_SIZE**: uint8_t
- Dynamic / Static: The buffer stores at least this many items.
- should be minimal 3.
- **MEDIAN_MAX_SIZE**: uint8_t
- Dynamic: Not used.
- Static: The buffer stores at most this many items.


## Interface
Expand All @@ -62,19 +63,19 @@ There are several options that can be configured via defines at compile time, th
### Constructor

- **RunningMedian(const uint8_t size)** Constructor, dynamically allocates memory.
- **~RunningMedian()** Destructor
- **uint8_t getSize()** returns size of internal array
- **uint8_t getCount()** returns current used elements, getCount() <= getSize()
- **~RunningMedian()** Destructor.
- **uint8_t getSize()** returns size of internal array.
- **uint8_t getCount()** returns current used elements, getCount() <= getSize().
- **bool isFull()** returns true if the internal buffer is 100% filled.


### Base functions

- **clear()** resets internal buffer and variables, effectively empty the buffer.
- **add(const float value)** adds a new value to internal buffer,
optionally replacing the oldest element if the buffer is full
- **float getMedian()** returns the median == middle element
- **float getAverage()** returns average of **all** the values in the internal buffer
optionally replacing the oldest element if the buffer is full.
- **float getMedian()** returns the median == middle element.
- **float getAverage()** returns average of **all** the values in the internal buffer.
- **float getAverage(uint8_t nMedian)** returns average of **the middle n** values.
This effectively removes noise from the outliers in the samples.
- **float getHighest()** get the largest values in the buffer.
Expand All @@ -86,19 +87,41 @@ This value is often interpolated.
### Less used functions

- **float getElement(const uint8_t n)** returns the n'th element from the values in time order.
- **float getSortedElement(const uint8_t n)** returns the n'th element from the values in size order (sorted ascending)
- **float getSortedElement(const uint8_t n)** returns the n'th element from the values in size order (sorted ascending).
- **float predict(const uint8_t n)** predict the maximum change of median after n additions,
n must be smaller than **getSize()/2**
n must be smaller than **getSize()/2**.


### SearchMode optimization

Since 0.3.7 the internal sort has been optimized.
It is now possible to select between LINEAR (=0) and BINARY (=1) insertion sort.
Pre-0.3.7 used linear insertion sort, and the new linear version is slightly optimized.
For larger internal arrays the performance gain of BINARY mode is substantial.

- **void setSearchMode(uint8_t searchMode = 0)** 0 = linear, 1 = binary - see table below.
Other values will set the searchMode to linear.
- **uint8_t getSearchMode()** returns the set mode

| searchMode | value | notes |
|:------------:|:-------:|:-------|
| LINEAR | 0 | fastest for smaller internal buffers (default)
| BINARY | 1 | faster for larger internal buffers

Depends on the board / clock used where the methods are equally fast.

Give it a try, and let me know your.


## Operation

See examples
See examples.


## Future

- improve documentation
- check for optimizations
- separate releaseNotes.md
-
- improve documentation.
- check for optimizations.
- get the median without (full) sorting. QuickSelect()
- move all code to .cpp file

Loading

0 comments on commit 7a10a4e

Please sign in to comment.