0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Python/C APIを読む その5(数値型プロトコル)

Posted at

#概要
Pythonの構造を理解する助けとして、C APIのドキュメントを読み砕いていく。

#内容
##環境
Python 3.9 (CPython)に話を固定したいが、必ずしもそうはならない。
tree (コミット; ブランチ)
(↑ githubのリンク)

##int PyNumber_Check(PyObject *o)
###<概説>
oがインデックス整数だった場合、1を返す。
###<定義>

定義 (cpython/Objects/abstract.c)
int
PyNumber_Check(PyObject *o)
{
    if (o == NULL)
        return 0;
    PyNumberMethods *nb = Py_TYPE(o)->tp_as_number;
    return nb && (nb->nb_index || nb->nb_int || nb->nb_float || PyComplex_Check(o));
}

(定義出典)

###<使用例>

使用例 (cpython/Objects/bytesobject.c)
    if (PyNumber_Check(v)) {

(使用例出典)

##PyObject* PyNumber_Add(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1o2を加算した結果を返し、失敗するとNULLを返す。
Pythonの式o1 + o2と同じ。
###<定義>

定義 (cpython/Objects/abstract.c)
PyObject *
PyNumber_Add(PyObject *v, PyObject *w)
{
    PyObject *result = BINARY_OP1(v, w, NB_SLOT(nb_add), "+");
    if (result != Py_NotImplemented) {
        return result;
    }
    Py_DECREF(result);

    PySequenceMethods *m = Py_TYPE(v)->tp_as_sequence;
    if (m && m->sq_concat) {
        result = (*m->sq_concat)(v, w);
        assert(_Py_CheckSlotResult(v, "+", result != NULL));
        return result;
    }

    return binop_type_error(v, w, "+");
}

(定義出典)

###<使用例>

使用例 (cpython/Objects/sliceobject.c)
        upper = PyNumber_Add(length, lower);

(使用例出典)

##PyObject* PyNumber_Subtract(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1からo2を減算した結果を返し、失敗するとNULLを返す。
Python の式o1 - o2と同じ。
###<定義>

定義 (cpython/Objects/abstract.c)
BINARY_FUNC(PyNumber_Subtract, nb_subtract, "-")

(定義出典)

###<定義補足>

BINARY_FUNC (cpython/Objects/abstract.c)
#define BINARY_FUNC(func, op, op_name) \
    PyObject * \
    func(PyObject *v, PyObject *w) { \
        return binary_op(v, w, NB_SLOT(op), op_name); \
    }
binary_op (cpython/Objects/abstract.c)
static PyObject *
binary_op(PyObject *v, PyObject *w, const int op_slot, const char *op_name)
{
    PyObject *result = BINARY_OP1(v, w, op_slot, op_name);
 ...
    return result;
}
BINARY_OP1 (cpython/Objects/abstract.c)
#  define BINARY_OP1(v, w, op_slot, op_name) binary_op1(v, w, op_slot)
binary_op1 (cpython/Objects/abstract.c)
static PyObject *
binary_op1(PyObject *v, PyObject *w, const int op_slot
           )
{
...
        slotv = NB_BINOP(Py_TYPE(v)->tp_as_number, op_slot);
...
        x = slotv(v, w);
        assert(_Py_CheckSlotResult(v, op_name, x != NULL));
        if (x != Py_NotImplemented) {
            return x;
        }
...
}

大筋を変えない程度に改変。

###<使用例>

使用例 (cpython/Python/ast_opt.c)
        newval = PyNumber_Subtract(lv, rv);

(使用例出典)

##PyObject* PyNumber_Multiply(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1o2を乗算した結果を返し、失敗するとNULLを返す。
Pythonの式o1 * o2と同じ。
###<定義>

定義 (cpython/Objects/abstract.c)
PyObject *
PyNumber_Multiply(PyObject *v, PyObject *w)
{
    PyObject *result = BINARY_OP1(v, w, NB_SLOT(nb_multiply), "*");
    if (result == Py_NotImplemented) {
        PySequenceMethods *mv = Py_TYPE(v)->tp_as_sequence;
        PySequenceMethods *mw = Py_TYPE(w)->tp_as_sequence;
        Py_DECREF(result);
        if  (mv && mv->sq_repeat) {
            return sequence_repeat(mv->sq_repeat, v, w);
        }
        else if (mw && mw->sq_repeat) {
            return sequence_repeat(mw->sq_repeat, w, v);
        }
        result = binop_type_error(v, w, "*");
    }
    return result;
}

(定義出典)

###<使用例>

使用例 (cpython/Python/ast_opt.c)
    return PyNumber_Multiply(v, w);

(使用例出典)

##PyObject* PyNumber_MatrixMultiply(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1o2を行列乗算した結果を返し、失敗するとNULLを返す。
Pythonの式o1 @ o2と同じ。
###<定義>

定義 (cpython/Objects/abstract.c)
PyObject *
PyNumber_MatrixMultiply(PyObject *v, PyObject *w)
{
    return binary_op(v, w, NB_SLOT(nb_matrix_multiply), "@");
}

(定義出典)

###<使用例>

使用例 (cpython/Python/ceval.c)
        case TARGET(BINARY_MATRIX_MULTIPLY): {
            PyObject *right = POP();
            PyObject *left = TOP();
            PyObject *res = PyNumber_MatrixMultiply(left, right);
            Py_DECREF(left);
            Py_DECREF(right);
            SET_TOP(res);
            if (res == NULL)
                goto error;
            DISPATCH();
        }

(使用例出典)

##PyObject* PyNumber_FloorDivide(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1o2で除算した切捨て値を返し、失敗するとNULLを返す。
"旧仕様の" 整数間での除算と同じ。
###<定義>

定義 (cpython/Objects/abstract.c)
PyObject *
PyNumber_FloorDivide(PyObject *v, PyObject *w)
{
    return binary_op(v, w, NB_SLOT(nb_floor_divide), "//");
}

(定義出典)

###<使用例>

使用例 (cpython/Python/ceval.c)
        case TARGET(BINARY_FLOOR_DIVIDE): {
            PyObject *divisor = POP();
            PyObject *dividend = TOP();
            PyObject *quotient = PyNumber_FloorDivide(dividend, divisor);
            Py_DECREF(dividend);
            Py_DECREF(divisor);
            SET_TOP(quotient);
            if (quotient == NULL)
                goto error;
            DISPATCH();
        }

(使用例出典)

##PyObject* PyNumber_TrueDivide(PyObject *o1, PyObject *o2)
###<概説>
成功すると、数学的なo1o2による除算値に対する妥当な近似(reasonable approximation)を返し、失敗するとNULLを返す。
全ての実数を2を基数として表現するのは不可能なため、二進の浮動小数点数は "近似値" しか表現できず、戻り値も近似になる。
この関数に二つの整数を渡した際、浮動小数点の値を返すことがある。
###<定義>

定義 (cpython/Objects/abstract.c)
PyObject *
PyNumber_TrueDivide(PyObject *v, PyObject *w)
{
    return binary_op(v, w, NB_SLOT(nb_true_divide), "/");
}

(定義出典)

###<使用例>

使用例 (cpython/Python/ceval.c)
        case TARGET(BINARY_TRUE_DIVIDE): {
            PyObject *divisor = POP();
            PyObject *dividend = TOP();
            PyObject *quotient = PyNumber_TrueDivide(dividend, divisor);
            Py_DECREF(dividend);
            Py_DECREF(divisor);
            SET_TOP(quotient);
            if (quotient == NULL)
                goto error;
            DISPATCH();
        }

(使用例出典)

##PyObject* PyNumber_Remainder(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1o2で除算した剰余を返し、失敗するとNULLを返す。
Pythonの式o1 % o2と同じ。
###<定義>

定義 (cpython/Objects/abstract.c)
PyObject *
PyNumber_Remainder(PyObject *v, PyObject *w)
{
    return binary_op(v, w, NB_SLOT(nb_remainder), "%");
}

(定義出典)

###<使用例>

使用例 (cpython/Python/ceval.c)
        case TARGET(BINARY_MODULO): {
            PyObject *divisor = POP();
            PyObject *dividend = TOP();
            PyObject *res;
            if (PyUnicode_CheckExact(dividend) && (
                  !PyUnicode_Check(divisor) || PyUnicode_CheckExact(divisor))) {
              // fast path; string formatting, but not if the RHS is a str subclass
              // (see issue28598)
              res = PyUnicode_Format(dividend, divisor);
            } else {
              res = PyNumber_Remainder(dividend, divisor);
            }
            Py_DECREF(divisor);
            Py_DECREF(dividend);
            SET_TOP(res);
            if (res == NULL)
                goto error;
            DISPATCH();
        }

(使用例出典)

##PyObject* PyNumber_Divmod(PyObject *o1, PyObject *o2)
###<概説>
組み込み関数divmod()を参照。失敗するとNULLを返す。
Pythonの式divmod(o1, o2)と同じ。
###<定義>

定義 (cpython/Objects/abstract.c)
BINARY_FUNC(PyNumber_Divmod, nb_divmod, "divmod()")

(定義出典)

###<使用例>

使用例 (cpython/Modules/_datetimemodule.c)
    PyObject *result = PyNumber_Divmod(a, b);

(使用例出典)

##PyObject* PyNumber_Power(PyObject *o1, PyObject *o2, PyObject *o3)
###<概説>
組み込み関数pow()を参照。失敗するとNULLを返す。
Python の式pow(o1, o2, o3)と同じ。o3はオプションo3を無視させたいなら、Py_Noneを入れる
###<定義>

定義 (cpython/Objects/abstract.c)
PyObject *
PyNumber_Power(PyObject *v, PyObject *w, PyObject *z)
{
    return ternary_op(v, w, z, NB_SLOT(nb_power), "** or pow()");
}

(定義出典)

###<使用例>

使用例 (cpython/Python/ceval.c)
        case TARGET(BINARY_POWER): {
            PyObject *exp = POP();
            PyObject *base = TOP();
            PyObject *res = PyNumber_Power(base, exp, Py_None);
            Py_DECREF(base);
            Py_DECREF(exp);
            SET_TOP(res);
            if (res == NULL)
                goto error;
            DISPATCH();
        }

(使用例出典)

##PyObject* PyNumber_Negative(PyObject *o)
###<概説>
成功するとoの符号反転を返し、失敗するとNULLを返す。Pythonの式-oと同じ。
###<定義>

定義 (cpython/Objects/abstract.c)
PyObject *
PyNumber_Negative(PyObject *o)
{
    if (o == NULL) {
        return null_error();
    }

    PyNumberMethods *m = Py_TYPE(o)->tp_as_number;
    if (m && m->nb_negative) {
        PyObject *res = (*m->nb_negative)(o);
        assert(_Py_CheckSlotResult(o, "__neg__", res != NULL));
        return res;
    }

    return type_error("bad operand type for unary -: '%.200s'", o);
}

(定義出典)

###<使用例>

使用例 (cpython/Python/ceval.c)
        case TARGET(UNARY_NEGATIVE): {
            PyObject *value = TOP();
            PyObject *res = PyNumber_Negative(value);
            Py_DECREF(value);
            SET_TOP(res);
            if (res == NULL)
                goto error;
            DISPATCH();
        }

(使用例出典)

##PyObject* PyNumber_Positive(PyObject *o)
###<概説>
成功するとoを返し、失敗するとNULLを返す。Pythonの式+oと同じ。
###<定義>

定義 (cpython/Objects/abstract.c)
PyObject *
PyNumber_Positive(PyObject *o)
{
    if (o == NULL) {
        return null_error();
    }

    PyNumberMethods *m = Py_TYPE(o)->tp_as_number;
    if (m && m->nb_positive) {
        PyObject *res = (*m->nb_positive)(o);
        assert(_Py_CheckSlotResult(o, "__pos__", res != NULL));
        return res;
    }

    return type_error("bad operand type for unary +: '%.200s'", o);
}

(定義出典)

###<使用例>

使用例 (cpython/Python/ceval.c)
        case TARGET(UNARY_POSITIVE): {
            PyObject *value = TOP();
            PyObject *res = PyNumber_Positive(value);
            Py_DECREF(value);
            SET_TOP(res);
            if (res == NULL)
                goto error;
            DISPATCH();
        }

(使用例出典)

##PyObject* PyNumber_Absolute(PyObject *o)
###<概説>
成功するとoの絶対値を返し、失敗するとNULLを返す。
Pythonの式abs(o)と同じ。
###<定義>

定義 (cpython/Objects/abstract.c)
PyObject *
PyNumber_Absolute(PyObject *o)
{
    if (o == NULL) {
        return null_error();
    }

    PyNumberMethods *m = Py_TYPE(o)->tp_as_number;
    if (m && m->nb_absolute) {
        PyObject *res = m->nb_absolute(o);
        assert(_Py_CheckSlotResult(o, "__abs__", res != NULL));
        return res;
    }

    return type_error("bad operand type for abs(): '%.200s'", o);
}

(定義出典)

###<使用例>

使用例 (cpython/Modules/mathmodule.c)
    ab = PyNumber_Absolute(m);

(使用例出典)

##PyObject* PyNumber_Invert(PyObject *o)
###<概説>
成功するとoのビット単位反転(bitwise negation)を返し、失敗するとNULLを返す。
Pythonの式~oと同じ。
###<定義>

定義 (cpython/Objects/abstract.c)
PyObject *
PyNumber_Invert(PyObject *o)
{
    if (o == NULL) {
        return null_error();
    }

    PyNumberMethods *m = Py_TYPE(o)->tp_as_number;
    if (m && m->nb_invert) {
        PyObject *res = (*m->nb_invert)(o);
        assert(_Py_CheckSlotResult(o, "__invert__", res != NULL));
        return res;
    }

    return type_error("bad operand type for unary ~: '%.200s'", o);
}

(定義出典)

###<使用例>

使用例 (cpython/Python/ceval.c)
        case TARGET(UNARY_INVERT): {
            PyObject *value = TOP();
            PyObject *res = PyNumber_Invert(value);
            Py_DECREF(value);
            SET_TOP(res);
            if (res == NULL)
                goto error;
            DISPATCH();
        }

(使用例出典)

##PyObject* PyNumber_Lshift(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1o2だけ左シフトした結果を返し、失敗するとNULLを返す。
Pythonの式o1 << o2と同じ。
###<定義>

定義 (cpython/Objects/abstract.c)
BINARY_FUNC(PyNumber_Lshift, nb_lshift, "<<")

(定義出典)

###<使用例>

使用例 (cpython/Python/ceval.c)
        case TARGET(BINARY_LSHIFT): {
            PyObject *right = POP();
            PyObject *left = TOP();
            PyObject *res = PyNumber_Lshift(left, right);
            Py_DECREF(left);
            Py_DECREF(right);
            SET_TOP(res);
            if (res == NULL)
                goto error;
            DISPATCH();
        }

(使用例出典)

##PyObject* PyNumber_Rshift(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1o2だけ右シフトした結果を返し、失敗するとNULLを返す。
Pythonの式o1 >> o2と同じ。
###<定義>

定義 (cpython/Objects/abstract.c)
BINARY_FUNC(PyNumber_Rshift, nb_rshift, ">>")

(定義出典)

###<使用例>

使用例 (cpython/Python/ceval.c)
        case TARGET(BINARY_RSHIFT): {
            PyObject *right = POP();
            PyObject *left = TOP();
            PyObject *res = PyNumber_Rshift(left, right);
            Py_DECREF(left);
            Py_DECREF(right);
            SET_TOP(res);
            if (res == NULL)
                goto error;
            DISPATCH();
        }

(使用例出典)

##PyObject* PyNumber_And(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1o2の "ビット単位論理積 (bitwise and)" を返し、失敗するとNULLを返す。
Pythonの式o1 & o2と同じ。

###<定義>

定義 (cpython/Objects/abstract.c)
BINARY_FUNC(PyNumber_And, nb_and, "&")

(定義出典)

###<使用例>

使用例 (cpython/Python/ceval.c)
        case TARGET(BINARY_AND): {
            PyObject *right = POP();
            PyObject *left = TOP();
            PyObject *res = PyNumber_And(left, right);
            Py_DECREF(left);
            Py_DECREF(right);
            SET_TOP(res);
            if (res == NULL)
                goto error;
            DISPATCH();
        }

(使用例出典)

##PyObject* PyNumber_Xor(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1o2の "ビット単位排他的論理和(bitwise exclusive or)"を返し、失敗するとNULLを返す。
Pythonの式o1 ^ o2と同じ。
###<定義>

定義 (cpython/Objects/abstract.c)
BINARY_FUNC(PyNumber_Xor, nb_xor, "^")

(定義出典)

###<使用例>

使用例 (cpython/Python/ceval.c)
        case TARGET(BINARY_XOR): {
            PyObject *right = POP();
            PyObject *left = TOP();
            PyObject *res = PyNumber_Xor(left, right);
            Py_DECREF(left);
            Py_DECREF(right);
            SET_TOP(res);
            if (res == NULL)
                goto error;
            DISPATCH();
        }

(使用例出典)

##PyObject* PyNumber_Or(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1o2の"ビット単位論理和 (bitwise or)"を返し失敗するとNULLを返す。
Pythonの式o1 | o2と同じ。
###<定義>

定義 (cpython/Objects/abstract.c)
BINARY_FUNC(PyNumber_Or, nb_or, "|")

(定義出典)

###<使用例>

使用例 (cpython/Python/ceval.c)
        case TARGET(BINARY_OR): {
            PyObject *right = POP();
            PyObject *left = TOP();
            PyObject *res = PyNumber_Or(left, right);
            Py_DECREF(left);
            Py_DECREF(right);
            SET_TOP(res);
            if (res == NULL)
                goto error;
            DISPATCH();
        }

(使用例出典)

##PyObject* PyNumber_InPlaceAdd(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1o2を加算した結果を返し、失敗するとNULLを返す。o1がin-place演算をサポートする場合、in-place演算を行う。
Pythonの文o1 += o2と同じ。
###<定義>

定義 (cpython/Objects/abstract.c)
PyObject *
PyNumber_InPlaceAdd(PyObject *v, PyObject *w)
{
    PyObject *result = BINARY_IOP1(v, w, NB_SLOT(nb_inplace_add),
                                   NB_SLOT(nb_add), "+=");
    if (result == Py_NotImplemented) {
        PySequenceMethods *m = Py_TYPE(v)->tp_as_sequence;
        Py_DECREF(result);
        if (m != NULL) {
            binaryfunc func = m->sq_inplace_concat;
            if (func == NULL)
                func = m->sq_concat;
            if (func != NULL) {
                result = func(v, w);
                assert(_Py_CheckSlotResult(v, "+=", result != NULL));
                return result;
            }
        }
        result = binop_type_error(v, w, "+=");
    }
    return result;
}

(定義出典)

###<使用例>

使用例 (cpython/Python/ceval.c)
        case TARGET(INPLACE_ADD): {
            PyObject *right = POP();
            PyObject *left = TOP();
            PyObject *sum;
            if (PyUnicode_CheckExact(left) && PyUnicode_CheckExact(right)) {
                sum = unicode_concatenate(tstate, left, right, f, next_instr);
                /* unicode_concatenate consumed the ref to left */
            }
            else {
                sum = PyNumber_InPlaceAdd(left, right);
                Py_DECREF(left);
            }
            Py_DECREF(right);
            SET_TOP(sum);
            if (sum == NULL)
                goto error;
            DISPATCH();
        }

(使用例出典)

##PyObject* PyNumber_InPlaceSubtract(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1からo2を減算した結果を返し、失敗するとNULLを返す。o1が in-place 演算をサポートする場合、in-place 演算を行う。
Pythonの文o1 -= o2と同じ。

###<定義>

定義 (cpython/Objects/abstract.c)
INPLACE_BINOP(PyNumber_InPlaceSubtract, nb_inplace_subtract, nb_subtract, "-=")

(定義出典)

###<定義補足>

INPLACE_BINOP (cpython/Objects/abstract.c)
#define INPLACE_BINOP(func, iop, op, op_name) \
    PyObject * \
    func(PyObject *v, PyObject *w) { \
        return binary_iop(v, w, NB_SLOT(iop), NB_SLOT(op), op_name); \
    }
binary_iop (cpython/Objects/abstract.c)
static PyObject *
binary_iop1(PyObject *v, PyObject *w, const int iop_slot, const int op_slot
            )
{
    PyNumberMethods *mv = Py_TYPE(v)->tp_as_number;
    if (mv != NULL) {
        binaryfunc slot = NB_BINOP(mv, iop_slot);
        if (slot) {
            PyObject *x = (slot)(v, w);
            assert(_Py_CheckSlotResult(v, op_name, x != NULL));
            if (x != Py_NotImplemented) {
                return x;
            }
            Py_DECREF(x);
        }
    }
    return binary_op1(v, w, op_slot);
}

大筋を変えない程度に改変。

###<使用例>

使用例 (cpython/Python/ceval.c)
        case TARGET(INPLACE_SUBTRACT): {
            PyObject *right = POP();
            PyObject *left = TOP();
            PyObject *diff = PyNumber_InPlaceSubtract(left, right);
            Py_DECREF(left);
            Py_DECREF(right);
            SET_TOP(diff);
            if (diff == NULL)
                goto error;
            DISPATCH();
        }

(使用例出典)

##PyObject* PyNumber_InPlaceMultiply(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1o2を乗算した結果を返し、失敗するとNULLを返す。o1がin-place演算をサポートする場合、in-place演算を行う。 Pythonの文o1 *= o2`と同じ。
###<定義>

定義 (cpython/Objects/abstract.c)
PyObject *
PyNumber_InPlaceMultiply(PyObject *v, PyObject *w)
{
    PyObject *result = BINARY_IOP1(v, w, NB_SLOT(nb_inplace_multiply),
                                   NB_SLOT(nb_multiply), "*=");
    if (result == Py_NotImplemented) {
        ssizeargfunc f = NULL;
        PySequenceMethods *mv = Py_TYPE(v)->tp_as_sequence;
        PySequenceMethods *mw = Py_TYPE(w)->tp_as_sequence;
        Py_DECREF(result);
        if (mv != NULL) {
            f = mv->sq_inplace_repeat;
            if (f == NULL)
                f = mv->sq_repeat;
            if (f != NULL)
                return sequence_repeat(f, v, w);
        }
        else if (mw != NULL) {
            /* Note that the right hand operand should not be
             * mutated in this case so sq_inplace_repeat is not
             * used. */
            if (mw->sq_repeat)
                return sequence_repeat(mw->sq_repeat, w, v);
        }
        result = binop_type_error(v, w, "*=");
    }
    return result;
}

(定義出典)

###<使用例>

使用例 (cpython/Python/ceval.c)
        case TARGET(INPLACE_MULTIPLY): {
            PyObject *right = POP();
            PyObject *left = TOP();
            PyObject *res = PyNumber_InPlaceMultiply(left, right);
            Py_DECREF(left);
            Py_DECREF(right);
            SET_TOP(res);
            if (res == NULL)
                goto error;
            DISPATCH();
        }

(使用例出典)

##PyObject* PyNumber_InPlaceMatrixMultiply(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1o2を行列乗算した結果を返し、失敗するとNULLを返す。o1がin-place演算をサポートする場合、in-place演算を行う。
Pythonの文o1 @= o2と同じ。
###<定義>

定義 (cpython/Objects/abstract.c)
PyObject *
PyNumber_InPlaceMatrixMultiply(PyObject *v, PyObject *w)
{
    return binary_iop(v, w, NB_SLOT(nb_inplace_matrix_multiply),
                      NB_SLOT(nb_matrix_multiply), "@=");
}

(定義出典)

###<使用例>

使用例 (cpython/Python/ceval.c)
        case TARGET(INPLACE_MATRIX_MULTIPLY): {
            PyObject *right = POP();
            PyObject *left = TOP();
            PyObject *res = PyNumber_InPlaceMatrixMultiply(left, right);
            Py_DECREF(left);
            Py_DECREF(right);
            SET_TOP(res);
            if (res == NULL)
                goto error;
            DISPATCH();
        }

(使用例出典)

##PyObject* PyNumber_InPlaceFloorDivide(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1o2で除算した切捨て値を返し、失敗するとNULLを返す。o1がin-place演算をサポートする場合、in-place演算を行う。
Pythonの文o1 //= o2と同じ。

###<定義>

定義 (cpython/Objects/abstract.c)
PyObject *
PyNumber_InPlaceFloorDivide(PyObject *v, PyObject *w)
{
    return binary_iop(v, w, NB_SLOT(nb_inplace_floor_divide),
                      NB_SLOT(nb_floor_divide), "//=");
}

(定義出典)

###<使用例>

使用例 (cpython/Python/ceval.c)
        case TARGET(INPLACE_FLOOR_DIVIDE): {
            PyObject *divisor = POP();
            PyObject *dividend = TOP();
            PyObject *quotient = PyNumber_InPlaceFloorDivide(dividend, divisor);
            Py_DECREF(dividend);
            Py_DECREF(divisor);
            SET_TOP(quotient);
            if (quotient == NULL)
                goto error;
            DISPATCH();
        }

(使用例出典)

##PyObject* PyNumber_InPlaceTrueDivide(PyObject *o1, PyObject *o2)
###<概説>
成功すると、数学的なo1o2による除算値に対する妥当な近似 (reasonable approximation) を返し、失敗するとNULLを返す。
全ての実数を2を基数として表現するのは不可能なため、二進の浮動小数点数は "近似値" しか表現できまず、戻り値も近似になる。
この関数に二つの整数を渡した際、浮動小数点の値を返すことがある。o1が in-place 演算をサポートする場合、in-place 演算を行う。
###<定義>

定義 (cpython/Objects/abstract.c)
PyObject *
PyNumber_InPlaceTrueDivide(PyObject *v, PyObject *w)
{
    return binary_iop(v, w, NB_SLOT(nb_inplace_true_divide),
                      NB_SLOT(nb_true_divide), "/=");
}

(定義出典)

###<使用例>

使用例 (cpython/Python/ceval.c)
        case TARGET(INPLACE_TRUE_DIVIDE): {
            PyObject *divisor = POP();
            PyObject *dividend = TOP();
            PyObject *quotient = PyNumber_InPlaceTrueDivide(dividend, divisor);
            Py_DECREF(dividend);
            Py_DECREF(divisor);
            SET_TOP(quotient);
            if (quotient == NULL)
                goto error;
            DISPATCH();
        }

(使用例出典)

##PyObject* PyNumber_InPlaceRemainder(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1o2で除算した剰余を返し、,失敗するとNULLを返す。o1が in-place演算をサポートする場合、in-place演算を行う。
Pythonの文o1 %= o2と同じ。
###<定義>

定義 (cpython/Objects/abstract.c)
PyObject *
PyNumber_InPlaceRemainder(PyObject *v, PyObject *w)
{
    return binary_iop(v, w, NB_SLOT(nb_inplace_remainder),
                            NB_SLOT(nb_remainder), "%=");
}

(定義出典)

###<使用例>

使用例 (cpython/Python/ceval.c)
        case TARGET(INPLACE_MODULO): {
            PyObject *right = POP();
            PyObject *left = TOP();
            PyObject *mod = PyNumber_InPlaceRemainder(left, right);
            Py_DECREF(left);
            Py_DECREF(right);
            SET_TOP(mod);
            if (mod == NULL)
                goto error;
            DISPATCH();
        }

(使用例出典)

##PyObject* PyNumber_InPlacePower(PyObject *o1, PyObject *o2, PyObject *o3)
###<概説>
組み込み関数pow()を参照してください。失敗するとNULLを返す。o1が in-place 演算をサポートする場合、in-place 演算を行う。この関数はo3Py_Noneの場合は Python 文o1 **= o2と同じで、それ以外の場合はpow(o1, o2, o3)の in-place 版です。o3を無視させたいなら、Py_Noneを入れる。
###<定義>

定義 (cpython/Objects/abstract.c)
PyObject *
PyNumber_InPlacePower(PyObject *v, PyObject *w, PyObject *z)
{
    return ternary_iop(v, w, z, NB_SLOT(nb_inplace_power),
                                NB_SLOT(nb_power), "**=");
}

(定義出典)

###<使用例>

使用例 (cpython/Python/ceval.c)
        case TARGET(INPLACE_POWER): {
            PyObject *exp = POP();
            PyObject *base = TOP();
            PyObject *res = PyNumber_InPlacePower(base, exp, Py_None);
            Py_DECREF(base);
            Py_DECREF(exp);
            SET_TOP(res);
            if (res == NULL)
                goto error;
            DISPATCH();
        }

(使用例出典)

##PyObject* PyNumber_InPlaceLshift(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1o2だけ左シフトした結果を返し、失敗するとNULLを返す。o1がin-place演算をサポートする場合、in-place演算を行う。
Pythonの文o1 <<= o2と同じ。
###<定義>

定義 (cpython/Objects/abstract.c)
INPLACE_BINOP(PyNumber_InPlaceLshift, nb_inplace_lshift, nb_lshift, "<<=")

(定義出典)

###<使用例>

使用例 (cpython/Python/ceval.c)
        case TARGET(INPLACE_LSHIFT): {
            PyObject *right = POP();
            PyObject *left = TOP();
            PyObject *res = PyNumber_InPlaceLshift(left, right);
            Py_DECREF(left);
            Py_DECREF(right);
            SET_TOP(res);
            if (res == NULL)
                goto error;
            DISPATCH();
        }

(使用例出典)

##PyObject* PyNumber_InPlaceRshift(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1o2だけ右シフトした結果を返し、失敗するとNULLを返す。o1が in-place 演算をサポートする場合、in-place 演算を行う。
Python の文o1 >>= o2と同じ。

###<定義>

定義 (cpython/Objects/abstract.c)
INPLACE_BINOP(PyNumber_InPlaceRshift, nb_inplace_rshift, nb_rshift, ">>=")

(定義出典)

###<使用例>

使用例 (cpython/Python/ceval.c)
        case TARGET(INPLACE_RSHIFT): {
            PyObject *right = POP();
            PyObject *left = TOP();
            PyObject *res = PyNumber_InPlaceRshift(left, right);
            Py_DECREF(left);
            Py_DECREF(right);
            SET_TOP(res);
            if (res == NULL)
                goto error;
            DISPATCH();
        }

(使用例出典)

##PyObject* PyNumber_InPlaceAnd(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1o2の "ビット単位論理積 (bitwise and)" を返し、失敗するとNULLを返す。o1が in-place 演算をサポートする場合、in-place 演算を行う。
Pythonの文o1 &= o2と同じ。
###<定義>

定義 (cpython/Objects/abstract.c)
INPLACE_BINOP(PyNumber_InPlaceAnd, nb_inplace_and, nb_and, "&=")

(定義出典)

###<使用例>

使用例 (cpython/Python/ceval.c)
        case TARGET(INPLACE_AND): {
            PyObject *right = POP();
            PyObject *left = TOP();
            PyObject *res = PyNumber_InPlaceAnd(left, right);
            Py_DECREF(left);
            Py_DECREF(right);
            SET_TOP(res);
            if (res == NULL)
                goto error;
            DISPATCH();
        }

(使用例出典)

##PyObject* PyNumber_InPlaceXor(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1o2の "ビット単位排他的論理和 (bitwise exclusive or)" を返し、失敗するとNULLを返す。o1が in-place 演算をサポートする場合、in-place 演算を行う。
Python の文o1 ^= o2と同じ。
###<定義>

定義 (cpython/Objects/abstract.c)
INPLACE_BINOP(PyNumber_InPlaceXor, nb_inplace_xor, nb_xor, "^=")

(定義出典)

###<使用例>

使用例 (cpython/Python/ceval.c)
        case TARGET(INPLACE_XOR): {
            PyObject *right = POP();
            PyObject *left = TOP();
            PyObject *res = PyNumber_InPlaceXor(left, right);
            Py_DECREF(left);
            Py_DECREF(right);
            SET_TOP(res);
            if (res == NULL)
                goto error;
            DISPATCH();
        }

(使用例出典)

##PyObject* PyNumber_InPlaceOr(PyObject *o1, PyObject *o2)
###<概説>
成功するとo1o2の "ビット単位論理和 (bitwise or)" を返し失敗するとNULLを返す。o1が in-place 演算をサポートする場合、in-place 演算を行う。
Python の文o1 |= o2と同じ。
###<定義>

定義 (cpython/Objects/abstract.c)
INPLACE_BINOP(PyNumber_InPlaceOr, nb_inplace_or, nb_or, "|=")

(定義出典)

###<使用例>

使用例 (cpython/Python/ceval.c)
        case TARGET(INPLACE_OR): {
            PyObject *right = POP();
            PyObject *left = TOP();
            PyObject *res = PyNumber_InPlaceOr(left, right);
            Py_DECREF(left);
            Py_DECREF(right);
            SET_TOP(res);
            if (res == NULL)
                goto error;
            DISPATCH();
        }

(使用例出典)

##PyObject* PyNumber_Long(PyObject *o)
###<概説>
成功するとoを整数に変換したものを返し、失敗するとNULLを返す。
Pythonの式int(o)と同じ。
###<定義>

定義 (cpython/Objects/abstract.c)
PyObject *
PyNumber_Long(PyObject *o)
{
...
    m = Py_TYPE(o)->tp_as_number;
    if (m && m->nb_int) { /* This should include subclasses of int */
        /* Convert using the nb_int slot, which should return something
           of exact type int. */
        result = m->nb_int(o);
...
        if (!result || PyLong_CheckExact(result)) {
            return result;
        }
...

(定義出典)

###<使用例>

使用例 (cpython/Objects/bytesobject.c)
            iobj = PyNumber_Long(v);

(使用例出典)

##PyObject* PyNumber_Float(PyObject *o)
###<概説>
成功するとoを浮動小数点数に変換したものを返し、失敗するとNULLを返す。
Pythonの式float(o)と同じ。
###<定義>

定義 (cpython/Objects/abstract.c)
PyObject *
PyNumber_Float(PyObject *o)
{
...
    PyNumberMethods *m = Py_TYPE(o)->tp_as_number;
    if (m && m->nb_float) { /* This should include subclasses of float */
        PyObject *res = m->nb_float(o);
...
        if (!res || PyFloat_CheckExact(res)) {
            return res;
        }
...

(定義出典)

###<使用例>

使用例 (cpython/Objects/complexobject.c)
        tmp = PyNumber_Float(i);

(使用例出典)

##PyObject* PyNumber_Index(PyObject *o)
###<概説>
oをPythonのint型に変換し、成功したらその値を返す。失敗したらNULLが返され、TypeError例外が送出される。
###<定義>

定義 (cpython/Objects/abstract.c)
PyObject *
PyNumber_Index(PyObject *item)
{
    PyObject *result = _PyNumber_Index(item);
    if (result != NULL && !PyLong_CheckExact(result)) {
        Py_SETREF(result, _PyLong_Copy((PyLongObject *)result));
    }
    return result;
}

(定義出典)

_PyNumber_Index (cpython/Objects/abstract.c)
/* Return a Python int from the object item.
   Can return an instance of int subclass.
   Raise TypeError if the result is not an int
   or if the object cannot be interpreted as an index.
*/
PyObject *
_PyNumber_Index(PyObject *item)
{
...
    PyObject *result = Py_TYPE(item)->tp_as_number->nb_index(item);
...
    if (!result || PyLong_CheckExact(result)) {
        return result;
    }
...

(補足出典)

###<使用例>

使用例 (cpython/Objects/rangeobject.c)
    step = PyNumber_Index(step);

(使用例出典)

##PyObject* PyNumber_ToBase(PyObject *n, int base)
###<概説>
base 進数に変換された整数nを文字列として返す。 base 引数は2, 8, 10または16のいずれかでなければならない。 基数2、8、16について、返される文字列の先頭には基数マーカー '0b' 、 '0o' または '0x' が、それぞれ付与される。 もしnが Python のint型でなければ、まずPyNumber_Index()で変換される。
###<定義>

定義 (cpython/Objects/abstract.c)
PyObject *
PyNumber_ToBase(PyObject *n, int base)
{
    if (!(base == 2 || base == 8 || base == 10 || base == 16)) {
        PyErr_SetString(PyExc_SystemError,
                        "PyNumber_ToBase: base must be 2, 8, 10 or 16");
        return NULL;
    }
    PyObject *index = _PyNumber_Index(n);
    if (!index)
        return NULL;
    PyObject *res = _PyLong_Format(index, base);
    Py_DECREF(index);
    return res;
}

(定義出典)

###<使用例>

使用例 (cpython/Python/bltinmodule.c)
static PyObject *
builtin_bin(PyObject *module, PyObject *number)
/*[clinic end generated code: output=b6fc4ad5e649f4f7 input=53f8a0264bacaf90]*/
{
    return PyNumber_ToBase(number, 2);
}

(使用例出典)

##Py_ssize_t PyNumber_AsSsize_t(PyObject *o, PyObject *exc)
###<概説>
oを整数として解釈可能だった場合、Py_ssize_t型の値に変換して返す。呼び出しが失敗したら、例外が送出され、-1が返される。

もしoがPythonのintに変換できたのに、Py_ssize_tへの変換がOverflowErrorになる場合は、exc引数で渡された型 (普通はIndexErrorOverflowError) の例外を送出します。もし、excNULLなら、例外はクリアされて、値が負の場合はPY_SSIZE_T_MINへ、正の場合はPY_SSIZE_T_MAXへと制限される。
###<定義>

定義 (cpython/Objects/abstract.c)
Py_ssize_t
PyNumber_AsSsize_t(PyObject *item, PyObject *err)
{
...
    /* We're done if PyLong_AsSsize_t() returns without error. */
    result = PyLong_AsSsize_t(value);
...
    return result;
}

(定義出典)

###<使用例>

使用例 (cpython/Objects/abstract.c)
            key_value = PyNumber_AsSsize_t(key, PyExc_IndexError);

(使用例出典)

##int PyIndex_Check(PyObject *o)
###<概説>
oがインデックス整数である場合 (tp_as_number構造体のnb_indexスロットが埋まっている場合) に1を返し、そうでない場合に0を返す。 この関数は常に成功する。
###<定義>

定義 (cpython/Objects/abstract.c)
int
PyIndex_Check(PyObject *obj)
{
    return _PyIndex_Check(obj);
}

(定義出典)
###<定義補足>

定義 (cpython/Include/internal/pycore_abstract.h)
// Fast inlined version of PyIndex_Check()
static inline int
_PyIndex_Check(PyObject *obj)
{
    PyNumberMethods *tp_as_number = Py_TYPE(obj)->tp_as_number;
    return (tp_as_number != NULL && tp_as_number->nb_index != NULL);
}

(定義補足出典)

###<使用例>

使用例 (cpython/Modules/mmapmodule.c)
    if (PyIndex_Check(item)) {

(使用例出典)

##蛇足

_PyEval_EvalFrameDefault (cpython/Objects/abstract.c)
PyObject* _Py_HOT_FUNCTION
_PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
{
...
    int opcode;        /* Current opcode */
    int oparg;         /* Current opcode argument, if any */
...
    /* push frame */
    tstate->frame = f;
    co = f->f_code;
...
    names = co->co_names;
    consts = co->co_consts;
    fastlocals = f->f_localsplus;
    freevars = f->f_localsplus + co->co_nlocals;
...
    stack_pointer = f->f_valuestack + f->f_stackdepth;
...
main_loop:
    for (;;) {
...
            opcode = _Py_OPCODE(*next_instr);
...
        switch (opcode) {

        /* BEWARE!
           It is essential that any operation that fails must goto error
           and that all operation that succeed call [FAST_]DISPATCH() ! */

        case TARGET(NOP): {
            DISPATCH();
        }

        case TARGET(LOAD_FAST): {
...

#参考にさせていただいた本・ページ

#感想
バージョンが混ざってしまっているが、雰囲気を掴みたかっただけなので、そこは厳密にはしなかった。
使用例については、CPythonの中で用いられているものに限定した。

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?