98 Commits

Author SHA1 Message Date
Yukihiro "Matz" Matsumoto 73255d3b70 mruby-numeric-ext: avoid signed overflow on Integer#gcd/lcm with MRB_INT_MIN
Negating MRB_INT_MIN (-2^63) is signed overflow (UB) because
2^63 does not fit in mrb_int.  Both `mrb_int_gcd` and `int_lcm`
took the absolute value via `if (x < 0) x = -x`, which trips on
MRB_INT_MIN.

Reported by ClusterFuzz testcase
clusterfuzz-testcase-minimized-mruby_fuzzer-5137605569347584.

* mrb_int_gcd: cast each input to mrb_uint before negating; the
  Euclidean reduction runs in unsigned.  The cast back at the
  end yields MRB_INT_MIN only when the mathematical gcd is 2^63
  (i.e., gcd(MIN, 0) or gcd(MIN, MIN)).
* int_gcd: detect the negative return value from mrb_int_gcd
  and raise via mrb_int_overflow, since the true result does
  not fit.
* int_lcm: short-circuit raise when either operand is
  MRB_INT_MIN (after the existing zero check), since the abs
  would overflow and the lcm with any non-zero operand could
  not fit anyway.

Co-authored-by: Claude <noreply@anthropic.com>
2026-05-19 12:05:33 +09:00
dearblue 6c4a8c09db Define mrb_bigint_p() always.
Define the `mrb_bigint_p()` macro function, which returns false if `MRB_USE_BIGINT` is undefined.
2026-03-24 22:16:15 +09:00
Yukihiro "Matz" Matsumoto 8956c5abb5 mruby.h: include mruby/presym.h for all source files
Since presym is now mandatory, mruby.h includes presym.h so that
MRB_SYM() macros are available everywhere without explicit include.
Remove redundant #include <mruby/presym.h> from all source files.

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-09 16:50:58 +09:00
Yukihiro "Matz" Matsumoto 71cb3c2e3a class.c: allocate ROM table wrappers per mrb_state
ROM method tables used static mrb_mt_tbl variables shared
across the process. The next pointer in each wrapper was
mutated by mrb_mt_init_rom(), causing cross-state
contamination when multiple mrb_state instances existed.

Allocate mrb_mt_tbl wrappers per-state via mrb_malloc().
The const mrb_mt_entry[] arrays remain static and shared.
Wrappers are tracked in mrb->rom_mt and freed at mrb_close().

Remove MRB_MT_ROM_TAB macro; add MRB_MT_INIT_ROM macro that
auto-computes size and calls the new mrb_mt_init_rom().

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-20 22:24:31 +09:00
Yukihiro "Matz" Matsumoto 483c155a41 class.c: store aspec in ROM method table entries
Restore MRB_ARGS_* argument specs and ISO section comments to all
709 ROM method table entries. The aspec is encoded in bits 4-27 of
the flags field; MRB_MT_NOARG is now auto-derived from aspec==0.

Add MRB_MT_ENTRY_PRIVATE() macro for private methods (53 entries)
and MRB_MT_ASPEC() accessor for extracting aspec from flags.

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-20 11:44:28 +09:00
Yukihiro "Matz" Matsumoto 20b9002214 class.c: merge conditional methods into ROM tables
Move conditional mrb_define_method_id() calls into ROM entry
arrays using #ifdef guards. With linear search, sizeof in
MRB_MT_ROM_TAB() adjusts automatically after preprocessing.

Cross-class ROM tables (methods a gem defines on a class it does
not own) are reverted to mrb_define_method_id(). Multiple gems
should not add ROM table layers to the same class; each layer
costs a 16-byte mrb_mt_tbl struct in RAM and deepens the lookup
chain. Use mrb_define_method_id() for cross-class methods.

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-20 11:05:03 +09:00
Yukihiro "Matz" Matsumoto 8adba34bd9 class.c: auto-set MRB_MT_FUNC in MRB_MT_ENTRY macro
Since ROM table entries are always C functions, have the
MRB_MT_ENTRY() macro set MRB_MT_FUNC automatically. This
simplifies entry definitions across all 32 source files.

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-20 10:37:06 +09:00
Yukihiro "Matz" Matsumoto 0fab703028 class.c: use linear search for method tables; make ROM entries const
Replace binary search with linear scan in mt_get(), mt_put(),
mt_del(), mt_chain_has(), and mrb_mt_foreach(). The method cache
makes repeated lookups O(1), so linear scan on cache misses is
acceptable.

