private TReal CommonRealType(TArithmetic x) { int rank = Math.Max(Rank, x.Rank); if (rank == TLDouble.Instance.Rank) { return(TLDouble.Instance); } if (rank == TDouble.Instance.Rank) { return(TDouble.Instance); } if (rank == TSingle.Instance.Rank) { return(TSingle.Instance); } /// Otherwise, the integer promotions are performed on both operands. /// Since both this and x are integer types, their promoted types are also integer types. TInteger a = IntPromote() as TInteger; TInteger b = x.IntPromote() as TInteger; /// Then the following rules are applied to the promoted operands. /// 1. If both operands have the same type, then no further conversion is needed. if (a.Equals(b)) { return(a); } /// 2. Otherwise, if both operands have signed integer types or both have unsigned integer types, /// the operand with the type of lesser integer conversion rank is converted to the type of the /// operand with greater rank. if (a.IsSigned == b.IsSigned) { return(a.Rank > b.Rank ? a : b); } /// 3. Otherwise, if the operand that has unsigned integer type has rank greater or equal to the /// rank of the type of the other operand, then the operand with signed integer type is converted /// to the type of the operand with unsigned integer type. TInteger u = a.IsSigned ? b : a; // The unsigned integer type. TInteger s = a.IsSigned ? a : b; // The signed integer type. if (u.Rank >= s.Rank) { return(u); } /// 4. Otherwise, if the type of the operand with signed integer type can represent all of the values /// of the type of the operand with unsigned integer type, then the operand with unsigned integer type /// is converted to the type of the operand with signed integer type. if (u.MAX < s.MAX && u.MIN > s.MIN) { return(s); } /// 5. Otherwise, both operands are converted to the unsigned integer type corresponding to the type of the /// operand with signed integer type. return(s.Unsigned); }
public override TArithmetic UsualArithConversion(TUnqualified other) { if (!other.IsArithmetic) { throw new ArgumentException(string.Format("Usual arithmetic conversion should be performed on arithmetic types, not {0}!", other)); } TArithmetic x = other as TArithmetic; // First determine a common real type. TReal crt = CommonRealType(x); // Check if both type domain are real. if (TypeDomain() == TDomain.REAL && other.TypeDomain() == TDomain.REAL) { return(crt); } else { // Convert the complex domain. return(crt.Complex); } }