1 module des.math.util.flatdata; 2 3 import std.traits; 4 import std..string; 5 import std.typetuple; 6 7 import des.util.testsuite; 8 import des.math.basic.traits; 9 import des.math.linear.vector; 10 11 /// 12 pure auto flatData(T,E...)( in E vals ) if( E.length > 0 ) 13 { 14 T[] buf; 15 foreach( e; vals ) buf ~= flatValue!T(e); 16 return buf; 17 } 18 19 /// 20 unittest 21 { 22 assert( eq( flatData!float([1.0,2],[[3,4]],5,[6,7]), [1,2,3,4,5,6,7] ) ); 23 static assert( !__traits(compiles,flatData!char([1.0,2],[[300,4]],5,[6,7])) ); 24 static assert( __traits(compiles,flatData!ubyte([1.0,2],[[300,4]],5,[6,7])) ); 25 static assert( __traits(compiles,flatData!char("hello", "world")) ); 26 assert( eq( flatData!cfloat(1-1i,2,3i), [1-1i,2+0i,0+3i] ) ); 27 } 28 29 /// 30 template hasIterableData(T) 31 { enum hasIterableData = is( typeof( isIterable!(typeof(T.init.data)) ) ); } 32 33 pure auto flatValue(T,E)( in E val ) 34 { 35 static if( isNumeric!T && isNumeric!E ) return [ cast(T)val ]; 36 else static if( isComplex!T && ( isNumeric!E || isImaginary!E ) ) return [ T(0+0i+val) ]; 37 else static if( is(typeof(T(val))) ) return [ T(val) ]; 38 else static if( isIterable!E ) 39 { 40 T[] buf; 41 foreach( v; val ) 42 buf ~= flatValue!T(v); 43 return buf; 44 } 45 else static if( hasIterableData!E ) return flatValue!T(val.data); 46 else static assert(0, format("uncompatible types %s and %s", T.stringof, E.stringof ) ); 47 } 48 49 bool canStaticFill(size_t N,T,E...)() pure @property 50 if( E.length > 0 ) 51 { return hasNoDynamic!E && N == getElemCount!E && isConvertable!(T,E); } 52 53 bool hasNoDynamic(E...)() pure @property 54 { 55 static if( E.length == 1 ) return !hasIndirections!(E[0]); 56 else return hasNoDynamic!(E[0]) && hasNoDynamic!(E[1..$]); 57 } 58 59 size_t getElemCount(E...)() pure @property 60 { 61 static if( E.length == 0 ) return 0; 62 else static if( E.length >= 1 ) 63 return getTypeElemCount!(E[0]) + getElemCount!(E[1..$]); 64 } 65 66 size_t getTypeElemCount(E)() pure @property 67 { 68 static if( isStaticArray!E ) return E.length; 69 else static if( isStaticVector!E ) return E.data.length; 70 else return 1; 71 } 72 73 bool isConvertable(T,E...)() pure @property 74 { 75 static if( E.length == 1 ) 76 { 77 alias E[0] X; 78 static if( is( typeof( T(X.init) ) ) ) return true; 79 else static if( isComplex!T && ( isNumeric!X || isImaginary!X ) ) return true; 80 else static if( isNumeric!X && isNumeric!T ) return true; 81 else static if( isStaticArray!X ) return isConvertable!(T,typeof(X.init[0])); 82 else static if( isStaticVector!X ) 83 { 84 static if( isStaticVector!T ) 85 return T.length == X.length && isConvertable!(T.datatype,X.datatype); 86 else 87 return isConvertable!(T,X.datatype); 88 } 89 else return false; 90 } 91 else return isConvertable!(T,E[0]) && isConvertable!(T,E[1..$]); 92 } 93 94 string vectorStaticFill(string type, string data, string vals, T, E...)() pure @property 95 if( E.length > 0 ) 96 { 97 string[] ret; 98 static if( isStaticVector!T ) 99 { 100 ret ~= convertValues!(T.datatype,E)( type~".datatype", data, vals ); 101 foreach( i, ref r; ret ) 102 r = format( "%1$s[%2$s/%3$s][%2$s%%%3$s] = %4$s;", data, i, T.length, r ); 103 } 104 else 105 { 106 ret ~= convertValues!(T,E)( type, data, vals ); 107 foreach( i, ref r; ret ) 108 r = format( "%s[%s] = %s;", data, i, r ); 109 } 110 return ret.join("\n"); 111 } 112 113 string matrixStaticFill(string type, string data, string vals, size_t W, T, E...)() pure @property 114 if( E.length > 0 ) 115 { 116 string[] ret; 117 ret ~= convertValues!(T,E)( type, data, vals ); 118 foreach( i, ref r; ret ) 119 r = format( "%s[%s][%s] = %s;", data, i/W, i%W, r ); 120 return ret.join("\n"); 121 } 122 123 string[] convertValues(T,E...)( string type, string data, string vals, size_t valno=0 ) pure 124 { 125 static if( E.length == 1 ) 126 return convertValue!(T,E[0])(type,data,vals,valno); 127 else 128 return convertValue!(T,E[0])(type,data,vals,valno) ~ 129 convertValues!(T,E[1..$])(type,data,vals,valno+1); 130 131 } 132 133 string[] convertValue(T, E)( string type, string data, string vals, size_t valno ) pure 134 { 135 static if( isStaticArray!E || isStaticVector!E ) 136 { 137 string[] ret; 138 foreach( i; 0 .. E.length ) 139 ret ~= format( convertRule!(T,typeof(E.init[0])), type, format( "%s[%d][%d]", vals, valno, i ) ); 140 return ret; 141 } 142 else 143 return [ format( convertRule!(T,E), type, format( "%s[%d]", vals, valno ) ) ]; 144 } 145 146 string convertRule(T,E)() pure @property 147 { 148 static if( isNumeric!E && isNumeric!T ) 149 return "cast(%s)(%s)"; 150 else static if( isComplex!T && ( isNumeric!E || isImaginary!E ) ) 151 return "%s(0+0i+%s)"; 152 else static if( is( typeof( T(E.init) ) ) ) 153 return "%s(%s)"; 154 else static assert( 0, "uncompatible types [convertRule]" ); 155 }