blob: c8f7ce482cfca61bebddae9b1d1f2da71ffb9240 [file] [log] [blame]
Nanang Izzuddin415fc6f2008-05-17 14:43:46 +00001/* $Id$ */
2/*
3 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#ifndef __PJ_MATH_H__
21#define __PJ_MATH_H__
22
23/**
24 * @file math.h
25 * @brief Mathematics and Statistics.
26 */
27
28#include <pj/string.h>
29#include <pj/compat/high_precision.h>
30
31PJ_BEGIN_DECL
32
33/**
34 * @defgroup pj_math Mathematics and Statistics
35 * @ingroup PJ_MISC
36 * @{
37 *
38 * Provides common mathematics constants and operations, and also standard
39 * statistics calculation (min, max, mean, standard deviation). Statistics
40 * calculation is done in realtime (statistics state is updated on time each
41 * new sample comes).
42 */
43
44/**
45 * Mathematical constants
46 */
47#define PJ_PI 3.14159265358979323846 /* pi */
48#define PJ_1_PI 0.318309886183790671538 /* 1/pi */
49
50/**
51 * Mathematical macro
52 */
53#define PJ_ABS(x) ((x) > 0 ? (x) : -(x))
54#define PJ_MAX(x, y) ((x) > (y)? (x) : (y))
55#define PJ_MIN(x, y) ((x) < (y)? (x) : (y))
56
57/**
58 * This structure describes statistics state.
59 */
60typedef struct pj_math_stat
61{
62 int n; /* number of samples */
63 int max; /* maximum value */
64 int min; /* minimum value */
65 int last; /* last value */
66 int mean; /* mean */
67
68 /* Private members */
69#if PJ_HAS_FLOATING_POINT
70 float fmean_; /* mean(floating point) */
71#else
72 int mean_res_; /* mean residu */
73#endif
74 pj_highprec_t m2_; /* variance * n */
75} pj_math_stat;
76
77/**
78 * Calculate integer square root of an integer.
79 *
80 * @param i Integer to be calculated.
81 *
82 * @return Square root result.
83 */
84PJ_INLINE(unsigned) pj_isqrt(unsigned i)
85{
86 unsigned res = 1, prev;
87
88 /* Rough guess, calculate half bit of input */
89 prev = i >> 2;
90 while (prev) {
91 prev >>= 2;
92 res <<= 1;
93 }
94
95 /* Babilonian method */
96 do {
97 prev = res;
98 res = (prev + i/prev) >> 1;
99 } while ((prev+res)>>1 != res);
100
101 return res;
102}
103
104/**
105 * Initialize statistics state.
106 *
107 * @param stat Statistic state.
108 */
109PJ_INLINE(void) pj_math_stat_init(pj_math_stat *stat)
110{
111 pj_bzero(stat, sizeof(pj_math_stat));
112}
113
114/**
115 * Update statistics state as a new sample comes.
116 *
117 * @param stat Statistic state.
118 * @param val The new sample data.
119 */
120PJ_INLINE(void) pj_math_stat_update(pj_math_stat *stat, int val)
121{
122#if PJ_HAS_FLOATING_POINT
123 float delta;
124#else
125 int delta;
126#endif
127
128 stat->last = val;
129
130 if (stat->n++) {
131 if (stat->min > val)
132 stat->min = val;
133 if (stat->max < val)
134 stat->max = val;
135 } else {
136 stat->min = stat->max = val;
137 }
138
139#if PJ_HAS_FLOATING_POINT
140 delta = val - stat->fmean_;
141 stat->fmean_ += delta/stat->n;
142 stat->mean = (int) stat->fmean_;
143
144 stat->m2_ += (int)(delta * (val-stat->fmean_));
145#else
146 delta = val - stat->mean;
147 stat->mean += delta/stat->n;
148 stat->mean_res_ += delta % stat->n;
149 if (stat->mean_res_ >= stat->n) {
150 ++stat->mean;
151 stat->mean_res_ -= stat->n;
152 } else if (stat->mean_res_ <= -stat->n) {
153 --stat->mean;
154 stat->mean_res_ += stat->n;
155 }
156
157 stat->m2_ += delta * (val-stat->mean);
158#endif
159}
160
161/**
162 * Get the standard deviation of specified statistics state.
163 *
164 * @param stat Statistic state.
165 *
166 * @return The standard deviation.
167 */
168PJ_INLINE(unsigned) pj_math_stat_get_stddev(pj_math_stat *stat)
169{
170 return (pj_isqrt((unsigned)(stat->m2_/stat->n)));
171}
172
173/**
174 * Set the standard deviation of statistics state. This is useful when
175 * the statistic state is operated in 'read-only' mode as a storage of
176 * statistical data.
177 *
178 * @param stat Statistic state.
179 *
180 * @param dev The standard deviation.
181 */
182PJ_INLINE(void) pj_math_stat_set_stddev(pj_math_stat *stat, unsigned dev)
183{
184 if (stat->n == 0)
185 stat->n = 1;
186 stat->m2_ = dev*dev*stat->n;
187}
188
189/** @} */
190
191PJ_END_DECL
192
193#endif /* __PJ_MATH_H__ */