This removes the sorting requirement, allowing ROM entry arrays
to be declared const. On embedded systems, const static data
resides in flash/ROM instead of RAM, saving ~8.4KB for ~700
method entries on 32-bit MCUs.

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-20 08:26:05 +09:00
Yukihiro "Matz" Matsumoto bde2202100 class.c: refactor ROM method tables to array-of-structs layout
Replace the parallel-arrays (struct-of-arrays) ROM method table
layout with an array-of-structs layout where each mrb_mt_entry
bundles its function pointer and symbol key together.

New MRB_MT_ENTRY() and MRB_MT_ROM_TAB() macros simplify ROM table
definitions from a 3-part pattern (SIZE define + anonymous struct +
mrb_mt_tbl) to a 2-part pattern (entries array + mrb_mt_tbl).

Internal mt_* functions in class.c are simplified: single memmove/
memcpy operations replace paired key+value operations.

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-19 23:59:30 +09:00
Yukihiro "Matz" Matsumoto 0ed26f8352 class.c: rename mt_/MT_ to mrb_mt_/MRB_MT_ for non-static identifiers
Follow mruby's naming convention: non-static types, macros, and
functions use the mrb_/MRB_ prefix. Renamed:
- union mt_ptr -> union mrb_mt_ptr
- mt_tbl -> mrb_mt_tbl
- MT_KEY(), MT_FUNC, MT_NOARG, MT_PUBLIC, MT_PRIVATE -> MRB_MT_*
- MT_KEY_SHIFT, MT_READONLY_BIT, MT_REMOVED_P -> MRB_MT_*
- mt_init_rom() -> mrb_mt_init_rom()
File-local static functions and macros in class.c are unchanged.

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-19 15:22:55 +09:00
Yukihiro "Matz" Matsumoto 9fbc11c6d0 mrbgems: remove MRB_NO_PRESYM guards from core extension gems
Co-authored-by: Claude <noreply@anthropic.com>
2026-02-19 12:17:34 +09:00
Yukihiro "Matz" Matsumoto b52d3936e6 mruby-numeric-ext: ROM method table for Integer extensions (9 methods)
Co-authored-by: Claude <noreply@anthropic.com>
2026-02-18 16:44:25 +09:00
Yukihiro "Matz" Matsumoto 070bef24ab mruby-numeric-ext: fix integer overflow in Integer#lcm
check for overflow using mrb_int_mul_overflow() in the LCM
computation to avoid undefined behavior when the result exceeds
mrb_int range. raises RangeError instead.

reported by OSS-Fuzz (clusterfuzz-testcase-6501272051318784).

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-16 16:34:20 +09:00
Yukihiro "Matz" Matsumoto 8f259fb560 mruby-bigint, mruby-numeric-ext: fix Integer#pow with negative modulus
Support negative modulus in Integer#pow(exp, mod) with proper Ruby
semantics. Previously, negative modulus caused an infinite loop in
Barrett reduction. Now:

- Use absolute value of modulus for computation
- Apply signed modulo adjustment (result + m for non-zero result
  when m is negative)
- Add early return for zero base with positive exponent (0^n = 0)

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-30 16:25:49 +09:00
Yukihiro "Matz" Matsumoto e60acfc6ff mruby-numeric-ext: add Integer#bit_length
Implement Integer#bit_length in mrbgems/mruby-numeric-ext.
- Fixnum: zero returns 0; negatives follow ~self rule; count bits by shifts.
- Bigint (MRB_USE_BIGINT): handle sign; negatives via mrb_bint_rev, then bit
  length via length of mrb_bint_to_s(..., 2).
- Add tests in mrbgems/mruby-numeric-ext/test/numeric.rb.
- Update README with examples.

