private static ConversionTypes ClassifyDimensionConversion(IntrinsicNumericTypeSymbol sourceType, IntrinsicNumericTypeSymbol targetType)
{
var targetDim0 = targetType.GetDimensionSize(0);
var targetDim1 = targetType.GetDimensionSize(1);
var sourceDim0 = sourceType.GetDimensionSize(0);
var sourceDim1 = sourceType.GetDimensionSize(1);
if ((sourceDim0 == targetDim0 && sourceDim1 == targetDim1) || (sourceDim1 == targetDim0 && sourceDim0 == targetDim1))
{
switch (sourceType.Kind)
{
case SymbolKind.IntrinsicMatrixType:
switch (targetType.Kind)
{
case SymbolKind.IntrinsicVectorType: // float1x1 => float1
case SymbolKind.IntrinsicScalarType: // float1x1 => float
return ConversionTypes.SameSizeTruncation;
}
break;
case SymbolKind.IntrinsicVectorType:
switch (targetType.Kind)
{
case SymbolKind.IntrinsicMatrixType: // float1 => float1x1
return ConversionTypes.SameSizePromotion;
case SymbolKind.IntrinsicScalarType: // float1 => float
return ConversionTypes.SameSizeTruncation;
}
break;
case SymbolKind.IntrinsicScalarType:
switch (targetType.Kind)
{
case SymbolKind.IntrinsicMatrixType: // float => float1x1
case SymbolKind.IntrinsicVectorType: // float => float1
return ConversionTypes.SameSizePromotion;
}
break;
}
}
else if ((sourceDim0 == targetDim1 && sourceDim1 == targetDim0) || (sourceDim1 == targetDim0 && sourceDim0 == targetDim1))
{
switch (sourceType.Kind)
{
case SymbolKind.IntrinsicMatrixType:
switch (targetType.Kind)
{
case SymbolKind.IntrinsicVectorType: // float3x1 => float1
return ConversionTypes.DimensionTruncation;
}
break;
case SymbolKind.IntrinsicVectorType:
switch (targetType.Kind)
{
case SymbolKind.IntrinsicMatrixType: // float3 => float3x1
return ConversionTypes.ScalarPromotion;
}
break;
}
}
else if (sourceDim0 == 1 && sourceDim1 == 1)
{
// float => float2x4
// float => float2
// float1 => float2
return ConversionTypes.ScalarPromotion;
}
else if ((sourceDim0 >= targetDim0 && sourceDim1 >= targetDim1) || (sourceDim1 >= targetDim0 && sourceDim0 >= targetDim1))
{
switch (sourceType.Kind)
{
case SymbolKind.IntrinsicMatrixType:
switch (targetType.Kind)
{
case SymbolKind.IntrinsicMatrixType:
if (sourceDim0 > targetDim0 && sourceDim1 > targetDim1) // float4x4 => float3x3
return ConversionTypes.RankTruncation2;
if (sourceDim0 > targetDim0 || sourceDim1 > targetDim1) // float4x4 => float4x3
return ConversionTypes.RankTruncation;
return ConversionTypes.None;
case SymbolKind.IntrinsicVectorType: // float4x4 => float3
return ConversionTypes.RankTruncation2;
case SymbolKind.IntrinsicScalarType: // float3x4 => float
return ConversionTypes.RankTruncation2;
default:
throw new ArgumentOutOfRangeException();
}
case SymbolKind.IntrinsicVectorType:
switch (targetType.Kind)
{
case SymbolKind.IntrinsicMatrixType: // float4 => float4x3
return ConversionTypes.RankTruncation;
case SymbolKind.IntrinsicVectorType: // float4 => float3
return ConversionTypes.RankTruncation2;
case SymbolKind.IntrinsicScalarType: // float4 => float
return ConversionTypes.RankTruncation2;
default:
throw new ArgumentOutOfRangeException();
}
default:
throw new ArgumentOutOfRangeException();
}
}
return ConversionTypes.None;
}
}