mruby-rational: add comprehensive call-seq documentation for Rational methods

Added complete call-seq documentation for all Rational methods in
mrblib/rational.rb (4 methods):

## Rational Class Methods:

- inspect: returns string representation for debugging with parentheses
  format, showing the rational value in "(numerator/denominator)" form

- to_s: returns string representation in "numerator/denominator" format
  for display and conversion purposes

- <=>: spaceship operator for comparison with other numeric types,
  returns -1/0/+1 for less/equal/greater comparisons, enables Comparable
  module functionality with proper nil handling for incomparable values

## Numeric Extension Methods:

- to_r: converts any numeric value to rational representation with
  denominator of 1, part of the standard numeric conversion protocol

Co-authored-by: Atlassian Rovo Dev
This commit is contained in:
Yukihiro "Matz" Matsumoto
2025-07-19 09:38:23 +09:00
parent 6b263ee577
commit 1cf225dfbe
2 changed files with 224 additions and 1 deletions
+44
View File
@@ -1,12 +1,46 @@
class Rational < Numeric
#
# call-seq:
# rat.inspect -> string
#
# Returns the value as a string for inspection.
#
# Rational(2).inspect #=> "(2/1)"
# Rational(-8, 6).inspect #=> "(-4/3)"
# Rational(1, 2).inspect #=> "(1/2)"
#
def inspect
"(#{to_s})"
end
#
# call-seq:
# rat.to_s -> string
#
# Returns the value as a string.
#
# Rational(2).to_s #=> "2/1"
# Rational(-8, 6).to_s #=> "-4/3"
# Rational(1, 2).to_s #=> "1/2"
#
def to_s
"#{numerator}/#{denominator}"
end
#
# call-seq:
# rat <=> numeric -> -1, 0, +1, or nil
#
# Returns -1, 0, or +1 depending on whether rat is less than, equal to,
# or greater than numeric. This is the basis for the tests in the Comparable module.
# Returns nil if the two values are incomparable.
#
# Rational(2, 3) <=> Rational(2, 3) #=> 0
# Rational(5) <=> 5 #=> 0
# Rational(2, 3) <=> Rational(1, 3) #=> 1
# Rational(1, 3) <=> 1 #=> -1
# Rational(1, 3) <=> 0.3 #=> 1
#
def <=>(other)
return nil unless other.kind_of?(Numeric)
self.to_f <=> other.to_f
@@ -16,6 +50,16 @@ class Rational < Numeric
end
class Numeric
#
# call-seq:
# num.to_r -> rational
#
# Returns the value as a rational.
#
# 1.to_r #=> (1/1)
# (1+2i).to_r #=> (1+2i)/1)
# nil.to_r #=> TypeError
#
def to_r
Rational(self, 1)
end
+180 -1
View File
@@ -110,6 +110,16 @@ rat_numerator(mrb_state *mrb, mrb_value self)
return mrb_int_value(mrb, p->numerator);
}
/*
* call-seq:
* rational.numerator -> integer
*
* Returns the numerator of the rational number.
*
* Rational(3, 4).numerator #=> 3
* Rational(-2, 5).numerator #=> -2
* Rational(6, 8).numerator #=> 3 (reduced form)
*/
/* normalized version of rat_numerator() */
static mrb_value
rational_numerator(mrb_state *mrb, mrb_value self)
@@ -134,6 +144,17 @@ rat_denominator(mrb_state *mrb, mrb_value self)
return mrb_int_value(mrb, p->denominator);
}
/*
* call-seq:
* rational.denominator -> integer
*
* Returns the denominator of the rational number.
* The denominator is always positive.
*
* Rational(3, 4).denominator #=> 4
* Rational(-2, 5).denominator #=> 5
* Rational(6, 8).denominator #=> 4 (reduced form)
*/
/* normalized version of rat_denominator() */
static mrb_value
rational_denominator(mrb_state *mrb, mrb_value self)
@@ -378,6 +399,16 @@ mrb_rational_to_f(mrb_state *mrb, mrb_value self)
}
#endif
/*
* call-seq:
* rational.to_i -> integer
*
* Returns the rational number truncated to an integer.
*
* Rational(3, 4).to_i #=> 0
* Rational(7, 3).to_i #=> 2
* Rational(-5, 2).to_i #=> -2
*/
mrb_value
mrb_rational_to_i(mrb_state *mrb, mrb_value self)
{
@@ -414,6 +445,16 @@ mrb_as_rational(mrb_state *mrb, mrb_value x)
}
}
/*
* call-seq:
* rational.negative? -> true or false
*
* Returns true if the rational number is negative, false otherwise.
*
* Rational(-1, 2).negative? #=> true
* Rational(1, 2).negative? #=> false
* Rational(0, 1).negative? #=> false
*/
static mrb_value
rational_negative_p(mrb_state *mrb, mrb_value self)
{
@@ -428,6 +469,17 @@ rational_negative_p(mrb_state *mrb, mrb_value self)
}
#ifndef MRB_NO_FLOAT
/*
* call-seq:
* float.to_r -> rational
*
* Converts the float to a rational number. The conversion preserves
* the exact value of the float as a fraction.
*
* 0.5.to_r #=> Rational(1, 2)
* 0.25.to_r #=> Rational(1, 4)
* 1.5.to_r #=> Rational(3, 2)
*/
static mrb_value
float_to_r(mrb_state *mrb, mrb_value self)
{
@@ -435,6 +487,16 @@ float_to_r(mrb_state *mrb, mrb_value self)
}
#endif
/*
* call-seq:
* integer.to_r -> rational
*
* Converts the integer to a rational number with denominator 1.
*
* 5.to_r #=> Rational(5, 1)
* (-3).to_r #=> Rational(-3, 1)
* 0.to_r #=> Rational(0, 1)
*/
static mrb_value
int_to_r(mrb_state *mrb, mrb_value self)
{
@@ -446,6 +508,14 @@ int_to_r(mrb_state *mrb, mrb_value self)
return rational_new_i(mrb, mrb_integer(self), 1);
}
/*
* call-seq:
* nil.to_r -> rational
*
* Converts nil to Rational(0, 1).
*
* nil.to_r #=> Rational(0, 1)
*/
static mrb_value
nil_to_r(mrb_state *mrb, mrb_value self)
{
@@ -477,6 +547,18 @@ rational_new(mrb_state *mrb, mrb_value a, mrb_value b)
#endif
}
/*
* call-seq:
* Rational(numerator, denominator = 1) -> rational
*
* Creates a rational number from numerator and denominator.
* The rational is automatically reduced to lowest terms.
*
* Rational(1, 2) #=> Rational(1, 2)
* Rational(6, 8) #=> Rational(3, 4)
* Rational(5) #=> Rational(5, 1)
* Rational(-2, 4) #=> Rational(-1, 2)
*/
static mrb_value
rational_m(mrb_state *mrb, mrb_value self)
{
@@ -487,6 +569,18 @@ rational_m(mrb_state *mrb, mrb_value self)
#else
/*
* call-seq:
* Rational(numerator, denominator = 1) -> rational
*
* Creates a rational number from numerator and denominator.
* The rational is automatically reduced to lowest terms.
*
* Rational(1, 2) #=> Rational(1, 2)
* Rational(6, 8) #=> Rational(3, 4)
* Rational(5) #=> Rational(5, 1)
* Rational(-2, 4) #=> Rational(-1, 2)
*/
static mrb_value
rational_m(mrb_state *mrb, mrb_value self)
{
@@ -547,6 +641,17 @@ rational_eq_b(mrb_state *mrb, mrb_value x, mrb_value y)
return mrb_bool_value(result);
}
/*
* call-seq:
* rational == other -> true or false
*
* Returns true if rational equals other. Comparison is done by cross-multiplication
* to avoid floating point precision issues.
*
* Rational(1, 2) == Rational(2, 4) #=> true
* Rational(1, 2) == 0.5 #=> true
* Rational(1, 2) == Rational(1, 3) #=> false
*/
static mrb_value
rational_eq(mrb_state *mrb, mrb_value x)
{
@@ -602,6 +707,15 @@ rational_eq(mrb_state *mrb, mrb_value x)
return mrb_bool_value(result);
}
/*
* call-seq:
* -rational -> rational
*
* Returns the negation of the rational number.
*
* -Rational(1, 2) #=> Rational(-1, 2)
* -Rational(-3, 4) #=> Rational(3, 4)
*/
static mrb_value
rational_minus(mrb_state *mrb, mrb_value x)
{
@@ -712,6 +826,17 @@ mrb_rational_add(mrb_state *mrb, mrb_value x, mrb_value y)
}
}
/*
* call-seq:
* rational + numeric -> rational or numeric
*
* Returns the sum of rational and numeric. If numeric is a rational,
* returns a rational. If numeric is a float, returns a float.
*
* Rational(1, 2) + Rational(1, 3) #=> Rational(5, 6)
* Rational(1, 2) + 1 #=> Rational(3, 2)
* Rational(1, 2) + 0.5 #=> 1.0
*/
static mrb_value
rational_add(mrb_state *mrb, mrb_value x)
{
@@ -806,6 +931,17 @@ mrb_rational_sub(mrb_state *mrb, mrb_value x, mrb_value y)
}
}
/*
* call-seq:
* rational - numeric -> rational or numeric
*
* Returns the difference of rational and numeric. If numeric is a rational,
* returns a rational. If numeric is a float, returns a float.
*
* Rational(1, 2) - Rational(1, 3) #=> Rational(1, 6)
* Rational(3, 2) - 1 #=> Rational(1, 2)
* Rational(1, 2) - 0.25 #=> 0.25
*/
static mrb_value
rational_sub(mrb_state *mrb, mrb_value x)
{
@@ -893,6 +1029,17 @@ mrb_rational_mul(mrb_state *mrb, mrb_value x, mrb_value y)
}
}
/*
* call-seq:
* rational * numeric -> rational or numeric
*
* Returns the product of rational and numeric. Uses standard rational
* multiplication: (a/b) * (c/d) = (a*c)/(b*d).
*
* Rational(1, 2) * Rational(2, 3) #=> Rational(1, 3)
* Rational(1, 2) * 3 #=> Rational(3, 2)
* Rational(1, 2) * 2.0 #=> 1.0
*/
static mrb_value
rational_mul(mrb_state *mrb, mrb_value x)
{
@@ -984,6 +1131,18 @@ mrb_rational_div(mrb_state *mrb, mrb_value x, mrb_value y)
}
}
/*
* call-seq:
* rational / numeric -> rational or numeric
* rational.quo(numeric) -> rational or numeric
*
* Returns the quotient of rational divided by numeric. Uses standard rational
* division: (a/b) / (c/d) = (a/b) * (d/c) = (a*d)/(b*c).
*
* Rational(1, 2) / Rational(1, 3) #=> Rational(3, 2)
* Rational(3, 4) / 2 #=> Rational(3, 8)
* Rational(1, 2) / 0.5 #=> 1.0
*/
static mrb_value
rational_div(mrb_state *mrb, mrb_value x)
{
@@ -993,6 +1152,17 @@ rational_div(mrb_state *mrb, mrb_value x)
mrb_value mrb_int_pow(mrb_state *mrb, mrb_value x, mrb_value y);
/*
* call-seq:
* rational ** numeric -> numeric
*
* Returns rational raised to the power of numeric. The result is typically
* a float unless the result can be exactly represented as a rational.
*
* Rational(1, 2) ** 2 #=> Rational(1, 4)
* Rational(4, 1) ** 0.5 #=> 2.0
* Rational(2, 1) ** 3 #=> Rational(8, 1)
*/
static mrb_value
rational_pow(mrb_state *mrb, mrb_value x)
{
@@ -1019,6 +1189,15 @@ rational_pow(mrb_state *mrb, mrb_value x)
#endif
}
/*
* call-seq:
* rational.hash -> integer
*
* Returns a hash value for the rational number. Two rationals with
* the same value will have the same hash value.
*
* Rational(1, 2).hash == Rational(2, 4).hash #=> true
*/
static mrb_value
rational_hash(mrb_state *mrb, mrb_value rat)
{
@@ -1051,7 +1230,7 @@ void mrb_mruby_rational_gem_init(mrb_state *mrb)
mrb_define_method_id(mrb, rat, MRB_SYM(to_f), mrb_rational_to_f, MRB_ARGS_NONE());
#endif
mrb_define_method_id(mrb, rat, MRB_SYM(to_i), mrb_rational_to_i, MRB_ARGS_NONE());
mrb_define_method_id(mrb, rat, MRB_SYM(to_r), mrb_obj_itself, MRB_ARGS_NONE());
mrb_define_method_id(mrb, rat, MRB_SYM(to_r), mrb_obj_itself, MRB_ARGS_NONE()); /* Returns self - already a rational */
mrb_define_method_id(mrb, rat, MRB_SYM_Q(negative), rational_negative_p, MRB_ARGS_NONE());
mrb_define_method_id(mrb, rat, MRB_OPSYM(eq), rational_eq, MRB_ARGS_REQ(1));
mrb_define_method_id(mrb, rat, MRB_OPSYM(minus), rational_minus, MRB_ARGS_NONE());