Co-authored-by: Codex CLI <codex@openai.com>
2025-08-14 10:53:12 +09:00
Yukihiro "Matz" Matsumoto 07b803e28a docs: replace xml-style markup with markdown in comments
Replace XML-style markup tags in comments with markdown equivalents:
- <code>...</code> to `...` (inline code)
- <tt>...</tt> to `...` (teletype/monospace)
- <i>...</i> to *...* (italics/emphasis)
- +...+ to `...` (parameter/variable references)

Updated 80+ files across core source, headers, mrbgems, and libraries
to use consistent markdown formatting in documentation comments.
Handled edge cases including special characters like <=> operators.

Co-authored-by: Atlassian Rovo Dev
2025-08-14 10:52:49 +09:00
Yukihiro "Matz" Matsumoto 9c944e2a1f mruby-numeric-ext: add call-seq documentation for Integer#integer? method
Added missing call-seq documentation for Integer#integer? method in
mrblib/numeric_ext.rb to complete documentation coverage:

- integer?: returns true for Integer objects, completing the integer?
  method documentation across both Numeric and Integer classes with
  consistent formatting and practical examples

Co-authored-by: Atlassian Rovo Dev
2025-08-14 10:52:47 +09:00
Yukihiro "Matz" Matsumoto fe4ed7e68d mruby-numeric-ext: implement integer#gcd and Integer#lcm methods
implement Integer#gcd and Integer#lcm methods in mruby-numeric-ext with full
support for both regular integers and bigints.

key changes:
- add mrb_int_gcd euclidean algorithm for regular integer gcd calculation
- implement int_gcd and int_lcm methods with proper type checking and bigint fallback
- add mrb_bint_gcd, mrb_bint_lcm, mrb_bint_abs functions to bigint api
- register gcd and lcm methods with integer class
- add comprehensive test coverage for both regular and bigint cases

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-14 10:52:46 +09:00
Yukihiro "Matz" Matsumoto 540bbc71e6 mruby-numeric-ext: add documentation for public methods
This commit adds `call-seq` documentation to the following methods
in `mruby-numeric-ext` to improve code clarity and maintainability:

- `Integer#even?`
- `Integer#odd?`
- `Integer.sqrt`
- `Float#remainder`

Additionally, it adds a comment to the internal `isqrt` function
to explain its implementation.

