| 431 | } |
| 432 | |
| 433 | static PyObject *LevenshteinDistances_call(LevenshteinDistances *self, PyObject *args, PyObject *kwargs) { |
| 434 | PyObject *a_obj = NULL, *b_obj = NULL, *device_obj = NULL, *out_obj = NULL; |
| 435 | |
| 436 | static char *kwlist[] = {"a", "b", "device", "out", NULL}; |
| 437 | if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|OO", kwlist, &a_obj, &b_obj, &device_obj, &out_obj)) return NULL; |
| 438 | |
| 439 | DeviceScope *device_scope = NULL; |
| 440 | if (device_obj != NULL && device_obj != Py_None) { |
| 441 | if (!PyObject_TypeCheck(device_obj, &DeviceScopeType)) { |
| 442 | PyErr_SetString(PyExc_TypeError, "device must be a DeviceScope instance"); |
| 443 | return NULL; |
| 444 | } |
| 445 | device_scope = (DeviceScope *)device_obj; |
| 446 | } |
| 447 | |
| 448 | szs_device_scope_t device_handle = device_scope ? device_scope->handle : default_device_scope; |
| 449 | sz_size_t kernel_input_size = 0; |
| 450 | void *kernel_a_texts_punned = NULL; |
| 451 | void *kernel_b_texts_punned = NULL; |
| 452 | sz_size_t *kernel_results = NULL; |
| 453 | sz_size_t kernel_results_stride = sizeof(sz_size_t); |
| 454 | sz_status_t (*kernel_punned)(szs_levenshtein_distances_t, szs_device_scope_t, void *, void *, sz_size_t *, |
| 455 | sz_size_t, char const **) = NULL; |
| 456 | |
| 457 | // Swap allocators only when using CUDA with a GPU device (inputs must be unified) |
| 458 | if (requires_unified_memory(self->capabilities)) |
| 459 | if (!try_swap_to_unified_allocator(a_obj) || !try_swap_to_unified_allocator(b_obj)) return NULL; |
| 460 | |
| 461 | // Handle 32-bit tape inputs |
| 462 | sz_sequence_u32tape_t a_u32tape, b_u32tape; |
| 463 | sz_bool_t a_is_u32tape = sz_py_export_strings_as_u32tape( // |
| 464 | a_obj, &a_u32tape.data, &a_u32tape.offsets, &a_u32tape.count); |
| 465 | sz_bool_t b_is_u32tape = sz_py_export_strings_as_u32tape( // |
| 466 | b_obj, &b_u32tape.data, &b_u32tape.offsets, &b_u32tape.count); |
| 467 | if (a_is_u32tape && b_is_u32tape) { |
| 468 | if (a_u32tape.count != b_u32tape.count) { |
| 469 | PyErr_SetString(PyExc_ValueError, "Input sequences must have the same length"); |
| 470 | return NULL; |
| 471 | } |
| 472 | |
| 473 | kernel_input_size = a_u32tape.count; |
| 474 | kernel_punned = szs_levenshtein_distances_u32tape; |
| 475 | kernel_a_texts_punned = &a_u32tape; |
| 476 | kernel_b_texts_punned = &b_u32tape; |
| 477 | } |
| 478 | |
| 479 | // Handle 64-bit tape inputs |
| 480 | sz_sequence_u64tape_t a_u64tape, b_u64tape; |
| 481 | sz_bool_t a_is_u64tape = !a_is_u32tape && sz_py_export_strings_as_u64tape( // |
| 482 | a_obj, &a_u64tape.data, &a_u64tape.offsets, &a_u64tape.count); |
| 483 | sz_bool_t b_is_u64tape = !b_is_u32tape && sz_py_export_strings_as_u64tape( // |
| 484 | b_obj, &b_u64tape.data, &b_u64tape.offsets, &b_u64tape.count); |
| 485 | if (a_is_u64tape && b_is_u64tape) { |
| 486 | if (a_u64tape.count != b_u64tape.count) { |
| 487 | PyErr_SetString(PyExc_ValueError, "Input sequences must have the same length"); |
| 488 | return NULL; |
| 489 | } |
| 490 | kernel_input_size = a_u64tape.count; |
nothing calls this directly
no test coverage detected
searching dependent graphs…