1 module des.math.util.valuelim; 2 3 import des.ts; 4 5 import std.traits; 6 import std.algorithm; 7 8 /// 9 struct ValueLimiter(size_t CNT,T=float) 10 if( CNT > 0 && isFloatingPoint!T ) 11 { 12 protected: 13 T min_limit; 14 T max_limit; 15 16 /// 17 T[CNT] values; 18 19 public: 20 @property 21 { 22 /// 23 T minLimit() const { return min_limit; } 24 25 /// 26 T minLimit( T v ) 27 { 28 min_limit = v > max_limit ? max_limit : v; 29 correctValuesMinMax(); 30 return min_limit; 31 } 32 33 /// 34 T maxLimit() const { return max_limit; } 35 36 /// 37 T maxLimit( T v ) 38 { 39 max_limit = v < min_limit ? min_limit : v; 40 correctValuesMinMax(); 41 return max_limit; 42 } 43 } 44 45 /// 46 T set( size_t i, T v ) 47 in{ assert( i < CNT ); } 48 body 49 { 50 values[i] = min( max( min_limit, v ), max_limit ); 51 moveValues(i); 52 return values[i]; 53 } 54 55 /// 56 T setNorm( size_t i, T nv ) 57 in 58 { 59 assert( i < CNT ); 60 assert( nv <= 1.0 ); 61 } 62 body 63 { 64 auto v = full(nv); 65 set(i,v); 66 return getNorm(i); 67 } 68 69 /// 70 T get( size_t i ) 71 in{ assert( i < CNT ); } 72 body { return values[i]; } 73 74 /// 75 T getNorm( size_t i ) 76 in{ assert( i < CNT ); } 77 body { return norm( get(i) ); } 78 79 protected: 80 81 void correctValuesMinMax() { foreach( ref v; values ) correctMinMax( v ); } 82 83 void correctMinMax( ref T v ) 84 { v = ( v >= min_limit ? ( v <= max_limit ? v : max_limit ) : min_limit ); } 85 86 void moveValues( size_t k ) 87 { 88 foreach( i, ref v; values ) 89 { 90 if( i == k ) continue; 91 if( i < k && v > values[k] ) 92 v = values[k]; 93 if( i > k && v < values[k] ) 94 v = values[k]; 95 } 96 } 97 98 T norm( T v ) const 99 { return (v - min_limit) / (max_limit - min_limit); } 100 101 T full( T v ) const 102 { return min_limit + v * (max_limit - min_limit); } 103 } 104 105 /// 106 unittest 107 { 108 auto vh = ValueLimiter!(2,float)(); 109 110 vh.minLimit = 0; 111 vh.maxLimit = 10; 112 113 vh.set( 0, 5 ); 114 vh.set( 1, 7 ); 115 116 assertEq( vh.get(0), 5 ); 117 assertEq( vh.get(1), 7 ); 118 119 vh.set(1,3); 120 121 assertEq( vh.get(0), 3 ); 122 assertEq( vh.get(1), 3 ); 123 124 vh.set(1,20); 125 assertEq( vh.get(0), 3 ); 126 assertEq( vh.get(1), 10 ); 127 } 128 129 unittest 130 { 131 auto vh = ValueLimiter!2(); 132 133 vh.minLimit = 0; 134 vh.maxLimit = 10; 135 136 vh.setNorm( 0, 0.5 ); 137 vh.setNorm( 1, 0.7 ); 138 139 assertEq( vh.get(0), 5 ); 140 assertEq( vh.get(1), 7 ); 141 142 vh.setNorm( 0, 0.8 ); 143 144 assertEq( vh.get(0), 8 ); 145 assertEq( vh.get(1), 8 ); 146 147 import std.math; 148 149 assertEq( vh.getNorm(0), .8 ); 150 assertEq( vh.getNorm(1), .8 ); 151 }