Back to index

python-biopython  1.60
cpairwise2module.c
Go to the documentation of this file.
00001 /* Copyright 2002 by Jeffrey Chang.  All rights reserved.
00002  * This code is part of the Biopython distribution and governed by its
00003  * license.  Please see the LICENSE file that should have been included
00004  * as part of this package.
00005  *
00006  * cpairwise2module.c
00007  * Created 30 Sep 2001
00008  *
00009  * Optimized C routines that complement pairwise2.py.
00010  */
00011 
00012 #include "Python.h"
00013 
00014 
00015 #define _PRECISION 1000
00016 #define rint(x) (int)((x)*_PRECISION+0.5)
00017 
00018 /* Return a PyNumber as a double.
00019  * Raises a TypeError if I can't do it.
00020  */
00021 static double PyNumber_AsDouble(PyObject *py_num)
00022 {
00023     double val;
00024     PyObject *floatobj;
00025 
00026     if((floatobj = PyNumber_Float(py_num)) == NULL)
00027        return(0.0);
00028     val = PyFloat_AsDouble(floatobj);
00029     Py_DECREF(floatobj);
00030     return val;
00031 }
00032 
00033 /* Functions in this module. */
00034 
00035 double calc_affine_penalty(int length, double open, double extend, 
00036     int penalize_extend_when_opening)
00037 {
00038     double penalty;
00039 
00040     if(length <= 0)
00041        return 0.0;
00042     penalty = open + extend * length;
00043     if(!penalize_extend_when_opening)
00044        penalty -= extend;
00045     return penalty;
00046 }
00047 
00048 struct IndexList {
00049     int num_used;
00050     int num_allocated;
00051     int *indexes; /* Array of ints.  Even ints are rows, odd ones are cols. */
00052 };
00053 
00054 static void IndexList_init(struct IndexList *il) 
00055 {
00056     /* il->num_used = 0;
00057     il->num_allocated = 0;
00058     il->indexes = NULL; */
00059     memset((void *)il, 0, sizeof(struct IndexList));
00060 }
00061 
00062 static void IndexList_free(struct IndexList *il) 
00063 {
00064     if(il->indexes)
00065        free(il->indexes);
00066     IndexList_init(il);
00067 }
00068 
00069 static void IndexList_clear(struct IndexList *il)
00070 {
00071     il->num_used = 0;
00072 }
00073 
00074 static int IndexList_contains(struct IndexList *il, 
00075                            const int row, const int col) 
00076 {
00077     int i;
00078     int stop;
00079 
00080     stop = il->num_used*2;
00081     for(i=0; i<stop; i+=2) {
00082        if((il->indexes[i] == row) && (il->indexes[i+1] == col))
00083            return 1;
00084     }
00085     return 0;
00086 }
00087 
00088 static int IndexList__verify_free_index(struct IndexList *il, int num_needed)
00089 {
00090     int *indexes;
00091     int num_to_allocate;
00092     int num_bytes;
00093 
00094     if(il->num_allocated >= num_needed)
00095        return 1;
00096 
00097     /* Nearly all the cases are for list of length 1 or 2.
00098        Empirically, the code seems to run fastest when I allocate the
00099        exact amount for these. */
00100     if(num_needed <= 2)
00101        num_to_allocate = num_needed;
00102     else 
00103        num_to_allocate = num_needed*2;
00104     num_bytes = num_to_allocate*sizeof(int)*2;
00105     if(!(indexes = realloc((void *)il->indexes, num_bytes))) {
00106        PyErr_SetString(PyExc_MemoryError, "Out of memory");
00107        return 0;
00108     }
00109     il->indexes = indexes;
00110     il->num_allocated = num_to_allocate;
00111     return 1;
00112 }
00113 
00114 static void IndexList_append(struct IndexList *il, 
00115                           const int row, const int col) 
00116 {
00117     int i;
00118     if(!IndexList__verify_free_index(il, il->num_used+1))
00119        return;
00120     i=il->num_used*2;
00121     il->indexes[i] = row;
00122     il->indexes[i+1] = col;
00123     il->num_used += 1;
00124 }
00125 
00126 static void IndexList_extend(struct IndexList *il1, struct IndexList *il2) 
00127 {
00128     int i1, i2;
00129     int stop;
00130 
00131     if(!IndexList__verify_free_index(il1, il1->num_used+il2->num_used))
00132        return;
00133     stop=il2->num_used * 2;
00134     for(i1=il1->num_used*2, i2=0; i2<stop; i1+=2, i2+=2) {
00135        il1->indexes[i1] = il2->indexes[i2];
00136        il1->indexes[i1+1] = il2->indexes[i2+1];
00137     }
00138     il1->num_used += il2->num_used;
00139 }
00140 
00141 /* static void IndexList_copy(struct IndexList *il1, struct IndexList *il2) 
00142 {
00143     IndexList_clear(il1);
00144     IndexList_extend(il1, il2);
00145     } */
00146 
00147 /* static void IndexList_assign(struct IndexList *il1, struct IndexList *il2)
00148 {
00149     if(il1->indexes)
00150        free(il1->indexes);
00151     il1->indexes = il2->indexes;
00152     il1->num_used = il2->num_used;
00153     il1->num_allocated = il2->num_allocated;
00154     } */
00155 
00156 
00157 double _get_match_score(PyObject *py_sequenceA, PyObject *py_sequenceB, 
00158                      PyObject *py_match_fn, int i, int j,
00159                      char *sequenceA, char *sequenceB, 
00160                      int use_sequence_cstring,
00161                      double match, double mismatch, 
00162                      int use_match_mismatch_scores)
00163 {
00164     PyObject *py_A=NULL, 
00165        *py_B=NULL;
00166     PyObject *py_arglist=NULL, *py_result=NULL;
00167     double score = 0;
00168 
00169     if(use_sequence_cstring && use_match_mismatch_scores) {
00170        score = (sequenceA[i] == sequenceB[j]) ? match : mismatch;
00171        return score;
00172     }
00173     /* Calculate the match score. */
00174     if(!(py_A = PySequence_GetItem(py_sequenceA, i)))
00175        goto _get_match_score_cleanup;
00176     if(!(py_B = PySequence_GetItem(py_sequenceB, j)))
00177        goto _get_match_score_cleanup;
00178     if(!(py_arglist = Py_BuildValue("(OO)", py_A, py_B)))
00179        goto _get_match_score_cleanup;
00180 
00181     if(!(py_result = PyEval_CallObject(py_match_fn, py_arglist)))
00182        goto _get_match_score_cleanup;
00183     score = PyNumber_AsDouble(py_result);
00184  _get_match_score_cleanup:
00185     if(py_A) {
00186        Py_DECREF(py_A);
00187     }
00188     if(py_B) {
00189        Py_DECREF(py_B);
00190     }
00191     if(py_arglist) {
00192        Py_DECREF(py_arglist);
00193     }
00194     if(py_result) {
00195        Py_DECREF(py_result);
00196     }
00197     return score;
00198 }
00199 
00200 #if PY_MAJOR_VERSION >= 3
00201 static PyObject* _create_bytes_object(PyObject* o) {
00202     PyObject* b;
00203     if (PyBytes_Check(o)) {
00204        return o;
00205     }
00206     if (!PyUnicode_Check(o)) {
00207         return NULL;
00208     }
00209     b = PyUnicode_AsASCIIString(o);
00210     if (!b) {
00211         PyErr_Clear();
00212         return NULL;
00213     }
00214     return b;
00215 }
00216 #endif
00217 
00218 /* This function is a more-or-less straightforward port of the
00219  * equivalent function in pairwise2.  Please see there for algorithm
00220  * documentation.
00221  */
00222 static PyObject *cpairwise2__make_score_matrix_fast(
00223     PyObject *self, PyObject *args)
00224 {
00225     int i;
00226     int row, col;
00227 
00228     PyObject *py_sequenceA, *py_sequenceB, *py_match_fn;
00229 #if PY_MAJOR_VERSION >= 3
00230     PyObject *py_bytesA, *py_bytesB;
00231 #endif
00232     char *sequenceA=NULL, *sequenceB=NULL;
00233     int use_sequence_cstring;
00234     double open_A, extend_A, open_B, extend_B;
00235     int penalize_extend_when_opening, penalize_end_gaps;
00236     int align_globally, score_only;
00237 
00238     PyObject *py_match=NULL, *py_mismatch=NULL;
00239     double first_A_gap, first_B_gap;
00240     double match, mismatch;
00241     int use_match_mismatch_scores;
00242     int lenA, lenB;
00243     double *score_matrix = (double *)NULL;
00244     struct IndexList *trace_matrix = (struct IndexList *)NULL;
00245     PyObject *py_score_matrix=NULL, *py_trace_matrix=NULL;
00246 
00247     double *row_cache_score = (double *)NULL, 
00248        *col_cache_score = (double *)NULL;
00249     struct IndexList *row_cache_index = (struct IndexList *)NULL, 
00250        *col_cache_index = (struct IndexList *)NULL;
00251 
00252     PyObject *py_retval = NULL;
00253 
00254     if(!PyArg_ParseTuple(args, "OOOddddiiii", &py_sequenceA, &py_sequenceB,
00255                       &py_match_fn, &open_A, &extend_A, &open_B, &extend_B,
00256                       &penalize_extend_when_opening, &penalize_end_gaps,
00257                       &align_globally, &score_only))
00258        return NULL;
00259     if(!PySequence_Check(py_sequenceA) || !PySequence_Check(py_sequenceB)) {
00260        PyErr_SetString(PyExc_TypeError, 
00261                      "py_sequenceA and py_sequenceB should be sequences.");
00262        return NULL;
00263     }
00264 
00265     /* Optimize for the common case.  Check to see if py_sequenceA and
00266        py_sequenceB are strings.  If they are, use the c string
00267        representation. */
00268 #if PY_MAJOR_VERSION < 3
00269     use_sequence_cstring = 0;
00270     if(PyString_Check(py_sequenceA) && PyString_Check(py_sequenceB)) {
00271        sequenceA = PyString_AS_STRING(py_sequenceA);
00272        sequenceB = PyString_AS_STRING(py_sequenceB);
00273        use_sequence_cstring = 1;
00274     }
00275 #else
00276     py_bytesA = _create_bytes_object(py_sequenceA);
00277     py_bytesB = _create_bytes_object(py_sequenceB);
00278     if (py_bytesA && py_bytesB) {
00279         sequenceA = PyBytes_AS_STRING(py_bytesA);
00280         sequenceB = PyBytes_AS_STRING(py_bytesB);
00281        use_sequence_cstring = 1;
00282     }
00283     else {
00284         Py_XDECREF(py_bytesA);
00285         Py_XDECREF(py_bytesB);
00286         use_sequence_cstring = 0;
00287     }
00288 #endif
00289 
00290     if(!PyCallable_Check(py_match_fn)) {
00291        PyErr_SetString(PyExc_TypeError, "py_match_fn must be callable.");
00292        return NULL;
00293     }
00294     /* Optimize for the common case.  Check to see if py_match_fn is
00295        an identity_match.  If so, pull out the match and mismatch
00296        member variables and calculate the scores myself. */
00297     match = mismatch = 0;
00298     use_match_mismatch_scores = 0;
00299     if(!(py_match = PyObject_GetAttrString(py_match_fn, "match")))
00300         goto cleanup_after_py_match_fn;
00301     match = PyNumber_AsDouble(py_match);
00302     if(PyErr_Occurred())
00303         goto cleanup_after_py_match_fn;
00304     if(!(py_mismatch = PyObject_GetAttrString(py_match_fn, "mismatch")))
00305         goto cleanup_after_py_match_fn;
00306     mismatch = PyNumber_AsDouble(py_mismatch);
00307     if(PyErr_Occurred())
00308         goto cleanup_after_py_match_fn;
00309     use_match_mismatch_scores = 1;
00310 cleanup_after_py_match_fn:
00311     if(PyErr_Occurred())
00312         PyErr_Clear();
00313     if(py_match) {
00314         Py_DECREF(py_match);
00315     }
00316     if(py_mismatch) {
00317         Py_DECREF(py_mismatch);
00318     }
00319 
00320     /* Cache some commonly used gap penalties */
00321     first_A_gap = calc_affine_penalty(1, open_A, extend_A, 
00322                                   penalize_extend_when_opening);
00323     first_B_gap = calc_affine_penalty(1, open_B, extend_B,
00324                                   penalize_extend_when_opening);
00325 
00326     /* Allocate matrices for storing the results and initalize them. */
00327     lenA = PySequence_Length(py_sequenceA);
00328     lenB = PySequence_Length(py_sequenceB);
00329     score_matrix = malloc(lenA*lenB*sizeof(*score_matrix));
00330     trace_matrix = malloc(lenA*lenB*sizeof(*trace_matrix));
00331     if(!score_matrix || !trace_matrix) {
00332        PyErr_SetString(PyExc_MemoryError, "Out of memory");
00333        goto _cleanup_make_score_matrix_fast;
00334     }
00335     for(i=0; i<lenA*lenB; i++) {
00336        score_matrix[i] = 0;
00337        IndexList_init(&trace_matrix[i]);
00338     }
00339 
00340     /* Initialize the first row and col of the score matrix. */
00341     for(i=0; i<lenA; i++) {
00342        double score = _get_match_score(py_sequenceA, py_sequenceB, 
00343                                    py_match_fn, i, 0,
00344                                    sequenceA, sequenceB,
00345                                    use_sequence_cstring,
00346                                    match, mismatch,
00347                                    use_match_mismatch_scores);
00348        if(PyErr_Occurred())
00349            goto _cleanup_make_score_matrix_fast;
00350        if(penalize_end_gaps)
00351            score += calc_affine_penalty(i, open_B, extend_B, 
00352                                     penalize_extend_when_opening);
00353        score_matrix[i*lenB] = score;
00354     }
00355     for(i=0; i<lenB; i++) {
00356        double score = _get_match_score(py_sequenceA, py_sequenceB, 
00357                                    py_match_fn, 0, i,
00358                                    sequenceA, sequenceB,
00359                                    use_sequence_cstring,
00360                                    match, mismatch,
00361                                    use_match_mismatch_scores);
00362        if(PyErr_Occurred())
00363            goto _cleanup_make_score_matrix_fast;
00364        if(penalize_end_gaps)
00365            score += calc_affine_penalty(i, open_A, extend_A, 
00366                                     penalize_extend_when_opening);
00367        score_matrix[i] = score;
00368     }
00369 
00370     /* Now initialize the row and col cache. */
00371     row_cache_score = malloc((lenA-1)*sizeof(*row_cache_score));
00372     row_cache_index = malloc((lenA-1)* sizeof(*row_cache_index));
00373     col_cache_score = malloc((lenB-1)*sizeof(*col_cache_score));
00374     col_cache_index = malloc((lenB-1)* sizeof(*col_cache_index));
00375     if(!row_cache_score || !row_cache_index || 
00376        !col_cache_score || !col_cache_index) {
00377        PyErr_SetString(PyExc_MemoryError, "Out of memory");
00378        goto _cleanup_make_score_matrix_fast;
00379     }
00380     memset((void *)row_cache_score, 0, (lenA-1)*sizeof(*row_cache_score));
00381     memset((void *)row_cache_index, 0, (lenA-1)*sizeof(*row_cache_index));
00382     memset((void *)col_cache_score, 0, (lenB-1)*sizeof(*col_cache_score));
00383     memset((void *)col_cache_index, 0, (lenB-1)*sizeof(*col_cache_index));
00384     for(i=0; i<lenA-1; i++) {
00385        row_cache_score[i] = score_matrix[i*lenB] + first_A_gap;
00386        IndexList_append(&row_cache_index[i], i, 0);
00387     }
00388     for(i=0; i<lenB-1; i++) {
00389        col_cache_score[i] = score_matrix[i] + first_B_gap;
00390        IndexList_append(&col_cache_index[i], 0, i);
00391     }
00392 
00393     /* Fill in the score matrix. */
00394     for(row=1; row<lenA; row++) {
00395        for(col=1; col<lenB; col++) {
00396            double nogap_score, row_score, col_score, best_score;
00397            int best_score_rint;
00398            struct IndexList *il;
00399 
00400            double score, open_score, extend_score;
00401            int open_score_rint, extend_score_rint;
00402 
00403            /* Calculate the best score. */
00404            nogap_score = score_matrix[(row-1)*lenB+col-1];
00405            if(col > 1) {
00406               row_score = row_cache_score[row-1];
00407            } else {
00408               row_score = nogap_score-1; /* Make sure it's not best score */
00409            }
00410            if(row > 1) {
00411               col_score = col_cache_score[col-1];
00412            } else {
00413               col_score = nogap_score-1; /* Make sure it's not best score */
00414            }
00415 
00416            best_score = (row_score > col_score) ? row_score : col_score;
00417            if(nogap_score > best_score)
00418               best_score = nogap_score;
00419            best_score_rint = rint(best_score);
00420 
00421            /* Set the score and traceback matrices. */
00422            score = best_score + _get_match_score(py_sequenceA, py_sequenceB, 
00423                                             py_match_fn, row, col,
00424                                             sequenceA, sequenceB,
00425                                             use_sequence_cstring,
00426                                             match, mismatch,
00427                                             use_match_mismatch_scores);
00428            if(PyErr_Occurred())
00429               goto _cleanup_make_score_matrix_fast;
00430            if(!align_globally && score < 0)
00431               score_matrix[row*lenB+col] = 0;
00432            else
00433               score_matrix[row*lenB+col] = score;
00434 
00435            il = &trace_matrix[row*lenB+col];
00436            if(best_score_rint == rint(nogap_score)) {
00437               IndexList_append(il, row-1, col-1);
00438            }
00439            if(best_score_rint == rint(row_score)) {
00440               IndexList_extend(il, &row_cache_index[row-1]);
00441            }
00442            if(best_score_rint == rint(col_score)) {
00443               IndexList_extend(il, &col_cache_index[col-1]);
00444            }
00445 
00446            /* Update the cached column scores. */
00447            open_score = score_matrix[(row-1)*lenB+col-1] + first_B_gap;
00448            extend_score = col_cache_score[col-1] + extend_B;
00449            open_score_rint = rint(open_score);
00450            extend_score_rint = rint(extend_score);
00451            if(open_score_rint > extend_score_rint) {
00452               col_cache_score[col-1] = open_score;
00453               IndexList_clear(&col_cache_index[col-1]);
00454               IndexList_append(&col_cache_index[col-1], row-1, col-1);
00455            } else if(extend_score_rint > open_score_rint) {
00456               col_cache_score[col-1] = extend_score;
00457            } else {
00458               col_cache_score[col-1] = open_score;
00459               if(!IndexList_contains(&col_cache_index[col-1], row-1, col-1))
00460                   IndexList_append(&col_cache_index[col-1], row-1, col-1);
00461            }
00462            
00463            /* Update the cached row scores. */
00464            open_score = score_matrix[(row-1)*lenB+col-1] + first_A_gap;
00465            extend_score = row_cache_score[row-1] + extend_A;
00466            open_score_rint = rint(open_score);
00467            extend_score_rint = rint(extend_score);
00468            if(open_score_rint > extend_score_rint) {
00469               row_cache_score[row-1] = open_score;
00470               IndexList_clear(&row_cache_index[row-1]);
00471               IndexList_append(&row_cache_index[row-1], row-1, col-1);
00472            } else if(extend_score_rint > open_score_rint) {
00473               row_cache_score[row-1] = extend_score;
00474            } else {
00475               row_cache_score[row-1] = open_score;
00476               if(!IndexList_contains(&row_cache_index[row-1], row-1, col-1))
00477                   IndexList_append(&row_cache_index[row-1], row-1, col-1);
00478            }
00479        }
00480     }
00481 
00482     /* Save the score and traceback matrices into real python objects. */
00483     if(!(py_score_matrix = PyList_New(lenA)))
00484        goto _cleanup_make_score_matrix_fast;
00485     if(!(py_trace_matrix = PyList_New(lenA)))
00486        goto _cleanup_make_score_matrix_fast;
00487     for(row=0; row<lenA; row++) {
00488        PyObject *py_score_row, *py_trace_row;
00489        if(!(py_score_row = PyList_New(lenB)))
00490            goto _cleanup_make_score_matrix_fast;
00491        PyList_SET_ITEM(py_score_matrix, row, py_score_row);
00492        if(!(py_trace_row = PyList_New(lenB)))
00493            goto _cleanup_make_score_matrix_fast;
00494        PyList_SET_ITEM(py_trace_matrix, row, py_trace_row);
00495 
00496        for(col=0; col<lenB; col++) {
00497            int i;
00498            PyObject *py_score, *py_indexlist;
00499            int offset = row*lenB + col;
00500            struct IndexList *il = &trace_matrix[offset];
00501 
00502            /* Set py_score_matrix[row][col] to the score. */
00503            if(!(py_score = PyFloat_FromDouble(score_matrix[offset])))
00504               goto _cleanup_make_score_matrix_fast;
00505            PyList_SET_ITEM(py_score_row, col, py_score);
00506 
00507            if(score_only)
00508               continue;
00509            /* Set py_trace_matrix[row][col] to a list of indexes.  On
00510               the edges of the matrix (row or column is 0), the
00511               matrix should be [None]. */
00512            if(!row || !col) {
00513               if(!(py_indexlist = PyList_New(1)))
00514                   goto _cleanup_make_score_matrix_fast;
00515               Py_INCREF(Py_None);
00516               PyList_SET_ITEM(py_indexlist, 0, Py_None);
00517            }
00518            else {
00519               if(!(py_indexlist = PyList_New(il->num_used)))
00520                   goto _cleanup_make_score_matrix_fast;
00521               for(i=0; i<il->num_used; i++) {
00522                   PyObject *py_index=NULL;
00523                   int row = il->indexes[i*2],
00524                      col = il->indexes[i*2+1];
00525                   if(!(py_index = Py_BuildValue("(ii)", row, col)))
00526                      goto _cleanup_make_score_matrix_fast;
00527                   PyList_SET_ITEM(py_indexlist, i, py_index);
00528               }
00529            }
00530            PyList_SET_ITEM(py_trace_row, col, py_indexlist);
00531        }
00532     }
00533 
00534     py_retval = Py_BuildValue("(OO)", py_score_matrix, py_trace_matrix);
00535 
00536 
00537  _cleanup_make_score_matrix_fast:
00538     if(score_matrix)
00539        free(score_matrix);
00540     if(trace_matrix) {
00541        for(i=0; i<lenA*lenB; i++)
00542            IndexList_free(&trace_matrix[i]);
00543        free(trace_matrix);
00544     }
00545     if(row_cache_score)
00546        free(row_cache_score);
00547     if(col_cache_score)
00548        free(col_cache_score);
00549     if(row_cache_index) {
00550        for(i=0; i<lenA-1; i++)
00551            IndexList_free(&row_cache_index[i]);
00552        free(row_cache_index);
00553     }
00554     if(col_cache_index) {
00555        for(i=0; i<lenB-1; i++) {
00556            IndexList_free(&col_cache_index[i]);
00557        }
00558        free(col_cache_index);
00559     }
00560     if(py_score_matrix) {
00561        Py_DECREF(py_score_matrix);
00562     }
00563     if(py_trace_matrix) {
00564        Py_DECREF(py_trace_matrix);
00565     }
00566 #if PY_MAJOR_VERSION >= 3
00567     if (py_bytesA != NULL && py_bytesA != py_sequenceA) Py_DECREF(py_bytesA);
00568     if (py_bytesB != NULL && py_bytesB != py_sequenceB) Py_DECREF(py_bytesB);
00569 #endif
00570 
00571     return py_retval;
00572 }
00573 
00574 static PyObject *cpairwise2_rint(
00575     PyObject *self, PyObject *args, PyObject *keywds)
00576 {
00577     double x;
00578     int precision = _PRECISION;
00579     int rint_x;
00580 
00581     static char *kwlist[] = {"x", "precision", NULL};
00582 
00583     if(!PyArg_ParseTupleAndKeywords(args, keywds, "d|l", kwlist,
00584                                 &x, &precision))
00585        return NULL;
00586     rint_x = (int)(x * precision + 0.5);
00587 #if PY_MAJOR_VERSION >= 3
00588     return PyLong_FromLong((long)rint_x);
00589 #else
00590     return PyInt_FromLong((long)rint_x);
00591 #endif
00592 }
00593 
00594 /* Module definition stuff */
00595 
00596 static PyMethodDef cpairwise2Methods[] = {
00597     {"_make_score_matrix_fast", 
00598      (PyCFunction)cpairwise2__make_score_matrix_fast, METH_VARARGS, ""},
00599     {"rint", (PyCFunction)cpairwise2_rint, METH_VARARGS|METH_KEYWORDS, ""},
00600     {NULL, NULL, 0, NULL}
00601 };
00602 
00603 static char cpairwise2__doc__[] =
00604 "XXX document here\n\
00605 \n\
00606 ";
00607 
00608 #if PY_MAJOR_VERSION >= 3
00609 
00610 static struct PyModuleDef moduledef = {
00611         PyModuleDef_HEAD_INIT,
00612         "cpairwise2",
00613         cpairwise2__doc__,
00614         -1,
00615         cpairwise2Methods,
00616         NULL,
00617         NULL,
00618         NULL,
00619         NULL
00620 };
00621 
00622 PyObject *
00623 PyInit_cpairwise2(void)
00624 
00625 #else
00626 
00627 void
00628 initcpairwise2(void)
00629 #endif
00630 
00631 {
00632 #if PY_MAJOR_VERSION >= 3
00633     PyObject* module = PyModule_Create(&moduledef);
00634     if (module==NULL) return NULL;
00635     return module;
00636 #else
00637     (void) Py_InitModule3("cpairwise2", cpairwise2Methods, cpairwise2__doc__);
00638 #endif
00639 }