From 8f0dba2985f0872e4c0c980c994d886d2cdacf94 Mon Sep 17 00:00:00 2001 From: dearblue Date: Mon, 10 Oct 2022 14:12:53 +0900 Subject: [PATCH] Add `examples/mrbgems/mruby-YOUR-bigint` --- .../mrbgems/mruby-YOUR-bigint/TODO-HINT.md | 39 +++++++++++ .../mrbgems/mruby-YOUR-bigint/core/bigint.c | 70 +++++++++++++++++++ .../mrbgems/mruby-YOUR-bigint/mrbgem.rake | 12 ++++ mrbgems/mruby-bigint/README.md | 2 + 4 files changed, 123 insertions(+) create mode 100644 examples/mrbgems/mruby-YOUR-bigint/TODO-HINT.md create mode 100644 examples/mrbgems/mruby-YOUR-bigint/core/bigint.c create mode 100644 examples/mrbgems/mruby-YOUR-bigint/mrbgem.rake diff --git a/examples/mrbgems/mruby-YOUR-bigint/TODO-HINT.md b/examples/mrbgems/mruby-YOUR-bigint/TODO-HINT.md new file mode 100644 index 000000000..7d1014254 --- /dev/null +++ b/examples/mrbgems/mruby-YOUR-bigint/TODO-HINT.md @@ -0,0 +1,39 @@ +# Hints for creating your own bigint GEM + +This example gem, mruby-YOUR-bigint, is available under the Creative Commons Zero License (CC0). + +This file is placed for the purpose of describing hints for creating a `mruby-bigint` compatible GEM to realize multiple integers. + +The file structure in this example is as follows: + +``` ++- mruby-YOUR-bigint/ <- Make this directory public if necessary. + | Change the name of copied directory. + | + +- TODO-HINT.md <- This file is currently viewing by you. + | Remove this from copied directory. + | + +- core/ + | | + | +- bigint.c <- Body of the implementation. + | + +- mrbgem.rake <- GEM name is "mruby-bigint". + May be depended on by other GEMs. +``` + +Implementors of own bigints should copy below this directory to another directory and do the following: + +* Rewrite `spec.author`, `spec.license`, `spec.homepage` and `spec.summary` in `/mrbgem.rake` file to those of your own implementors. +* Implement the respective functions in `/core/bigint.c`. + * Define and use an object structure for `MRB_TT_BIGINT` type-tag. + It is recommended to use `mrb_static_assert_object_size()` to ensure that the size of the object structure is within 6 words. +* Delete this file from the destination of the copy. + +If you wish to use it as an alternative to the `mruby-bigint` provided by mruby, please leave the GEM name in `/mrbgem.rake` as it is. +This is an important factor when it is depended from other GEMs with `spec.add_dependency 'mruby-bigint'`. + +The name of the top directory of GEM can be changed arbitrarily. +The name of the git repository can also be changed arbitrarily. + +Note that there is no need for an initialization function as there is in normal GEM. +If you need it, create a file `/src/bigint.c` for example, and implement the `mrb_mruby_bigint_gem_init()` function. diff --git a/examples/mrbgems/mruby-YOUR-bigint/core/bigint.c b/examples/mrbgems/mruby-YOUR-bigint/core/bigint.c new file mode 100644 index 000000000..3cfc717b0 --- /dev/null +++ b/examples/mrbgems/mruby-YOUR-bigint/core/bigint.c @@ -0,0 +1,70 @@ +/* + * If placed under the "mruby/examples/mrbgems/mruby-YOUR-bigint" directory, + * this file is available under the Creative Commons Zero License (CC0). + * Note that file is incomplete. + * + * TODO: If this file is copied and another implementation is written, + * remove this comment block from the copied file. + */ + +#include +#include + +/* + * The "mruby/internal.h" file should be placed after the other mruby header files. + */ +#include + +/* + * The "mruby/presym.h" file is placed at the end of the mruby header file. + */ +#include + +/* + * Define your own struct RBigint. + * + * - Object type must be MRB_TT_BIGINT. + * - If the structure is named RBigint, MRB_OBJ_ALLOC() can be used as is. + */ +struct RBigint { + /* + * Put MRB_OBJECT_HEADER before the first member of the structure. + */ + MRB_OBJECT_HEADER; + + /* + * Up to 3 words can be freely configured. + */ + size_t len; + size_t capa; + uintptr_t *num; +}; + +/* + * Assert with mrb_static_assert_object_size() that the entire structure is within 6 words. + */ +mrb_static_assert_object_size(struct RBigint); + +/* + * The lower 16 bits of the object flags (`obj->flags`) can be used freely by the GEM author. + */ +#define MY_BIGINT_NEGATIVE_FLAG 1 +#define MY_BIGINT_NEGATIVE_P(obj) ((obj)->flags & MY_BIGINT_NEGATIVE_FLAG) + +/* + * Implement the functions declared in `#ifdef MRUBY_USE_BIGINT ... #endif` in the "mruby/internal.h" file. + */ + +mrb_value +mrb_bint_new_int(mrb_state *mrb, mrb_int x) +{ + struct RBigint *obj = MRB_OBJ_ALLOC(mrb, MRB_TT_BIGINT, mrb->integer_class); + + ... + + return mrb_obj_value(obj); +} + +/* + * The implementation function continues... + */ diff --git a/examples/mrbgems/mruby-YOUR-bigint/mrbgem.rake b/examples/mrbgems/mruby-YOUR-bigint/mrbgem.rake new file mode 100644 index 000000000..9695a3f83 --- /dev/null +++ b/examples/mrbgems/mruby-YOUR-bigint/mrbgem.rake @@ -0,0 +1,12 @@ +MRuby::Gem::Specification.new('mruby-bigint') do |spec| + spec.author = 'YOUR-NAME-HERE' + spec.license = 'YOUR-LICENSE-HERE' + spec.summary = 'Yet another multi-precision Integer extension' + spec.homepage = 'https://gem.example/for/mruby-YOUR-bigint' + spec.build.defines << 'MRB_USE_BIGINT' + #spec.build.linker.libraries << 'gmp' # when uses libgmp + + spec.build.libmruby_core_objs << Dir.glob(File.join(__dir__, 'core/**/*.c')).map { |fn| + objfile(fn.relative_path_from(__dir__).pathmap("#{spec.build_dir}/%X")) + } +end diff --git a/mrbgems/mruby-bigint/README.md b/mrbgems/mruby-bigint/README.md index 3b1e1d910..5a5316bbd 100644 --- a/mrbgems/mruby-bigint/README.md +++ b/mrbgems/mruby-bigint/README.md @@ -3,3 +3,5 @@ This extension uses fgmp, which is a public domain implementation of a subset of the GNU gmp library by Mark Henderson . But it's heavily modified to fit with mruby. You can get the original source code from . You can read the original README for fgmp in [README-fgmp.md](README-fgmp.md). + +If you want to create your own Multi-precision Integer GEM, see [examples/mrbgems/mruby-YOUR-bigint/TODO-HINT.md](../../examples/mrbgems/mruby-YOUR-bigint/TODO-HINT.md).