Co-authored-by: Gemini <gemini@google.com>
2025-07-11 09:20:01 +09:00
Yukihiro "Matz" Matsumoto 5e5b4445ff mruby-numeric-ext: add README.md
The document is written by Google Jules.
2025-06-10 10:58:22 +09:00
Yukihiro "Matz" Matsumoto e42523fcf4 mruby-numeric-ext: add test for Integer.sqrt() 2025-04-16 23:30:23 +09:00
Yukihiro "Matz" Matsumoto ddfe65763e mruby-numeric-ext (int_sqrt): support bigint 2025-04-16 23:08:23 +09:00
Yukihiro "Matz" Matsumoto dee661913f mruby-numeric-ext (int_sqrt): Integer.sqrt implemented
This is the first version. It should support bigint eventually.
2025-04-16 22:37:06 +09:00
Yukihiro "Matz" Matsumoto 79dda053a5 mruby-numeric-ext: add test for Integer#digits 2024-11-23 23:16:47 +09:00
Hoshiumi Arata 612941dcbc Add test code for even?/odd? 2024-07-23 21:09:17 +09:00
Hoshiumi Arata 80502b30fb Optimize even?/odd? for big integers 2024-07-23 21:05:10 +09:00
Yukihiro "Matz" Matsumoto d2878138d9 mruby-numeric-ext: implement Integer#even? and Integer#odd? 2024-07-23 07:23:13 +09:00
Yukihiro "Matz" Matsumoto ca28e639c6 mruby-numeric-ext: move allbits?, anybits?, nobits? to Integer class 2024-07-15 21:35:42 +09:00
Yukihiro "Matz" Matsumoto 3f5138a6ac mruby-numeric-ext: implement Numeric#integer? method 2024-07-15 21:35:42 +09:00
Yukihiro "Matz" Matsumoto c75f7587bc mruby-numeric-ext: add call-seq reference for Integer#size 2024-07-10 14:56:13 +09:00
Yukihiro "Matz" Matsumoto ee296f024b mruby-numeric-ext: add Integer#size method
Although CRuby uses clz() for the biggest word, mruby bigint only counts
number of digit words.
2024-07-10 14:50:54 +09:00
Yukihiro "Matz" Matsumoto 6361f6d661 mruby-numeric-ext: use presym for initialization 2024-06-14 00:35:44 +09:00
Yukihiro "Matz" Matsumoto d944a079a3 mruby-numeric-ext (int_digits): avoid variable name override 2024-01-03 07:23:55 +09:00
Yukihiro "Matz" Matsumoto a22ea766e2 mruby-numeric-ext/numeric_ext.c: use local variables. 2023-08-08 11:24:14 +09:00
Yukihiro "Matz" Matsumoto d482eabfa2 mruby-bigint/bigint.c: int.pow(n,m) to take bigint as exponential 2023-03-31 08:26:47 +09:00
Yukihiro "Matz" Matsumoto 35cedfb400 mruby-numeric-ext/numeric.c: Integer#pow fix for 2nd argument type
`int.pow()` takes 2nd argument only if 1st argument is an integer.
2023-03-30 08:18:27 +09:00
Yukihiro "Matz" Matsumoto 52b2e12f07 numeric_ext.c: implement Integer#digits method.
Which is added in Ruby 2.4.
2022-09-17 16:43:06 +09:00
Yukihiro "Matz" Matsumoto 3662d3d9da fixup! numeric_ext.c: use the reference from mrb structure. 2022-09-12 10:27:30 +09:00
Yukihiro "Matz" Matsumoto fc85523cf1 numeric_ext.c: use the reference from mrb structure. 2022-09-12 10:27:29 +09:00
Yukihiro "Matz" Matsumoto f05574606e mruby-numeric-ext: add ceildiv test with Float and Rational. 2022-09-12 10:27:29 +09:00
Yukihiro "Matz" Matsumoto b6d7564846 numeric_ext.rb: add Integer#ceildiv. 2022-09-12 10:27:28 +09:00
Yukihiro "Matz" Matsumoto 8c1b2ee0bb numeric_ext.c (int_powm): avoid integer overflow by modulo first.
We do not fall back to big integer calculation unless absolutely necessary.
2022-08-27 22:18:38 +09:00
Yukihiro "Matz" Matsumoto 5b1e14b96b numeric_ext.c (int_powm): better error message. 2022-08-26 14:27:54 +09:00
Yukihiro "Matz" Matsumoto 6598732892 numeric_ext.c (int_powm): try bigint pow when overflow. 2022-08-26 12:37:54 +09:00
Yukihiro "Matz" Matsumoto d14fd77148 numeric.c (mrb_int_pow): make the function to take 2 operands. 2022-08-12 12:19:21 +09:00
Yukihiro "Matz" Matsumoto 04ec65b87a mruby-numeric-ext/numeric.rb: add reference description.
- zero?
- nonzero?
- positive?
- negative?
2022-07-18 15:46:47 +09:00
Yukihiro "Matz" Matsumoto 56af812b98 mruby-numeric-ext/numeric.rb: bit predicates are implemented in Ruby now. 2022-07-18 12:59:10 +09:00
dearblue cc3a213fef Move bigint implementation files to mruby-bigint
Users can now switch to their own implementation of GEM.
However, we do not guarantee that this will not be a problem in the current situation.
This may need to be improved in the future.
2022-04-23 21:19:12 +09:00
Yukihiro "Matz" Matsumoto dcaf4083d5 src/bigint.c: implement multi-precision integer.
To enable multi-precision integer support, you need to link
`mruby-bigint` mrbgem. The gem itself is empty but it turns on
the "bigint" support.
2022-04-09 17:16:10 +09:00
Yukihiro "Matz" Matsumoto 4dcdf78f8a numeric_ext.c: add Integer#pow() method.
Which takes optional second argument of modulo.
2022-03-17 23:25:50 +09:00