/// <summary> /// Returns a type which is able to represent either of two given types without loss of precision /// </summary> /// <param name="td1">first given type</param> /// <param name="td2">second given type</param> /// <returns></returns> private static TypeDescriptor GetCommonType(TypeDescriptor td1, TypeDescriptor td2) { if (td1.Equals(td2)) return td1; if (IsSFix(td1) && IsUFix(td2)) { var fmt1 = SFix.GetFormat(td1); var fmt2 = UFix.GetFormat(td2); return SFix.MakeType( Math.Max(fmt1.IntWidth, fmt2.IntWidth + 1), Math.Max(fmt1.FracWidth, fmt2.FracWidth)); } else if (IsUFix(td1) && IsSFix(td2)) { return GetCommonType(td2, td1); } else if (IsSFix(td1) && IsSFix(td2)) { var fmt1 = SFix.GetFormat(td1); var fmt2 = SFix.GetFormat(td2); return SFix.MakeType( Math.Max(fmt1.IntWidth, fmt2.IntWidth), Math.Max(fmt1.FracWidth, fmt2.FracWidth)); } else if (IsUFix(td1) && IsUFix(td2)) { var fmt1 = UFix.GetFormat(td1); var fmt2 = UFix.GetFormat(td2); return UFix.MakeType( Math.Max(fmt1.IntWidth, fmt2.IntWidth), Math.Max(fmt1.FracWidth, fmt2.FracWidth)); } else if (IsSigned(td1)) { var fmt = SFix.GetFormat(td1); var td1x = SFix.MakeType(fmt.IntWidth, fmt.FracWidth); return GetCommonType(td1x, td2); } else if (IsSigned(td2)) { return GetCommonType(td2, td1); } else if (IsUnsigned(td1)) { var fmt = UFix.GetFormat(td1); var td1x = UFix.MakeType(fmt.IntWidth, fmt.FracWidth); return GetCommonType(td1x, td2); } else if (IsUnsigned(td2)) { return GetCommonType(td2, td1); } else { throw new NotSupportedException( "Cannot determine common type between " + td1.ToString() + " and " + td2.ToString()); } }