annotate CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/lib/python3.8/site-packages/Bio/cpairwise2module.c @ 69:33d812a61356

planemo upload commit 2e9511a184a1ca667c7be0c6321a36dc4e3d116d
author jpayne
date Tue, 18 Mar 2025 17:55:14 -0400
parents
children
rev   line source
jpayne@69 1 /* Copyright 2002 by Jeffrey Chang.
jpayne@69 2 * Copyright 2016, 2019 by Markus Piotrowski.
jpayne@69 3 * All rights reserved.
jpayne@69 4 *
jpayne@69 5 * This file is part of the Biopython distribution and governed by your
jpayne@69 6 * choice of the "Biopython License Agreement" or the "BSD 3-Clause License".
jpayne@69 7 * Please see the LICENSE file that should have been included as part of this
jpayne@69 8 * package.
jpayne@69 9 *
jpayne@69 10 * cpairwise2module.c
jpayne@69 11 * Created 30 Sep 2001
jpayne@69 12 *
jpayne@69 13 * Optimized C routines that complement pairwise2.py.
jpayne@69 14 */
jpayne@69 15
jpayne@69 16 #include "Python.h"
jpayne@69 17
jpayne@69 18
jpayne@69 19 #define _PRECISION 1000
jpayne@69 20 #define rint(x) (int)((x)*_PRECISION+0.5)
jpayne@69 21
jpayne@69 22 /* Functions in this module. */
jpayne@69 23
jpayne@69 24 static double calc_affine_penalty(int length, double open, double extend,
jpayne@69 25 int penalize_extend_when_opening)
jpayne@69 26 {
jpayne@69 27 double penalty;
jpayne@69 28
jpayne@69 29 if(length <= 0)
jpayne@69 30 return 0.0;
jpayne@69 31 penalty = open + extend * length;
jpayne@69 32 if(!penalize_extend_when_opening)
jpayne@69 33 penalty -= extend;
jpayne@69 34 return penalty;
jpayne@69 35 }
jpayne@69 36
jpayne@69 37 static double _get_match_score(PyObject *py_sequenceA, PyObject *py_sequenceB,
jpayne@69 38 PyObject *py_match_fn, int i, int j,
jpayne@69 39 char *sequenceA, char *sequenceB,
jpayne@69 40 int use_sequence_cstring,
jpayne@69 41 double match, double mismatch,
jpayne@69 42 int use_match_mismatch_scores)
jpayne@69 43 {
jpayne@69 44 PyObject *py_A=NULL, *py_B=NULL;
jpayne@69 45 PyObject *py_arglist=NULL, *py_result=NULL;
jpayne@69 46 double score = 0;
jpayne@69 47
jpayne@69 48 if(use_sequence_cstring && use_match_mismatch_scores) {
jpayne@69 49 score = (sequenceA[i] == sequenceB[j]) ? match : mismatch;
jpayne@69 50 return score;
jpayne@69 51 }
jpayne@69 52 /* Calculate the match score. */
jpayne@69 53 if(!(py_A = PySequence_GetItem(py_sequenceA, i)))
jpayne@69 54 goto _get_match_score_cleanup;
jpayne@69 55 if(!(py_B = PySequence_GetItem(py_sequenceB, j)))
jpayne@69 56 goto _get_match_score_cleanup;
jpayne@69 57 if(!(py_arglist = Py_BuildValue("(OO)", py_A, py_B)))
jpayne@69 58 goto _get_match_score_cleanup;
jpayne@69 59
jpayne@69 60 if(!(py_result = PyEval_CallObject(py_match_fn, py_arglist)))
jpayne@69 61 goto _get_match_score_cleanup;
jpayne@69 62 score = PyFloat_AsDouble(py_result);
jpayne@69 63
jpayne@69 64 _get_match_score_cleanup:
jpayne@69 65 if(py_A) {
jpayne@69 66 Py_DECREF(py_A);
jpayne@69 67 }
jpayne@69 68 if(py_B) {
jpayne@69 69 Py_DECREF(py_B);
jpayne@69 70 }
jpayne@69 71 if(py_arglist) {
jpayne@69 72 Py_DECREF(py_arglist);
jpayne@69 73 }
jpayne@69 74 if(py_result) {
jpayne@69 75 Py_DECREF(py_result);
jpayne@69 76 }
jpayne@69 77 return score;
jpayne@69 78 }
jpayne@69 79
jpayne@69 80 #if PY_MAJOR_VERSION >= 3
jpayne@69 81 static PyObject* _create_bytes_object(PyObject* o)
jpayne@69 82 {
jpayne@69 83 PyObject* b;
jpayne@69 84 if (PyBytes_Check(o)) {
jpayne@69 85 return o;
jpayne@69 86 }
jpayne@69 87 if (!PyUnicode_Check(o)) {
jpayne@69 88 return NULL;
jpayne@69 89 }
jpayne@69 90 b = PyUnicode_AsASCIIString(o);
jpayne@69 91 if (!b) {
jpayne@69 92 PyErr_Clear();
jpayne@69 93 return NULL;
jpayne@69 94 }
jpayne@69 95 return b;
jpayne@69 96 }
jpayne@69 97 #endif
jpayne@69 98
jpayne@69 99 /* This function is a more-or-less straightforward port of the
jpayne@69 100 * equivalent function in pairwise2. Please see there for algorithm
jpayne@69 101 * documentation.
jpayne@69 102 */
jpayne@69 103 static PyObject *cpairwise2__make_score_matrix_fast(PyObject *self,
jpayne@69 104 PyObject *args)
jpayne@69 105 {
jpayne@69 106 int i;
jpayne@69 107 int row, col;
jpayne@69 108 PyObject *py_sequenceA, *py_sequenceB, *py_match_fn;
jpayne@69 109 #if PY_MAJOR_VERSION >= 3
jpayne@69 110 PyObject *py_bytesA, *py_bytesB;
jpayne@69 111 #endif
jpayne@69 112 char *sequenceA=NULL, *sequenceB=NULL;
jpayne@69 113 int use_sequence_cstring;
jpayne@69 114 double open_A, extend_A, open_B, extend_B;
jpayne@69 115 int penalize_extend_when_opening, penalize_end_gaps_A, penalize_end_gaps_B;
jpayne@69 116 int align_globally, score_only;
jpayne@69 117
jpayne@69 118 PyObject *py_match=NULL, *py_mismatch=NULL;
jpayne@69 119 double first_A_gap, first_B_gap;
jpayne@69 120 double match, mismatch;
jpayne@69 121 double score;
jpayne@69 122 double best_score = 0;
jpayne@69 123 double local_max_score = 0;
jpayne@69 124 int use_match_mismatch_scores;
jpayne@69 125 int lenA, lenB;
jpayne@69 126 double *score_matrix = NULL;
jpayne@69 127 unsigned char *trace_matrix = NULL;
jpayne@69 128 PyObject *py_score_matrix=NULL, *py_trace_matrix=NULL;
jpayne@69 129
jpayne@69 130 double *col_cache_score = NULL;
jpayne@69 131 PyObject *py_retval = NULL;
jpayne@69 132
jpayne@69 133 if(!PyArg_ParseTuple(args, "OOOddddi(ii)ii", &py_sequenceA, &py_sequenceB,
jpayne@69 134 &py_match_fn, &open_A, &extend_A, &open_B, &extend_B,
jpayne@69 135 &penalize_extend_when_opening,
jpayne@69 136 &penalize_end_gaps_A, &penalize_end_gaps_B,
jpayne@69 137 &align_globally, &score_only))
jpayne@69 138 return NULL;
jpayne@69 139 if(!PySequence_Check(py_sequenceA) || !PySequence_Check(py_sequenceB)) {
jpayne@69 140 PyErr_SetString(PyExc_TypeError,
jpayne@69 141 "py_sequenceA and py_sequenceB should be sequences.");
jpayne@69 142 return NULL;
jpayne@69 143 }
jpayne@69 144
jpayne@69 145 /* Optimize for the common case. Check to see if py_sequenceA and
jpayne@69 146 py_sequenceB are strings. If they are, use the c string
jpayne@69 147 representation. */
jpayne@69 148 #if PY_MAJOR_VERSION < 3
jpayne@69 149 use_sequence_cstring = 0;
jpayne@69 150 if(PyString_Check(py_sequenceA) && PyString_Check(py_sequenceB)) {
jpayne@69 151 sequenceA = PyString_AS_STRING(py_sequenceA);
jpayne@69 152 sequenceB = PyString_AS_STRING(py_sequenceB);
jpayne@69 153 use_sequence_cstring = 1;
jpayne@69 154 }
jpayne@69 155 #else
jpayne@69 156 py_bytesA = _create_bytes_object(py_sequenceA);
jpayne@69 157 py_bytesB = _create_bytes_object(py_sequenceB);
jpayne@69 158 if (py_bytesA && py_bytesB) {
jpayne@69 159 sequenceA = PyBytes_AS_STRING(py_bytesA);
jpayne@69 160 sequenceB = PyBytes_AS_STRING(py_bytesB);
jpayne@69 161 use_sequence_cstring = 1;
jpayne@69 162 }
jpayne@69 163 else {
jpayne@69 164 Py_XDECREF(py_bytesA);
jpayne@69 165 Py_XDECREF(py_bytesB);
jpayne@69 166 use_sequence_cstring = 0;
jpayne@69 167 }
jpayne@69 168 #endif
jpayne@69 169
jpayne@69 170 if(!PyCallable_Check(py_match_fn)) {
jpayne@69 171 PyErr_SetString(PyExc_TypeError, "py_match_fn must be callable.");
jpayne@69 172 return NULL;
jpayne@69 173 }
jpayne@69 174 /* Optimize for the common case. Check to see if py_match_fn is
jpayne@69 175 an identity_match. If so, pull out the match and mismatch
jpayne@69 176 member variables and calculate the scores myself. */
jpayne@69 177 match = mismatch = 0;
jpayne@69 178 use_match_mismatch_scores = 0;
jpayne@69 179 if(!(py_match = PyObject_GetAttrString(py_match_fn, "match")))
jpayne@69 180 goto cleanup_after_py_match_fn;
jpayne@69 181 match = PyFloat_AsDouble(py_match);
jpayne@69 182 if(match==-1.0 && PyErr_Occurred())
jpayne@69 183 goto cleanup_after_py_match_fn;
jpayne@69 184 if(!(py_mismatch = PyObject_GetAttrString(py_match_fn, "mismatch")))
jpayne@69 185 goto cleanup_after_py_match_fn;
jpayne@69 186 mismatch = PyFloat_AsDouble(py_mismatch);
jpayne@69 187 if(mismatch==-1.0 && PyErr_Occurred())
jpayne@69 188 goto cleanup_after_py_match_fn;
jpayne@69 189 use_match_mismatch_scores = 1;
jpayne@69 190
jpayne@69 191 cleanup_after_py_match_fn:
jpayne@69 192 if(PyErr_Occurred())
jpayne@69 193 PyErr_Clear();
jpayne@69 194 if(py_match) {
jpayne@69 195 Py_DECREF(py_match);
jpayne@69 196 }
jpayne@69 197 if(py_mismatch) {
jpayne@69 198 Py_DECREF(py_mismatch);
jpayne@69 199 }
jpayne@69 200 /* Cache some commonly used gap penalties */
jpayne@69 201 first_A_gap = calc_affine_penalty(1, open_A, extend_A,
jpayne@69 202 penalize_extend_when_opening);
jpayne@69 203 first_B_gap = calc_affine_penalty(1, open_B, extend_B,
jpayne@69 204 penalize_extend_when_opening);
jpayne@69 205
jpayne@69 206 /* Allocate matrices for storing the results and initialize first row and col. */
jpayne@69 207 lenA = PySequence_Length(py_sequenceA);
jpayne@69 208 lenB = PySequence_Length(py_sequenceB);
jpayne@69 209 score_matrix = malloc((lenA+1)*(lenB+1)*sizeof(*score_matrix));
jpayne@69 210 if(!score_matrix) {
jpayne@69 211 PyErr_SetString(PyExc_MemoryError, "Out of memory");
jpayne@69 212 goto _cleanup_make_score_matrix_fast;
jpayne@69 213 }
jpayne@69 214 for(i=0; i<(lenB+1); i++)
jpayne@69 215 score_matrix[i] = 0;
jpayne@69 216 for(i=0; i<(lenA+1)*(lenB+1); i += (lenB+1))
jpayne@69 217 score_matrix[i] = 0;
jpayne@69 218 /* If we only want the score, we don't need the trace matrix. */
jpayne@69 219 if (!score_only){
jpayne@69 220 trace_matrix = malloc((lenA+1)*(lenB+1)*sizeof(*trace_matrix));
jpayne@69 221 if(!trace_matrix) {
jpayne@69 222 PyErr_SetString(PyExc_MemoryError, "Out of memory");
jpayne@69 223 goto _cleanup_make_score_matrix_fast;
jpayne@69 224 }
jpayne@69 225 for(i=0; i<(lenB+1); i++)
jpayne@69 226 trace_matrix[i] = 0;
jpayne@69 227 for(i=0; i<(lenA+1)*(lenB+1); i += (lenB+1))
jpayne@69 228 trace_matrix[i] = 0;
jpayne@69 229 }
jpayne@69 230 else
jpayne@69 231 trace_matrix = malloc(1);
jpayne@69 232
jpayne@69 233 /* Initialize the first row and col of the score matrix. */
jpayne@69 234 for(i=0; i<=lenA; i++) {
jpayne@69 235 if(penalize_end_gaps_B)
jpayne@69 236 score = calc_affine_penalty(i, open_B, extend_B,
jpayne@69 237 penalize_extend_when_opening);
jpayne@69 238 else
jpayne@69 239 score = 0;
jpayne@69 240 score_matrix[i*(lenB+1)] = score;
jpayne@69 241 }
jpayne@69 242 for(i=0; i<=lenB; i++) {
jpayne@69 243 if(penalize_end_gaps_A)
jpayne@69 244 score = calc_affine_penalty(i, open_A, extend_A,
jpayne@69 245 penalize_extend_when_opening);
jpayne@69 246 else
jpayne@69 247 score = 0;
jpayne@69 248 score_matrix[i] = score;
jpayne@69 249 }
jpayne@69 250
jpayne@69 251 /* Now initialize the col cache. */
jpayne@69 252 col_cache_score = malloc((lenB+1)*sizeof(*col_cache_score));
jpayne@69 253 memset((void *)col_cache_score, 0, (lenB+1)*sizeof(*col_cache_score));
jpayne@69 254 for(i=0; i<=lenB; i++) {
jpayne@69 255 col_cache_score[i] = calc_affine_penalty(i, (2*open_B), extend_B,
jpayne@69 256 penalize_extend_when_opening);
jpayne@69 257 }
jpayne@69 258
jpayne@69 259 /* Fill in the score matrix. The row cache is calculated on the fly.*/
jpayne@69 260 for(row=1; row<=lenA; row++) {
jpayne@69 261 double row_cache_score = calc_affine_penalty(row, (2*open_A), extend_A,
jpayne@69 262 penalize_extend_when_opening);
jpayne@69 263 for(col=1; col<=lenB; col++) {
jpayne@69 264 double match_score, nogap_score;
jpayne@69 265 double row_open, row_extend, col_open, col_extend;
jpayne@69 266 int best_score_rint, row_score_rint, col_score_rint;
jpayne@69 267 unsigned char row_trace_score, col_trace_score, trace_score;
jpayne@69 268
jpayne@69 269 /* Calculate the best score. */
jpayne@69 270 match_score = _get_match_score(py_sequenceA, py_sequenceB,
jpayne@69 271 py_match_fn, row-1, col-1,
jpayne@69 272 sequenceA, sequenceB,
jpayne@69 273 use_sequence_cstring,
jpayne@69 274 match, mismatch,
jpayne@69 275 use_match_mismatch_scores);
jpayne@69 276 if(match_score==-1.0 && PyErr_Occurred())
jpayne@69 277 goto _cleanup_make_score_matrix_fast;
jpayne@69 278 nogap_score = score_matrix[(row-1)*(lenB+1)+col-1] + match_score;
jpayne@69 279
jpayne@69 280 if (!penalize_end_gaps_A && row==lenA) {
jpayne@69 281 row_open = score_matrix[(row)*(lenB+1)+col-1];
jpayne@69 282 row_extend = row_cache_score;
jpayne@69 283 }
jpayne@69 284 else {
jpayne@69 285 row_open = score_matrix[(row)*(lenB+1)+col-1] + first_A_gap;
jpayne@69 286 row_extend = row_cache_score + extend_A;
jpayne@69 287 }
jpayne@69 288 row_cache_score = (row_open > row_extend) ? row_open : row_extend;
jpayne@69 289
jpayne@69 290 if (!penalize_end_gaps_B && col==lenB){
jpayne@69 291 col_open = score_matrix[(row-1)*(lenB+1)+col];
jpayne@69 292 col_extend = col_cache_score[col];
jpayne@69 293 }
jpayne@69 294 else {
jpayne@69 295 col_open = score_matrix[(row-1)*(lenB+1)+col] + first_B_gap;
jpayne@69 296 col_extend = col_cache_score[col] + extend_B;
jpayne@69 297 }
jpayne@69 298 col_cache_score[col] = (col_open > col_extend) ? col_open : col_extend;
jpayne@69 299
jpayne@69 300 best_score = (row_cache_score > col_cache_score[col]) ? row_cache_score : col_cache_score[col];
jpayne@69 301 if(nogap_score > best_score)
jpayne@69 302 best_score = nogap_score;
jpayne@69 303
jpayne@69 304 if (best_score > local_max_score)
jpayne@69 305 local_max_score = best_score;
jpayne@69 306
jpayne@69 307 if(!align_globally && best_score < 0)
jpayne@69 308 score_matrix[row*(lenB+1)+col] = 0;
jpayne@69 309 else
jpayne@69 310 score_matrix[row*(lenB+1)+col] = best_score;
jpayne@69 311
jpayne@69 312 if (!score_only) {
jpayne@69 313 row_score_rint = rint(row_cache_score);
jpayne@69 314 col_score_rint = rint(col_cache_score[col]);
jpayne@69 315 row_trace_score = 0;
jpayne@69 316 col_trace_score = 0;
jpayne@69 317 if (rint(row_open) == row_score_rint)
jpayne@69 318 row_trace_score = row_trace_score|1;
jpayne@69 319 if (rint(row_extend) == row_score_rint)
jpayne@69 320 row_trace_score = row_trace_score|8;
jpayne@69 321 if (rint(col_open) == col_score_rint)
jpayne@69 322 col_trace_score = col_trace_score|4;
jpayne@69 323 if (rint(col_extend) == col_score_rint)
jpayne@69 324 col_trace_score = col_trace_score|16;
jpayne@69 325
jpayne@69 326 trace_score = 0;
jpayne@69 327 best_score_rint = rint(best_score);
jpayne@69 328 if (rint(nogap_score) == best_score_rint)
jpayne@69 329 trace_score = trace_score|2;
jpayne@69 330 if (row_score_rint == best_score_rint)
jpayne@69 331 trace_score += row_trace_score;
jpayne@69 332 if (col_score_rint == best_score_rint)
jpayne@69 333 trace_score += col_trace_score;
jpayne@69 334 trace_matrix[row*(lenB+1)+col] = trace_score;
jpayne@69 335 }
jpayne@69 336 }
jpayne@69 337 }
jpayne@69 338
jpayne@69 339 if (!align_globally)
jpayne@69 340 best_score = local_max_score;
jpayne@69 341
jpayne@69 342 /* Save the score and traceback matrices into real python objects. */
jpayne@69 343 if(!score_only) {
jpayne@69 344 if(!(py_score_matrix = PyList_New(lenA+1)))
jpayne@69 345 goto _cleanup_make_score_matrix_fast;
jpayne@69 346 if(!(py_trace_matrix = PyList_New(lenA+1)))
jpayne@69 347 goto _cleanup_make_score_matrix_fast;
jpayne@69 348
jpayne@69 349 for(row=0; row<=lenA; row++) {
jpayne@69 350 PyObject *py_score_row, *py_trace_row;
jpayne@69 351 if(!(py_score_row = PyList_New(lenB+1)))
jpayne@69 352 goto _cleanup_make_score_matrix_fast;
jpayne@69 353 PyList_SET_ITEM(py_score_matrix, row, py_score_row);
jpayne@69 354 if(!(py_trace_row = PyList_New(lenB+1)))
jpayne@69 355 goto _cleanup_make_score_matrix_fast;
jpayne@69 356 PyList_SET_ITEM(py_trace_matrix, row, py_trace_row);
jpayne@69 357
jpayne@69 358 for(col=0; col<=lenB; col++) {
jpayne@69 359 PyObject *py_score, *py_trace;
jpayne@69 360 int offset = row*(lenB+1) + col;
jpayne@69 361
jpayne@69 362 /* Set py_score_matrix[row][col] to the score. */
jpayne@69 363 if(!(py_score = PyFloat_FromDouble(score_matrix[offset])))
jpayne@69 364 goto _cleanup_make_score_matrix_fast;
jpayne@69 365 PyList_SET_ITEM(py_score_row, col, py_score);
jpayne@69 366
jpayne@69 367 /* Set py_trace_matrix[row][col] to a list of indexes. On
jpayne@69 368 the edges of the matrix (row or column is 0), the
jpayne@69 369 matrix should be [None]. */
jpayne@69 370 if(!row || !col) {
jpayne@69 371 if(!(py_trace = Py_BuildValue("B", 1)))
jpayne@69 372 goto _cleanup_make_score_matrix_fast;
jpayne@69 373 Py_INCREF(Py_None);
jpayne@69 374 PyList_SET_ITEM(py_trace_row, col, Py_None);
jpayne@69 375 }
jpayne@69 376 else {
jpayne@69 377 if(!(py_trace = Py_BuildValue("B", trace_matrix[offset])))
jpayne@69 378 goto _cleanup_make_score_matrix_fast;
jpayne@69 379 PyList_SET_ITEM(py_trace_row, col, py_trace);
jpayne@69 380
jpayne@69 381 }
jpayne@69 382 }
jpayne@69 383 }
jpayne@69 384 }
jpayne@69 385 else {
jpayne@69 386 py_score_matrix = PyList_New(1);
jpayne@69 387 py_trace_matrix = PyList_New(1);
jpayne@69 388 }
jpayne@69 389 py_retval = Py_BuildValue("(OOd)", py_score_matrix, py_trace_matrix, best_score);
jpayne@69 390
jpayne@69 391 _cleanup_make_score_matrix_fast:
jpayne@69 392 if(score_matrix)
jpayne@69 393 free(score_matrix);
jpayne@69 394 if(trace_matrix)
jpayne@69 395 free(trace_matrix);
jpayne@69 396 if(col_cache_score)
jpayne@69 397 free(col_cache_score);
jpayne@69 398 if(py_score_matrix){
jpayne@69 399 Py_DECREF(py_score_matrix);
jpayne@69 400 }
jpayne@69 401 if(py_trace_matrix){
jpayne@69 402 Py_DECREF(py_trace_matrix);
jpayne@69 403 }
jpayne@69 404
jpayne@69 405 #if PY_MAJOR_VERSION >= 3
jpayne@69 406 if (py_bytesA != NULL && py_bytesA != py_sequenceA) Py_DECREF(py_bytesA);
jpayne@69 407 if (py_bytesB != NULL && py_bytesB != py_sequenceB) Py_DECREF(py_bytesB);
jpayne@69 408 #endif
jpayne@69 409
jpayne@69 410 return py_retval;
jpayne@69 411 }
jpayne@69 412
jpayne@69 413 static PyObject *cpairwise2_rint(PyObject *self, PyObject *args,
jpayne@69 414 PyObject *keywds)
jpayne@69 415 {
jpayne@69 416 double x;
jpayne@69 417 int precision = _PRECISION;
jpayne@69 418 int rint_x;
jpayne@69 419
jpayne@69 420 static char *kwlist[] = {"x", "precision", NULL};
jpayne@69 421
jpayne@69 422 if(!PyArg_ParseTupleAndKeywords(args, keywds, "d|l", kwlist,
jpayne@69 423 &x, &precision))
jpayne@69 424 return NULL;
jpayne@69 425 rint_x = (int)(x * precision + 0.5);
jpayne@69 426 #if PY_MAJOR_VERSION >= 3
jpayne@69 427 return PyLong_FromLong((long)rint_x);
jpayne@69 428 #else
jpayne@69 429 return PyInt_FromLong((long)rint_x);
jpayne@69 430 #endif
jpayne@69 431 }
jpayne@69 432
jpayne@69 433 /* Module definition stuff */
jpayne@69 434
jpayne@69 435 static PyMethodDef cpairwise2Methods[] = {
jpayne@69 436 {"_make_score_matrix_fast",
jpayne@69 437 (PyCFunction)cpairwise2__make_score_matrix_fast, METH_VARARGS, ""},
jpayne@69 438 {"rint", (PyCFunction)cpairwise2_rint, METH_VARARGS|METH_KEYWORDS, ""},
jpayne@69 439 {NULL, NULL, 0, NULL}
jpayne@69 440 };
jpayne@69 441
jpayne@69 442 static char cpairwise2__doc__[] =
jpayne@69 443 "Optimized C routines that complement pairwise2.py. These are called from within pairwise2.py.\n\
jpayne@69 444 \n\
jpayne@69 445 ";
jpayne@69 446
jpayne@69 447 #if PY_MAJOR_VERSION >= 3
jpayne@69 448
jpayne@69 449 static struct PyModuleDef moduledef = {
jpayne@69 450 PyModuleDef_HEAD_INIT,
jpayne@69 451 "cpairwise2",
jpayne@69 452 cpairwise2__doc__,
jpayne@69 453 -1,
jpayne@69 454 cpairwise2Methods,
jpayne@69 455 NULL,
jpayne@69 456 NULL,
jpayne@69 457 NULL,
jpayne@69 458 NULL
jpayne@69 459 };
jpayne@69 460
jpayne@69 461 PyObject *
jpayne@69 462 PyInit_cpairwise2(void)
jpayne@69 463
jpayne@69 464 #else
jpayne@69 465
jpayne@69 466 void
jpayne@69 467 /* for Windows: _declspec(dllexport) initcpairwise2(void) */
jpayne@69 468 initcpairwise2(void)
jpayne@69 469 #endif
jpayne@69 470
jpayne@69 471 {
jpayne@69 472 #if PY_MAJOR_VERSION >= 3
jpayne@69 473 PyObject* module = PyModule_Create(&moduledef);
jpayne@69 474 if (module==NULL) return NULL;
jpayne@69 475 return module;
jpayne@69 476 #else
jpayne@69 477 (void) Py_InitModule3("cpairwise2", cpairwise2Methods, cpairwise2__doc__);
jpayne@69 478 #endif
jpayne@69 479 }