/// <summary> /// Performs an ISO/IEC 10967 operation rem-f, i.e. reminder with flooring truncation towards negative infinity. /// </summary> /// <remarks> /// See ISO/IEC 10967: /// 4.1 Symbols (... about truncation) /// 5.1.3 Axioms /// Defined as: /// divI-f(x,y): x - ( div-f(x, y) * y ) /// </remarks> private Expression ReminderIntF(Expression arg1, Expression arg2, Type type1, Type type2) { if (BuiltInPrimitiveEncoder.IsUnsignedType(type1) && BuiltInPrimitiveEncoder.IsUnsignedType(type2)) { return(Expression.Modulo(arg1, arg2)); } Expression zero1 = this.GetZero(type1); Expression zero2 = this.GetZero(type2); // C# pseudocode: // if (arg1 >= 0) // if (arg2 => 0) // return arg1 % arg2; // else // return -(arg1 % -arg2); // else // if (arg2 => 0) // return -arg1 % arg2; // else // return arg1 % arg2; // same as: -(-arg1 % -arg2) Expression modulo = Expression.Modulo( Expression.Condition( Expression.GreaterThanOrEqual(arg1, zero1), arg1, Expression.Negate(arg1)), arg2); return(Expression.Condition( Expression.GreaterThanOrEqual(arg2, zero2), modulo, Expression.Negate(modulo))); }
/// <summary> /// Performs an ISO/IEC 10967 integer operation divI-f, i.e. division with flooring truncation towards negative infinity. /// </summary> /// <remarks> /// See ISO/IEC 10967: /// 4.1 Symbols (... about truncation) /// 5.1.3 Axioms /// Defined as: /// divI-f(x,y): [x/y] /// [x]: Largest integer where: x-1 ˂ [x] ˂= x /// Example: /// divI-f( -3, 2) =˃ -2 /// divI-f( -2, 2) =˃ -1 /// divI-f( -1, 2) =˃ -1 /// divI-f( 0, 2) =˃ 0 /// divI-f( 1, 2) =˃ 0 /// divI-f( 2, 2) =˃ 1 /// divI-f( 3, 2) =˃ 1 /// </remarks> private Expression DivideIntF(Expression arg1, Expression arg2, Type type1, Type type2) { // BUGBUG: Do we throw an OverflowException? if (BuiltInPrimitiveEncoder.IsUnsignedType(type1) && BuiltInPrimitiveEncoder.IsUnsignedType(type2)) { return(Expression.Divide(arg1, arg2)); } // C# pseudocode: // if ((arg1 >= 0) ^ (arg2 >= 0)) // if ((arg1 % arg2) == 0) // return arg1 / arg2; // else // return (arg1 / arg2) - 1; // else // return arg1 / arg2; Expression zero = this.GetZero(type1); Expression one = this.GetOne(type1); Expression division = Expression.Divide(arg1, arg2); Expression modulo = Expression.Modulo(arg1, arg2); return(Expression.Condition( Expression.ExclusiveOr( Expression.GreaterThanOrEqual(arg1, zero), Expression.GreaterThanOrEqual(arg2, zero)), Expression.Condition( Expression.Equal(modulo, zero), division, Expression.Subtract(division, one)), division)); }