public FixedPointDecimal(decimal? val)
{
// Test for null.
if(!val.HasValue)
{ // Unset hasvalue bit.
_data = 0;
return;
}
// Get underlying bits
int[] bits = decimal.GetBits(val.Value);
// Check high significand bytes .
if(0 != bits[1] || 0 != bits[2])
{
throw new Exception(__RangeScaleExceptionMsg);
}
// Read significand.
uint significand = (uint)bits[0];
// Read exponent and sign bit.
uint tmp = (uint)bits[3];
// Get exponent.
uint exponent = (tmp & 0x00FF0000u) >> 16;
// Check the value is within range and precision of a FixedDecimal;
// Rescale the significand based on the value having 4 decimal places.
switch(exponent)
{
case 0:
if(significand > 1073u)
{
throw new Exception(__RangeScaleExceptionMsg);
}
significand *= 1000000u;
break;
case 1:
if(significand > 10737u)
{
throw new Exception(__RangeScaleExceptionMsg);
}
significand *= 100000u;
break;
case 2:
if(significand > 107374u)
{
throw new Exception(__RangeScaleExceptionMsg);
}
significand *= 10000u;
break;
case 3:
if(significand > 1073741u)
{
throw new Exception(__RangeScaleExceptionMsg);
}
significand *= 1000u;
break;
case 4:
if(significand > 10737418u)
{
throw new Exception(__RangeScaleExceptionMsg);
}
significand *= 100u;
break;
case 5:
if(significand > 107374182u)
{
throw new Exception(__RangeScaleExceptionMsg);
}
significand *= 10u;
break;
case 6:
if(significand > 1073741823u)
{
throw new Exception(__RangeScaleExceptionMsg);
}
break;
default:
throw new Exception(__RangeScaleExceptionMsg);
}
// Store significand and HasValue bit.
_data = 0x80000000 | significand;
// Store sign bit (we explicitly convert -0 to +0, although decimal already does this).
if((tmp & 0x80000000) != 0 && significand !=0)
{
_data |= 0x40000000;
}
}