Type conversion
Psychological Cleanup via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Sat Sep 9 19:08:59 PDT 2017
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);
}
More information about the Digitalmars-d-learn
mailing list