digitalmars.D.learn - Type conversion
- Psychological Cleanup (103/103) Sep 09 2017 I've been trying to get this code to work properly over the last
I've been trying to get this code to work properly over the last days. I simply want to convert one sample format to another. This involves simply scaling the values down or up so that they map the entire range. There are now two problems. One is that after I added some more pad's to make the formatting easier to read, I get out of memory errors. Second, and the real issue, is that the scaling is not done properly. One would think that it would be simple matter of a linear map from [minF,maxF] to [minT,maxT], which is just the equation (maxT - minT)/(maxF - minF)*(value - minF) + minT but for some reason it does not map perfectly, I suspect, due to rounding... but it would be nice for a proper solution that is relatively simple and fast as this(using ctfe/templates) to solve the problem. For example, if value = (maxF + minF)/2 we would expect the result to be (maxT + minT)/2 and this is true from the formula, but the SampleConvert function does not produce this value. One can see this because the test computes this value at compile time directly and this is what the SampleConvert should be doing. string SampleConverterTest()() { string pad(string s, int L) { import std.array; if (L - s.length <= 0) return s; return replicate(" ", L - s.length)~s; } import std.string; string str; static foreach(f; AliasSeq!(ubyte, byte, ushort, short, uint, int, float, double)) { { static if (is(f == float) || is (f == double)) { enum minF = -1; enum maxF = 1; enum midF = 0; } else { enum minF = f.min; enum maxF = f.max; enum midF = (maxF + minF)/2; } static foreach(t; AliasSeq!(ubyte, byte, ushort, short, uint, int, float, double)) { { static if (is(t == float) || is (t == double)) { enum minT = -1; enum maxT = 1; enum midT = 0; } else { enum minT = t.min; enum maxT = t.max; enum midT = (maxT + minT)/2; } import mTemplateHelpers; enum resmF1 = (SampleConvert!(t,f)(minF)); enum resMF1 = (SampleConvert!(t,f)(maxF)); enum resMidF1 = (SampleConvert!(t,f)(midF)); enum resmF = tRemoveCast!(resmF1); enum resMF = tRemoveCast!(resMF1); enum resMidF = tRemoveCast!(resMidF1); enum s1 = ((maxT - minT)/(cast(double)(maxF - minF))); enum s = tRemoveCast!(s1); pragma(msg, "F/T(", pad(f.stringof, 6), ", ", pad(t.stringof, 6), ") -- m/C/M F(", pad(to!string(minF),11), ", ", pad(to!string(midF),11), ", ", pad(to!string(maxF),11), ") -- m/C/M T(", pad(to!string(minT),11), ", ", pad(to!string(midT),11), ", ", pad(to!string(maxT),11), ") -- m/C/M C(", pad(resmF,6), ", ", pad(resMidF,6), ", ", pad(resMF,6), ") -- s = ", s); } } } } return str; } T SampleConvert(T, F)(F from) { import std.algorithm; static if (is(T == F)) return from; static foreach(t; ["F", "T"]) mixin(" static if (is("~t~" == float) || is ("~t~" == double)) { enum min"~t~" = -1; enum max"~t~" = 1; } else { enum min"~t~" = "~t~".min; enum max"~t~" = "~t~".max; }"); enum s = (maxT - minT)/(cast(double)(maxF - minF)); return cast(T)(s*(from - minF) + minT); }
Sep 09 2017