/// <summary> /// Takes a TNumber and returns its absolute value. /// </summary> /// <param name="interpreter">The interpreter that the method is being called from.</param> /// <param name="value">The TNumber to get the absolute value of.</param> /// <returns> /// The TType resulting from the operation. An MExcpetion or null is returned when there is an error. /// </returns> public static TType Modulus(Interpreter interpreter, TType value) { TNumber number; TException exception = AssignNumberValue(interpreter, out number, value); if (exception != null) { return(exception); } // No errors yet, but make sure it's not a string if (number == null) { return(new TException(interpreter, "Strings cannot be used in modulus operations")); } switch (number.TypeName) { case TType.T_INTEGER_TYPENAME: return(new TInteger(System.Math.Abs(number.TIntegerValue))); case TType.T_REAL_TYPENAME: return(new TReal(System.Math.Abs(number.TRealValue))); case TType.T_FRACTION_TYPENAME: TFraction fraction = number as TFraction; return(new TFraction(System.Math.Abs(fraction.Numerator), fraction.Denominator)); // No need to abs denominator as TFraction denominators are automatically kept positive } return(null); }
/// <summary> /// Takes two TNumbers and returns the first one to the power of the other. /// </summary> /// <param name="interpreter">The interpreter that the method is being called from.</param> /// <param name="a">The left hand operand of the operation.</param> /// <param name="b">The right hand operand of the operation.</param> /// <returns> /// The TType resulting from the operation. An MExcpetion or null is returned when there is an error. /// </returns> public static TType Pow(Interpreter interpreter, TType a, TType b) { // Try to get TNumber values from the TType arguments TNumber numberA, numberB; TException exception = AssignNumberValue(interpreter, out numberA, a); if (exception != null) { return(exception); } exception = AssignNumberValue(interpreter, out numberB, b); if (exception != null) { return(exception); } // No errors, but one or both of the arguments could be a TString; check them if ((numberA == null) || (numberB == null)) { return(new TException(interpreter, "Strings cannot be used in exponentiation operations")); } switch (numberA.TypeName) { case TType.T_INTEGER_TYPENAME: return(new TInteger( (long)System.Math.Round(System.Math.Pow(numberA.TRealValue, numberB.TRealValue)))); case TType.T_REAL_TYPENAME: return(new TReal(System.Math.Pow(numberA.TRealValue, numberB.TRealValue))); case TType.T_FRACTION_TYPENAME: TFraction fraction = numberA as TFraction; long numerator = (long)System.Math.Round(System.Math.Pow(fraction.Numerator, numberB.TRealValue)); long denominator = (long)System.Math.Round(System.Math.Pow(fraction.Denominator, numberB.TRealValue)); return(new TFraction(numerator, denominator)); } return(null); }
/// <summary> /// Takes two TNumbers or two TStrings (or up to two TVariables containing TNumbers or TStrings) and /// adds them together. /// </summary> /// <param name="interpreter">The interpreter that the method is being called from.</param> /// <param name="a">The left hand operand of the operation.</param> /// <param name="b">The right hand operand of the operation.</param> /// <returns> /// The TType resulting from the operation. An MExcpetion or null is returned when there is an error. /// </returns> public static TType Add(Interpreter interpreter, TType a, TType b) { // Convert arguments 'a' and 'b' into either a TNumber or a TString TNumber numberA, numberB; TString strA = null, strB = null; TException exception = AssignNumberValue(interpreter, out numberA, a); if (exception != null) { return(exception); } if (numberA == null) { // No errors yet, and numberA is null, so argument 'a' could be a TString or a TVariable // containing a TString strA = a as TString; if (strA == null) { TVariable variable = a as TVariable; if (variable != null) { strA = variable.Value as TString; } } } if ((numberA == null) && (strA == null)) // Nothing useful, return a TException { return(new TException(interpreter, "Value is not a number or string")); } // Same procedure for argument 'b' exception = AssignNumberValue(interpreter, out numberB, b); if (exception != null) { return(exception); } if (numberB == null) { strB = b as TString; if (strB == null) { TVariable variable = b as TVariable; if (variable != null) { strB = variable.Value as TString; } } } if ((numberB == null) && (strB == null)) { return(new TException(interpreter, "Value is not a number or string")); } // Attempt addition if both operands are the same type, otherwise return a TException if ((numberB == null) && (strA == null)) { return(new TException(interpreter, "Attempted addition of a string to a number")); } else if ((numberA == null) && (strB == null)) { return(new TException(interpreter, "Attempted addition of a number to a string")); } else if ((numberA == null) && (numberB == null)) { return(new TString(strA.Value + strB.Value)); } else { //The left hand operand decides the type of the returned value switch (numberA.TypeName) { case TType.T_INTEGER_TYPENAME: { // If the other operand is a fraction, treat this integer as a fraction (i.e. value/1) TFraction fraction = numberB as TFraction; if (fraction != null) { // Copy the right hand fraction and add the left hand integer to it fraction = new TFraction(fraction.Numerator, fraction.Denominator); fraction.Add(numberA.TIntegerValue, 1); return(fraction); } return(new TInteger(numberA.TIntegerValue + numberB.TIntegerValue)); } case TType.T_REAL_TYPENAME: return(new TReal(numberA.TRealValue + numberB.TRealValue)); case TType.T_FRACTION_TYPENAME: { // Create a copy of the left hand fraction TFraction fraction = numberA as TFraction; fraction = new TFraction(fraction.Numerator, fraction.Denominator); // Convert the right hand operand to a fraction long numerator, denominator; TFraction otherFraction = numberB as TFraction; if (otherFraction != null) // If it's a fraction, simply copy the values { numerator = otherFraction.Numerator; denominator = otherFraction.Denominator; } else { // Check if it's a TInteger first. It might not need to use DoubleToFraction if (numberB is TInteger) { numerator = numberB.TIntegerValue; denominator = 1; } else { Operations.Misc.DoubleToFraction(numberB.TRealValue, out numerator, out denominator); } } fraction.Add(numerator, denominator); return(fraction); } } } return(null); }
/// <summary> /// Takes two TNumbers and divides one by the other. /// </summary> /// <param name="interpreter">The interpreter that the method is being called from.</param> /// <param name="a">The left hand operand of the operation.</param> /// <param name="b">The right hand operand of the operation.</param> /// <returns> /// The TType resulting from the operation. An MExcpetion or null is returned when there is an error. /// </returns> public static TType Divide(Interpreter interpreter, TType a, TType b) { // Try to get TNumber values from the TType arguments TNumber numberA, numberB; TException exception = AssignNumberValue(interpreter, out numberA, a); if (exception != null) { return(exception); } exception = AssignNumberValue(interpreter, out numberB, b); if (exception != null) { return(exception); } // No errors, but one or both of the arguments could be a TString; check them if ((numberA == null) || (numberB == null)) { return(new TException(interpreter, "Strings cannot be used in division operations")); } switch (numberA.TypeName) { case TType.T_INTEGER_TYPENAME: { // If the other operand is a fraction, treat this integer as a fraction (i.e. value/1) TFraction rhsFraction = numberB as TFraction; if (rhsFraction != null) { // Order of fractions matters in this case TFraction lhsFraction = new TFraction(numberA.TIntegerValue, 1); lhsFraction.Divide(rhsFraction.Numerator, rhsFraction.Denominator); return(lhsFraction); } if (numberB.TypeName == TType.T_INTEGER_TYPENAME) { return(new TFraction(numberA.TIntegerValue, numberB.TIntegerValue)); } return(new TInteger(numberA.TIntegerValue / numberB.TIntegerValue)); } case TType.T_REAL_TYPENAME: return(new TReal(numberA.TRealValue / numberB.TRealValue)); case TType.T_FRACTION_TYPENAME: { // Create a copy of the left hand fraction TFraction fraction = numberA as TFraction; fraction = new TFraction(fraction.Numerator, fraction.Denominator); // Convert the right hand operand to a fraction long numerator, denominator; TFraction otherFraction = numberB as TFraction; if (otherFraction != null) // If it's a fraction, simply copy the values { numerator = otherFraction.Numerator; denominator = otherFraction.Denominator; } else { // Check if it's a TInteger first. It might not need to use DoubleToFraction if (numberB is TInteger) { numerator = numberB.TIntegerValue; denominator = 1; } else { Operations.Misc.DoubleToFraction(numberB.TRealValue, out numerator, out denominator); } } fraction.Divide(numerator, denominator); return(fraction); } } return(null); }