Last active
September 6, 2024 21:22
-
-
Save royratcliffe/670884e9d763f6ead09a50fb5121cd09 to your computer and use it in GitHub Desktop.
C++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cassert> | |
/*! | |
* \brief True if the first string ends with the second string. | |
* \param ends String with some required ending for which to test. | |
* \param with Ending to test the first string against. | |
*/ | |
bool ends_with(const std::string &ends, const std::string &with) { | |
return ends.length() >= with.length() && | |
ends.compare(ends.length() - with.length(), with.length(), with) == 0; | |
} | |
int ends_with_test(int argc, char **argv) { | |
assert(ends_with("abc", "c")); | |
assert(ends_with("abc", "")); | |
assert(!ends_with("abc", "z")); | |
assert(ends_with("a.bmp", ".bmp")); | |
return EXIT_SUCCESS; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//** $Id: SAC.hpp,v 1.2 2000/11/01 07:57:06 royr Exp $ | |
// | |
//** Name | |
// | |
// sac.h -- statistical accumulator | |
// | |
//** Description | |
// | |
// Objects of the StatisticalAccumulator<T> class emulate a | |
// scientific calculator in statistical mode. You can use it to | |
// compute the following statistics: | |
// | |
// arithmetic mean (average) | |
// standard deviation, sample-based | |
// standard deviation, population-based | |
// minimum | |
// maximum | |
// | |
// Use the += operator to add data to the accumulator. This is | |
// equivalent to the M+ button on a calculator. The statistics are | |
// updated to reflect the new data value. | |
// | |
// All the accumulator's behaviors involve floating-point | |
// operations if your template type is float or double. So these | |
// objects should not normally be used in interrupt handlers unless | |
// the floating-point unit permits re-entrancy. The statistics are | |
// only partially computed when the data are added to the | |
// accumulator. The mean and standard deviation statistics are | |
// calculated from the sum of the data and the sum of the data | |
// squared only when the caller invokes the member functions. The | |
// getAverage, getStDev and getStDevP operations are therefore | |
// relatively slow. | |
// | |
// The class provides the following interface: | |
// | |
// StatisticalAccumulator() | |
// StatisticalAccumulator& operator+=(T x) | |
// StatisticalAccumulator& operator-=(T x) | |
// void clear() | |
// unsigned int getCount() const | |
// T getAverage() const | |
// T getStDev() const | |
// T getStDevP() const | |
// T getVar() const | |
// T getMin() const | |
// T getMax() const | |
// | |
// The first four modify the state of an accumulator. The get* | |
// member functions access the statistical information. | |
// | |
// Accumulator objects do not throw exceptions. The quiet SAC_NaN | |
// constant is returned to indicate an error. | |
// | |
//** Example | |
// | |
// #include "sac.h" | |
// #include <iostream> | |
// | |
// . . . | |
// | |
// StatisticalAccumulator<double> sac; | |
// ((sac += 1) += 2) += 3; | |
// cout << "Average = " << sac.getAverage() << endl | |
// << "StDev = " << sac.getStDev() << endl | |
// << "StDevP = " << sac.getStDevP() << endl | |
// << "Min = " << sac.getMin() << endl | |
// << "Max = " << sac.getMax() << endl; | |
// | |
//********************************************************************** | |
#pragma once | |
#ifndef __cplusplus | |
//////////////////////////////////////////////////////////////////////// | |
template <typename T> class StatisticalAccumulator { | |
// interface | |
public: | |
StatisticalAccumulator(); | |
StatisticalAccumulator &operator+=(T x); | |
StatisticalAccumulator &operator-=(T x); | |
void clear(); | |
size_t getCount() const; | |
T getSum() const { return sigmaX; } | |
T getSum2() const { return sigmaX2; } | |
T getAverage() const; | |
T getStDev() const; | |
T getStDevP() const; | |
T getVar() const; | |
T getMin() const; | |
T getMax() const; | |
// implementation | |
private: | |
size_t n; // n | |
T sigmaX; // sum of x | |
T sigmaX2; // sum of x * x | |
T min; // minimum of x | |
T max; // maximum of x | |
}; | |
//////////////////////////////////////////////////////////////////////// | |
#include <limits> // numeric_limits | |
//********************************************************************** | |
// StatisticalAccumulator::StatisticalAccumulator | |
//********************************************************************** | |
// | |
//** Synopsis | |
// | |
// StatisticalAccumulator() | |
// | |
//** Description | |
// | |
// The StatisticalAccumulator constructor puts a new accumulator | |
// object into an initial state by calling clear. | |
// | |
//********************************************************************** | |
template <typename T> StatisticalAccumulator<T>::StatisticalAccumulator() { | |
clear(); | |
} | |
//********************************************************************** | |
// StatisticalAccumulator::operator+= | |
//********************************************************************** | |
// | |
//** Synopsis | |
// | |
// StatisticalAccumulator& operator+=(T x) | |
// | |
//** Description | |
// | |
// The += operator adds a value to the accumulator. | |
// | |
//********************************************************************** | |
template <typename T> | |
StatisticalAccumulator<T> &StatisticalAccumulator<T>::operator+=(T x) { | |
// Update the counter, the sum of X, the sum of X squared, and the | |
// minimum and maximum values. | |
++n; | |
sigmaX += x; | |
sigmaX2 += x * x; | |
if (n == 1) { | |
min = x; | |
max = x; | |
} else { | |
if (x < min) { | |
min = x; | |
} | |
if (x > max) { | |
max = x; | |
} | |
} | |
return *this; | |
} | |
//********************************************************************** | |
// StatisticalAccumulator::operator-= | |
//********************************************************************** | |
// | |
//** Synopsis | |
// | |
// StatisticalAccumulator& operator-=(T x) | |
// | |
//** Description | |
// | |
// The -= operator subtracts a value from the accumulator. This | |
// assumes that the given value has previously been added to the | |
// accumulator with the += operator. | |
// | |
// This operator does not modify the minimum and maximum. The | |
// values returned by getMin and getMax are invalid when the -= | |
// operator is used. | |
// | |
//********************************************************************** | |
template <typename T> | |
StatisticalAccumulator<T> &StatisticalAccumulator<T>::operator-=(T x) { | |
if (n) { | |
--n; | |
sigmaX -= x; | |
sigmaX2 -= x * x; | |
// min and max are now invalid! | |
} | |
return *this; | |
} | |
//********************************************************************** | |
// StatisticalAccumulator::clear | |
//********************************************************************** | |
// | |
//** Synopsis | |
// | |
// void clear() | |
// | |
//** Description | |
// | |
// The clear operation resets the statistical accumulator. The | |
// number of data values is cleared to zero. | |
// | |
//********************************************************************** | |
template <typename T> void StatisticalAccumulator<T>::clear() { | |
n = 0; | |
sigmaX = 0; | |
sigmaX2 = 0; | |
min = numeric_limits<T>::quiet_NaN(); | |
max = numeric_limits<T>::quiet_NaN(); | |
} | |
//********************************************************************** | |
// StatisticalAccumulator::getCount | |
//********************************************************************** | |
// | |
//** Synopsis | |
// | |
// unsigned int getCount() const | |
// | |
//** Description | |
// | |
// The getCount member function tells how many numbers have been | |
// added so far. | |
// | |
//********************************************************************** | |
template <typename T> unsigned int StatisticalAccumulator<T>::getCount() const { | |
return n; | |
} | |
//********************************************************************** | |
// StatisticalAccumulator::getAverage | |
//********************************************************************** | |
// | |
//** Synopsis | |
// | |
// T getAverage() const | |
// | |
//** Description | |
// | |
// GetAverage returns the average, or arithmetic mean, of the data. | |
// | |
//** Return Value | |
// | |
// The return value is not-a-number if the accumulator is clear. | |
// | |
//********************************************************************** | |
template <typename T> T StatisticalAccumulator<T>::getAverage() const { | |
if (n == 0) { | |
return numeric_limits<T>::quiet_NaN(); | |
} | |
return sigmaX / n; | |
} | |
//********************************************************************** | |
// StatisticalAccumulator::getStDev | |
//********************************************************************** | |
// | |
//** Synopsis | |
// | |
// T getStDev() const | |
// | |
//** Description | |
// | |
// The getStDev function calculates and returns the standard | |
// deviation of a sample. | |
// | |
// GetStDev assumes that the accumulated data are just a sample of | |
// the whole population. | |
// | |
//** Return Value | |
// | |
// Not-a-number is returned if the accumulator contains less than | |
// two values. | |
// | |
//********************************************************************** | |
template <typename T> T StatisticalAccumulator<T>::getStDev() const { | |
if (n < 2) { | |
return numeric_limits<T>::quiet_NaN(); | |
} | |
return sqrt((n * sigmaX2 - sigmaX * sigmaX) / (n * (n - 1))); | |
} | |
//********************************************************************** | |
// StatisticalAccumulator::getStDevP | |
//********************************************************************** | |
// | |
//** Synopsis | |
// | |
// T getStDevP() const | |
// | |
//** Description | |
// | |
// The getStDevP function calculates the standard deviation of an | |
// entire population. | |
// | |
// GetStDevP assumes that the accumulated data are the entire | |
// population, not just a sample. | |
// | |
//** Return Value | |
// | |
// Not-a-number is returned if the accumulator is empty. | |
// | |
//********************************************************************** | |
template <typename T> T StatisticalAccumulator<T>::getStDevP() const { | |
if (n < 1) { | |
return numeric_limits<T>::quiet_NaN(); | |
} | |
return sqrt((n * sigmaX2 - sigmaX * sigmaX) / (n * n)); | |
} | |
//********************************************************************** | |
// StatisticalAccumulator::getVar | |
//********************************************************************** | |
// | |
//** Synopsis | |
// | |
// T getVar() const | |
// | |
//** Description | |
// | |
// The getVar function calculates the statistical variance, or | |
// standard deviation squared. | |
// | |
//** Return Value | |
// | |
// Not-a-number is returned if the accumulator is empty. | |
// | |
//********************************************************************** | |
template <typename T> T StatisticalAccumulator<T>::getVar() const { | |
if (n < 1) { | |
return numeric_limits<T>::quiet_NaN(); | |
} | |
return (n * sigmaX2 - sigmaX * sigmaX) / (n * n); | |
} | |
//********************************************************************** | |
// StatisticalAccumulator::getMin | |
//********************************************************************** | |
// | |
//** Synopsis | |
// | |
// T getMin() const | |
// | |
//** Description | |
// | |
// The getMin member function returns the value of the smallest | |
// number that has been added to the accumulator. | |
// | |
//********************************************************************** | |
template <typename T> T StatisticalAccumulator<T>::getMin() const { | |
if (n == 0) { | |
return numeric_limits<T>::quiet_NaN(); | |
} | |
return min; | |
} | |
//********************************************************************** | |
// StatisticalAccumulator::getMax | |
//********************************************************************** | |
// | |
//** Synopsis | |
// | |
// T getMax() const | |
// | |
//** Description | |
// | |
// The getMax member function returns the value of the largest | |
// number that has been added to the accumulator. | |
// | |
//********************************************************************** | |
template <typename T> T StatisticalAccumulator<T>::getMax() const { | |
if (n == 0) { | |
return numeric_limits<T>::quiet_NaN(); | |
} | |
return max; | |
} | |
#endif // __cplusplus | |
#include <limits.h> | |
#include <math.h> | |
#ifndef SAC_SCALAR_TYPE | |
#define SAC_SCALAR_TYPE double | |
#endif | |
#ifndef SAC_SIZE_TYPE | |
#define SAC_SIZE_TYPE size_t | |
#endif | |
#ifndef SAC_NAN | |
#define SAC_NAN NAN | |
#endif | |
#ifndef SAC_SQRT | |
#define SAC_SQRT sqrt | |
#endif | |
struct statistical_accumulator { | |
SAC_SIZE_TYPE n; // n | |
SAC_SCALAR_TYPE sigmaX; // sum of x | |
SAC_SCALAR_TYPE sigmaX2; // sum of x * x | |
SAC_SCALAR_TYPE min; // minimum of x | |
SAC_SCALAR_TYPE max; // maximum of x | |
}; | |
static inline struct statistical_accumulator * | |
sac_add(struct statistical_accumulator *sac, SAC_SCALAR_TYPE x) { | |
// Update the counter, the sum of X, the sum of X squared, and the | |
// minimum and maximum values. | |
sac->sigmaX += x; | |
sac->sigmaX2 += x * x; | |
if (++sac->n == 1) { | |
sac->min = x; | |
sac->max = x; | |
} else { | |
if (x < sac->min) | |
sac->min = x; | |
if (x > sac->max) | |
sac->max = x; | |
} | |
return sac; | |
} | |
static inline struct statistical_accumulator * | |
sac_clear(struct statistical_accumulator *sac) { | |
sac->n = 0; | |
sac->sigmaX = 0; | |
sac->sigmaX2 = 0; | |
sac->min = SAC_NAN; | |
sac->max = SAC_NAN; | |
return sac; | |
} | |
static inline SAC_SIZE_TYPE | |
sac_count(const struct statistical_accumulator *sac) { | |
return sac->n; | |
} | |
static inline SAC_SCALAR_TYPE | |
sac_average(const struct statistical_accumulator *sac) { | |
const SAC_SIZE_TYPE n = sac->n; | |
if (n == 0) | |
return SAC_NAN; | |
return sac->sigmaX / n; | |
} | |
static inline SAC_SCALAR_TYPE | |
sac_st_dev(const struct statistical_accumulator *sac) { | |
const SAC_SIZE_TYPE n = sac->n; | |
if (n < 2) | |
return SAC_NAN; | |
const SAC_SCALAR_TYPE sigmaX = sac->sigmaX; | |
return SAC_SQRT((sac->n * sac->sigmaX2 - sigmaX * sigmaX) / (n * (n - 1))); | |
} | |
static inline SAC_SCALAR_TYPE | |
sac_st_dev_p(const struct statistical_accumulator *sac) { | |
const SAC_SIZE_TYPE n = sac->n; | |
if (n < 1) | |
return SAC_NAN; | |
const SAC_SCALAR_TYPE sigmaX = sac->sigmaX; | |
return SAC_SQRT((n * sac->sigmaX2 - sigmaX * sigmaX) / (n * n)); | |
} | |
static inline SAC_SCALAR_TYPE | |
sac_var(const struct statistical_accumulator *sac) { | |
const SAC_SIZE_TYPE n = sac->n; | |
if (n < 1) | |
return SAC_NAN; | |
const SAC_SCALAR_TYPE sigmaX = sac->sigmaX; | |
return (n * sac->sigmaX2 - sigmaX * sigmaX) / (n * n); | |
} | |
static inline SAC_SCALAR_TYPE | |
sac_min(const struct statistical_accumulator *sac) { | |
if (sac->n == 0) | |
return SAC_NAN; | |
return sac->min; | |
} | |
static inline SAC_SCALAR_TYPE | |
sac_max(const struct statistical_accumulator *sac) { | |
if (sac->n == 0) | |
return SAC_NAN; | |
return sac->max; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment