summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
author卜部昌平 <shyouhei@ruby-lang.org>2021-03-12 14:16:11 +0900
committer卜部昌平 <shyouhei@ruby-lang.org>2021-09-10 20:00:06 +0900
commit14e6e122e73fc0b5a05a68e277895c6b965092b8 (patch)
tree76a005f97b2e80f5c483dd8e4b68242c95cdf91d /include
parentd43accae15cdfc245052f6b08c5880913a35ae9e (diff)
include/ruby/internal/intern/numeric.h: add doxygen
Must not be a bad idea to improve documents. [ci skip]
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/4815
Diffstat (limited to 'include')
-rw-r--r--include/ruby/internal/intern/numeric.h185
1 files changed, 175 insertions, 10 deletions
diff --git a/include/ruby/internal/intern/numeric.h b/include/ruby/internal/intern/numeric.h
index 7b6578cc68..30863fb0c8 100644
--- a/include/ruby/internal/intern/numeric.h
+++ b/include/ruby/internal/intern/numeric.h
@@ -20,22 +20,187 @@
* extension libraries. They could be written in C++98.
* @brief Public APIs related to ::rb_cNumeric.
*/
+#include "ruby/internal/attr/cold.h"
+#include "ruby/internal/attr/noreturn.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
-#include "ruby/backward/2/attributes.h"
+
+/**
+ * @private
+ *
+ * @deprecated This macro once was a thing in the old days, but makes no sense
+ * any longer today. Exists here for backwards compatibility
+ * only. You can safely forget about it.
+ */
+#define RB_NUM_COERCE_FUNCS_NEED_OPID 1
RBIMPL_SYMBOL_EXPORT_BEGIN()
/* numeric.c */
-NORETURN(void rb_num_zerodiv(void));
-#define RB_NUM_COERCE_FUNCS_NEED_OPID 1
-VALUE rb_num_coerce_bin(VALUE, VALUE, ID);
-VALUE rb_num_coerce_cmp(VALUE, VALUE, ID);
-VALUE rb_num_coerce_relop(VALUE, VALUE, ID);
-VALUE rb_num_coerce_bit(VALUE, VALUE, ID);
-VALUE rb_num2fix(VALUE);
-VALUE rb_fix2str(VALUE, int);
-CONSTFUNC(VALUE rb_dbl_cmp(double, double));
+
+RBIMPL_ATTR_NORETURN()
+RBIMPL_ATTR_COLD()
+/**
+ * Just always raises an exception.
+ *
+ * @exception rb_eZeroDivError Division by zero error.
+ */
+void rb_num_zerodiv(void);
+
+/**
+ * @name Coercion operators.
+ *
+ * What is a coercion? Well Ruby is basically an OOPL but it also has
+ * arithmetic operators. They are implemented in OO manners. For instance
+ * `a+b` is a binary operation `+`, whose receiver is `a`, and whose (sole)
+ * argument is `b`.
+ *
+ * The problem is, you often want `a+b == b+a` to hold. That is easy if both
+ * `a` and `b` belongs to the same class... Ensuring `1 + 2 == 2 + 1` is kind
+ * of intuitive. But if you want `1.0 + 2 == 2 + 1.0`, things start getting
+ * complicated. `1.0+2` is `Float#+`, while `2+1.0` is `Integer#+`. In order
+ * to achieve the equality Float's and Integer's methods must agree with their
+ * behaviours.
+ *
+ * Now. Floats versus Integers situation is still controllable because they
+ * are both built-in. But in Ruby you can define your own numeric classes.
+ * BigDecimal, which is a rubygems gem distributed along with the interpreter,
+ * is one of such examples. Rational was another such example before. In
+ * short you cannot create list of all possible combination of the classes that
+ * could be the operand of `+` operator. Then how do we achieve the
+ * commutativity?
+ *
+ * Here comes the concept of coercion. If a definition of an operator
+ * encounters an object which is unknown to the author, just assumes that the
+ * unknown object knows how to handle the situation. So for instance when
+ * `1+x` has unknown `x`, it lets the `x` handle this.
+ *
+ * ```ruby
+ * class Foo
+ * def +(x)
+ * if we_know_what_is_x? then
+ * ... # handle here
+ * else
+ * y, z = x.coerce self
+ * return y + z
+ * end
+ * end
+ * end
+ * ```
+ *
+ * The `x.coerce` method returns a 2-element array which are "casted" versions
+ * of `x` and `self`.
+ *
+ * @{
+ */
+
+/**
+ * Coerced binary operation. This function first coerces the two objects, then
+ * applies the operation.
+ *
+ * @param[in] lhs LHS operand.
+ * @param[in] rhs RHS operand.
+ * @param[in] op Operator method name.
+ * @exception rb_eTypeError Coercion failed for some reason.
+ * @return `lhs op rhs`, in a coerced way.
+ */
+VALUE rb_num_coerce_bin(VALUE lhs, VALUE rhs, ID op);
+
+/**
+ * Identical to rb_num_coerce_bin(), except for return values. This function
+ * best suits for comparison operators e.g. `<=>`.
+ *
+ * @param[in] lhs LHS operand.
+ * @param[in] rhs RHS operand.
+ * @param[in] op Operator method name.
+ * @retval RUBY_Qnil Coercion failed for some reason.
+ * @retval otherwise `lhs op rhs`, in a coerced way.
+ */
+VALUE rb_num_coerce_cmp(VALUE lhs, VALUE rhs, ID op);
+
+/**
+ * Identical to rb_num_coerce_cmp(), except for return values. This function
+ * best suits for relationship operators e.g. `<=`.
+ *
+ * @param[in] lhs LHS operand.
+ * @param[in] rhs RHS operand.
+ * @param[in] op Operator method name.
+ * @exception rb_eArgError Coercion failed for some reason.
+ * @return `lhs op rhs`, in a coerced way.
+ */
+VALUE rb_num_coerce_relop(VALUE lhs, VALUE rhs, ID op);
+
+/**
+ * This one is optimised for bitwise operations, but the API is identical to
+ * rb_num_coerce_bin().
+ *
+ * @param[in] lhs LHS operand.
+ * @param[in] rhs RHS operand.
+ * @param[in] op Operator method name.
+ * @exception rb_eArgError Coercion failed for some reason.
+ * @return `lhs op rhs`, in a coerced way.
+ */
+VALUE rb_num_coerce_bit(VALUE lhs, VALUE rhs, ID op);
+
+/** @} */
+
+/**
+ * Converts a numeric value into a Fixnum. This is not a preserving
+ * conversion; for instance 1.5 would be converted into 1.
+ *
+ * @param[in] val A numeric object.
+ * @exception rb_eTypeError No conversion from `val` to Integer.
+ * @exception rb_eRangeError `val` out of range.
+ * @return A fixnum converted from `val`.
+ *
+ * @internal
+ *
+ * This seems used from nowhere?
+ */
+VALUE rb_num2fix(VALUE val);
+
+/**
+ * Generates a place-value representation of the given Fixnum, with given
+ * radix.
+ *
+ * @param[in] val A fixnum to stringify.
+ * @param[in] base `2` to `36` inclusive for each radix.
+ * @exception rb_eArgError `base` is out of range.
+ * @return An instance of ::rb_cString representing `val`.
+ * @pre `val` must be a Fixnum (no checks performed).
+ */
+VALUE rb_fix2str(VALUE val, int base);
+
+RBIMPL_ATTR_CONST()
+/**
+ * Compares two `double`s. Handy when implementing a spaceship operator.
+ *
+ * @param[in] lhs A value.
+ * @param[in] rhs Another value.
+ * @retval RB_INT2FIX(-1) `lhs` is "bigger than" `rhs`.
+ * @retval RB_INT2FIX(1) `rhs` is "bigger than" `lhs`.
+ * @retval RB_INT2FIX(0) They are equal.
+ * @retval RUBY_Qnil Not comparable, e.g. NaN.
+ */
+VALUE rb_dbl_cmp(double lhs, double rhs);
+
+/**
+ * Raises the passed `x` to the power of `y`.
+ *
+ * @note The return value can be really big.
+ * @note Also the return value can be really small, in case `x` is a
+ * negative number.
+ * @param[in] x A number.
+ * @param[in] y Another number.
+ * @retval Inf Cannot express the result.
+ * @retval 1 Either `y` is 0 or `x` is 1.
+ * @retval otherwise An instance of ::rb_cInteger whose value is `x ** y`.
+ *
+ * @internal
+ *
+ * This function returns Infinity when `y` is big enough not to fit into a
+ * Fixnum. Warning is issued then.
+ */
RUBY_EXTERN VALUE rb_int_positive_pow(long x, unsigned long y);
RBIMPL_SYMBOL_EXPORT_END()