1 module des.math.util.flatdata;
2 
3 import std.traits;
4 import std..string;
5 import std.meta;
6 
7 import des.ts;
8 import des.stdx.traits;
9 import des.math.linear.vector;
10 public import des.stdx.range : flatData;
11 
12 ///
13 template hasIterableData(T)
14 { enum hasIterableData = is( typeof( isIterable!(typeof(T.init.data)) ) ); }
15 
16 ///
17 template hasStaticIterableData(T)
18 {
19     static if( hasIterableData!T )
20         enum hasStaticIterableData = isStaticArray!(typeof(T.init.data));
21     else
22         enum hasStaticIterableData = false;
23 }
24 
25 bool canStaticFill(size_t N,T,E...)() pure @property
26 if( E.length > 0 )
27 { return hasNoDynamic!E && N == getElemCount!E && isConvertable!(T,E); }
28 
29 bool hasNoDynamic(E...)() pure @property
30 {
31     static if( E.length == 1 ) return !hasIndirections!(E[0]);
32     else return hasNoDynamic!(E[0]) && hasNoDynamic!(E[1..$]);
33 }
34 
35 size_t getElemCount(E...)() pure @property
36 {
37     static if( E.length == 0 ) return 0;
38     else static if( E.length >= 1 )
39         return getTypeElemCount!(E[0]) + getElemCount!(E[1..$]);
40 }
41 
42 size_t getTypeElemCount(E)() pure @property
43 {
44     static if( isStaticArray!E ) return E.length;
45     else static if( hasStaticIterableData!E ) return E.data.length;
46     else return 1;
47 }
48 
49 bool isConvertable(T,E...)() pure @property
50 {
51     static if( E.length == 1 )
52     {
53         alias E[0] X;
54         static if( is( typeof( T(X.init) ) ) ) return true;
55         else static if( isComplex!T && ( isNumeric!X || isImaginary!X ) ) return true;
56         else static if( isNumeric!X && isNumeric!T ) return true;
57         else static if( isStaticArray!X ) return isConvertable!(T,typeof(X.init[0]));
58         else static if( isStaticVector!X )
59         {
60             static if( isStaticVector!T )
61                 return T.length == X.length && isConvertable!(T.datatype,X.datatype);
62             else
63                 return isConvertable!(T,X.datatype);
64         }
65         else return false;
66     }
67     else return isConvertable!(T,E[0]) && isConvertable!(T,E[1..$]);
68 }
69 
70 string vectorStaticFill(string type, string data, string vals, T, E...)() pure @property
71 if( E.length > 0 )
72 {
73     string[] ret;
74     static if( isStaticVector!T )
75     {
76         ret ~= convertValues!(T.datatype,E)( type~".datatype", data, vals );
77         foreach( i, ref r; ret )
78             r = format( "%1$s[%2$s/%3$s][%2$s%%%3$s] = %4$s;", data, i, T.length, r );
79     }
80     else
81     {
82         ret ~= convertValues!(T,E)( type, data, vals );
83         foreach( i, ref r; ret )
84             r = format( "%s[%s] = %s;", data, i, r );
85     }
86     return ret.join("\n");
87 }
88 
89 string matrixStaticFill(string type, string data, string vals, size_t W, T, E...)() pure @property
90 if( E.length > 0 )
91 {
92     string[] ret;
93     ret ~= convertValues!(T,E)( type, data, vals );
94     foreach( i, ref r; ret )
95         r = format( "%s[%s][%s] = %s;", data, i/W, i%W, r );
96     return ret.join("\n");
97 }
98 
99 string[] convertValues(T,E...)( string type, string data, string vals, size_t valno=0 ) pure
100 {
101     static if( E.length == 1 )
102         return convertValue!(T,E[0])(type,data,vals,valno);
103     else
104         return convertValue!(T,E[0])(type,data,vals,valno) ~ 
105                convertValues!(T,E[1..$])(type,data,vals,valno+1); 
106 }
107 
108 string[] convertValue(T, E)( string type, string data, string vals, size_t valno ) pure
109 {
110     static if( isStaticArray!E || isStaticVector!E )
111     {
112         string[] ret;
113         foreach( i; 0 .. E.length )
114             ret ~= format( convertRule!(T,typeof(E.init[0])), type, format( "%s[%d][%d]", vals, valno, i ) );
115         return ret;
116     }
117     else
118         return [ format( convertRule!(T,E), type, format( "%s[%d]", vals, valno ) ) ];
119 }
120 
121 string convertRule(T,E)() pure @property
122 {
123     static if( isNumeric!E && isNumeric!T )
124         return "cast(%s)(%s)";
125     else static if( isComplex!T && ( isNumeric!E || isImaginary!E ) )
126         return "%s(0+0i+%s)";
127     else static if( is( typeof( T(E.init) ) ) )
128         return "%s(%s)";
129     else static assert( 0, "uncompatible types [convertRule]" );
130 }