| 1610 | } |
| 1611 | |
| 1612 | static PyObject *Fingerprints_call(Fingerprints *self, PyObject *args, PyObject *kwargs) { |
| 1613 | |
| 1614 | PyObject *texts_obj = NULL, *device_obj = NULL, *out_obj = NULL; |
| 1615 | static char *kwlist[] = {"texts", "device", "out", NULL}; |
| 1616 | if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OO", kwlist, &texts_obj, &device_obj, &out_obj)) return NULL; |
| 1617 | |
| 1618 | DeviceScope *device_scope = NULL; |
| 1619 | if (device_obj != NULL && device_obj != Py_None) { |
| 1620 | if (!PyObject_TypeCheck(device_obj, &DeviceScopeType)) { |
| 1621 | PyErr_SetString(PyExc_TypeError, "device must be a DeviceScope instance"); |
| 1622 | return NULL; |
| 1623 | } |
| 1624 | device_scope = (DeviceScope *)device_obj; |
| 1625 | } |
| 1626 | |
| 1627 | szs_device_scope_t device_handle = device_scope ? device_scope->handle : default_device_scope; |
| 1628 | |
| 1629 | // Handle empty input - return tuple of empty arrays |
| 1630 | if (PySequence_Check(texts_obj) && PySequence_Size(texts_obj) == 0) { |
| 1631 | npy_intp dims[2] = {0, self->ndim}; |
| 1632 | PyArrayObject *empty_hashes = (PyArrayObject *)PyArray_SimpleNew(2, dims, NPY_UINT32); |
| 1633 | PyArrayObject *empty_counts = (PyArrayObject *)PyArray_SimpleNew(2, dims, NPY_UINT32); |
| 1634 | |
| 1635 | if (!empty_hashes || !empty_counts) { |
| 1636 | Py_XDECREF(empty_hashes); |
| 1637 | Py_XDECREF(empty_counts); |
| 1638 | return PyErr_NoMemory(); |
| 1639 | } |
| 1640 | |
| 1641 | PyObject *result_tuple = PyTuple_New(2); |
| 1642 | if (!result_tuple) { |
| 1643 | Py_DECREF(empty_hashes); |
| 1644 | Py_DECREF(empty_counts); |
| 1645 | return NULL; |
| 1646 | } |
| 1647 | |
| 1648 | PyTuple_SET_ITEM(result_tuple, 0, (PyObject *)empty_hashes); |
| 1649 | PyTuple_SET_ITEM(result_tuple, 1, (PyObject *)empty_counts); |
| 1650 | return result_tuple; |
| 1651 | } |
| 1652 | |
| 1653 | // Swap allocators only when using CUDA with a GPU device (inputs must be unified) |
| 1654 | sz_bool_t need_unified = requires_unified_memory(self->capabilities); |
| 1655 | if (need_unified) |
| 1656 | if (!try_swap_to_unified_allocator(texts_obj)) return NULL; |
| 1657 | |
| 1658 | sz_size_t kernel_input_size = 0; |
| 1659 | void *kernel_texts_punned = NULL; |
| 1660 | sz_status_t (*kernel_punned)(szs_fingerprints_t, szs_device_scope_t, void *, sz_u32_t *, sz_size_t, sz_u32_t *, |
| 1661 | sz_size_t, char const **) = NULL; |
| 1662 | |
| 1663 | // Handle 32-bit tape inputs |
| 1664 | sz_sequence_u32tape_t texts_u32tape; |
| 1665 | sz_bool_t texts_is_u32tape = sz_py_export_strings_as_u32tape( // |
| 1666 | texts_obj, &texts_u32tape.data, &texts_u32tape.offsets, &texts_u32tape.count); |
| 1667 | if (texts_is_u32tape) { |
| 1668 | kernel_input_size = texts_u32tape.count; |
| 1669 | kernel_punned = szs_fingerprints_u32tape; |
nothing calls this directly
no test coverage detected
searching dependent graphs…