| 195 | } |
| 196 | |
| 197 | StatusOr<py::object> LiteralToPython(std::shared_ptr<xla::Literal> literal) { |
| 198 | xla::Literal& m = *literal; |
| 199 | if (m.shape().IsTuple()) { |
| 200 | std::vector<Literal> elems = m.DecomposeTuple(); |
| 201 | std::vector<py::object> arrays(elems.size()); |
| 202 | for (int i = 0; i < elems.size(); ++i) { |
| 203 | TF_ASSIGN_OR_RETURN( |
| 204 | arrays[i], |
| 205 | LiteralToPython(absl::make_unique<Literal>(std::move(elems[i])))); |
| 206 | } |
| 207 | py::tuple result(elems.size()); |
| 208 | for (int i = 0; i < elems.size(); ++i) { |
| 209 | PyTuple_SET_ITEM(result.ptr(), i, arrays[i].release().ptr()); |
| 210 | } |
| 211 | return result; |
| 212 | } |
| 213 | TF_RET_CHECK(m.shape().IsArray()); |
| 214 | |
| 215 | py::object literal_object = py::cast(literal); |
| 216 | TF_ASSIGN_OR_RETURN(std::string format, FormatDescriptorForPrimitiveType( |
| 217 | m.shape().element_type())); |
| 218 | py::buffer_info info( |
| 219 | m.untyped_data(), // Pointer to buffer |
| 220 | xla::ShapeUtil::ByteSizeOfPrimitiveType( |
| 221 | m.shape().element_type()), // Size of one scalar |
| 222 | format, // Python struct-style format descriptor |
| 223 | m.shape().dimensions_size(), // Number of dimensions |
| 224 | m.shape().dimensions(), // Buffer dimensions |
| 225 | ByteStridesForShape(m.shape()) // Strides (in bytes) for each index |
| 226 | ); |
| 227 | |
| 228 | py::array array(pybind11::dtype(info), info.shape, info.strides, info.ptr, |
| 229 | literal_object); |
| 230 | if (m.shape().element_type() == xla::BF16) { |
| 231 | // We requested an array of uint16 since NumPy doesn't know how |
| 232 | // to produce our custom bfloat16 type. Reinterpret the array as bfloat16 |
| 233 | // before handing it back to the caller. |
| 234 | TF_ASSIGN_OR_RETURN(py::object bfloat16, Bfloat16Dtype()); |
| 235 | array = py::reinterpret_steal<py::array>( |
| 236 | PyArray_View(reinterpret_cast<PyArrayObject*>(array.ptr()), |
| 237 | reinterpret_cast<PyArray_Descr*>(bfloat16.release().ptr()), |
| 238 | static_cast<PyTypeObject*>(nullptr))); |
| 239 | } |
| 240 | return array; |
| 241 | } |
| 242 | |
| 243 | StatusOr<PythonBufferTree> GetPythonBufferTree(const py::object& argument) { |
| 244 | PythonBufferTree tree; |
no test coverage detected