| 688 | } |
| 689 | |
| 690 | ndarray_handle* ndarray_create( |
| 691 | void* value, |
| 692 | size_t ndim, |
| 693 | const size_t* shape_in, |
| 694 | PyObject* owner, |
| 695 | const int64_t* strides_in, |
| 696 | dlpack::dtype* dtype, |
| 697 | int32_t device_type, |
| 698 | int32_t device_id |
| 699 | ) |
| 700 | { |
| 701 | /* DLPack mandates 256-byte alignment of the 'DLTensor::data' field, but |
| 702 | PyTorch unfortunately ignores the 'byte_offset' value.. :-( */ |
| 703 | #if 0 |
| 704 | uintptr_t value_int = (uintptr_t) value, |
| 705 | value_rounded = (value_int / 256) * 256; |
| 706 | #else |
| 707 | uintptr_t value_int = (uintptr_t)value, value_rounded = value_int; |
| 708 | #endif |
| 709 | |
| 710 | scoped_pymalloc<managed_dltensor> ndarray; |
| 711 | scoped_pymalloc<ndarray_handle> result; |
| 712 | scoped_pymalloc<int64_t> shape(ndim), strides(ndim); |
| 713 | |
| 714 | auto deleter = [](managed_dltensor* mt) |
| 715 | { |
| 716 | gil_scoped_acquire guard; |
| 717 | ndarray_handle* th = (ndarray_handle*)mt->manager_ctx; |
| 718 | ndarray_dec_ref(th); |
| 719 | }; |
| 720 | |
| 721 | for (size_t i = 0; i < ndim; ++i) |
| 722 | shape[i] = (int64_t)shape_in[i]; |
| 723 | |
| 724 | if (ndim > 0) |
| 725 | { |
| 726 | int64_t prod = 1; |
| 727 | for (size_t i = ndim - 1;;) |
| 728 | { |
| 729 | if (strides_in) |
| 730 | { |
| 731 | strides[i] = strides_in[i]; |
| 732 | } |
| 733 | else |
| 734 | { |
| 735 | strides[i] = prod; |
| 736 | prod *= (int64_t)shape_in[i]; |
| 737 | } |
| 738 | if (i == 0) |
| 739 | break; |
| 740 | --i; |
| 741 | } |
| 742 | } |
| 743 | |
| 744 | ndarray->dltensor.data = (void*)value_rounded; |
| 745 | ndarray->dltensor.device.device_type = device_type; |
| 746 | ndarray->dltensor.device.device_id = device_id; |
| 747 | ndarray->dltensor.ndim = (int32_t)ndim; |
no test coverage detected