【NumPy C-API】型互換性を判定してスッキリ! `npy_bool PyArray_EquivTypenums()` 関数


  1. 型番号が一致する
    それぞれの配列の dtype.type_num 属性が同じである必要があります。
  2. 型がサブクラスである
    一方の配列の型がもう一方の配列の型のサブクラスである場合、互換性があるとみなされます。

この関数は、以下の引数を取ります。

  • npy_intp typenum2: 2番目の配列の型番号
  • npy_intp typenum1: 最初の配列の型番号

この関数は、以下の値を返します。

  • npy_bool: 2つの型が互換性がある場合は NPY_TRUE、そうでない場合は NPY_FALSE

#include <numpy/ndarray.h>

int main() {
  PyArrayObject *arr1 = PyArray_New(&PyArray_Descr{NPY_INT32}, Py_DIM(1), NULL);
  PyArrayObject *arr2 = PyArray_New(&PyArray_Descr{NPY_INT64}, Py_DIM(1), NULL);

  npy_bool equiv = PyArray_EquivTypenums(arr1->dtype->type_num, arr2->dtype->type_num);
  printf("arr1 と arr2 は互換性がありますか?: %s\n", equiv ? "はい" : "いいえ");

  Py_DECREF(arr1);
  Py_DECREF(arr2);

  return 0;
}

この例では、arr1arr2 という2つの NumPy 配列を作成します。arr1NPY_INT32 型、arr2NPY_INT64 型です。PyArray_EquivTypenums() 関数を使用して、これらの配列の型が互換性があるかどうかを判定します。NPY_INT64 型は NPY_INT32 型のサブクラスであるため、PyArray_EquivTypenums() 関数は NPY_TRUE を返します。

PyArray_EquivTypenums() 関数は、以下の用途で使用できます。

  • 型変換を行う
  • 配列を操作する前に、互換性があることを確認する
  • 2つの NumPy 配列を比較する


型番号の比較

#include <numpy/ndarray.h>

int main() {
  PyArrayObject *arr1 = PyArray_New(&PyArray_Descr{NPY_INT32}, Py_DIM(1), NULL);
  PyArrayObject *arr2 = PyArray_New(&PyArray_Descr{NPY_INT32}, Py_DIM(1), NULL);

  npy_bool equiv = PyArray_EquivTypenums(arr1->dtype->type_num, arr2->dtype->type_num);
  printf("arr1 と arr2 の型番号は一致していますか?: %s\n", equiv ? "はい" : "いいえ");

  Py_DECREF(arr1);
  Py_DECREF(arr2);

  return 0;
}

このコードを実行すると、以下の出力が表示されます。

arr1 と arr2 の型番号は一致していますか?: はい

型の互換性チェック

この例では、PyArray_EquivTypenums() 関数を使用して、2つの NumPy 配列の型が互換性があるかどうかを判定します。

#include <numpy/ndarray.h>

int main() {
  PyArrayObject *arr1 = PyArray_New(&PyArray_Descr{NPY_INT32}, Py_DIM(1), NULL);
  PyArrayObject *arr2 = PyArray_New(&PyArray_Descr{NPY_INT64}, Py_DIM(1), NULL);

  npy_bool equiv = PyArray_EquivTypenums(arr1->dtype->type_num, arr2->dtype->type_num);
  printf("arr1 と arr2 は互換性がありますか?: %s\n", equiv ? "はい" : "いいえ");

  Py_DECREF(arr1);
  Py_DECREF(arr2);

  return 0;
}
arr1 と arr2 は互換性がありますか?: はい

型変換の確認

この例では、PyArray_EquivTypenums() 関数を使用して、NumPy 配列を型変換する前に、元の型と変換後の型が互換性があるかどうかを判定します。

#include <numpy/ndarray.h>

int main() {
  PyArrayObject *arr = PyArray_New(&PyArray_Descr{NPY_INT32}, Py_DIM(1), NULL);

  npy_bool equiv = PyArray_EquivTypenums(arr->dtype->type_num, NPY_FLOAT64);
  if (equiv) {
    PyArray_INCREF(arr);
    PyArray_CastToType(arr, &PyArray_Descr{NPY_FLOAT64}, 0, NULL);
    printf("arr を型変換しました: %s\n", arr->dtype->name);
  } else {
    printf("arr を型変換できません: 型が互換性がありません\n");
  }

  Py_DECREF(arr);

  return 0;
}
arr を型変換しました: float64


型番号の比較

以下のコードは、PyArray_EquivTypenums() 関数と同様に、2つの NumPy 配列の型番号が一致するかどうかを判定します。

#include <numpy/ndarray.h>

int main() {
  PyArrayObject *arr1 = PyArray_New(&PyArray_Descr{NPY_INT32}, Py_DIM(1), NULL);
  PyArrayObject *arr2 = PyArray_New(&PyArray_Descr{NPY_INT32}, Py_DIM(1), NULL);

  if (arr1->dtype->type_num == arr2->dtype->type_num) {
    printf("arr1 と arr2 の型番号は一致しています\n");
  } else {
    printf("arr1 と arr2 の型番号は一致しません\n");
  }

  Py_DECREF(arr1);
  Py_DECREF(arr2);

  return 0;
}

型の比較

#include <numpy/ndarray.h>

int main() {
  PyArrayObject *arr1 = PyArray_New(&PyArray_Descr{NPY_INT32}, Py_DIM(1), NULL);
  PyArrayObject *arr2 = PyArray_New(&PyArray_Descr{NPY_INT64}, Py_DIM(1), NULL);

  if (PyArray_IsSubtype(arr2->dtype, arr1->dtype)) {
    printf("arr1 と arr2 は互換性があります\n");
  } else {
    printf("arr1 と arr2 は互換性がありません\n");
  }

  Py_DECREF(arr1);
  Py_DECREF(arr2);

  return 0;
}

PyArray_CanCastSafely() 関数の使用

PyArray_CanCastSafely() 関数は、NumPy 配列を型変換できるかどうかを判定します。この関数は、PyArray_EquivTypenums() 関数よりも汎用性が高く、型変換後の値の範囲も考慮します。

#include <numpy/ndarray.h>

int main() {
  PyArrayObject *arr = PyArray_New(&PyArray_Descr{NPY_INT32}, Py_DIM(1), NULL);

  if (PyArray_CanCastSafely(arr->dtype, NPY_FLOAT64)) {
    PyArray_INCREF(arr);
    PyArray_CastToType(arr, &PyArray_Descr{NPY_FLOAT64}, 0, NULL);
    printf("arr を型変換しました: %s\n", arr->dtype->name);
  } else {
    printf("arr を型変換できません: 型変換が安全ではありません\n");
  }

  Py_DECREF(arr);

  return 0;
}

これらの方法は、PyArray_EquivTypenums() 関数の機能を代替するだけでなく、より汎用性が高かったり、型変換後の値の範囲を考慮したりするなどの利点があります。

  • 上記の方法はあくまでも代替方法であり、状況に応じて適切な方法を選択する必要があります。