おいも貴婦人ブログ

生物系博士課程満期退学をしたAIエンジニアのブログ。

Python のモジュールをCで書く。行列の積。

python から2次元のリストを2つ投げて、行列の積を2次元のリストでを返すモジュールをCで書いてみました。buildはiccを使った時のものです。

#include <Python.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

static PyObject* matrix(PyObject *matrix1,PyObject *matrix2)
{
    long i,j,k;
    PyObject* out_matrix,*d1_list,*temp_l1,*temp_l2;
    long line1=PyList_Size(matrix1);
    long low1=PyList_Size(PyList_GetItem(matrix1,0));
    long line2=PyList_Size(matrix2);
    long low2=PyList_Size(PyList_GetItem(matrix2,0));
    double double1,double2;
    double d2_outmat[line1][low2];
    out_matrix=PyList_New(line1);

    if(low1!=line2){
        return NULL;
    }
    for(i=0;i<line1;i++){
        for(j=0;j<low2;j++){
            d2_outmat[i][j]=0;
        }
    }

    for(i=0;i<line1;i++){
        for(j=0;j<low2;j++){
            for(k=0;k<low1;k++){
                temp_l1=PyList_GetItem(matrix1,i);
                temp_l2=PyList_GetItem(matrix2,k);
                double1=PyFloat_AsDouble(PyList_GetItem(temp_l1,k));
                double2=PyFloat_AsDouble(PyList_GetItem(temp_l2,j));
                d2_outmat[i][j]+=double1*double2;
            }
        }
    }
    
    for(i=0;i<line1;i++){
        d1_list=PyList_New(low2);
        for(j=0;j<low2;j++){
            PyList_SetItem(d1_list,j,PyInt_FromLong(d2_outmat[i][j]));
        }
        PyList_SetItem(out_matrix,i,d1_list);
    }

    return out_matrix;

}
static PyObject* wrap_matrix(PyObject* self,PyObject* args)
{
    PyObject *matrix1,*matrix2;
    if(!PyArg_ParseTuple(args,"OO",
                         &matrix1,
                         &matrix2
                         )){
        return NULL;
    }
    return matrix(matrix1,matrix2);
}

static PyMethodDef matrixmethods[]={
    {"matrix",wrap_matrix,METH_VARARGS},
    {NULL},
};

void initmatrix()
{
    Py_InitModule("matrix",matrixmethods);
}

build

#! /usr/enb/bin python
from distutils.core import setup,Extension

from distutils.command import build_py, build_ext
from distutils.errors import DistutilsPlatformError
from distutils.unixccompiler import UnixCCompiler

class MyIntelCCompiler(UnixCCompiler):
    compiler_type = "intel"
    executables = dict(UnixCCompiler.executables)
    executables.update({
        "compiler"      : ["icc", "-O3", "-xhost", "-no-prec-div","-fpic"],
        "compiler_so"   : ["icc", "-O3", "-xhost", "-no-prec-div","-fpic"],
        "compiler_cxx"  : ["icc", "-O3", "-xhost", "-no-prec-div","-fpic"],
        "linker_so"     : ["icc", "-shared"],
        "linker_exe"    : ["icc"],
    })

    
class matrix_build_ext(build_ext.build_ext):
    def run(self):
        import distutils.ccompiler
        def wrap_new_compiler(func):
            def _wrap_new_compiler(*args, **kwargs):
                try: return func(*args, **kwargs)
                except DistutilsPlatformError:
                    return MyIntelCCompiler(None, kwargs["dry_run"], kwargs["force"])
            return _wrap_new_compiler
        distutils.ccompiler.new_compiler = wrap_new_compiler(distutils.ccompiler.new_compiler)
        self.compiler = "intel"
        build_ext.build_ext.run(self)
        
module1=Extension("matrixmodule",["cal_matrix.c"],extra_link_args=["-fPIC"])
    
setup(name='matrixmodule',version='1.0',
      cmdclass={"build_ext":matrix_build_ext},
      description='calculate matrix',
      ext_modules=[module1])