1 /+ 2 The MIT License (MIT) 3 4 Copyright (c) <2013> <Oleg Butko (deviator), Anton Akzhigitov (Akzwar)> 5 6 Permission is hereby granted, free of charge, to any person obtaining a copy 7 of this software and associated documentation files (the "Software"), to deal 8 in the Software without restriction, including without limitation the rights 9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 copies of the Software, and to permit persons to whom the Software is 11 furnished to do so, subject to the following conditions: 12 13 The above copyright notice and this permission notice shall be included in 14 all copies or substantial portions of the Software. 15 16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 THE SOFTWARE. 23 +/ 24 25 module des.util.algo; 26 27 public import std.array; 28 public import std.algorithm; 29 public import std.range; 30 public import std.traits; 31 32 template amap(fun...) if ( fun.length >= 1 ) 33 { 34 auto amap(Range)(Range r) 35 if (isInputRange!(Unqual!Range)) 36 { return array( map!fun(r) ); } 37 } 38 39 unittest 40 { 41 int[] res = [ 1, 2, 3 ]; 42 void func( int[] arr ) { res ~= arr; } 43 func( amap!(a=>a^^2)(res) ); 44 assert( res == [ 1, 2, 3, 1, 4, 9 ] ); 45 } 46 47 bool oneOf(E,T)( T val ) 48 { 49 foreach( pv; [EnumMembers!E] ) 50 if( pv == val ) return true; 51 return false; 52 } 53 54 private version(unittest) 55 { 56 enum TestEnum 57 { 58 ONE = 1, 59 TWO = 2, 60 FOUR = 4 61 } 62 } 63 64 unittest 65 { 66 assert( !oneOf!TestEnum(0) ); 67 assert( oneOf!TestEnum(1) ); 68 assert( oneOf!TestEnum(2) ); 69 assert( !oneOf!TestEnum(3) ); 70 assert( oneOf!TestEnum(4) ); 71 assert( !oneOf!TestEnum(5) ); 72 } 73 74 bool oneOf(E,T)( E[] arr, T val ) 75 if( is( typeof( arr[0] == val ) ) ) 76 { 77 foreach( pv; arr ) if( pv == val ) return true; 78 return false; 79 } 80 81 unittest 82 { 83 assert( !oneOf( [TestEnum.ONE, TestEnum.TWO], 0) ); 84 assert( oneOf( [TestEnum.ONE, TestEnum.TWO], 2) ); 85 } 86 87 struct lim_t(T) if( isNumeric!T ) 88 { 89 T minimum=0, maximum=T.max; 90 bool fix = false; 91 92 pure nothrow this( T Min, T Max ) 93 { 94 minimum = Min; 95 maximum = Max; 96 } 97 98 T opCall( T old, T nval ) const 99 { 100 if( fix ) return old; 101 return nval >= minimum ? ( nval < maximum ? nval : maximum ) : minimum; 102 } 103 } 104 105 struct ValueHandler(size_t CNT,T=float) 106 if( CNT > 0 && isFloatingPoint!T ) 107 { 108 protected: 109 T min_limit; 110 T max_limit; 111 112 T[CNT] values; 113 114 public: 115 @property 116 { 117 T minLimit() const { return min_limit; } 118 119 T minLimit( T v ) 120 { 121 min_limit = v > max_limit ? max_limit : v; 122 correctValuesMinMax(); 123 return min_limit; 124 } 125 126 T maxLimit() const { return max_limit; } 127 128 T maxLimit( T v ) 129 { 130 max_limit = v < min_limit ? min_limit : v; 131 correctValuesMinMax(); 132 return max_limit; 133 } 134 } 135 136 T set( size_t i, T v ) 137 in{ assert( i < CNT ); } 138 body 139 { 140 import std.algorithm; 141 values[i] = min( max( min_limit, v ), max_limit ); 142 moveValues(i); 143 return values[i]; 144 } 145 146 T setNorm( size_t i, T nv ) 147 in 148 { 149 assert( i < CNT ); 150 assert( nv <= 1.0 ); 151 } 152 body 153 { 154 auto v = full(nv); 155 set(i,v); 156 return getNorm(i); 157 } 158 159 T get( size_t i ) 160 in{ assert( i < CNT ); } 161 body { return values[i]; } 162 163 T getNorm( size_t i ) 164 in{ assert( i < CNT ); } 165 body { return norm( get(i) ); } 166 167 protected: 168 169 void correctValuesMinMax() { foreach( ref v; values ) correctMinMax( v ); } 170 171 void correctMinMax( ref T v ) 172 { v = ( v >= min_limit ? ( v <= max_limit ? v : max_limit ) : min_limit ); } 173 174 void moveValues( size_t k ) 175 { 176 foreach( i, ref v; values ) 177 { 178 if( i == k ) continue; 179 if( i < k && v > values[k] ) 180 v = values[k]; 181 if( i > k && v < values[k] ) 182 v = values[k]; 183 } 184 } 185 186 T norm( T v ) const 187 { return (v - min_limit) / (max_limit - min_limit); } 188 189 T full( T v ) const 190 { return min_limit + v * (max_limit - min_limit); } 191 } 192 193 unittest 194 { 195 auto vh = ValueHandler!(2,float)(); 196 197 vh.minLimit = 0; 198 vh.maxLimit = 10; 199 200 vh.set( 0, 5 ); 201 vh.set( 1, 7 ); 202 203 assert( vh.get(0) == 5 ); 204 assert( vh.get(1) == 7 ); 205 206 vh.set(1,3); 207 208 assert( vh.get(0) == 3 ); 209 assert( vh.get(1) == 3 ); 210 } 211 212 unittest 213 { 214 auto vh = ValueHandler!2(); 215 216 vh.minLimit = 0; 217 vh.maxLimit = 10; 218 219 vh.setNorm( 0, 0.5 ); 220 vh.setNorm( 1, 0.7 ); 221 222 assert( vh.get(0) == 5 ); 223 assert( vh.get(1) == 7 ); 224 225 vh.setNorm( 0, 0.8 ); 226 227 assert( vh.get(0) == 8 ); 228 assert( vh.get(1) == 8 ); 229 230 import std.math; 231 232 assert( abs( vh.getNorm(0) - .8 ) < float.epsilon * 2 ); 233 assert( abs( vh.getNorm(1) - .8 ) < float.epsilon * 2 ); 234 }