From 64d390b9e06acfd60e3e715702fc813225ea0986 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 5 Jun 2025 12:32:19 +0900 Subject: [PATCH] numeric.c : add descriptive comments for public functions - mrb_int_overflow - mrb_int_zerodiv - mrb_int_pow - mrb_div_int - mrb_div_int_value - mrb_float_to_str - mrb_check_num_exact - mrb_int_mul - mrb_num_shift - mrb_float_to_integer - mrb_int_add - mrb_int_sub - mrb_int_to_cstr - mrb_integer_to_str - mrb_cmp The comments were written by Google Jules. --- src/numeric.c | 183 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) diff --git a/src/numeric.c b/src/numeric.c index 78e282440..71ffa74c6 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -21,12 +21,27 @@ #endif #endif +/** + * This function is called to raise a RangeError when an integer operation + * results in an overflow. It's marked mrb_noreturn as it always raises an + * exception and does not return. + * + * @param mrb The mruby state. + * @param reason A string describing the operation that caused the overflow + * (e.g., "addition", "multiplication"). + */ mrb_noreturn void mrb_int_overflow(mrb_state *mrb, const char *reason) { mrb_raisef(mrb, E_RANGE_ERROR, "integer overflow in %s", reason); } +/** + * This function is called to raise a ZeroDivisionError. It's marked + * mrb_noreturn as it always raises an exception and does not return. + * + * @param mrb The mruby state. + */ mrb_noreturn void mrb_int_zerodiv(mrb_state *mrb) { @@ -39,6 +54,21 @@ mrb_int_noconv(mrb_state *mrb, mrb_value y) mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %Y into Integer", y); } +/** + * Calculates x raised to the power of y, where x is an integer. + * y can be an integer or float. The result type can be Integer, + * Float, or BigInt depending on the inputs and intermediate calculations. + * + * @param mrb The mruby state. + * @param x The base (must be an integer type, possibly BigInt). + * @param y The exponent (can be Integer or Float). + * @return An mrb_value representing the result of the exponentiation. + * This can be an Integer, Float, or BigInt. + * Handles potential overflows by promoting to BigInt if MRB_USE_BIGINT is defined, + * or by raising RangeError if not. + * Handles negative exponents by returning a Float if MRB_NO_FLOAT is not defined, + * or raising RangeError if it is. + */ mrb_value mrb_int_pow(mrb_state *mrb, mrb_value x, mrb_value y) { @@ -113,6 +143,17 @@ int_pow(mrb_state *mrb, mrb_value x) return mrb_int_pow(mrb, x, mrb_get_arg1(mrb)); } +/** + * Performs integer division of x by y. This function implements specific + * rounding behavior for negative numbers to match Ruby's / operator for + * integers (floor division). + * + * @param x The dividend. + * @param y The divisor. + * @return The result of the integer division (mrb_int). + * Note: This function does not handle division by zero; the caller is + * expected to check for this. + */ mrb_int mrb_div_int(mrb_int x, mrb_int y) { @@ -124,6 +165,17 @@ mrb_div_int(mrb_int x, mrb_int y) return div; } +/** + * Performs integer division of x by y and returns the result as an mrb_value. + * It uses mrb_div_int for the division logic. + * + * @param mrb The mruby state. + * @param x The dividend. + * @param y The divisor. + * @return An mrb_value (integer) representing the result of the division. + * @raise ZeroDivisionError if y is 0. + * @raise RangeError for overflow conditions (specifically MRB_INT_MIN / -1). + */ mrb_value mrb_div_int_value(mrb_state *mrb, mrb_int x, mrb_int y) { @@ -351,6 +403,17 @@ num_fdiv(mrb_state *mrb, mrb_value x) return flo_div(mrb, mrb_ensure_float_type(mrb, x)); } +/** + * Converts an mrb_value float to a new mrb_value string. + * It handles formatting to ensure the string representation includes a + * decimal point and fractional part (e.g., ".0" is appended if not present). + * + * @param mrb The mruby state. + * @param flo The float mrb_value to convert. + * @param fmt This argument is noted as no longer used and can be NULL. + * The function uses a default format. + * @return A new mrb_value string representing the float. + */ /* the argument `fmt` is no longer used; you can pass `NULL` */ mrb_value mrb_float_to_str(mrb_state *mrb, mrb_value flo, const char *fmt) @@ -690,6 +753,16 @@ flo_finite_p(mrb_state *mrb, mrb_value num) * FloatDomainError: Infinity */ /* ------------------------------------------------------------------------*/ +/** + * Checks if a mrb_float value is Infinity or NaN. If it is, this function + * raises a FloatDomainError. This is used to prevent conversions of these + * special float values to exact number types like Integer. + * + * @param mrb The mruby state. + * @param num The float value to check. + * It does not return a value (void function) but will raise an exception + * if the number is not exact. + */ void mrb_check_num_exact(mrb_state *mrb, mrb_float num) { @@ -995,6 +1068,22 @@ flo_abs(mrb_state *mrb, mrb_value num) * methods simply return the receiver. */ +/** + * Multiplies two mrb_values, x and y, where x is expected to be an integer. + * y can be an integer, BigInt, Rational, Complex, or Float. The function + * handles type promotion and dispatches to appropriate handlers + * (e.g., mrb_bint_mul for BigInts). + * + * @param mrb The mruby state. + * @param x The first operand (integer). + * @param y The second operand (can be various numeric types). + * @return An mrb_value representing the product. The type of the result + * depends on the types of the inputs and the magnitude of the result + * (e.g., could be Integer, BigInt, Float, Rational, Complex). + * Handles potential integer overflows by promoting to BigInt if MRB_USE_BIGINT + * is defined, or raising RangeError otherwise. + * If y is not a recognized numeric type, it raises E_TYPE_ERROR. + */ mrb_value mrb_int_mul(mrb_state *mrb, mrb_value x, mrb_value y) { @@ -1339,6 +1428,25 @@ int_xor(mrb_state *mrb, mrb_value x) #define NUMERIC_SHIFT_WIDTH_MAX (MRB_INT_BIT-1) +/** + * Performs a bitwise shift operation (left or right) on an mrb_int value + * (val) by width positions. + * + * @param mrb The mruby state (though not directly used in the function + * logic, it's often part of MRB_API signatures). + * @param val The integer value to be shifted. + * @param width The number of positions to shift. Positive for left shift, + * negative for right shift. + * @param num A pointer to an mrb_int where the result of the shift will be + * stored. + * @return An mrb_bool indicating whether the shift was successful. + * - TRUE if the shift was performed without overflow. + * - FALSE if the shift would result in an overflow (e.g., shifting + * a large positive number too far left, or a negative number + * too far left). + * Special handling for right shifts of negative numbers (arithmetic shift) + * and large shift widths. + */ mrb_bool mrb_num_shift(mrb_state *mrb, mrb_int val, mrb_int width, mrb_int *num) { @@ -1668,6 +1776,15 @@ int_to_f(mrb_state *mrb, mrb_value num) return mrb_float_value(mrb, (mrb_float)mrb_integer(num)); } +/** + * Converts an mrb_value float to an mrb_value integer. + * + * @param mrb The mruby state. + * @param x The float mrb_value to convert. + * @return An mrb_value integer if the conversion is successful. + * @raise E_TYPE_ERROR if the input is not a float. + * @raise E_RANGE_ERROR if the float is Infinity or NaN. + */ MRB_API mrb_value mrb_float_to_integer(mrb_state *mrb, mrb_value x) { @@ -1682,6 +1799,22 @@ mrb_float_to_integer(mrb_state *mrb, mrb_value x) } #endif +/** + * Adds two mrb_values, x and y, where x is expected to be an integer. + * y can be an integer, BigInt, Rational, Complex, or Float. The function + * handles type promotion and dispatches to appropriate handlers. + * + * @param mrb The mruby state. + * @param x The first operand (integer). + * @param y The second operand (can be various numeric types). + * @return An mrb_value representing the sum. The type of the result depends + * on the types of the inputs and the magnitude of the result. + * Handles potential integer overflows by promoting to BigInt if MRB_USE_BIGINT + * is defined, or raising RangeError otherwise. + * If y is not a recognized numeric type and MRB_NO_FLOAT is defined, it + * raises E_TYPE_ERROR. If MRB_NO_FLOAT is not defined, it attempts to + * convert y to a float. + */ mrb_value mrb_int_add(mrb_state *mrb, mrb_value x, mrb_value y) { @@ -1748,6 +1881,22 @@ int_add(mrb_state *mrb, mrb_value self) return mrb_int_add(mrb, self, other); } +/** + * Subtracts mrb_value y from mrb_value x, where x is expected to be an + * integer. y can be an integer, BigInt, Rational, Complex, or Float. + * The function handles type promotion and dispatches to appropriate handlers. + * + * @param mrb The mruby state. + * @param x The minuend (integer). + * @param y The subtrahend (can be various numeric types). + * @return An mrb_value representing the difference. The type of the result + * depends on the types of the inputs and the magnitude of the result. + * Handles potential integer overflows by promoting to BigInt if MRB_USE_BIGINT + * is defined, or raising RangeError otherwise. + * If y is not a recognized numeric type and MRB_NO_FLOAT is defined, it + * raises E_TYPE_ERROR. If MRB_NO_FLOAT is not defined, it attempts to + * convert y to a float. + */ mrb_value mrb_int_sub(mrb_state *mrb, mrb_value x, mrb_value y) { @@ -1812,6 +1961,16 @@ int_sub(mrb_state *mrb, mrb_value self) return mrb_int_sub(mrb, self, other); } +/** + * Converts an mrb_int to a C-style string. + * + * @param buf The buffer to write the string to. + * @param len The size of the buffer. + * @param n The integer to convert. + * @param base The radix for conversion (2-36). + * @return A pointer to the beginning of the string in the buffer, + * or NULL if an error occurs (e.g., invalid base, buffer too small). + */ MRB_API char* mrb_int_to_cstr(char *buf, size_t len, mrb_int n, mrb_int base) { @@ -1845,6 +2004,15 @@ mrb_int_to_cstr(char *buf, size_t len, mrb_int n, mrb_int base) return b; } +/** + * Converts an mrb_value representing an integer to a new mrb_value string. + * + * @param mrb The mruby state. + * @param x The integer mrb_value to convert. + * @param base The radix for conversion (2-36). + * @return A new mrb_value string representing the integer, + * or raises an E_ARGUMENT_ERROR if the base is invalid. + */ MRB_API mrb_value mrb_integer_to_str(mrb_state *mrb, mrb_value x, mrb_int base) { @@ -2062,6 +2230,21 @@ num_ge(mrb_state *mrb, mrb_value self) return mrb_false_value(); } +/** + * Compares two mrb_value objects (obj1 and obj2). + * + * @param mrb The mruby state. + * @param obj1 The first object. + * @param obj2 The second object. + * @return An mrb_int indicating the comparison result: + * - 0 if obj1 is equal to obj2. + * - 1 if obj1 is greater than obj2. + * - -1 if obj1 is less than obj2. + * - -2 if the objects are not comparable (error). + * It handles comparisons for integers, floats, bigints, and strings directly. + * For other types, it attempts to call the <=> (spaceship) operator on obj1 + * with obj2 as an argument. + */ MRB_API mrb_int mrb_cmp(mrb_state *mrb, mrb_value obj1, mrb_value obj2) {