Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
CastHelper.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using SiliconStudio.Shaders.Ast;
5 
6 namespace SiliconStudio.Shaders.Analysis
7 {
8  internal class CastHelper
9  {
10  /// <summary>
11  /// Check if convert is necessary
12  /// </summary>
13  /// <param name="leftType">Type of the left.</param>
14  /// <param name="rightType">Type of the right.</param>
15  /// <returns>True if a cast is necessary between this two types</returns>
16  public static bool NeedConvertForBinary(TypeBase leftType, TypeBase rightType)
17  {
18  return leftType != null && rightType != null && leftType != rightType
19  &&
20  !((leftType is ScalarType && (rightType is VectorType || rightType is MatrixType) && TypeBase.GetBaseType(rightType) == leftType)
21  || (rightType is ScalarType && (leftType is VectorType || leftType is MatrixType) && TypeBase.GetBaseType(leftType) == rightType));
22  }
23 
24  /// <summary>
25  /// Gets the type of the binary implicit conversion.
26  /// </summary>
27  /// <param name="left">The left.</param>
28  /// <param name="right">The right.</param>
29  /// <param name="isBooleanOperator">if set to <c>true</c> [is boolean operator].</param>
30  /// <returns>
31  /// The implicit conversion between between to two types
32  /// </returns>
33  public static TypeBase GetBinaryImplicitConversionType(TypeBase left, TypeBase right, bool isBooleanOperator)
34  {
35  if (left is MatrixType && right is MatrixType)
36  {
37  var leftMatrix = (MatrixType)left;
38  var rightMatrix = (MatrixType)right;
39 
40  var leftDimension1 = leftMatrix.RowCount;
41  var leftDimension2 = leftMatrix.ColumnCount;
42  var rightDimension1 = rightMatrix.RowCount;
43  var rightDimension2 = rightMatrix.ColumnCount;
44 
45  if (!((leftDimension1 >= rightDimension1 && leftDimension2 >= rightDimension2) || (leftDimension1 <= rightDimension1 && leftDimension2 <= rightDimension2)))
46  {
47  return null;
48  }
49 
50  var type = isBooleanOperator ? ScalarType.Bool : GetBinaryImplicitScalarConversionType(leftMatrix.Type.ResolveType(), rightMatrix.Type.ResolveType());
51  if (type != null)
52  return new MatrixType(type, Math.Min(leftDimension1, rightDimension1), Math.Min(leftDimension2, rightDimension2));
53 
54  return null;
55  }
56 
57  // Swap to handle next case with same code (always put bigger type on the left)
58  // Works for Vector*Matrix, Scalar*Matrix and Scalar*Vector
59  if (right is MatrixType || (!(left is MatrixType) && !(left is VectorType)))
60  {
61  var temp = left;
62  left = right;
63  right = temp;
64  }
65 
66  if (left is MatrixType && right is VectorType)
67  {
68  var leftMatrix = (MatrixType)left;
69  var rightVector = (VectorType)right;
70 
71  var leftDimension1 = leftMatrix.RowCount;
72  var leftDimension2 = leftMatrix.ColumnCount;
73  var rightDimension1 = rightVector.Dimension;
74 
75  // Matrix must have at least one dimension (row or column count == 1)
76  if (leftDimension1 != 1 && leftDimension2 != 1)
77  {
78  return null;
79  }
80 
81  var type = isBooleanOperator ? ScalarType.Bool : GetBinaryImplicitScalarConversionType(leftMatrix.Type.ResolveType(), rightVector.Type.ResolveType());
82  if (type != null)
83  return new VectorType(type, Math.Min(Math.Max(leftDimension1, leftDimension2), rightDimension1));
84  return null;
85  }
86 
87  if (left is MatrixType)
88  {
89  var leftMatrix = (MatrixType)left;
90 
91  var leftDimension1 = leftMatrix.RowCount;
92  var leftDimension2 = leftMatrix.ColumnCount;
93 
94  var type = isBooleanOperator ? ScalarType.Bool : GetBinaryImplicitScalarConversionType(leftMatrix.Type.ResolveType(), right);
95  if (type != null)
96  return new MatrixType(type, leftDimension1, leftDimension2);
97  return null;
98  }
99 
100  if (left is VectorType)
101  {
102  var leftVector = (VectorType)left;
103  var leftDimension1 = leftVector.Dimension;
104 
105  var rightDimension1 = right is VectorType ? ((VectorType)right).Dimension : 1;
106 
107  var rightBaseType = right is VectorType ? ((VectorType)right).Type.ResolveType() : right;
108 
109  int dimension = Math.Min(leftDimension1, rightDimension1);
110  if (rightDimension1 == 1 || leftDimension1 == 1)
111  dimension = Math.Max(leftDimension1, rightDimension1);
112 
113  var type = isBooleanOperator ? ScalarType.Bool : GetBinaryImplicitScalarConversionType(leftVector.Type.ResolveType(), rightBaseType);
114  if (type != null) return new VectorType(type, dimension);
115  return null;
116  }
117 
118  return (isBooleanOperator) ? ScalarType.Bool : GetBinaryImplicitScalarConversionType(left, right);
119  }
120 
121  /// <summary>
122  /// Gets the type of the binary implicit conversion in case of a multiplication.
123  /// </summary>
124  /// <param name="left">the left.</param>
125  /// <param name="right">the right.</param>
126  /// <returns>The implicit conversion between between to two types</returns>
127  public static TypeBase GetMultiplyImplicitConversionType(TypeBase left, TypeBase right)
128  {
129  if ((left is VectorType || left is MatrixType) && right is ScalarType)
130  return GetMultiplyImplicitConversionType(right, left);
131 
132  if (left is ScalarType)
133  {
134  TypeBase componentType = null;
135  if (right is VectorType) { componentType = (right as VectorType).Type; }
136  else if (right is MatrixType) { componentType = (right as MatrixType).Type; }
137 
138  if (componentType != null)
139  {
140  ScalarType resultComponentType = null;
141  if (left == ScalarType.Double || componentType == ScalarType.Double)
142  resultComponentType = ScalarType.Double;
143  else if (left == ScalarType.Float || componentType == ScalarType.Float)
144  resultComponentType = ScalarType.Float;
145  else if (left == ScalarType.Half || componentType == ScalarType.Half)
146  resultComponentType = ScalarType.Half;
147  else if (left == ScalarType.Int || componentType == ScalarType.Int)
148  resultComponentType = ScalarType.Int;
149  else if (left == ScalarType.UInt || componentType == ScalarType.UInt)
150  resultComponentType = ScalarType.UInt;
151 
152  if (resultComponentType != null)
153  {
154  if (right is VectorType)
155  return new VectorType(resultComponentType, (right as VectorType).Dimension);
156 
157  if (right is MatrixType)
158  return new MatrixType(resultComponentType, (right as MatrixType).RowCount, (right as MatrixType).ColumnCount);
159  }
160  }
161  }
162 
163  return GetBinaryImplicitConversionType(left, right, false);
164  }
165 
166  /// <summary>
167  /// Gets the type of the binary implicit conversion in case of a division
168  /// </summary>
169  /// <param name="left">the left.</param>
170  /// <param name="right">the right.</param>
171  /// <returns>The implicit conversion between between to two types</returns>
172  public static TypeBase GetDivideImplicitConversionType(TypeBase left, TypeBase right)
173  {
174  if (right is ScalarType)
175  {
176  TypeBase componentType = null;
177  if (left is VectorType) { componentType = (left as VectorType).Type; }
178  else if (left is MatrixType) { componentType = (left as MatrixType).Type; }
179 
180  if (componentType != null)
181  {
182  ScalarType resultComponentType = null;
183  if (left == ScalarType.Double || componentType == ScalarType.Double)
184  resultComponentType = ScalarType.Double;
185  else if (left == ScalarType.Float || componentType == ScalarType.Float)
186  resultComponentType = ScalarType.Float;
187  else if (left == ScalarType.Half || componentType == ScalarType.Half)
188  resultComponentType = ScalarType.Half;
189  else if (left == ScalarType.Int || componentType == ScalarType.Int)
190  resultComponentType = ScalarType.Int;
191  else if (left == ScalarType.UInt || componentType == ScalarType.UInt)
192  resultComponentType = ScalarType.UInt;
193 
194  if (resultComponentType != null)
195  {
196  if (left is VectorType)
197  return new VectorType(resultComponentType, (left as VectorType).Dimension);
198 
199  if (left is MatrixType)
200  return new MatrixType(resultComponentType, (left as MatrixType).RowCount, (left as MatrixType).ColumnCount);
201  }
202  }
203  }
204 
205  return GetBinaryImplicitConversionType(left, right, false);
206  }
207 
208  /// <summary>
209  /// Gets the type of the binary implicit scalar conversion.
210  /// </summary>
211  /// <param name="left">The left.</param>
212  /// <param name="right">The right.</param>
213  /// <returns>
214  /// The implicit conversion between the two scalar types
215  /// </returns>
216  public static ScalarType GetBinaryImplicitScalarConversionType(TypeBase left, TypeBase right)
217  {
218  if (left is ScalarType && right is ScalarType)
219  {
220  if (left == right)
221  return (ScalarType)left;
222 
223  foreach (var type in new[] { ScalarType.Double, ScalarType.Float, ScalarType.Half, ScalarType.UInt, ScalarType.Int, ScalarType.Bool })
224  {
225  if (left == type || right == type)
226  return type;
227  }
228  }
229  return null;
230  }
231  }
232 }
Base class for all vector types
Definition: VectorType.cs:10
SiliconStudio.Paradox.Games.Mathematics.Half Half
static TypeBase GetBaseType(TypeBase type)
Definition: TypeBase.cs:127
Base type for all types.
Definition: TypeBase.cs:11