1 module des.math.method.stat.moment; 2 3 import des.util.testsuite; 4 5 /// expected value 6 T mean(T)( in T[] arr ) pure nothrow @property @nogc 7 if( is( typeof( T.init + T.init ) == T ) && is( typeof( T.init / 1UL ) == T ) ) 8 in { assert( arr.length > 0 ); } body 9 { 10 if( arr.length == 1 ) return arr[0]; 11 T res = arr[0]; 12 foreach( i; 1 .. arr.length ) 13 res = res + arr[i]; 14 return res / arr.length; 15 } 16 17 /// 18 unittest 19 { 20 auto a = [ 1.0f, 2, 3 ]; 21 assert( a.mean == 2.0f ); 22 23 static assert( !__traits(compiles,[1,2,3].mean) ); 24 static assert( __traits(compiles,[1.0f,2,3].mean) ); 25 } 26 27 /// 28 unittest 29 { 30 import des.math.linear.vector; 31 32 auto a = [ vec3(1,2,3), vec3(2,3,4), vec3(3,4,5) ]; 33 assert( a.mean == vec3(2,3,4) ); 34 } 35 36 /// 37 T variance(T)( in T[] arr ) pure nothrow @property @nogc 38 if( is( typeof( T.init + T.init ) == T ) && 39 is( typeof( T.init - T.init ) == T ) && 40 is( typeof( T.init * T.init ) == T ) && 41 is( typeof( T.init / 1UL ) == T ) ) 42 in { assert( arr.length > 1 ); } body 43 { 44 T res = arr[0] - arr[0]; 45 auto m = arr.mean; 46 foreach( val; arr ) 47 res = res + ( m - val ) * ( m - val ); 48 return res / ( arr.length - 1 ); 49 } 50 51 /// 52 unittest 53 { 54 auto a = [ 1.0f, 1, 1 ]; 55 assert( a.variance == 0.0f ); 56 57 auto b = [ 1.0f, 2, 3 ]; 58 assert( b.variance == 1.0f ); 59 } 60 61 /// 62 unittest 63 { 64 import des.math.linear.vector; 65 66 auto a = [ vec3(1,2,3), vec3(2,3,4), vec3(3,4,5) ]; 67 assert( a.variance == vec3(1,1,1) ); 68 } 69 70 /++ returns: 71 mean (0 element), variance (1 element) 72 +/ 73 T[2] mean_variance(T)( in T[] arr ) pure nothrow @property @nogc 74 if( is( typeof( T.init + T.init ) == T ) && 75 is( typeof( T.init - T.init ) == T ) && 76 is( typeof( T.init * T.init ) == T ) && 77 is( typeof( T.init / 1UL ) == T ) ) 78 in { assert( arr.length > 1 ); } body 79 { 80 T res = arr[0] - arr[0]; 81 auto m = arr.mean; 82 foreach( val; arr ) 83 res = res + ( m - val ) * ( m - val ); 84 return [ m, res / ( arr.length - 1 ) ]; 85 } 86 87 /// 88 unittest 89 { 90 auto a = [ 1.0f, 1, 1 ]; 91 assert( a.mean_variance == [ 1.0f, 0.0f ] ); 92 93 auto b = [ 1.0f, 2, 3 ]; 94 assert( b.mean_variance == [ 2.0f, 1.0f ] ); 95 } 96 97 /// 98 unittest 99 { 100 import des.math.linear.vector; 101 102 auto a = [ vec3(1,2,3), vec3(2,3,4), vec3(3,4,5) ]; 103 assert( a.mean_variance == [ vec3(2,3,4), vec3(1,1,1) ] ); 104 } 105 106 /// 107 T rawMoment(T)( in T[] arr, size_t k=1 ) pure nothrow @property @nogc 108 if( is( typeof( T.init + T.init ) == T ) && 109 is( typeof( T.init * T.init ) == T ) && 110 is( typeof( T.init / T.init ) == T ) && 111 is( typeof( T.init / 1UL ) == T ) ) 112 in { assert( arr.length > 0 ); } body 113 { 114 if( arr.length == 1 ) return spow( arr[0], k ); 115 T res = arr[0]; 116 foreach( i; 1 .. arr.length ) 117 res = res + spow( arr[i], k ); 118 return res / arr.length; 119 } 120 121 /// 122 unittest 123 { 124 auto a = [ 1.0f, 2 ]; 125 assert( a.rawMoment == 1.5 ); 126 assert( a.rawMoment(2) == 2.5 ); 127 } 128 129 /// 130 T spow(T)( in T val, size_t k ) pure nothrow @nogc 131 if( is( typeof( T.init / T.init ) == T ) && is( typeof( T.init * T.init ) == T ) ) 132 { 133 //TODO: optimize 134 T ret = val / val; 135 if( k == 0 ) return ret; 136 if( k == 1 ) return val; 137 if( k == 2 ) return val * val; 138 foreach( i; 0 .. k ) ret = ret * val; 139 return ret; 140 } 141 142 /// 143 unittest 144 { 145 import des.math.linear.vector; 146 assert( spow( vec3( 1, 2, 3 ), 3 ) == vec3( 1, 8, 27 ) ); 147 assert( spow( 10, 0 ) == 1 ); 148 assert( spow( 10, 1 ) == 10 ); 149 assert( spow( 10, 2 ) == 100 ); 150 assert( spow( 10, 3 ) == 1000 ); 151 assert( spow( 10, 4 ) == 10000 ); 152 } 153 154 /// 155 T centralMoment(T)( in T[] arr, size_t k=1 ) pure nothrow @property @nogc 156 if( is( typeof( T.init + T.init ) == T ) && 157 is( typeof( T.init * T.init ) == T ) && 158 is( typeof( T.init / T.init ) == T ) && 159 is( typeof( T.init / 1UL ) == T ) ) 160 in { assert( arr.length > 0 ); } body 161 { 162 T res = arr[0] - arr[0]; 163 auto m = arr.mean; 164 foreach( val; arr ) 165 res = res + spow( val - m, k ); 166 return res / arr.length; 167 } 168 169 /// 170 unittest 171 { 172 auto a = [ 1.0f, 2, 3, 4 ]; 173 assert( a.centralMoment(1) == 0 ); 174 assert( a.centralMoment(2) == 1.25 ); 175 assert( a.centralMoment(3) == 0 ); 176 } 177 178 /// 179 class MovingAverage(T) if( is(typeof(T[].init.mean)) ) 180 { 181 /// 182 T[] array; 183 /// 184 size_t cur_index = 0; 185 /// 186 size_t max_length = 1; 187 188 /// 189 this( size_t mlen ) { max_length = mlen; } 190 191 invariant() 192 { 193 assert( array.length <= max_length ); 194 } 195 196 /// 197 void append( in T val ) 198 { 199 if( array.length < max_length ) array ~= val; 200 else array[cur_index++%max_length] = val; 201 } 202 203 @property 204 { 205 /// 206 size_t maxLength() const { return max_length; } 207 /// 208 void maxLength( size_t mlen ) 209 { 210 max_length = mlen; 211 if( array.length > mlen ) 212 array.length = mlen; 213 } 214 215 /// 216 T avg() const { return array.mean; } 217 } 218 } 219 220 unittest 221 { 222 auto ma = new MovingAverage!float( 3 ); 223 mustExcept({ ma.avg; }); 224 ma.append( 1 ); 225 assertEq( ma.avg, 1 ); 226 ma.append( 1 ); 227 assertEq( ma.avg, 1 ); 228 ma.append( 4 ); 229 assertEq( ma.avg, 2 ); 230 ma.append( 4 ); 231 ma.append( 4 ); 232 assertEq( ma.avg, 4 ); 233 assertEq( ma.array.length, 3 ); 234 }