NumPy C-APIにおけるint identityの役割と使い方を徹底解説!


整数型データの識別子

NumPy C-API では、様々な整数型データを扱うために、それぞれに対応する整数識別子が定義されています。例えば、以下のようなものがあります。

  • NPY_UINT64: 64ビット符号なし整数
  • NPY_UINT32: 32ビット符号なし整数
  • NPY_UINT16: 16ビット符号なし整数
  • NPY_UINT8: 8ビット符号なし整数
  • NPY_INT64: 64ビット符号付き整数
  • NPY_INT32: 32ビット符号付き整数
  • NPY_INT16: 16ビット符号付き整数
  • NPY_INT8: 8ビット符号付き整数

これらの整数識別子は、npy_int 型の変数に格納されます。npy_int 型は、NumPy C-API で定義されている整数型データを表す型です。

配列の次元数

NumPy C-API では、配列の次元数を表すために int 型の変数が使用されます。例えば、3次元配列の場合は、int 型の変数に 3 を格納します。

例:整数型データの識別子

#include <numpy/ndarray.h>

int main() {
  npy_int dtype = NPY_INT32;

  // 32ビット符号付き整数を表す `npy_int` 型変数を作成
  npy_int value = 10;

  // `dtype` に対応する NumPy データ型を取得
  PyArray_Descr *descr = PyArray_DescrFromType(dtype);

  // `value` の値を `descr` のデータ型に変換
  void *ptr = PyArray_Scalar_FromInt(value, descr);

  // ...

  // メモリ解放
  PyArray_Scalar_DECREF(ptr);
  PyArray_Descr_DecRef(descr);

  return 0;
}
#include <numpy/ndarray.h>

int main() {
  // 3次元配列を作成
  npy_int ndims = 3;
  npy_int shape[ndims] = {2, 3, 4};

  // 3次元配列を作成
  PyArrayObject *arr = PyArray_SimpleNew(ndims, shape, NPY_INT32);

  // ...

  // メモリ解放
  PyArray_DECREF(arr);

  return 0;
}


整数型データの識別

この例では、int identity を用いて、32ビット符号付き整数データの識別子を取得し、その値を使用して NumPy 配列を作成します。

#include <numpy/ndarray.h>

int main() {
  // 32ビット符号付き整数の識別子を取得
  npy_int dtype = NPY_INT32;

  // 32ビット符号付き整数の値を格納する変数
  int value = 10;

  // `dtype` に対応する NumPy データ型を取得
  PyArray_Descr *descr = PyArray_DescrFromType(dtype);

  // `value` の値を `descr` のデータ型に変換
  void *ptr = PyArray_Scalar_FromInt(value, descr);

  // 1要素の NumPy 配列を作成
  npy_int ndims = 1;
  npy_int shape[ndims] = {1};
  PyArrayObject *arr = PyArray_NewFromScalar(ptr, ndims, shape, descr, NPY_ORDER_C);

  // 配列の内容を出力
  printf("Array data: %d\n", *(int *)PyArray_DATA(arr));

  // メモリ解放
  PyArray_Scalar_DECREF(ptr);
  PyArray_Descr_DecRef(descr);
  PyArray_DECREF(arr);

  return 0;
}

配列の次元数

この例では、int identity を用いて、3次元 NumPy 配列の次元数を設定し、その配列に要素を代入します。

#include <numpy/ndarray.h>

int main() {
  // 3次元配列の次元数
  npy_int ndims = 3;

  // 各次元の要素数を格納する配列
  npy_int shape[ndims] = {2, 3, 4};

  // 3次元 NumPy 配列を作成
  PyArrayObject *arr = PyArray_SimpleNew(ndims, shape, NPY_INT32);

  // 配列要素へのアクセス
  for (int i = 0; i < ndims; i++) {
    for (int j = 0; j < shape[i]; j++) {
      for (int k = 0; k < shape[i]; k++) {
        PyArray_SET_ITEM(arr, i, j, k, (int)(i * shape[i] * shape[i] + j * shape[i] + k));
      }
    }
  }

  // 配列の内容を出力
  for (int i = 0; i < ndims; i++) {
    for (int j = 0; j < shape[i]; j++) {
      for (int k = 0; k < shape[i]; k++) {
        printf("arr[%d, %d, %d]: %d\n", i, j, k, PyArray_GET_ITEM(arr, i, j, k));
      }
    }
  }

  // メモリ解放
  PyArray_DECREF(arr);

  return 0;
}


  1. 整数型データの識別子
  2. 配列の次元数

これらの概念を表現するには、"int identity" 以外にも様々な方法があります。以下では、それぞれの代替方法について詳しく説明します。

整数型データの識別子

"int identity" の代替方法として、以下の方法が考えられます。

  • 文字列による識別子: NumPy C-API では、各整数型データに対応する文字列識別子が定義されています。例えば、以下のようなものがあります。
    • "NPY_INT8": 8ビット符号付き整数
    • "NPY_INT16": 16ビット符号付き整数
    • "NPY_INT32": 32ビット符号付き整数
    • "NPY_INT64": 64ビット符号付き整数
    • "NPY_UINT8": 8ビット符号なし整数
    • "NPY_UINT16": 16ビット符号なし整数
    • "NPY_UINT32": 32ビット符号なし整数
    • "NPY_UINT64": 64ビット符号なし整数

これらの文字列識別子は、PyArray_DescrFromType 関数で使用することができます。

#include <numpy/ndarray.h>

int main() {
  // 文字列識別子を使用して 32ビット符号付き整数の NumPy データ型を取得
  PyArray_Descr *descr = PyArray_DescrFromType("NPY_INT32");

  // ...

  // メモリ解放
  PyArray_Descr_DecRef(descr);

  return 0;
}
  • PyArray_Descr 構造体: NumPy C-API では、各整数型データに対応する PyArray_Descr 構造体が定義されています。この構造体には、データ型に関する様々な情報が含まれています。例えば、以下のような情報が含まれています。
    • typecode: 整数型データの識別子を表す文字列
    • type: 整数型データの型
    • itemsize: データ型の要素サイズ
    • byteorder: バイトオーダー

PyArray_DescrFromType 関数に加えて、PyArray_DescrNew 関数を使用して PyArray_Descr 構造体を直接作成することもできます。

#include <numpy/ndarray.h>

int main() {
  // `PyArray_Descr` 構造体を直接作成
  PyArray_Descr *descr = PyArray_DescrNew(NPY_INT32);

  // ...

  // メモリ解放
  PyArray_Descr_DecRef(descr);

  return 0;
}

配列の次元数

  • 配列次元数の配列: 配列の次元数を表すために、npy_int 型の変数の配列を使用することができます。
#include <numpy/ndarray.h>

int main() {
  // 3次元配列の次元数を表す配列
  npy_int ndims = 3;
  npy_int shape[ndims] = {2, 3, 4};

  // ...

  // メモリ解放
  PyArray_DECREF(arr);

  return 0;
}
  • PyArray_Dims 構造体: NumPy C-API では、配列の次元数を表す PyArray_Dims 構造体が定義されています。この構造体には、以下の情報が含まれています。
    • ndims: 配列の次元数
    • shape: 各次元の要素数を格納する配列
    • strides: 各次元のストライド

PyArray_SimpleNew 関数に加えて、PyArray_NewFromDims 関数を使用して PyArray_Dims 構造体を直接作成することもできます。

#include <numpy/ndarray.h>

int main() {
  // `PyArray_Dims` 構造体を直接作成
  PyArray_Dims dims = {3, {2, 3, 4}};

  // ...

  // メモリ解放
  PyArray_DECREF(arr);

  return 0;
}