www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Type conversion

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