/// <summary> /// Subtract operator. /// </summary> public static PhpNumber Sub(PhpValue x, PhpNumber y) { PhpNumber x_number; var x_info = x.ToNumber(out x_number); if ((x_info & (Convert.NumberInfo.Unconvertible | Convert.NumberInfo.IsPhpArray)) != 0) { throw new ArgumentException(); // return 0 } // return(x_number - y); }
public static double Multiply(double dx, PhpValue y) { PhpNumber ynumber; if ((y.ToNumber(out ynumber) & (Convert.NumberInfo.Unconvertible | Convert.NumberInfo.IsPhpArray)) != 0) { //PhpException.UnsupportedOperandTypes(); //return 0.0; throw new ArgumentException(); } // return(dx * ynumber.ToDouble()); }
/// <summary> /// Subtract operator. /// </summary> public static double Sub(double dx, PhpValue y) { PhpNumber y_number; var y_info = y.ToNumber(out y_number); if ((y_info & (Convert.NumberInfo.Unconvertible | Convert.NumberInfo.IsPhpArray)) != 0) { throw new ArgumentException(); // return 0 } // return(dx - y_number.ToDouble()); }
/// <summary> /// Implements <c>+</c> operator on numbers. /// </summary> public static double Add(double x, PhpValue y) { PhpNumber number; if ((y.ToNumber(out number) & (Convert.NumberInfo.Unconvertible | Convert.NumberInfo.IsPhpArray)) != 0) { //PhpException.UnsupportedOperandTypes(); //return 0.0; throw new ArgumentException(); // TODO: ErrCode & return 0 } // return(x + number.ToDouble()); }
/// <summary> /// Multiply operator. /// </summary> public static double Multiply(PhpValue x, double dy) { PhpNumber xnumber; if (((x.ToNumber(out xnumber)) & (Convert.NumberInfo.Unconvertible | Convert.NumberInfo.IsPhpArray)) != 0) { //PhpException.UnsupportedOperandTypes(); //return 0.0; throw new ArgumentException(); } // return(xnumber.ToDouble() * dy); }
/// <summary> /// Performs division according to PHP semantics. /// </summary> /// <remarks>The division operator ("/") returns a float value unless the two operands are integers /// (or strings that get converted to integers) and the numbers are evenly divisible, /// in which case an integer value will be returned.</remarks> internal static PhpNumber Div(ref PhpValue x, ref PhpValue y) { PhpNumber nx, ny; var info = x.ToNumber(out nx) | y.ToNumber(out ny); if ((info & Convert.NumberInfo.IsPhpArray) != 0) { //PhpException.UnsupportedOperandTypes(); //return PhpNumber.Create(0.0); throw new NotImplementedException(); // PhpException } // TODO: // division by zero: //if (y == 0) //{ // PhpException.Throw(PhpError.Warning, CoreResources.GetString("division_by_zero")); // return false; //} return(nx / ny); }
public Convert.NumberInfo ToNumber(out PhpNumber number) => Value.ToNumber(out number);
/// <summary> /// Checks whether a dereferenced variable is numeric. /// </summary> /// <param name="variable">The variable.</param> /// <returns>Whether <paramref name="variable"/> is integer, double or numeric string. /// <seealso cref="PHP.Core.Convert.StringToNumber"/></returns> public static bool is_numeric(PhpValue variable) { switch (variable.TypeCode) { case PhpTypeCode.Int32: case PhpTypeCode.Long: case PhpTypeCode.Double: return true; case PhpTypeCode.String: case PhpTypeCode.WritableString: PhpNumber tmp; return (variable.ToNumber(out tmp) & Core.Convert.NumberInfo.IsNumber) != 0; default: return false; } }
/// <summary> /// Creates an array containing range of elements with arbitrary step. /// </summary> /// <param name="ctx">Current runtime context.</param> /// <param name="low">Lower bound of the interval.</param> /// <param name="high">Upper bound of the interval.</param> /// <param name="step">The step.</param> /// <returns>The array.</returns> /// <remarks> /// Implements PHP awful range function. The result depends on types and /// content of parameters under the following rules: /// <list type="number"> /// <item> /// <description> /// If at least one parameter (low, high or step) is of type double or is a string wholly representing /// double value (i.e. whole string is converted to a number and no chars remains, /// e.g. "1.5" is wholly representing but the value "1.5x" is not) /// than /// range of double values is generated with a step treated as a double value /// (e.g. <c>range("1x","2.5x","0.5") = array(1.0, 1.5, 2.0, 2.5)</c> etc.) /// otherwise /// </description> /// </item> /// <item> /// <description> /// if at least one bound (i.e. low or high parameter) is of type int or is a string wholly representing /// integer value /// than /// range of integer values is generated with a step treated as integer value /// (e.g. <c>range("1x","2","1.5") = array(1, 2, 3, 4)</c> etc.) /// otherwise /// </description> /// </item> /// <item> /// <description> /// low and high are both non-empty strings (otherwise one of the two previous conditions would be true), /// so the first characters of these strings are taken and a sequence of characters is generated. /// </description> /// </item> /// </list> /// Moreover, if <paramref name="low"/> is greater than <paramref name="high"/> then descending sequence is generated /// and ascending one otherwise. If <paramref name="step"/> is less than zero than an absolute value is used. /// </remarks> /// <exception cref="PhpException">Thrown if the <paramref name="step"/> argument is zero (or its absolute value less than 1 in the case 2).</exception> public static PhpArray range(Context ctx, PhpValue low, PhpValue high, PhpValue step) { PhpNumber num_low, num_high, num_step; // converts each parameter to a number, determines what type of number it is (int/double) // and whether it wholly represents that number: var info_step = step.ToNumber(out num_step); var info_low = low.ToNumber(out num_low); var info_high = high.ToNumber(out num_high); var is_step_double = (info_step & Core.Convert.NumberInfo.Double) != 0; var is_low_double = (info_low & Core.Convert.NumberInfo.Double) != 0; var is_high_double = (info_high & Core.Convert.NumberInfo.Double) != 0; var w_step = (info_step & Core.Convert.NumberInfo.IsNumber) != 0; var w_low = (info_low & Core.Convert.NumberInfo.IsNumber) != 0; var w_high = (info_high & Core.Convert.NumberInfo.IsNumber) != 0; // at least one parameter is a double or its numeric value is wholly double: if (is_low_double && w_low || is_high_double && w_high || is_step_double && w_step) { return RangeOfDoubles(num_low.ToDouble(), num_high.ToDouble(), num_step.ToDouble()); } // at least one bound is wholly integer (doesn't matter what the step is): if (!is_low_double && w_low || !is_high_double && w_high) { // at least one long integer: return RangeOfLongInts(num_low.ToLong(), num_high.ToLong(), num_step.ToLong()); } // both bounds are strings which are not wholly representing numbers (other types wholly represents a number): string slow = low.ToString(ctx); string shigh = high.ToString(ctx); // because each string doesn't represent a number it isn't empty: Debug.Assert(slow != "" && shigh != ""); return RangeOfChars(slow[0], shigh[0], (int)num_step.ToLong()); }
/// <summary> /// Performs division according to PHP semantics. /// </summary> /// <remarks>The division operator ("/") returns a float value unless the two operands are integers /// (or strings that get converted to integers) and the numbers are evenly divisible, /// in which case an integer value will be returned.</remarks> internal static PhpNumber Div(ref PhpValue x, ref PhpValue y) { PhpNumber nx, ny; var info = x.ToNumber(out nx) | y.ToNumber(out ny); if ((info & Convert.NumberInfo.IsPhpArray) != 0) { //PhpException.UnsupportedOperandTypes(); //return PhpNumber.Create(0.0); throw new NotImplementedException(); // PhpException } // TODO: // division by zero: //if (y == 0) //{ // PhpException.Throw(PhpError.Warning, CoreResources.GetString("division_by_zero")); // return false; //} return nx / ny; }
/// <summary> /// Performs conversion of a value to a number. /// Additional conversion warnings may be thrown. /// </summary> public static PhpNumber ToNumber(PhpValue value) { PhpNumber n; if ((value.ToNumber(out n) & NumberInfo.IsNumber) == 0) { // TODO: Err } return n; }