Skip to content

Updated Japanese API documentation #236

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
248 changes: 144 additions & 104 deletions doc/api.ja.md
Original file line number Diff line number Diff line change
@@ -1,105 +1,133 @@
# API of Next NArray

under development

## NArray演算の仕様

### NArray Types
#define NARRAY_DATA_T 0x1 // データを保持する。contiguousアクセスのみ可能。
#define NARRAY_VIEW_T 0x2 // データを保持しない。他のNArrayを参照。stride/index アクセスが可能
#define NARRAY_FILEMAP_T 0x3 // ファイルマップ(TBI)

NArrayの型は、以下の3つのタイプに分類される。

```c
#define NARRAY_DATA_T 0x1 // データを保持する。contiguousアクセスのみ可能。
#define NARRAY_VIEW_T 0x2 // データを保持しない。他のNArrayを参照。stride/index アクセスが可能
#define NARRAY_FILEMAP_T 0x3 // ファイルマップ(TBI)
```

### Loop Rule
method( a[nz,1,nz], b[nz,ny,1] ) => c[nz,ny,nx]

NArrayの演算は、以下のルールに従って行われる。

```text
method( a[nz,1,nz], b[nz,ny,1] ) => c[nz,ny,nx]
```

* サイズ1の次元は、1エレメントを繰り返し参照される。外積のようなもの
* すべての演算・メソッドについて同様のルールが適用

### Inplace
a.inplace + b => a に結果が保存される

## NArrayメソッド定義の例
NArrayの演算は通常、新しい配列を生成する。`inplace`メソッドを使うと、元の配列に直接結果を保存する。

単純なループ演算を行うイテレータ関数を定義し、
ndfunc_alloc関数で ndfunc_t構造体に登録し、
ndfunc_do関数で多次元ループ処理を行う。
配列のキャスト、出力配列の準備、および多次元ループ処理については、内部で自動的に行う。
```ruby
a.inplace + b # => a に結果が保存される
```

#define cT numo_cDFloat
// 最も内側のループごとに呼ばれるイテレータ関数
static void
iter_dfloat_add(na_loop_t *const lp)
{
size_t n = lp->n[0];
double *a = (double*)(lp->args[0].ptr + lp->args[0].iter[0].pos);
double *b = (double*)(lp->args[1].ptr + lp->args[1].iter[0].pos);
double *c = (double*)(lp->args[2].ptr + lp->args[2].iter[0].pos);
size_t i;

for (i=0; i<n; i++) {
c[i] = a[i] + b[i];
}
}
## NArrayメソッド定義の例

// Rubyメソッドに対応するC関数を定義
static VALUE
nary_dfloat_add_self(VALUE self, VALUE other)
{
ndfunc_arg_in_t ain[2] = {{cT,0},{cT,0}};
ndfunc_arg_out_t aout[1] = {{cT,0}};
ndfunc_t ndf = { iter_dfloat_add, STRIDE_LOOP, 2, 1, ain, aout };
ここでは、NArrayのメソッド `+` を定義する例を示す。

return na_ndloop(&ndf, 2, self, other);
}
単純なループ演算を行うイテレータ関数 `iter_dfloat_add` を定義し、
ループの仕様を記録するための `ndfunc_t` 構造体を定義する。
`na_ndloop` 関数で多次元ループ処理を行う。
配列のキャスト、出力配列の準備、および多次元ループ処理については、内部で自動的に行う。

