~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/bcachefs/mean_and_variance.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /fs/bcachefs/mean_and_variance.c (Architecture alpha) and /fs/bcachefs/mean_and_variance.c (Architecture sparc64)


  1 // SPDX-License-Identifier: GPL-2.0                 1 // SPDX-License-Identifier: GPL-2.0
  2 /*                                                  2 /*
  3  * Functions for incremental mean and variance      3  * Functions for incremental mean and variance.
  4  *                                                  4  *
  5  * This program is free software; you can redi      5  * This program is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public L      6  * under the terms of the GNU General Public License version 2 as published by
  7  * the Free Software Foundation.                    7  * the Free Software Foundation.
  8  *                                                  8  *
  9  * This program is distributed in the hope tha      9  * This program is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warr     10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the      11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 12  * more details.                                   12  * more details.
 13  *                                                 13  *
 14  * Copyright © 2022 Daniel B. Hill                14  * Copyright © 2022 Daniel B. Hill
 15  *                                                 15  *
 16  * Author: Daniel B. Hill <daniel@gluo.nz>         16  * Author: Daniel B. Hill <daniel@gluo.nz>
 17  *                                                 17  *
 18  * Description:                                    18  * Description:
 19  *                                                 19  *
 20  * This is includes some incremental algorithm     20  * This is includes some incremental algorithms for mean and variance calculation
 21  *                                                 21  *
 22  * Derived from the paper: https://fanf2.user.     22  * Derived from the paper: https://fanf2.user.srcf.net/hermes/doc/antiforgery/stats.pdf
 23  *                                                 23  *
 24  * Create a struct and if it's the weighted va     24  * Create a struct and if it's the weighted variant set the w field (weight = 2^k).
 25  *                                                 25  *
 26  * Use mean_and_variance[_weighted]_update() o     26  * Use mean_and_variance[_weighted]_update() on the struct to update it's state.
 27  *                                                 27  *
 28  * Use the mean_and_variance[_weighted]_get_*      28  * Use the mean_and_variance[_weighted]_get_* functions to calculate the mean and variance, some computation
 29  * is deferred to these functions for performa     29  * is deferred to these functions for performance reasons.
 30  *                                                 30  *
 31  * see lib/math/mean_and_variance_test.c for e     31  * see lib/math/mean_and_variance_test.c for examples of usage.
 32  *                                                 32  *
 33  * DO NOT access the mean and variance fields      33  * DO NOT access the mean and variance fields of the weighted variants directly.
 34  * DO NOT change the weight after calling upda     34  * DO NOT change the weight after calling update.
 35  */                                                35  */
 36                                                    36 
 37 #include <linux/bug.h>                             37 #include <linux/bug.h>
 38 #include <linux/compiler.h>                        38 #include <linux/compiler.h>
 39 #include <linux/export.h>                          39 #include <linux/export.h>
 40 #include <linux/limits.h>                          40 #include <linux/limits.h>
 41 #include <linux/math.h>                            41 #include <linux/math.h>
 42 #include <linux/math64.h>                          42 #include <linux/math64.h>
 43 #include <linux/module.h>                          43 #include <linux/module.h>
 44                                                    44 
 45 #include "mean_and_variance.h"                     45 #include "mean_and_variance.h"
 46                                                    46 
 47 u128_u u128_div(u128_u n, u64 d)                   47 u128_u u128_div(u128_u n, u64 d)
 48 {                                                  48 {
 49         u128_u r;                                  49         u128_u r;
 50         u64 rem;                                   50         u64 rem;
 51         u64 hi = u128_hi(n);                       51         u64 hi = u128_hi(n);
 52         u64 lo = u128_lo(n);                       52         u64 lo = u128_lo(n);
 53         u64  h =  hi & ((u64) U32_MAX  << 32);     53         u64  h =  hi & ((u64) U32_MAX  << 32);
 54         u64  l = (hi &  (u64) U32_MAX) << 32;      54         u64  l = (hi &  (u64) U32_MAX) << 32;
 55                                                    55 
 56         r =             u128_shl(u64_to_u128(d     56         r =             u128_shl(u64_to_u128(div64_u64_rem(h,                d, &rem)), 64);
 57         r = u128_add(r, u128_shl(u64_to_u128(d     57         r = u128_add(r, u128_shl(u64_to_u128(div64_u64_rem(l  + (rem << 32), d, &rem)), 32));
 58         r = u128_add(r,          u64_to_u128(d     58         r = u128_add(r,          u64_to_u128(div64_u64_rem(lo + (rem << 32), d, &rem)));
 59         return r;                                  59         return r;
 60 }                                                  60 }
 61 EXPORT_SYMBOL_GPL(u128_div);                       61 EXPORT_SYMBOL_GPL(u128_div);
 62                                                    62 
 63 /**                                                63 /**
 64  * mean_and_variance_get_mean() - get mean fro     64  * mean_and_variance_get_mean() - get mean from @s
 65  * @s: mean and variance number of samples and     65  * @s: mean and variance number of samples and their sums
 66  */                                                66  */
 67 s64 mean_and_variance_get_mean(struct mean_and     67 s64 mean_and_variance_get_mean(struct mean_and_variance s)
 68 {                                                  68 {
 69         return s.n ? div64_u64(s.sum, s.n) : 0     69         return s.n ? div64_u64(s.sum, s.n) : 0;
 70 }                                                  70 }
 71 EXPORT_SYMBOL_GPL(mean_and_variance_get_mean);     71 EXPORT_SYMBOL_GPL(mean_and_variance_get_mean);
 72                                                    72 
 73 /**                                                73 /**
 74  * mean_and_variance_get_variance() -  get var     74  * mean_and_variance_get_variance() -  get variance from @s1
 75  * @s1: mean and variance number of samples an     75  * @s1: mean and variance number of samples and sums
 76  *                                                 76  *
 77  * see linked pdf equation 12.                     77  * see linked pdf equation 12.
 78  */                                                78  */
 79 u64 mean_and_variance_get_variance(struct mean     79 u64 mean_and_variance_get_variance(struct mean_and_variance s1)
 80 {                                                  80 {
 81         if (s1.n) {                                81         if (s1.n) {
 82                 u128_u s2 = u128_div(s1.sum_sq     82                 u128_u s2 = u128_div(s1.sum_squares, s1.n);
 83                 u64  s3 = abs(mean_and_varianc     83                 u64  s3 = abs(mean_and_variance_get_mean(s1));
 84                                                    84 
 85                 return u128_lo(u128_sub(s2, u1     85                 return u128_lo(u128_sub(s2, u128_square(s3)));
 86         } else {                                   86         } else {
 87                 return 0;                          87                 return 0;
 88         }                                          88         }
 89 }                                                  89 }
 90 EXPORT_SYMBOL_GPL(mean_and_variance_get_varian     90 EXPORT_SYMBOL_GPL(mean_and_variance_get_variance);
 91                                                    91 
 92 /**                                                92 /**
 93  * mean_and_variance_get_stddev() - get standa     93  * mean_and_variance_get_stddev() - get standard deviation from @s
 94  * @s: mean and variance number of samples and     94  * @s: mean and variance number of samples and their sums
 95  */                                                95  */
 96 u32 mean_and_variance_get_stddev(struct mean_a     96 u32 mean_and_variance_get_stddev(struct mean_and_variance s)
 97 {                                                  97 {
 98         return int_sqrt64(mean_and_variance_ge     98         return int_sqrt64(mean_and_variance_get_variance(s));
 99 }                                                  99 }
100 EXPORT_SYMBOL_GPL(mean_and_variance_get_stddev    100 EXPORT_SYMBOL_GPL(mean_and_variance_get_stddev);
101                                                   101 
102 /**                                               102 /**
103  * mean_and_variance_weighted_update() - expon    103  * mean_and_variance_weighted_update() - exponentially weighted variant of mean_and_variance_update()
104  * @s: mean and variance number of samples and    104  * @s: mean and variance number of samples and their sums
105  * @x: new value to include in the &mean_and_v    105  * @x: new value to include in the &mean_and_variance_weighted
106  * @initted: caller must track whether this is    106  * @initted: caller must track whether this is the first use or not
107  * @weight: ewma weight                           107  * @weight: ewma weight
108  *                                                108  *
109  * see linked pdf: function derived from equat    109  * see linked pdf: function derived from equations 140-143 where alpha = 2^w.
110  * values are stored bitshifted for performanc    110  * values are stored bitshifted for performance and added precision.
111  */                                               111  */
112 void mean_and_variance_weighted_update(struct     112 void mean_and_variance_weighted_update(struct mean_and_variance_weighted *s,
113                 s64 x, bool initted, u8 weight    113                 s64 x, bool initted, u8 weight)
114 {                                                 114 {
115         // previous weighted variance.            115         // previous weighted variance.
116         u8 w            = weight;                 116         u8 w            = weight;
117         u64 var_w0      = s->variance;            117         u64 var_w0      = s->variance;
118         // new value weighted.                    118         // new value weighted.
119         s64 x_w         = x << w;                 119         s64 x_w         = x << w;
120         s64 diff_w      = x_w - s->mean;          120         s64 diff_w      = x_w - s->mean;
121         s64 diff        = fast_divpow2(diff_w,    121         s64 diff        = fast_divpow2(diff_w, w);
122         // new mean weighted.                     122         // new mean weighted.
123         s64 u_w1        = s->mean + diff;         123         s64 u_w1        = s->mean + diff;
124                                                   124 
125         if (!initted) {                           125         if (!initted) {
126                 s->mean = x_w;                    126                 s->mean = x_w;
127                 s->variance = 0;                  127                 s->variance = 0;
128         } else {                                  128         } else {
129                 s->mean = u_w1;                   129                 s->mean = u_w1;
130                 s->variance = ((var_w0 << w) -    130                 s->variance = ((var_w0 << w) - var_w0 + ((diff_w * (x_w - u_w1)) >> w)) >> w;
131         }                                         131         }
132 }                                                 132 }
133 EXPORT_SYMBOL_GPL(mean_and_variance_weighted_u    133 EXPORT_SYMBOL_GPL(mean_and_variance_weighted_update);
134                                                   134 
135 /**                                               135 /**
136  * mean_and_variance_weighted_get_mean() - get    136  * mean_and_variance_weighted_get_mean() - get mean from @s
137  * @s: mean and variance number of samples and    137  * @s: mean and variance number of samples and their sums
138  * @weight: ewma weight                           138  * @weight: ewma weight
139  */                                               139  */
140 s64 mean_and_variance_weighted_get_mean(struct    140 s64 mean_and_variance_weighted_get_mean(struct mean_and_variance_weighted s,
141                 u8 weight)                        141                 u8 weight)
142 {                                                 142 {
143         return fast_divpow2(s.mean, weight);      143         return fast_divpow2(s.mean, weight);
144 }                                                 144 }
145 EXPORT_SYMBOL_GPL(mean_and_variance_weighted_g    145 EXPORT_SYMBOL_GPL(mean_and_variance_weighted_get_mean);
146                                                   146 
147 /**                                               147 /**
148  * mean_and_variance_weighted_get_variance() -    148  * mean_and_variance_weighted_get_variance() -- get variance from @s
149  * @s: mean and variance number of samples and    149  * @s: mean and variance number of samples and their sums
150  * @weight: ewma weight                           150  * @weight: ewma weight
151  */                                               151  */
152 u64 mean_and_variance_weighted_get_variance(st    152 u64 mean_and_variance_weighted_get_variance(struct mean_and_variance_weighted s,
153                 u8 weight)                        153                 u8 weight)
154 {                                                 154 {
155         // always positive don't need fast div    155         // always positive don't need fast divpow2
156         return s.variance >> weight;              156         return s.variance >> weight;
157 }                                                 157 }
158 EXPORT_SYMBOL_GPL(mean_and_variance_weighted_g    158 EXPORT_SYMBOL_GPL(mean_and_variance_weighted_get_variance);
159                                                   159 
160 /**                                               160 /**
161  * mean_and_variance_weighted_get_stddev() - g    161  * mean_and_variance_weighted_get_stddev() - get standard deviation from @s
162  * @s: mean and variance number of samples and    162  * @s: mean and variance number of samples and their sums
163  * @weight: ewma weight                           163  * @weight: ewma weight
164  */                                               164  */
165 u32 mean_and_variance_weighted_get_stddev(stru    165 u32 mean_and_variance_weighted_get_stddev(struct mean_and_variance_weighted s,
166                 u8 weight)                        166                 u8 weight)
167 {                                                 167 {
168         return int_sqrt64(mean_and_variance_we    168         return int_sqrt64(mean_and_variance_weighted_get_variance(s, weight));
169 }                                                 169 }
170 EXPORT_SYMBOL_GPL(mean_and_variance_weighted_g    170 EXPORT_SYMBOL_GPL(mean_and_variance_weighted_get_stddev);
171                                                   171 
172 MODULE_AUTHOR("Daniel B. Hill");                  172 MODULE_AUTHOR("Daniel B. Hill");
173 MODULE_LICENSE("GPL");                            173 MODULE_LICENSE("GPL");
174                                                   174 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php