static VALUE
nary_dfloat_add(VALUE self, VALUE other)
{
VALUE klass, v;
klass = na_upcast(CLASS_OF(self),CLASS_OF(other));
if (klass==cT) {
return nary_dfloat_add_self(self, other);
} else {
v = rb_funcall(klass, id_cast, 1, self);
return rb_funcall(v, '+', 1, other);
}
```c
#define cT numo_cDFloat
// 最も内側のループごとに呼ばれるイテレータ関数
static void
iter_dfloat_add(na_loop_t *const lp)
{
size_t n = lp->n[0];
double *a = (double*)(lp->args[0].ptr + lp->args[0].iter[0].pos);
double *b = (double*)(lp->args[1].ptr + lp->args[1].iter[0].pos);
double *c = (double*)(lp->args[2].ptr + lp->args[2].iter[0].pos);
size_t i;

for (i=0; i<n; i++) {
c[i] = a[i] + b[i];
}

// RubyメソッドをC関数として定義
void
Init_nary_dfloat()
{
rb_define_method(cT, "+", nary_dfloat_add, 1);
}

// Rubyメソッドに対応するC関数を定義
static VALUE
nary_dfloat_add_self(VALUE self, VALUE other)
{
ndfunc_arg_in_t ain[2] = {{cT,0},{cT,0}};
ndfunc_arg_out_t aout[1] = {{cT,0}};
ndfunc_t ndf = { iter_dfloat_add, STRIDE_LOOP, 2, 1, ain, aout };

return na_ndloop(&ndf, 2, self, other);
}

// ほかのNArray型との演算を行うためのキャストと演算を行う関数
static VALUE
nary_dfloat_add(VALUE self, VALUE other)
{
VALUE klass, v;
klass = na_upcast(CLASS_OF(self),CLASS_OF(other));
if (klass==cT) {
return nary_dfloat_add_self(self, other);
} else {
v = rb_funcall(klass, id_cast, 1, self);
return rb_funcall(v, '+', 1, other);
}
}

// RubyメソッドをC関数として定義
void
Init_nary_dfloat()
{
rb_define_method(cT, "+", nary_dfloat_add, 1);
}
```

## 関数説明

### ndfunc_t 構造体

ループのスペックを記録する構造体。na_ndloop 関数に渡す。
ループのスペックを記録する構造体。`na_ndloop` 関数に渡す。
malloc で確保すると例外が起きると回収されないので、スタックで確保する。

typedef struct NDFUNCTION {
na_iter_func_t func; // user function
unsigned int flag; // what kind of loop user function supports
int nin; // # of arguments
int nout; // # of results
ndfunc_arg_in_t *ain; // spec of input arguments
ndfunc_arg_out_t *aout; // spec of output result
} ndfunc_t;
```c
typedef struct NDFUNCTION {
na_iter_func_t func; // user function
unsigned int flag; // what kind of loop user function supports
int nin; // # of arguments
int nout; // # of results
ndfunc_arg_in_t *ain; // spec of input arguments
ndfunc_arg_out_t *aout; // spec of output result
} ndfunc_t;
```

* func: イテレータ関数
* flag: イテレータのタイプをフラグで指定

#define NDF_HAS_LOOP (1<<0) // x[i]
#define NDF_STRIDE_LOOP (1<<1) // *(x+stride*i)
#define NDF_INDEX_LOOP (1<<2) // *(x+idx[i])
#define NDF_KEEP_DIM (1<<3)
#define NDF_INPLACE (1<<4)
#define NDF_ACCEPT_BYTESWAP (1<<5)
```c
#define NDF_HAS_LOOP (1<<0) // x[i]
#define NDF_STRIDE_LOOP (1<<1) // *(x+stride*i)
#define NDF_INDEX_LOOP (1<<2) // *(x+idx[i])
#define NDF_KEEP_DIM (1<<3)
#define NDF_INPLACE (1<<4)
#define NDF_ACCEPT_BYTESWAP (1<<5)
```

* flagの複合例(他にもあり。詳細は ndloop.h を参照):

/* example */ #define FULL_LOOP_NIP (NDF_HAS_LOOP|NDF_STRIDE_LOOP|NDF_INDEX_LOOP)
```c
/* example */
#define FULL_LOOP_NIP (NDF_HAS_LOOP|NDF_STRIDE_LOOP|NDF_INDEX_LOOP)
```

* nin: 引数として渡す入力NArrayの数
* nout: 結果として戻る出力NArrayの数
Expand All @@ -108,10 +136,12 @@ malloc で確保すると例外が起きると回収されないので、スタ

入力引数の引数のタイプとユーザ次元を指定する。

typedef struct NDF_ARG_IN {
VALUE type; // argument types
int dim; // # of dimension of argument handled by user function
} ndfunc_arg_in_t;
```c
typedef struct NDF_ARG_IN {
VALUE type; // argument types
int dim; // # of dimension of argument handled by user function
} ndfunc_arg_in_t;
```

* type が Qnil のとき、キャストは行われない。
* type が NArray型クラスのとき、その型へキャストが行われる。
Expand All @@ -125,58 +155,68 @@ malloc で確保すると例外が起きると回収されないので、スタ

結果をストアするnarrayのタイプとユーザ次元を指定する。

```c
typedef struct NDF_ARG_OUT {
VALUE type; // argument types
int dim; // # of dimension of argument handled by user function
size_t *shape;
} ndfunc_arg_out_t;
```

* type が i (Fixnum) のとき、入力引数のi番目の型を使用する。

* イテレータ関数がループをサポートする場合、次のいずれかの方法で指示。
* flag にループ可能であることを指定。
* dim を 1 以上にセットする。さらに出力配列の場合は shape に配列サイズをセットする。

### na_ndloop関数
### na_ndloop 関数

多次元ループのメイン処理を行う。イテレータ関数を呼んで多次元ループを行う。

VALUE na_ndloop(ndfunc_t *nf, int argc, ...)
VALUE na_ndloop2(ndfunc_t *nf, VALUE args)
VALUE na_ndloop3(ndfunc_t *nf, void *opt_ptr, int argc, ...)
VALUE na_ndloop4(ndfunc_t *nf, void *opt_ptr, VALUE args)
```c
VALUE na_ndloop(ndfunc_t *nf, int argc, ...)
VALUE na_ndloop2(ndfunc_t *nf, VALUE args)
VALUE na_ndloop3(ndfunc_t *nf, void *opt_ptr, int argc, ...)
VALUE na_ndloop4(ndfunc_t *nf, void *opt_ptr, VALUE args)
```

* 戻り値は、ndfunc_t 構造体で指定した戻り値を返す
* 戻り値は、`ndfunc_t` 構造体で指定した戻り値を返す

### イテレータ関数
配列情報を格納した na_loop_t 構造体へのポインタが引数として渡される。

例: iter_dfloat_add(na_loop_t *const lp)
配列情報を格納した `na_loop_t` 構造体へのポインタが引数として渡される。

```c
iter_dfloat_add(na_loop_t *const lp)
```

### na_loop_t 構造体
引数の配列と、配列へのアクセス方法の情報を格納する。

typedef struct NA_LOOP {
int narg;
int ndim; // n of user dimension
size_t *n; // n of elements for each dim
na_loop_args_t *args; // for each arg
VALUE option;
void *opt_ptr;
VALUE err_type;//* ??? これは非公開? ???
} na_loop_t;

typedef struct NA_LOOP_ARGS {
VALUE value;
ssize_t elmsz;
char *ptr;
int ndim; // required for each argument.
size_t *shape;
na_loop_iter_t *iter; (moved from na_loop_t)
} na_loop_args_t;

typedef struct NA_LOOP_ITER {
ssize_t pos; // - required for each dimension.
ssize_t step;
size_t *idx;
} na_loop_iter_t;
引数の配列と、配列へのアクセス方法の情報を格納する。

```c
typedef struct NA_LOOP {
int narg;
int ndim; // n of user dimension
size_t *n; // n of elements for each dim
na_loop_args_t *args; // for each arg
VALUE option;
void *opt_ptr;
VALUE err_type;//* ??? これは非公開? ???
} na_loop_t;

typedef struct NA_LOOP_ARGS {
VALUE value;
ssize_t elmsz;
char *ptr;
int ndim; // required for each argument.
size_t *shape;
na_loop_iter_t *iter; // (moved from na_loop_t)
} na_loop_args_t;

typedef struct NA_LOOP_ITER {
ssize_t pos; // - required for each dimension.
ssize_t step;
size_t *idx;
} na_loop_iter_t;
```