2017-12-27 23:59:41 +00:00
|
|
|
# Generates Python bindings for ATen functions
|
|
|
|
|
#
|
|
|
|
|
# The bindings are generated as methods on python_variable or functions on the
|
2021-11-20 03:45:55 +00:00
|
|
|
# torch._C._nn. torch._C._fft, torch._C._linalg, torch._C._sparse or torch._C._special objects.
|
2018-01-17 23:27:42 +00:00
|
|
|
#
|
2020-01-30 08:26:16 +00:00
|
|
|
|
|
|
|
|
# Code tries to stick to the following rules:
|
|
|
|
|
#
|
|
|
|
|
# - templates should be colocated with the functions that use them.
|
|
|
|
|
# no templates are currently shared between functions, but if that
|
|
|
|
|
# happens, maybe put the template with the first one
|
|
|
|
|
#
|
|
|
|
|
# - don't use environment dictionaries when calling template.substitute().
|
|
|
|
|
# pass named arguments directly for everything, otherwise it's much too
|
|
|
|
|
# hard to track what's actually being used and by who
|
|
|
|
|
#
|
|
|
|
|
# - colocate any new hacks/adjustments with existing ones of the same kind.
|
|
|
|
|
# ideally in a data structure rather than code if possible. See e.g.
|
|
|
|
|
# SCHEMA_DEFAULT_CONVERSION_HACKS, etc.
|
|
|
|
|
#
|
|
|
|
|
# - similarly, conversions from one format to another should ideally happen
|
|
|
|
|
# all at once in a single place.
|
|
|
|
|
#
|
|
|
|
|
# - no nontrivial nested functions. couple-liners are ok but please no more.
|
|
|
|
|
# especially avoid functions that read/write outer variables defined far away.
|
|
|
|
|
#
|
|
|
|
|
# - raise RuntimeError instead of asserting, and put as much
|
|
|
|
|
# information as is available into the message. I.e. no need to
|
|
|
|
|
# plumb in new params whose only purpose is to fill out an error
|
|
|
|
|
# message, but use what's there
|
|
|
|
|
#
|
|
|
|
|
|
2018-01-17 23:27:42 +00:00
|
|
|
from collections import defaultdict
|
2020-11-08 09:03:59 +00:00
|
|
|
import itertools
|
2018-01-17 23:27:42 +00:00
|
|
|
import re
|
2020-11-14 10:22:37 +00:00
|
|
|
import yaml
|
|
|
|
|
|
2020-11-09 19:55:37 +00:00
|
|
|
from .gen_trace_type import should_trace
|
2017-10-06 16:12:50 +00:00
|
|
|
|
Rename tools/codegen to torchgen (#76275)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/76275
In preparation for addressing
https://github.com/pytorch/pytorch/issues/73212
Diff was generated with:
```
git mv tools/codegen torchgen
git grep -l 'tools.codegen' | xargs sed -i 's/tools.codegen/torchgen/g'
sed -i "s/\${TOOLS_PATH}\/codegen/\${TORCH_ROOT}\/torchgen/g" caffe2/CMakeLists.txt
```
and a manual edits to:
* tools/test/test_gen_backend_stubs.py
* torchgen/build.bzl
* torchgen/gen_backend_stubs.py
aka this diff:
```
diff --git a/tools/test/test_gen_backend_stubs.py b/tools/test/test_gen_backend_stubs.py
index 3dc26c6d2d..104054575e 100644
--- a/tools/test/test_gen_backend_stubs.py
+++ b/tools/test/test_gen_backend_stubs.py
@@ -9,7 +9,7 @@ from torchgen.gen_backend_stubs import run
from torchgen.gen import _GLOBAL_PARSE_NATIVE_YAML_CACHE # noqa: F401
path = os.path.dirname(os.path.realpath(__file__))
-gen_backend_stubs_path = os.path.join(path, '../torchgen/gen_backend_stubs.py')
+gen_backend_stubs_path = os.path.join(path, '../../torchgen/gen_backend_stubs.py')
# gen_backend_stubs.py is an integration point that is called directly by external backends.
# The tests here are to confirm that badly formed inputs result in reasonable error messages.
diff --git a/torchgen/build.bzl b/torchgen/build.bzl
index ed04e35a43..d00078a3cf 100644
--- a/torchgen/build.bzl
+++ b/torchgen/build.bzl
@@ -1,6 +1,6 @@
def define_targets(rules):
rules.py_library(
- name = "codegen",
+ name = "torchgen",
srcs = rules.glob(["**/*.py"]),
deps = [
rules.requirement("PyYAML"),
@@ -11,6 +11,6 @@ def define_targets(rules):
rules.py_binary(
name = "gen",
- srcs = [":codegen"],
+ srcs = [":torchgen"],
visibility = ["//visibility:public"],
)
diff --git a/torchgen/gen_backend_stubs.py b/torchgen/gen_backend_stubs.py
index c1a672a655..beee7a15e0 100644
--- a/torchgen/gen_backend_stubs.py
+++ b/torchgen/gen_backend_stubs.py
@@ -474,7 +474,7 @@ def run(
) -> None:
# Assumes that this file lives at PYTORCH_ROOT/torchgen/gen_backend_stubs.py
- pytorch_root = pathlib.Path(__file__).parent.parent.parent.absolute()
+ pytorch_root = pathlib.Path(__file__).parent.parent.absolute()
template_dir = os.path.join(pytorch_root, "aten/src/ATen/templates")
def make_file_manager(install_dir: str) -> FileManager:
```
run_all_fbandroid_tests
Test Plan: sandcastle
Reviewed By: albanD, ngimel
Differential Revision: D35770317
fbshipit-source-id: 153ac4a7fef15b1e750812a90bfafdbc8f1ebcdf
(cherry picked from commit c6d485d1d4648fa1c8a4c14c5bf3d8e899b9b4dd)
2022-04-25 01:32:01 +00:00
|
|
|
from torchgen.code_template import CodeTemplate
|
|
|
|
|
from torchgen.api import cpp
|
|
|
|
|
from torchgen.api.types import CppSignatureGroup
|
|
|
|
|
from torchgen.api.python import (
|
2022-04-20 12:51:02 +00:00
|
|
|
PythonArgument,
|
|
|
|
|
PythonSignature,
|
|
|
|
|
PythonSignatureDeprecated,
|
|
|
|
|
PythonSignatureGroup,
|
|
|
|
|
PythonSignatureNativeFunctionPair,
|
|
|
|
|
arg_parser_output_exprs,
|
|
|
|
|
argument_type_str,
|
|
|
|
|
cpp_dispatch_exprs,
|
|
|
|
|
cpp_dispatch_target,
|
|
|
|
|
dispatch_lambda_args,
|
|
|
|
|
dispatch_lambda_exprs,
|
|
|
|
|
dispatch_lambda_return_str,
|
|
|
|
|
has_tensor_options,
|
|
|
|
|
namedtuple_fieldnames,
|
|
|
|
|
signature,
|
|
|
|
|
)
|
Rename tools/codegen to torchgen (#76275)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/76275
In preparation for addressing
https://github.com/pytorch/pytorch/issues/73212
Diff was generated with:
```
git mv tools/codegen torchgen
git grep -l 'tools.codegen' | xargs sed -i 's/tools.codegen/torchgen/g'
sed -i "s/\${TOOLS_PATH}\/codegen/\${TORCH_ROOT}\/torchgen/g" caffe2/CMakeLists.txt
```
and a manual edits to:
* tools/test/test_gen_backend_stubs.py
* torchgen/build.bzl
* torchgen/gen_backend_stubs.py
aka this diff:
```
diff --git a/tools/test/test_gen_backend_stubs.py b/tools/test/test_gen_backend_stubs.py
index 3dc26c6d2d..104054575e 100644
--- a/tools/test/test_gen_backend_stubs.py
+++ b/tools/test/test_gen_backend_stubs.py
@@ -9,7 +9,7 @@ from torchgen.gen_backend_stubs import run
from torchgen.gen import _GLOBAL_PARSE_NATIVE_YAML_CACHE # noqa: F401
path = os.path.dirname(os.path.realpath(__file__))
-gen_backend_stubs_path = os.path.join(path, '../torchgen/gen_backend_stubs.py')
+gen_backend_stubs_path = os.path.join(path, '../../torchgen/gen_backend_stubs.py')
# gen_backend_stubs.py is an integration point that is called directly by external backends.
# The tests here are to confirm that badly formed inputs result in reasonable error messages.
diff --git a/torchgen/build.bzl b/torchgen/build.bzl
index ed04e35a43..d00078a3cf 100644
--- a/torchgen/build.bzl
+++ b/torchgen/build.bzl
@@ -1,6 +1,6 @@
def define_targets(rules):
rules.py_library(
- name = "codegen",
+ name = "torchgen",
srcs = rules.glob(["**/*.py"]),
deps = [
rules.requirement("PyYAML"),
@@ -11,6 +11,6 @@ def define_targets(rules):
rules.py_binary(
name = "gen",
- srcs = [":codegen"],
+ srcs = [":torchgen"],
visibility = ["//visibility:public"],
)
diff --git a/torchgen/gen_backend_stubs.py b/torchgen/gen_backend_stubs.py
index c1a672a655..beee7a15e0 100644
--- a/torchgen/gen_backend_stubs.py
+++ b/torchgen/gen_backend_stubs.py
@@ -474,7 +474,7 @@ def run(
) -> None:
# Assumes that this file lives at PYTORCH_ROOT/torchgen/gen_backend_stubs.py
- pytorch_root = pathlib.Path(__file__).parent.parent.parent.absolute()
+ pytorch_root = pathlib.Path(__file__).parent.parent.absolute()
template_dir = os.path.join(pytorch_root, "aten/src/ATen/templates")
def make_file_manager(install_dir: str) -> FileManager:
```
run_all_fbandroid_tests
Test Plan: sandcastle
Reviewed By: albanD, ngimel
Differential Revision: D35770317
fbshipit-source-id: 153ac4a7fef15b1e750812a90bfafdbc8f1ebcdf
(cherry picked from commit c6d485d1d4648fa1c8a4c14c5bf3d8e899b9b4dd)
2022-04-25 01:32:01 +00:00
|
|
|
from torchgen.gen import cpp_string, parse_native_yaml
|
|
|
|
|
from torchgen.context import with_native_function
|
|
|
|
|
from torchgen.model import (
|
2022-04-20 12:51:02 +00:00
|
|
|
Argument,
|
|
|
|
|
BaseOperatorName,
|
|
|
|
|
NativeFunction,
|
|
|
|
|
Type,
|
|
|
|
|
Variant,
|
|
|
|
|
)
|
Rename tools/codegen to torchgen (#76275)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/76275
In preparation for addressing
https://github.com/pytorch/pytorch/issues/73212
Diff was generated with:
```
git mv tools/codegen torchgen
git grep -l 'tools.codegen' | xargs sed -i 's/tools.codegen/torchgen/g'
sed -i "s/\${TOOLS_PATH}\/codegen/\${TORCH_ROOT}\/torchgen/g" caffe2/CMakeLists.txt
```
and a manual edits to:
* tools/test/test_gen_backend_stubs.py
* torchgen/build.bzl
* torchgen/gen_backend_stubs.py
aka this diff:
```
diff --git a/tools/test/test_gen_backend_stubs.py b/tools/test/test_gen_backend_stubs.py
index 3dc26c6d2d..104054575e 100644
--- a/tools/test/test_gen_backend_stubs.py
+++ b/tools/test/test_gen_backend_stubs.py
@@ -9,7 +9,7 @@ from torchgen.gen_backend_stubs import run
from torchgen.gen import _GLOBAL_PARSE_NATIVE_YAML_CACHE # noqa: F401
path = os.path.dirname(os.path.realpath(__file__))
-gen_backend_stubs_path = os.path.join(path, '../torchgen/gen_backend_stubs.py')
+gen_backend_stubs_path = os.path.join(path, '../../torchgen/gen_backend_stubs.py')
# gen_backend_stubs.py is an integration point that is called directly by external backends.
# The tests here are to confirm that badly formed inputs result in reasonable error messages.
diff --git a/torchgen/build.bzl b/torchgen/build.bzl
index ed04e35a43..d00078a3cf 100644
--- a/torchgen/build.bzl
+++ b/torchgen/build.bzl
@@ -1,6 +1,6 @@
def define_targets(rules):
rules.py_library(
- name = "codegen",
+ name = "torchgen",
srcs = rules.glob(["**/*.py"]),
deps = [
rules.requirement("PyYAML"),
@@ -11,6 +11,6 @@ def define_targets(rules):
rules.py_binary(
name = "gen",
- srcs = [":codegen"],
+ srcs = [":torchgen"],
visibility = ["//visibility:public"],
)
diff --git a/torchgen/gen_backend_stubs.py b/torchgen/gen_backend_stubs.py
index c1a672a655..beee7a15e0 100644
--- a/torchgen/gen_backend_stubs.py
+++ b/torchgen/gen_backend_stubs.py
@@ -474,7 +474,7 @@ def run(
) -> None:
# Assumes that this file lives at PYTORCH_ROOT/torchgen/gen_backend_stubs.py
- pytorch_root = pathlib.Path(__file__).parent.parent.parent.absolute()
+ pytorch_root = pathlib.Path(__file__).parent.parent.absolute()
template_dir = os.path.join(pytorch_root, "aten/src/ATen/templates")
def make_file_manager(install_dir: str) -> FileManager:
```
run_all_fbandroid_tests
Test Plan: sandcastle
Reviewed By: albanD, ngimel
Differential Revision: D35770317
fbshipit-source-id: 153ac4a7fef15b1e750812a90bfafdbc8f1ebcdf
(cherry picked from commit c6d485d1d4648fa1c8a4c14c5bf3d8e899b9b4dd)
2022-04-25 01:32:01 +00:00
|
|
|
from torchgen.utils import split_name_params, YamlLoader, FileManager
|
[pytorch] rewrite of the python binding codegen with the v2 API (#46244)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/46244
- What does the generated binding code do?
The Python binding codegen produces code that takes the input list of
PyObjects, finds the matching ATen C++ function using PythonArgParser,
converts the PyObjects into C++ types and calls the ATen C++ function:
```
+--------+ parsing +------------------------+ binding +-----------------------+
| PyObjs | ---------> | PythonArgParser Output | ---------> | Cpp Function Dispatch |
+--------+ +------------------------+ +-----------------------+
```
- Are Python arguments 1-1 mapped to C++ arguments?
Python arguments might be reordered, packed, unpacked when binding to
C++ arguments, as illustrated below:
```
// Binding - Reorder & Packing
// aten::empty.names(int[] size, *, Dimname[]? names, ScalarType? dtype=None, Layout? layout=None,
Device? device=None, bool? pin_memory=None, MemoryFormat? memory_format=None) -> Tensor
Python Args Cpp Args
-----------------------------------------------------------
0: size size
1: names names
2: memory_format -------+
3: dtype -----+-|--> options
4: layout / |
5: device / +--> memory_format
6: pin_memory /
7: requires_grad -+
// Binding - Unpacking
// aten::max.names_dim(Tensor self, Dimname dim, bool keepdim=False) -> (Tensor values, Tensor indices)
Python Args Cpp Args
-----------------------------------------------------------
+----> max
/-----> max_values
0: input / self
1: dim / dim
2: keepdim / keepdim
3: out -----+
```
- Why do we want to rewrite the python binding codegen?
The old codegen takes Declarations.yaml as input. It doesn't distinguish
between Python arguments and C++ arguments - they are all mixed together
as a bag of non-typed dict objects. Different methods process these arg
objects and add new attributes for various different purposes. It's not so
obvious to figure out the semantics of these attributes. The complicated
binding logic happens implicitly and scatteredly.
```
+--------------------+
| Native Functions |
+--------------------+
|
|
v
+--------------------+
| Cpp Signatures |
+--------------------+
|
|
v
+--------------------+
| Declarations.yaml |
+--------------------+
| +-------------------------------------+
| +-------> | PythonArgParser Schema |
| | +-------------------------------------+
| | .
| | .
v | .
+--------------------+ +-------------------------------------+
| NonTyped Args Objs | --> | PythonArgParser -> Cpp Args Binding |
+--------------------+ +-------------------------------------+
| .
| .
| .
| +-------------------------------------+
+-------> | Cpp Function Dispatch |
+-------------------------------------+
```
This PR leverages the new immutable data models introduced in the new
aten codegen. It introduces dedicated data models for python schema.
This way, we can not only avoid subtle Declaration.yaml conversions but
also decouple the generation of python schema, python to c++ binding and
c++ function call.
The ultimate state will be like the following diagram:
```
+-------------------+ +-------------------------------------+
+-------> | Python Signatures | --> | PythonArgParser Schema |
| +-------------------+ +-------------------------------------+
| | .
| | .
| | .
+------------------+ | +-------------------------------------+
| Native Functions | +-------> | PythonArgParser -> Cpp Args Binding |
+------------------+ | +-------------------------------------+
| | .
| | .
| | .
| +-------------------+ +-------------------------------------+
+-------> | Cpp Signatures | --> | Cpp Function Dispatch |
+-------------------+ +-------------------------------------+
```
This PR has migrated the core binding logic from
tools/autograd/gen_python_functions.py to tools/codegen/api/python.py.
It produces the byte-for-byte same results (tested with #46243).
Will migrate the rest of gen_python_functions.py in subsequent PRs.
Test Plan: Imported from OSS
Reviewed By: bhosmer
Differential Revision: D24388874
Pulled By: ljk53
fbshipit-source-id: f88b6df4e917cf90d868a2bbae2d5ffb680d1841
2020-10-20 00:34:45 +00:00
|
|
|
|
2020-11-14 10:22:37 +00:00
|
|
|
from typing import Dict, Optional, List, Tuple, Set, Sequence, Callable
|
|
|
|
|
|
2020-01-30 08:26:16 +00:00
|
|
|
#
|
2020-08-18 22:09:45 +00:00
|
|
|
# declarations blocklist
|
2020-01-30 08:26:16 +00:00
|
|
|
# We skip codegen for these functions, for various reasons.
|
|
|
|
|
# Future PRs will categorize this list and eliminate or hoist
|
|
|
|
|
# them out of eager-only codegen.
|
|
|
|
|
# See https://github.com/pytorch/pytorch/issues/30788
|
|
|
|
|
#
|
|
|
|
|
|
2018-01-17 23:27:42 +00:00
|
|
|
# These functions require manual Python bindings or are not exposed to Python
|
2021-06-12 13:55:44 +00:00
|
|
|
_SKIP_PYTHON_BINDINGS = [
|
2022-04-20 12:51:02 +00:00
|
|
|
"alias",
|
|
|
|
|
"contiguous",
|
|
|
|
|
"is_cuda",
|
|
|
|
|
"is_sparse",
|
|
|
|
|
"is_sparse_csr",
|
|
|
|
|
"size",
|
|
|
|
|
"stride",
|
|
|
|
|
".*_backward",
|
|
|
|
|
".*_backward_(out|input|weight|bias)",
|
|
|
|
|
".*_forward",
|
|
|
|
|
".*_forward_out",
|
|
|
|
|
"_unsafe_view",
|
|
|
|
|
"tensor",
|
|
|
|
|
"_?sparse_coo_tensor.*",
|
|
|
|
|
"_?sparse_csr_tensor.*",
|
|
|
|
|
"_arange.*",
|
|
|
|
|
"_range.*",
|
|
|
|
|
"linspace.*",
|
|
|
|
|
"logspace.*",
|
|
|
|
|
"_sparse_add_out",
|
|
|
|
|
"_sparse_div.*",
|
|
|
|
|
"_sparse_mul.*",
|
|
|
|
|
"_sparse_sub.*",
|
|
|
|
|
"_sparse_dense_add_out",
|
|
|
|
|
"index",
|
|
|
|
|
"unique_dim_consecutive",
|
|
|
|
|
"_cumsum.*",
|
|
|
|
|
"_cumprod.*",
|
|
|
|
|
"_sum.*",
|
|
|
|
|
"_prod.*",
|
|
|
|
|
"_th_.*",
|
|
|
|
|
"_thnn_.*",
|
|
|
|
|
"arange.*",
|
|
|
|
|
"range.*",
|
|
|
|
|
"_solve.*",
|
|
|
|
|
"_inverse.*",
|
|
|
|
|
"full(_out)?",
|
|
|
|
|
"_cholesky.*",
|
|
|
|
|
"_triangular_solve.*",
|
|
|
|
|
"_qr.*",
|
|
|
|
|
"_symeig.*",
|
|
|
|
|
"_svd.*",
|
|
|
|
|
"slice",
|
|
|
|
|
"randint(_out)?",
|
|
|
|
|
"item",
|
|
|
|
|
"_local_scalar_dense",
|
|
|
|
|
"to",
|
|
|
|
|
"_to_copy",
|
|
|
|
|
"copy_sparse_to_sparse_",
|
|
|
|
|
"copy_",
|
|
|
|
|
"numpy_T",
|
|
|
|
|
"matrix_H",
|
|
|
|
|
"mT",
|
|
|
|
|
"mH", # these need to be an attributes in Python, not functions
|
|
|
|
|
"nonzero(_(out|numpy))?",
|
|
|
|
|
"set_data",
|
|
|
|
|
".*_overrideable", # overrideable functions for backend extension
|
|
|
|
|
"data",
|
|
|
|
|
"is_leaf",
|
|
|
|
|
"output_nr",
|
|
|
|
|
"_version",
|
|
|
|
|
"requires_grad_",
|
|
|
|
|
"retains_grad",
|
|
|
|
|
"set_",
|
|
|
|
|
"_fw_primal",
|
|
|
|
|
"fake_quantize_per_tensor_affine_cachemask",
|
|
|
|
|
"fake_quantize_per_channel_affine_cachemask",
|
|
|
|
|
"_new_zeros_with_same_feature_meta",
|
|
|
|
|
"_has_same_storage_numel", # used for forward AD internals
|
|
|
|
|
"_reshape_alias",
|
|
|
|
|
"replace_", # only used by the functionalization pass, doesn't need to be exposed to python
|
2022-04-25 19:01:17 +00:00
|
|
|
"zero", # only used by the functionalization pass, doesn't need to be exposed to python
|
2018-01-17 23:27:42 +00:00
|
|
|
]
|
|
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
SKIP_PYTHON_BINDINGS = list(
|
|
|
|
|
map(lambda pattern: re.compile(rf"^{pattern}$"), _SKIP_PYTHON_BINDINGS)
|
|
|
|
|
)
|
2021-06-12 13:55:44 +00:00
|
|
|
|
Implement add, sub, mul, div using TensorIterator (#8919)
Summary:
```
This adds TensorIterator, a helper class for computing element-wise
operations that's intended to replace the CPU and CUDA apply utils
functions.
CPU kernels are implemented as functions that operate on strided 1-d
tensors compared to CPUApplyUtils which operated individual elements. This
allows the kernels to handle vectorization, while TensorIterator handles
parallelization and non-coalesced dimensions.
GPU kernels continue to operate on elements, but the number of
specializations is reduced. The contiguous case remains the same. The
non-contiguous case uses a single (reduced) shape for all operands and
the fast integer division from THCIntegerDivider. To avoid extra
specializations for indexing with 64-bits, large operations are split
into smaller operations that can be indexed with 32-bits.
Major semantic changes:
- No more s_add, s_mul, s_div, or s_sub. Broadcasting is handled by
TensorIterator. The autograd engine performs the reduction assuming
standard broadcasting if the gradient shape does not match the
expected shape. Functions that do not use standard broadcasting rules
should either continue to trace the expand calls or handle the
reduction in their derivative formula.
- Use ONNX v7, which supports broadcasting ops.
Performance impact:
- Small increased fixed overhead (~0.5 us)
- Larger overhead for wrapped numbers (~2.5 us)
- No significant change for ops on contiguous tensors
- Much faster worst-case performance for non-contiguous GPU tensors
- Faster CPU bias addition (~2x)
- Faster GPU bias addition (~30% faster)
Future work:
- Decrease overhead, especially for wrapping numbers in Tensors
- Handle general inter-type operations
- Extend to unary ops and reductions
- Use buffering for compute-bound operations on non-contiguous tensors
(pull in from CPUApplyUtils)
```
Pull Request resolved: https://github.com/pytorch/pytorch/pull/8919
Differential Revision: D8677600
Pulled By: colesbury
fbshipit-source-id: 61bc9cc2a36931dfd00eb7153501003fe0584afd
2018-07-27 21:30:31 +00:00
|
|
|
# These function signatures are not exposed to Python. Note that this signature
|
|
|
|
|
# list does not support regex.
|
|
|
|
|
SKIP_PYTHON_BINDINGS_SIGNATURES = [
|
2022-04-20 12:51:02 +00:00
|
|
|
"add.Scalar(Tensor self, Scalar other, Scalar alpha=1) -> Tensor",
|
|
|
|
|
"add_.Scalar(Tensor(a!) self, Scalar other, Scalar alpha=1) -> Tensor(a!)",
|
|
|
|
|
"sub.Scalar(Tensor self, Scalar other, Scalar alpha=1) -> Tensor",
|
|
|
|
|
"sub_.Scalar(Tensor(a!) self, Scalar other, Scalar alpha=1) -> Tensor(a!)",
|
|
|
|
|
"mul.Scalar(Tensor self, Scalar other) -> Tensor",
|
|
|
|
|
"mul_.Scalar(Tensor(a!) self, Scalar other) -> Tensor(a!)",
|
|
|
|
|
"div.Scalar(Tensor self, Scalar other) -> Tensor",
|
|
|
|
|
"div_.Scalar(Tensor(a!) self, Scalar other) -> Tensor(a!)",
|
Implement add, sub, mul, div using TensorIterator (#8919)
Summary:
```
This adds TensorIterator, a helper class for computing element-wise
operations that's intended to replace the CPU and CUDA apply utils
functions.
CPU kernels are implemented as functions that operate on strided 1-d
tensors compared to CPUApplyUtils which operated individual elements. This
allows the kernels to handle vectorization, while TensorIterator handles
parallelization and non-coalesced dimensions.
GPU kernels continue to operate on elements, but the number of
specializations is reduced. The contiguous case remains the same. The
non-contiguous case uses a single (reduced) shape for all operands and
the fast integer division from THCIntegerDivider. To avoid extra
specializations for indexing with 64-bits, large operations are split
into smaller operations that can be indexed with 32-bits.
Major semantic changes:
- No more s_add, s_mul, s_div, or s_sub. Broadcasting is handled by
TensorIterator. The autograd engine performs the reduction assuming
standard broadcasting if the gradient shape does not match the
expected shape. Functions that do not use standard broadcasting rules
should either continue to trace the expand calls or handle the
reduction in their derivative formula.
- Use ONNX v7, which supports broadcasting ops.
Performance impact:
- Small increased fixed overhead (~0.5 us)
- Larger overhead for wrapped numbers (~2.5 us)
- No significant change for ops on contiguous tensors
- Much faster worst-case performance for non-contiguous GPU tensors
- Faster CPU bias addition (~2x)
- Faster GPU bias addition (~30% faster)
Future work:
- Decrease overhead, especially for wrapping numbers in Tensors
- Handle general inter-type operations
- Extend to unary ops and reductions
- Use buffering for compute-bound operations on non-contiguous tensors
(pull in from CPUApplyUtils)
```
Pull Request resolved: https://github.com/pytorch/pytorch/pull/8919
Differential Revision: D8677600
Pulled By: colesbury
fbshipit-source-id: 61bc9cc2a36931dfd00eb7153501003fe0584afd
2018-07-27 21:30:31 +00:00
|
|
|
]
|
|
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
|
2020-11-14 10:22:37 +00:00
|
|
|
@with_native_function
|
|
|
|
|
def should_generate_py_binding(f: NativeFunction) -> bool:
|
|
|
|
|
name = cpp.name(f.func)
|
2021-06-12 13:55:44 +00:00
|
|
|
for skip_regex in SKIP_PYTHON_BINDINGS:
|
|
|
|
|
if skip_regex.match(name):
|
2020-11-14 10:22:37 +00:00
|
|
|
return False
|
|
|
|
|
|
2021-06-12 13:55:44 +00:00
|
|
|
signature = str(f.func)
|
2020-11-14 10:22:37 +00:00
|
|
|
for pattern in SKIP_PYTHON_BINDINGS_SIGNATURES:
|
2021-06-12 13:55:44 +00:00
|
|
|
if pattern == signature:
|
2020-11-14 10:22:37 +00:00
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
|
2020-11-18 20:17:37 +00:00
|
|
|
def get_pycname(name: BaseOperatorName) -> str:
|
2022-04-20 12:51:02 +00:00
|
|
|
return f"THPVariable_{name}"
|
|
|
|
|
|
2020-08-07 17:16:56 +00:00
|
|
|
|
2020-11-14 10:22:37 +00:00
|
|
|
def is_noarg(overloads: Sequence[PythonSignatureNativeFunctionPair]) -> bool:
|
|
|
|
|
return len(overloads) == 1 and overloads[0].signature.arguments_count() == 0
|
2020-08-07 17:16:56 +00:00
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
|
2020-11-14 10:22:37 +00:00
|
|
|
def is_py_variable_method(f: NativeFunction) -> bool:
|
|
|
|
|
return f.python_module is None and Variant.method in f.variants
|
2020-08-07 17:16:56 +00:00
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
|
2020-11-14 10:22:37 +00:00
|
|
|
def is_py_torch_function(f: NativeFunction) -> bool:
|
|
|
|
|
return f.python_module is None and Variant.function in f.variants
|
2020-08-06 07:18:51 +00:00
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
|
2020-11-14 10:22:37 +00:00
|
|
|
def is_py_nn_function(f: NativeFunction) -> bool:
|
2022-04-20 12:51:02 +00:00
|
|
|
return f.python_module == "nn"
|
|
|
|
|
|
2018-01-17 23:27:42 +00:00
|
|
|
|
2020-11-14 10:22:37 +00:00
|
|
|
def is_py_fft_function(f: NativeFunction) -> bool:
|
2022-04-20 12:51:02 +00:00
|
|
|
return f.python_module == "fft"
|
|
|
|
|
|
2019-01-29 19:19:51 +00:00
|
|
|
|
2020-11-14 10:22:37 +00:00
|
|
|
def is_py_linalg_function(f: NativeFunction) -> bool:
|
2022-04-20 12:51:02 +00:00
|
|
|
return f.python_module == "linalg"
|
|
|
|
|
|
2019-01-29 19:19:51 +00:00
|
|
|
|
2021-11-20 03:45:55 +00:00
|
|
|
def is_py_sparse_function(f: NativeFunction) -> bool:
|
2022-04-20 12:51:02 +00:00
|
|
|
return f.python_module == "sparse"
|
|
|
|
|
|
2021-11-20 03:45:55 +00:00
|
|
|
|
2021-03-04 08:00:09 +00:00
|
|
|
def is_py_special_function(f: NativeFunction) -> bool:
|
2022-04-20 12:51:02 +00:00
|
|
|
return f.python_module == "special"
|
|
|
|
|
|
2021-03-04 08:00:09 +00:00
|
|
|
|
2020-11-14 10:22:37 +00:00
|
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
|
|
|
|
|
#
|
|
|
|
|
# Main Function
|
|
|
|
|
#
|
|
|
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
|
2019-01-29 19:19:51 +00:00
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
|
|
|
|
|
def gen(
|
|
|
|
|
out: str, native_yaml_path: str, deprecated_yaml_path: str, template_path: str
|
|
|
|
|
) -> None:
|
2020-11-14 10:22:37 +00:00
|
|
|
fm = FileManager(install_dir=out, template_dir=template_path, dry_run=False)
|
2022-03-28 18:04:38 +00:00
|
|
|
native_functions = parse_native_yaml(native_yaml_path).native_functions
|
2021-06-12 13:55:44 +00:00
|
|
|
native_functions = list(filter(should_generate_py_binding, native_functions))
|
2018-01-17 23:27:42 +00:00
|
|
|
|
2021-06-12 13:55:44 +00:00
|
|
|
methods = load_signatures(native_functions, deprecated_yaml_path, method=True)
|
2020-11-14 10:22:37 +00:00
|
|
|
create_python_bindings(
|
2022-04-20 12:51:02 +00:00
|
|
|
fm,
|
|
|
|
|
methods,
|
|
|
|
|
is_py_variable_method,
|
|
|
|
|
None,
|
|
|
|
|
"python_variable_methods.cpp",
|
|
|
|
|
method=True,
|
|
|
|
|
)
|
2020-02-21 16:31:23 +00:00
|
|
|
|
2021-08-25 22:05:14 +00:00
|
|
|
# NOTE: num_shards here must be synced with gatherTorchFunctions in
|
|
|
|
|
# torch/csrc/autograd/python_torch_functions_manual.cpp
|
2021-06-12 13:55:44 +00:00
|
|
|
functions = load_signatures(native_functions, deprecated_yaml_path, method=False)
|
2021-08-25 22:05:14 +00:00
|
|
|
create_python_bindings_sharded(
|
2022-04-20 12:51:02 +00:00
|
|
|
fm,
|
|
|
|
|
functions,
|
|
|
|
|
is_py_torch_function,
|
|
|
|
|
"torch",
|
|
|
|
|
"python_torch_functions.cpp",
|
|
|
|
|
method=False,
|
|
|
|
|
num_shards=3,
|
|
|
|
|
)
|
2018-01-17 23:27:42 +00:00
|
|
|
|
2020-11-14 10:22:37 +00:00
|
|
|
create_python_bindings(
|
2022-04-20 12:51:02 +00:00
|
|
|
fm,
|
|
|
|
|
functions,
|
|
|
|
|
is_py_nn_function,
|
|
|
|
|
"torch.nn",
|
|
|
|
|
"python_nn_functions.cpp",
|
|
|
|
|
method=False,
|
|
|
|
|
)
|
2018-01-17 23:27:42 +00:00
|
|
|
|
2020-11-14 10:22:37 +00:00
|
|
|
create_python_bindings(
|
2022-04-20 12:51:02 +00:00
|
|
|
fm,
|
|
|
|
|
functions,
|
|
|
|
|
is_py_fft_function,
|
|
|
|
|
"torch.fft",
|
|
|
|
|
"python_fft_functions.cpp",
|
|
|
|
|
method=False,
|
|
|
|
|
)
|
2017-10-06 16:12:50 +00:00
|
|
|
|
2020-11-14 10:22:37 +00:00
|
|
|
create_python_bindings(
|
2022-04-20 12:51:02 +00:00
|
|
|
fm,
|
|
|
|
|
functions,
|
|
|
|
|
is_py_linalg_function,
|
|
|
|
|
"torch.linalg",
|
|
|
|
|
"python_linalg_functions.cpp",
|
|
|
|
|
method=False,
|
|
|
|
|
)
|
2018-01-17 23:27:42 +00:00
|
|
|
|
2021-11-20 03:45:55 +00:00
|
|
|
create_python_bindings(
|
2022-04-20 12:51:02 +00:00
|
|
|
fm,
|
|
|
|
|
functions,
|
|
|
|
|
is_py_sparse_function,
|
|
|
|
|
"torch.sparse",
|
|
|
|
|
"python_sparse_functions.cpp",
|
|
|
|
|
method=False,
|
|
|
|
|
)
|
2021-11-20 03:45:55 +00:00
|
|
|
|
2021-03-04 08:00:09 +00:00
|
|
|
create_python_bindings(
|
2022-04-20 12:51:02 +00:00
|
|
|
fm,
|
|
|
|
|
functions,
|
|
|
|
|
is_py_special_function,
|
|
|
|
|
"torch.special",
|
|
|
|
|
"python_special_functions.cpp",
|
|
|
|
|
method=False,
|
|
|
|
|
)
|
2021-03-04 08:00:09 +00:00
|
|
|
|
expose return_types in Python (#66614)
Summary:
https://github.com/facebookresearch/functorch/issues/87
TODO:
* [x] Add comments
* [x] Add test
* [x] Fix XLA
<details>
<summary>Generated python_return_types.cpp</summary>
```cpp
#include <Python.h>
#include <vector>
#include <map>
#include <string>
#include "torch/csrc/autograd/python_return_types.h"
#include "torch/csrc/utils/structseq.h"
#include "torch/csrc/Exceptions.h"
namespace {
PyTypeObject* get__det_lu_based_helper_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"det", ""}, {"lu", ""}, {"pivs", ""}, {nullptr} };
static PyTypeObject _det_lu_based_helperNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._det_lu_based_helper", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&_det_lu_based_helperNamedTuple, &desc);
_det_lu_based_helperNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_det_lu_based_helperNamedTuple;
}
PyTypeObject* get__fake_quantize_per_tensor_affine_cachemask_tensor_qparams_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"output", ""}, {"mask", ""}, {nullptr} };
static PyTypeObject _fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._fake_quantize_per_tensor_affine_cachemask_tensor_qparams", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple, &desc);
_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple;
}
PyTypeObject* get__fused_moving_avg_obs_fq_helper_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"output", ""}, {"mask", ""}, {nullptr} };
static PyTypeObject _fused_moving_avg_obs_fq_helperNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._fused_moving_avg_obs_fq_helper", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_fused_moving_avg_obs_fq_helperNamedTuple, &desc);
_fused_moving_avg_obs_fq_helperNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_fused_moving_avg_obs_fq_helperNamedTuple;
}
PyTypeObject* get__lu_with_info_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"LU", ""}, {"pivots", ""}, {"info", ""}, {nullptr} };
static PyTypeObject _lu_with_infoNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._lu_with_info", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&_lu_with_infoNamedTuple, &desc);
_lu_with_infoNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_lu_with_infoNamedTuple;
}
PyTypeObject* get__unpack_dual_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"primal", ""}, {"tangent", ""}, {nullptr} };
static PyTypeObject _unpack_dualNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._unpack_dual", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_unpack_dualNamedTuple, &desc);
_unpack_dualNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_unpack_dualNamedTuple;
}
PyTypeObject* get_aminmax_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"min", ""}, {"max", ""}, {nullptr} };
static PyTypeObject aminmaxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.aminmax", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&aminmaxNamedTuple, &desc);
aminmaxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &aminmaxNamedTuple;
}
PyTypeObject* get_aminmax_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"min", ""}, {"max", ""}, {nullptr} };
static PyTypeObject aminmax_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.aminmax_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&aminmax_outNamedTuple1, &desc);
aminmax_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &aminmax_outNamedTuple1;
}
PyTypeObject* get_cummax_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummaxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummax", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummaxNamedTuple, &desc);
cummaxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummaxNamedTuple;
}
PyTypeObject* get_cummax_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummax_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummax_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummax_outNamedTuple1, &desc);
cummax_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummax_outNamedTuple1;
}
PyTypeObject* get_cummin_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cumminNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummin", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cumminNamedTuple, &desc);
cumminNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cumminNamedTuple;
}
PyTypeObject* get_cummin_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummin_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummin_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummin_outNamedTuple1, &desc);
cummin_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummin_outNamedTuple1;
}
PyTypeObject* get_eig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject eig_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.eig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&eig_outNamedTuple, &desc);
eig_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &eig_outNamedTuple;
}
PyTypeObject* get_eig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject eigNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.eig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&eigNamedTuple1, &desc);
eigNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &eigNamedTuple1;
}
PyTypeObject* get_frexp_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"mantissa", ""}, {"exponent", ""}, {nullptr} };
static PyTypeObject frexpNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.frexp", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&frexpNamedTuple, &desc);
frexpNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &frexpNamedTuple;
}
PyTypeObject* get_frexp_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"mantissa", ""}, {"exponent", ""}, {nullptr} };
static PyTypeObject frexp_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.frexp_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&frexp_outNamedTuple1, &desc);
frexp_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &frexp_outNamedTuple1;
}
PyTypeObject* get_geqrf_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"a", ""}, {"tau", ""}, {nullptr} };
static PyTypeObject geqrf_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.geqrf_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&geqrf_outNamedTuple, &desc);
geqrf_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &geqrf_outNamedTuple;
}
PyTypeObject* get_geqrf_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"a", ""}, {"tau", ""}, {nullptr} };
static PyTypeObject geqrfNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.geqrf", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&geqrfNamedTuple1, &desc);
geqrfNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &geqrfNamedTuple1;
}
PyTypeObject* get_histogram_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"hist", ""}, {"bin_edges", ""}, {nullptr} };
static PyTypeObject histogram_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.histogram_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&histogram_outNamedTuple, &desc);
histogram_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &histogram_outNamedTuple;
}
PyTypeObject* get_histogram_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"hist", ""}, {"bin_edges", ""}, {nullptr} };
static PyTypeObject histogramNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.histogram", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&histogramNamedTuple1, &desc);
histogramNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &histogramNamedTuple1;
}
PyTypeObject* get_kthvalue_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject kthvalueNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.kthvalue", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&kthvalueNamedTuple, &desc);
kthvalueNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &kthvalueNamedTuple;
}
PyTypeObject* get_kthvalue_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject kthvalue_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.kthvalue_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&kthvalue_outNamedTuple1, &desc);
kthvalue_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &kthvalue_outNamedTuple1;
}
PyTypeObject* get_linalg_cholesky_ex_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"L", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_cholesky_exNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_cholesky_ex", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_cholesky_exNamedTuple, &desc);
linalg_cholesky_exNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_cholesky_exNamedTuple;
}
PyTypeObject* get_linalg_cholesky_ex_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"L", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_cholesky_ex_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_cholesky_ex_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_cholesky_ex_outNamedTuple1, &desc);
linalg_cholesky_ex_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_cholesky_ex_outNamedTuple1;
}
PyTypeObject* get_linalg_eig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eigNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eigNamedTuple, &desc);
linalg_eigNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eigNamedTuple;
}
PyTypeObject* get_linalg_eig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eig_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eig_outNamedTuple1, &desc);
linalg_eig_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eig_outNamedTuple1;
}
PyTypeObject* get_linalg_eigh_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eighNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eigh", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eighNamedTuple, &desc);
linalg_eighNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eighNamedTuple;
}
PyTypeObject* get_linalg_eigh_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eigh_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eigh_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eigh_outNamedTuple1, &desc);
linalg_eigh_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eigh_outNamedTuple1;
}
PyTypeObject* get_linalg_inv_ex_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"inverse", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_inv_exNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_inv_ex", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_inv_exNamedTuple, &desc);
linalg_inv_exNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_inv_exNamedTuple;
}
PyTypeObject* get_linalg_inv_ex_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"inverse", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_inv_ex_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_inv_ex_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_inv_ex_outNamedTuple1, &desc);
linalg_inv_ex_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_inv_ex_outNamedTuple1;
}
PyTypeObject* get_linalg_lstsq_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"residuals", ""}, {"rank", ""}, {"singular_values", ""}, {nullptr} };
static PyTypeObject linalg_lstsqNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_lstsq", nullptr, NamedTuple_fields, 4 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_lstsqNamedTuple, &desc);
linalg_lstsqNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_lstsqNamedTuple;
}
PyTypeObject* get_linalg_lstsq_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"residuals", ""}, {"rank", ""}, {"singular_values", ""}, {nullptr} };
static PyTypeObject linalg_lstsq_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_lstsq_out", nullptr, NamedTuple_fields, 4 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_lstsq_outNamedTuple1, &desc);
linalg_lstsq_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_lstsq_outNamedTuple1;
}
PyTypeObject* get_linalg_qr_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject linalg_qrNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_qr", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_qrNamedTuple, &desc);
linalg_qrNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_qrNamedTuple;
}
PyTypeObject* get_linalg_qr_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject linalg_qr_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_qr_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_qr_outNamedTuple1, &desc);
linalg_qr_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_qr_outNamedTuple1;
}
PyTypeObject* get_linalg_slogdet_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject linalg_slogdetNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_slogdet", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_slogdetNamedTuple, &desc);
linalg_slogdetNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_slogdetNamedTuple;
}
PyTypeObject* get_linalg_slogdet_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject linalg_slogdet_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_slogdet_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_slogdet_outNamedTuple1, &desc);
linalg_slogdet_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_slogdet_outNamedTuple1;
}
PyTypeObject* get_linalg_svd_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"Vh", ""}, {nullptr} };
static PyTypeObject linalg_svd_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_svd_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_svd_outNamedTuple, &desc);
linalg_svd_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_svd_outNamedTuple;
}
PyTypeObject* get_linalg_svd_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"Vh", ""}, {nullptr} };
static PyTypeObject linalg_svdNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_svd", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_svdNamedTuple1, &desc);
linalg_svdNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_svdNamedTuple1;
}
PyTypeObject* get_lstsq_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"QR", ""}, {nullptr} };
static PyTypeObject lstsq_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lstsq_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&lstsq_outNamedTuple, &desc);
lstsq_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lstsq_outNamedTuple;
}
PyTypeObject* get_lstsq_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"QR", ""}, {nullptr} };
static PyTypeObject lstsqNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lstsq", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&lstsqNamedTuple1, &desc);
lstsqNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lstsqNamedTuple1;
}
PyTypeObject* get_lu_unpack_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"P", ""}, {"L", ""}, {"U", ""}, {nullptr} };
static PyTypeObject lu_unpackNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lu_unpack", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&lu_unpackNamedTuple, &desc);
lu_unpackNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lu_unpackNamedTuple;
}
PyTypeObject* get_lu_unpack_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"P", ""}, {"L", ""}, {"U", ""}, {nullptr} };
static PyTypeObject lu_unpack_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lu_unpack_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&lu_unpack_outNamedTuple1, &desc);
lu_unpack_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lu_unpack_outNamedTuple1;
}
PyTypeObject* get_max_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject maxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.max", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&maxNamedTuple, &desc);
maxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &maxNamedTuple;
}
PyTypeObject* get_max_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject max_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.max_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&max_outNamedTuple1, &desc);
max_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &max_outNamedTuple1;
}
PyTypeObject* get_median_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject medianNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.median", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&medianNamedTuple, &desc);
medianNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &medianNamedTuple;
}
PyTypeObject* get_median_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject median_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.median_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&median_outNamedTuple1, &desc);
median_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &median_outNamedTuple1;
}
PyTypeObject* get_min_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject minNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.min", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&minNamedTuple, &desc);
minNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &minNamedTuple;
}
PyTypeObject* get_min_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject min_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.min_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&min_outNamedTuple1, &desc);
min_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &min_outNamedTuple1;
}
PyTypeObject* get_mode_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject modeNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.mode", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&modeNamedTuple, &desc);
modeNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &modeNamedTuple;
}
PyTypeObject* get_mode_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject mode_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.mode_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&mode_outNamedTuple1, &desc);
mode_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &mode_outNamedTuple1;
}
PyTypeObject* get_nanmedian_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject nanmedianNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.nanmedian", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&nanmedianNamedTuple, &desc);
nanmedianNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &nanmedianNamedTuple;
}
PyTypeObject* get_nanmedian_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject nanmedian_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.nanmedian_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&nanmedian_outNamedTuple1, &desc);
nanmedian_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &nanmedian_outNamedTuple1;
}
PyTypeObject* get_qr_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject qr_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.qr_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&qr_outNamedTuple, &desc);
qr_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &qr_outNamedTuple;
}
PyTypeObject* get_qr_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject qrNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.qr", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&qrNamedTuple1, &desc);
qrNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &qrNamedTuple1;
}
PyTypeObject* get_slogdet_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject slogdetNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.slogdet", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&slogdetNamedTuple, &desc);
slogdetNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &slogdetNamedTuple;
}
PyTypeObject* get_solve_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"LU", ""}, {nullptr} };
static PyTypeObject solveNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.solve", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&solveNamedTuple, &desc);
solveNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &solveNamedTuple;
}
PyTypeObject* get_solve_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"LU", ""}, {nullptr} };
static PyTypeObject solve_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.solve_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&solve_outNamedTuple1, &desc);
solve_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &solve_outNamedTuple1;
}
PyTypeObject* get_sort_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject sort_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.sort_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&sort_outNamedTuple, &desc);
sort_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &sort_outNamedTuple;
}
PyTypeObject* get_sort_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject sortNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.sort", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&sortNamedTuple1, &desc);
sortNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &sortNamedTuple1;
}
PyTypeObject* get_svd_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"V", ""}, {nullptr} };
static PyTypeObject svd_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.svd_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&svd_outNamedTuple, &desc);
svd_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &svd_outNamedTuple;
}
PyTypeObject* get_svd_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"V", ""}, {nullptr} };
static PyTypeObject svdNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.svd", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&svdNamedTuple1, &desc);
svdNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &svdNamedTuple1;
}
PyTypeObject* get_symeig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject symeig_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.symeig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&symeig_outNamedTuple, &desc);
symeig_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &symeig_outNamedTuple;
}
PyTypeObject* get_symeig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject symeigNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.symeig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&symeigNamedTuple1, &desc);
symeigNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &symeigNamedTuple1;
}
PyTypeObject* get_topk_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject topk_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.topk_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&topk_outNamedTuple, &desc);
topk_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &topk_outNamedTuple;
}
PyTypeObject* get_topk_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject topkNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.topk", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&topkNamedTuple1, &desc);
topkNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &topkNamedTuple1;
}
PyTypeObject* get_triangular_solve_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"cloned_coefficient", ""}, {nullptr} };
static PyTypeObject triangular_solve_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.triangular_solve_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&triangular_solve_outNamedTuple, &desc);
triangular_solve_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &triangular_solve_outNamedTuple;
}
PyTypeObject* get_triangular_solve_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"cloned_coefficient", ""}, {nullptr} };
static PyTypeObject triangular_solveNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.triangular_solve", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&triangular_solveNamedTuple1, &desc);
triangular_solveNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &triangular_solveNamedTuple1;
}
}
namespace torch {
namespace autograd {
std::map<std::string, PyTypeObject*>& get_namedtuple_types_map() {
// [NOTE] Non-global map
// This map calls Python functions during its initialization.
// If it is a global static variable and in case it is loaded
// before Python interpreter is ready, then the calls it makes during
// initialization will SEGFAULT.
// To avoid this we make it function static variable so that it is
// initialized only after the Python interpreter is ready.
static std::map<std::string, PyTypeObject*> namedtuple_types_map = {
{"_det_lu_based_helper", get__det_lu_based_helper_namedtuple()},
{"_fake_quantize_per_tensor_affine_cachemask_tensor_qparams", get__fake_quantize_per_tensor_affine_cachemask_tensor_qparams_namedtuple()},
{"_fused_moving_avg_obs_fq_helper", get__fused_moving_avg_obs_fq_helper_namedtuple()},
{"_lu_with_info", get__lu_with_info_namedtuple()},
{"_unpack_dual", get__unpack_dual_namedtuple()},
{"aminmax", get_aminmax_namedtuple()},
{"aminmax_out", get_aminmax_out_namedtuple()},
{"cummax", get_cummax_namedtuple()},
{"cummax_out", get_cummax_out_namedtuple()},
{"cummin", get_cummin_namedtuple()},
{"cummin_out", get_cummin_out_namedtuple()},
{"eig_out", get_eig_out_namedtuple()},
{"eig", get_eig_namedtuple()},
{"frexp", get_frexp_namedtuple()},
{"frexp_out", get_frexp_out_namedtuple()},
{"geqrf_out", get_geqrf_out_namedtuple()},
{"geqrf", get_geqrf_namedtuple()},
{"histogram_out", get_histogram_out_namedtuple()},
{"histogram", get_histogram_namedtuple()},
{"kthvalue", get_kthvalue_namedtuple()},
{"kthvalue_out", get_kthvalue_out_namedtuple()},
{"linalg_cholesky_ex", get_linalg_cholesky_ex_namedtuple()},
{"linalg_cholesky_ex_out", get_linalg_cholesky_ex_out_namedtuple()},
{"linalg_eig", get_linalg_eig_namedtuple()},
{"linalg_eig_out", get_linalg_eig_out_namedtuple()},
{"linalg_eigh", get_linalg_eigh_namedtuple()},
{"linalg_eigh_out", get_linalg_eigh_out_namedtuple()},
{"linalg_inv_ex", get_linalg_inv_ex_namedtuple()},
{"linalg_inv_ex_out", get_linalg_inv_ex_out_namedtuple()},
{"linalg_lstsq", get_linalg_lstsq_namedtuple()},
{"linalg_lstsq_out", get_linalg_lstsq_out_namedtuple()},
{"linalg_qr", get_linalg_qr_namedtuple()},
{"linalg_qr_out", get_linalg_qr_out_namedtuple()},
{"linalg_slogdet", get_linalg_slogdet_namedtuple()},
{"linalg_slogdet_out", get_linalg_slogdet_out_namedtuple()},
{"linalg_svd_out", get_linalg_svd_out_namedtuple()},
{"linalg_svd", get_linalg_svd_namedtuple()},
{"lstsq_out", get_lstsq_out_namedtuple()},
{"lstsq", get_lstsq_namedtuple()},
{"lu_unpack", get_lu_unpack_namedtuple()},
{"lu_unpack_out", get_lu_unpack_out_namedtuple()},
{"max", get_max_namedtuple()},
{"max_out", get_max_out_namedtuple()},
{"median", get_median_namedtuple()},
{"median_out", get_median_out_namedtuple()},
{"min", get_min_namedtuple()},
{"min_out", get_min_out_namedtuple()},
{"mode", get_mode_namedtuple()},
{"mode_out", get_mode_out_namedtuple()},
{"nanmedian", get_nanmedian_namedtuple()},
{"nanmedian_out", get_nanmedian_out_namedtuple()},
{"qr_out", get_qr_out_namedtuple()},
{"qr", get_qr_namedtuple()},
{"slogdet", get_slogdet_namedtuple()},
{"solve", get_solve_namedtuple()},
{"solve_out", get_solve_out_namedtuple()},
{"sort_out", get_sort_out_namedtuple()},
{"sort", get_sort_namedtuple()},
{"svd_out", get_svd_out_namedtuple()},
{"svd", get_svd_namedtuple()},
{"symeig_out", get_symeig_out_namedtuple()},
{"symeig", get_symeig_namedtuple()},
{"topk_out", get_topk_out_namedtuple()},
{"topk", get_topk_namedtuple()},
{"triangular_solve_out", get_triangular_solve_out_namedtuple()},
{"triangular_solve", get_triangular_solve_namedtuple()},
};
return namedtuple_types_map;
}
PyTypeObject* get_namedtuple(std::string name) {
static auto& namedtuple_types_map = get_namedtuple_types_map();
return namedtuple_types_map[name];
}
void initReturnTypes(PyObject* module) {
static struct PyModuleDef def = {
PyModuleDef_HEAD_INIT, "torch._C._return_types", nullptr, -1, {}};
PyObject* return_types_module = PyModule_Create(&def);
if (!return_types_module) {
throw python_error();
}
for (const auto& return_type_pair : get_namedtuple_types_map()) {
// hold onto the TypeObject for the unlikely case of user
// deleting or overriding it.
Py_INCREF(return_type_pair.second);
if (PyModule_AddObject(
return_types_module,
return_type_pair.first.c_str(),
(PyObject*)return_type_pair.second) != 0) {
Py_DECREF((PyObject*)return_type_pair.second);
throw python_error();
}
}
// steals a reference to return_types on success
if (PyModule_AddObject(module, "_return_types", return_types_module) != 0) {
Py_DECREF(return_types_module);
throw python_error();
}
}
} // namespace autograd
} // namespace torch
```
</details>
<details>
<summary>Eg. updated call in other python_*_functions</summary>
```cpp
// linalg_cholesky_ex
static PyObject * THPVariable_linalg_cholesky_ex(PyObject* self_, PyObject* args, PyObject* kwargs)
{
HANDLE_TH_ERRORS
static PyTypeObject* NamedTuple = get_namedtuple("linalg_cholesky_ex");
static PyTypeObject* NamedTuple1 = get_namedtuple("linalg_cholesky_ex_out");
static PythonArgParser parser({
"linalg_cholesky_ex(Tensor input, *, bool upper=False, bool check_errors=False, TensorList[2] out=None)",
}, /*traceable=*/true);
ParsedArgs<4> parsed_args;
auto _r = parser.parse(nullptr, args, kwargs, parsed_args);
if(_r.has_torch_function()) {
return handle_torch_function(_r, nullptr, args, kwargs, THPLinalgVariableFunctionsModule, "torch.linalg");
}
if (_r.isNone(3)) {
// aten::linalg_cholesky_ex(Tensor self, *, bool upper=False, bool check_errors=False) -> (Tensor L, Tensor info)
auto dispatch_linalg_cholesky_ex = [](const at::Tensor & self, bool upper, bool check_errors) -> ::std::tuple<at::Tensor,at::Tensor> {
pybind11::gil_scoped_release no_gil;
return at::linalg_cholesky_ex(self, upper, check_errors);
};
return wrap(NamedTuple, dispatch_linalg_cholesky_ex(_r.tensor(0), _r.toBool(1), _r.toBool(2)));
} else {
// aten::linalg_cholesky_ex.L(Tensor self, *, bool upper=False, bool check_errors=False, Tensor(a!) L, Tensor(b!) info) -> (Tensor(a!) L, Tensor(b!) info)
auto out = _r.tensorlist_n<2>(3);
auto dispatch_linalg_cholesky_ex_out = [](at::Tensor & L, at::Tensor & info, const at::Tensor & self, bool upper, bool check_errors) -> ::std::tuple<at::Tensor,at::Tensor> {
pybind11::gil_scoped_release no_gil;
return at::linalg_cholesky_ex_out(L, info, self, upper, check_errors);
};
return wrap(NamedTuple1, dispatch_linalg_cholesky_ex_out(out[0], out[1], _r.tensor(0), _r.toBool(1), _r.toBool(2)));
}
Py_RETURN_NONE;
END_HANDLE_TH_ERRORS
}
```
</details>
Pull Request resolved: https://github.com/pytorch/pytorch/pull/66614
Reviewed By: H-Huang
Differential Revision: D32741134
Pulled By: zou3519
fbshipit-source-id: 27bada30d20e66333ca1be1775608d9f0cbf9f59
2021-12-06 17:03:11 +00:00
|
|
|
# Currently, we only use `functions` to generate `return_types` bindings.
|
|
|
|
|
# All methods which return namedtuple have function variant at this point.
|
|
|
|
|
# If any method only operator with namedtuple is added in the future,
|
|
|
|
|
# we will have to address that.
|
|
|
|
|
create_python_return_type_bindings(
|
2022-04-20 12:51:02 +00:00
|
|
|
fm, functions, lambda fn: True, "python_return_types.cpp"
|
|
|
|
|
)
|
|
|
|
|
|
expose return_types in Python (#66614)
Summary:
https://github.com/facebookresearch/functorch/issues/87
TODO:
* [x] Add comments
* [x] Add test
* [x] Fix XLA
<details>
<summary>Generated python_return_types.cpp</summary>
```cpp
#include <Python.h>
#include <vector>
#include <map>
#include <string>
#include "torch/csrc/autograd/python_return_types.h"
#include "torch/csrc/utils/structseq.h"
#include "torch/csrc/Exceptions.h"
namespace {
PyTypeObject* get__det_lu_based_helper_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"det", ""}, {"lu", ""}, {"pivs", ""}, {nullptr} };
static PyTypeObject _det_lu_based_helperNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._det_lu_based_helper", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&_det_lu_based_helperNamedTuple, &desc);
_det_lu_based_helperNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_det_lu_based_helperNamedTuple;
}
PyTypeObject* get__fake_quantize_per_tensor_affine_cachemask_tensor_qparams_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"output", ""}, {"mask", ""}, {nullptr} };
static PyTypeObject _fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._fake_quantize_per_tensor_affine_cachemask_tensor_qparams", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple, &desc);
_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple;
}
PyTypeObject* get__fused_moving_avg_obs_fq_helper_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"output", ""}, {"mask", ""}, {nullptr} };
static PyTypeObject _fused_moving_avg_obs_fq_helperNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._fused_moving_avg_obs_fq_helper", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_fused_moving_avg_obs_fq_helperNamedTuple, &desc);
_fused_moving_avg_obs_fq_helperNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_fused_moving_avg_obs_fq_helperNamedTuple;
}
PyTypeObject* get__lu_with_info_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"LU", ""}, {"pivots", ""}, {"info", ""}, {nullptr} };
static PyTypeObject _lu_with_infoNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._lu_with_info", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&_lu_with_infoNamedTuple, &desc);
_lu_with_infoNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_lu_with_infoNamedTuple;
}
PyTypeObject* get__unpack_dual_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"primal", ""}, {"tangent", ""}, {nullptr} };
static PyTypeObject _unpack_dualNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._unpack_dual", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_unpack_dualNamedTuple, &desc);
_unpack_dualNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_unpack_dualNamedTuple;
}
PyTypeObject* get_aminmax_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"min", ""}, {"max", ""}, {nullptr} };
static PyTypeObject aminmaxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.aminmax", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&aminmaxNamedTuple, &desc);
aminmaxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &aminmaxNamedTuple;
}
PyTypeObject* get_aminmax_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"min", ""}, {"max", ""}, {nullptr} };
static PyTypeObject aminmax_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.aminmax_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&aminmax_outNamedTuple1, &desc);
aminmax_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &aminmax_outNamedTuple1;
}
PyTypeObject* get_cummax_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummaxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummax", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummaxNamedTuple, &desc);
cummaxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummaxNamedTuple;
}
PyTypeObject* get_cummax_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummax_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummax_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummax_outNamedTuple1, &desc);
cummax_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummax_outNamedTuple1;
}
PyTypeObject* get_cummin_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cumminNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummin", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cumminNamedTuple, &desc);
cumminNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cumminNamedTuple;
}
PyTypeObject* get_cummin_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummin_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummin_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummin_outNamedTuple1, &desc);
cummin_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummin_outNamedTuple1;
}
PyTypeObject* get_eig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject eig_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.eig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&eig_outNamedTuple, &desc);
eig_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &eig_outNamedTuple;
}
PyTypeObject* get_eig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject eigNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.eig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&eigNamedTuple1, &desc);
eigNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &eigNamedTuple1;
}
PyTypeObject* get_frexp_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"mantissa", ""}, {"exponent", ""}, {nullptr} };
static PyTypeObject frexpNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.frexp", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&frexpNamedTuple, &desc);
frexpNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &frexpNamedTuple;
}
PyTypeObject* get_frexp_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"mantissa", ""}, {"exponent", ""}, {nullptr} };
static PyTypeObject frexp_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.frexp_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&frexp_outNamedTuple1, &desc);
frexp_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &frexp_outNamedTuple1;
}
PyTypeObject* get_geqrf_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"a", ""}, {"tau", ""}, {nullptr} };
static PyTypeObject geqrf_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.geqrf_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&geqrf_outNamedTuple, &desc);
geqrf_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &geqrf_outNamedTuple;
}
PyTypeObject* get_geqrf_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"a", ""}, {"tau", ""}, {nullptr} };
static PyTypeObject geqrfNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.geqrf", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&geqrfNamedTuple1, &desc);
geqrfNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &geqrfNamedTuple1;
}
PyTypeObject* get_histogram_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"hist", ""}, {"bin_edges", ""}, {nullptr} };
static PyTypeObject histogram_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.histogram_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&histogram_outNamedTuple, &desc);
histogram_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &histogram_outNamedTuple;
}
PyTypeObject* get_histogram_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"hist", ""}, {"bin_edges", ""}, {nullptr} };
static PyTypeObject histogramNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.histogram", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&histogramNamedTuple1, &desc);
histogramNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &histogramNamedTuple1;
}
PyTypeObject* get_kthvalue_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject kthvalueNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.kthvalue", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&kthvalueNamedTuple, &desc);
kthvalueNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &kthvalueNamedTuple;
}
PyTypeObject* get_kthvalue_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject kthvalue_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.kthvalue_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&kthvalue_outNamedTuple1, &desc);
kthvalue_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &kthvalue_outNamedTuple1;
}
PyTypeObject* get_linalg_cholesky_ex_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"L", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_cholesky_exNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_cholesky_ex", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_cholesky_exNamedTuple, &desc);
linalg_cholesky_exNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_cholesky_exNamedTuple;
}
PyTypeObject* get_linalg_cholesky_ex_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"L", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_cholesky_ex_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_cholesky_ex_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_cholesky_ex_outNamedTuple1, &desc);
linalg_cholesky_ex_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_cholesky_ex_outNamedTuple1;
}
PyTypeObject* get_linalg_eig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eigNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eigNamedTuple, &desc);
linalg_eigNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eigNamedTuple;
}
PyTypeObject* get_linalg_eig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eig_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eig_outNamedTuple1, &desc);
linalg_eig_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eig_outNamedTuple1;
}
PyTypeObject* get_linalg_eigh_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eighNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eigh", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eighNamedTuple, &desc);
linalg_eighNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eighNamedTuple;
}
PyTypeObject* get_linalg_eigh_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eigh_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eigh_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eigh_outNamedTuple1, &desc);
linalg_eigh_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eigh_outNamedTuple1;
}
PyTypeObject* get_linalg_inv_ex_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"inverse", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_inv_exNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_inv_ex", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_inv_exNamedTuple, &desc);
linalg_inv_exNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_inv_exNamedTuple;
}
PyTypeObject* get_linalg_inv_ex_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"inverse", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_inv_ex_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_inv_ex_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_inv_ex_outNamedTuple1, &desc);
linalg_inv_ex_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_inv_ex_outNamedTuple1;
}
PyTypeObject* get_linalg_lstsq_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"residuals", ""}, {"rank", ""}, {"singular_values", ""}, {nullptr} };
static PyTypeObject linalg_lstsqNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_lstsq", nullptr, NamedTuple_fields, 4 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_lstsqNamedTuple, &desc);
linalg_lstsqNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_lstsqNamedTuple;
}
PyTypeObject* get_linalg_lstsq_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"residuals", ""}, {"rank", ""}, {"singular_values", ""}, {nullptr} };
static PyTypeObject linalg_lstsq_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_lstsq_out", nullptr, NamedTuple_fields, 4 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_lstsq_outNamedTuple1, &desc);
linalg_lstsq_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_lstsq_outNamedTuple1;
}
PyTypeObject* get_linalg_qr_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject linalg_qrNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_qr", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_qrNamedTuple, &desc);
linalg_qrNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_qrNamedTuple;
}
PyTypeObject* get_linalg_qr_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject linalg_qr_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_qr_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_qr_outNamedTuple1, &desc);
linalg_qr_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_qr_outNamedTuple1;
}
PyTypeObject* get_linalg_slogdet_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject linalg_slogdetNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_slogdet", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_slogdetNamedTuple, &desc);
linalg_slogdetNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_slogdetNamedTuple;
}
PyTypeObject* get_linalg_slogdet_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject linalg_slogdet_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_slogdet_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_slogdet_outNamedTuple1, &desc);
linalg_slogdet_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_slogdet_outNamedTuple1;
}
PyTypeObject* get_linalg_svd_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"Vh", ""}, {nullptr} };
static PyTypeObject linalg_svd_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_svd_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_svd_outNamedTuple, &desc);
linalg_svd_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_svd_outNamedTuple;
}
PyTypeObject* get_linalg_svd_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"Vh", ""}, {nullptr} };
static PyTypeObject linalg_svdNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_svd", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_svdNamedTuple1, &desc);
linalg_svdNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_svdNamedTuple1;
}
PyTypeObject* get_lstsq_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"QR", ""}, {nullptr} };
static PyTypeObject lstsq_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lstsq_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&lstsq_outNamedTuple, &desc);
lstsq_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lstsq_outNamedTuple;
}
PyTypeObject* get_lstsq_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"QR", ""}, {nullptr} };
static PyTypeObject lstsqNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lstsq", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&lstsqNamedTuple1, &desc);
lstsqNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lstsqNamedTuple1;
}
PyTypeObject* get_lu_unpack_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"P", ""}, {"L", ""}, {"U", ""}, {nullptr} };
static PyTypeObject lu_unpackNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lu_unpack", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&lu_unpackNamedTuple, &desc);
lu_unpackNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lu_unpackNamedTuple;
}
PyTypeObject* get_lu_unpack_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"P", ""}, {"L", ""}, {"U", ""}, {nullptr} };
static PyTypeObject lu_unpack_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lu_unpack_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&lu_unpack_outNamedTuple1, &desc);
lu_unpack_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lu_unpack_outNamedTuple1;
}
PyTypeObject* get_max_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject maxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.max", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&maxNamedTuple, &desc);
maxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &maxNamedTuple;
}
PyTypeObject* get_max_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject max_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.max_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&max_outNamedTuple1, &desc);
max_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &max_outNamedTuple1;
}
PyTypeObject* get_median_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject medianNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.median", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&medianNamedTuple, &desc);
medianNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &medianNamedTuple;
}
PyTypeObject* get_median_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject median_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.median_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&median_outNamedTuple1, &desc);
median_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &median_outNamedTuple1;
}
PyTypeObject* get_min_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject minNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.min", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&minNamedTuple, &desc);
minNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &minNamedTuple;
}
PyTypeObject* get_min_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject min_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.min_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&min_outNamedTuple1, &desc);
min_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &min_outNamedTuple1;
}
PyTypeObject* get_mode_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject modeNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.mode", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&modeNamedTuple, &desc);
modeNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &modeNamedTuple;
}
PyTypeObject* get_mode_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject mode_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.mode_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&mode_outNamedTuple1, &desc);
mode_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &mode_outNamedTuple1;
}
PyTypeObject* get_nanmedian_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject nanmedianNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.nanmedian", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&nanmedianNamedTuple, &desc);
nanmedianNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &nanmedianNamedTuple;
}
PyTypeObject* get_nanmedian_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject nanmedian_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.nanmedian_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&nanmedian_outNamedTuple1, &desc);
nanmedian_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &nanmedian_outNamedTuple1;
}
PyTypeObject* get_qr_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject qr_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.qr_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&qr_outNamedTuple, &desc);
qr_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &qr_outNamedTuple;
}
PyTypeObject* get_qr_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject qrNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.qr", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&qrNamedTuple1, &desc);
qrNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &qrNamedTuple1;
}
PyTypeObject* get_slogdet_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject slogdetNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.slogdet", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&slogdetNamedTuple, &desc);
slogdetNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &slogdetNamedTuple;
}
PyTypeObject* get_solve_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"LU", ""}, {nullptr} };
static PyTypeObject solveNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.solve", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&solveNamedTuple, &desc);
solveNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &solveNamedTuple;
}
PyTypeObject* get_solve_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"LU", ""}, {nullptr} };
static PyTypeObject solve_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.solve_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&solve_outNamedTuple1, &desc);
solve_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &solve_outNamedTuple1;
}
PyTypeObject* get_sort_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject sort_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.sort_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&sort_outNamedTuple, &desc);
sort_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &sort_outNamedTuple;
}
PyTypeObject* get_sort_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject sortNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.sort", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&sortNamedTuple1, &desc);
sortNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &sortNamedTuple1;
}
PyTypeObject* get_svd_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"V", ""}, {nullptr} };
static PyTypeObject svd_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.svd_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&svd_outNamedTuple, &desc);
svd_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &svd_outNamedTuple;
}
PyTypeObject* get_svd_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"V", ""}, {nullptr} };
static PyTypeObject svdNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.svd", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&svdNamedTuple1, &desc);
svdNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &svdNamedTuple1;
}
PyTypeObject* get_symeig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject symeig_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.symeig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&symeig_outNamedTuple, &desc);
symeig_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &symeig_outNamedTuple;
}
PyTypeObject* get_symeig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject symeigNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.symeig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&symeigNamedTuple1, &desc);
symeigNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &symeigNamedTuple1;
}
PyTypeObject* get_topk_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject topk_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.topk_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&topk_outNamedTuple, &desc);
topk_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &topk_outNamedTuple;
}
PyTypeObject* get_topk_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject topkNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.topk", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&topkNamedTuple1, &desc);
topkNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &topkNamedTuple1;
}
PyTypeObject* get_triangular_solve_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"cloned_coefficient", ""}, {nullptr} };
static PyTypeObject triangular_solve_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.triangular_solve_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&triangular_solve_outNamedTuple, &desc);
triangular_solve_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &triangular_solve_outNamedTuple;
}
PyTypeObject* get_triangular_solve_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"cloned_coefficient", ""}, {nullptr} };
static PyTypeObject triangular_solveNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.triangular_solve", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&triangular_solveNamedTuple1, &desc);
triangular_solveNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &triangular_solveNamedTuple1;
}
}
namespace torch {
namespace autograd {
std::map<std::string, PyTypeObject*>& get_namedtuple_types_map() {
// [NOTE] Non-global map
// This map calls Python functions during its initialization.
// If it is a global static variable and in case it is loaded
// before Python interpreter is ready, then the calls it makes during
// initialization will SEGFAULT.
// To avoid this we make it function static variable so that it is
// initialized only after the Python interpreter is ready.
static std::map<std::string, PyTypeObject*> namedtuple_types_map = {
{"_det_lu_based_helper", get__det_lu_based_helper_namedtuple()},
{"_fake_quantize_per_tensor_affine_cachemask_tensor_qparams", get__fake_quantize_per_tensor_affine_cachemask_tensor_qparams_namedtuple()},
{"_fused_moving_avg_obs_fq_helper", get__fused_moving_avg_obs_fq_helper_namedtuple()},
{"_lu_with_info", get__lu_with_info_namedtuple()},
{"_unpack_dual", get__unpack_dual_namedtuple()},
{"aminmax", get_aminmax_namedtuple()},
{"aminmax_out", get_aminmax_out_namedtuple()},
{"cummax", get_cummax_namedtuple()},
{"cummax_out", get_cummax_out_namedtuple()},
{"cummin", get_cummin_namedtuple()},
{"cummin_out", get_cummin_out_namedtuple()},
{"eig_out", get_eig_out_namedtuple()},
{"eig", get_eig_namedtuple()},
{"frexp", get_frexp_namedtuple()},
{"frexp_out", get_frexp_out_namedtuple()},
{"geqrf_out", get_geqrf_out_namedtuple()},
{"geqrf", get_geqrf_namedtuple()},
{"histogram_out", get_histogram_out_namedtuple()},
{"histogram", get_histogram_namedtuple()},
{"kthvalue", get_kthvalue_namedtuple()},
{"kthvalue_out", get_kthvalue_out_namedtuple()},
{"linalg_cholesky_ex", get_linalg_cholesky_ex_namedtuple()},
{"linalg_cholesky_ex_out", get_linalg_cholesky_ex_out_namedtuple()},
{"linalg_eig", get_linalg_eig_namedtuple()},
{"linalg_eig_out", get_linalg_eig_out_namedtuple()},
{"linalg_eigh", get_linalg_eigh_namedtuple()},
{"linalg_eigh_out", get_linalg_eigh_out_namedtuple()},
{"linalg_inv_ex", get_linalg_inv_ex_namedtuple()},
{"linalg_inv_ex_out", get_linalg_inv_ex_out_namedtuple()},
{"linalg_lstsq", get_linalg_lstsq_namedtuple()},
{"linalg_lstsq_out", get_linalg_lstsq_out_namedtuple()},
{"linalg_qr", get_linalg_qr_namedtuple()},
{"linalg_qr_out", get_linalg_qr_out_namedtuple()},
{"linalg_slogdet", get_linalg_slogdet_namedtuple()},
{"linalg_slogdet_out", get_linalg_slogdet_out_namedtuple()},
{"linalg_svd_out", get_linalg_svd_out_namedtuple()},
{"linalg_svd", get_linalg_svd_namedtuple()},
{"lstsq_out", get_lstsq_out_namedtuple()},
{"lstsq", get_lstsq_namedtuple()},
{"lu_unpack", get_lu_unpack_namedtuple()},
{"lu_unpack_out", get_lu_unpack_out_namedtuple()},
{"max", get_max_namedtuple()},
{"max_out", get_max_out_namedtuple()},
{"median", get_median_namedtuple()},
{"median_out", get_median_out_namedtuple()},
{"min", get_min_namedtuple()},
{"min_out", get_min_out_namedtuple()},
{"mode", get_mode_namedtuple()},
{"mode_out", get_mode_out_namedtuple()},
{"nanmedian", get_nanmedian_namedtuple()},
{"nanmedian_out", get_nanmedian_out_namedtuple()},
{"qr_out", get_qr_out_namedtuple()},
{"qr", get_qr_namedtuple()},
{"slogdet", get_slogdet_namedtuple()},
{"solve", get_solve_namedtuple()},
{"solve_out", get_solve_out_namedtuple()},
{"sort_out", get_sort_out_namedtuple()},
{"sort", get_sort_namedtuple()},
{"svd_out", get_svd_out_namedtuple()},
{"svd", get_svd_namedtuple()},
{"symeig_out", get_symeig_out_namedtuple()},
{"symeig", get_symeig_namedtuple()},
{"topk_out", get_topk_out_namedtuple()},
{"topk", get_topk_namedtuple()},
{"triangular_solve_out", get_triangular_solve_out_namedtuple()},
{"triangular_solve", get_triangular_solve_namedtuple()},
};
return namedtuple_types_map;
}
PyTypeObject* get_namedtuple(std::string name) {
static auto& namedtuple_types_map = get_namedtuple_types_map();
return namedtuple_types_map[name];
}
void initReturnTypes(PyObject* module) {
static struct PyModuleDef def = {
PyModuleDef_HEAD_INIT, "torch._C._return_types", nullptr, -1, {}};
PyObject* return_types_module = PyModule_Create(&def);
if (!return_types_module) {
throw python_error();
}
for (const auto& return_type_pair : get_namedtuple_types_map()) {
// hold onto the TypeObject for the unlikely case of user
// deleting or overriding it.
Py_INCREF(return_type_pair.second);
if (PyModule_AddObject(
return_types_module,
return_type_pair.first.c_str(),
(PyObject*)return_type_pair.second) != 0) {
Py_DECREF((PyObject*)return_type_pair.second);
throw python_error();
}
}
// steals a reference to return_types on success
if (PyModule_AddObject(module, "_return_types", return_types_module) != 0) {
Py_DECREF(return_types_module);
throw python_error();
}
}
} // namespace autograd
} // namespace torch
```
</details>
<details>
<summary>Eg. updated call in other python_*_functions</summary>
```cpp
// linalg_cholesky_ex
static PyObject * THPVariable_linalg_cholesky_ex(PyObject* self_, PyObject* args, PyObject* kwargs)
{
HANDLE_TH_ERRORS
static PyTypeObject* NamedTuple = get_namedtuple("linalg_cholesky_ex");
static PyTypeObject* NamedTuple1 = get_namedtuple("linalg_cholesky_ex_out");
static PythonArgParser parser({
"linalg_cholesky_ex(Tensor input, *, bool upper=False, bool check_errors=False, TensorList[2] out=None)",
}, /*traceable=*/true);
ParsedArgs<4> parsed_args;
auto _r = parser.parse(nullptr, args, kwargs, parsed_args);
if(_r.has_torch_function()) {
return handle_torch_function(_r, nullptr, args, kwargs, THPLinalgVariableFunctionsModule, "torch.linalg");
}
if (_r.isNone(3)) {
// aten::linalg_cholesky_ex(Tensor self, *, bool upper=False, bool check_errors=False) -> (Tensor L, Tensor info)
auto dispatch_linalg_cholesky_ex = [](const at::Tensor & self, bool upper, bool check_errors) -> ::std::tuple<at::Tensor,at::Tensor> {
pybind11::gil_scoped_release no_gil;
return at::linalg_cholesky_ex(self, upper, check_errors);
};
return wrap(NamedTuple, dispatch_linalg_cholesky_ex(_r.tensor(0), _r.toBool(1), _r.toBool(2)));
} else {
// aten::linalg_cholesky_ex.L(Tensor self, *, bool upper=False, bool check_errors=False, Tensor(a!) L, Tensor(b!) info) -> (Tensor(a!) L, Tensor(b!) info)
auto out = _r.tensorlist_n<2>(3);
auto dispatch_linalg_cholesky_ex_out = [](at::Tensor & L, at::Tensor & info, const at::Tensor & self, bool upper, bool check_errors) -> ::std::tuple<at::Tensor,at::Tensor> {
pybind11::gil_scoped_release no_gil;
return at::linalg_cholesky_ex_out(L, info, self, upper, check_errors);
};
return wrap(NamedTuple1, dispatch_linalg_cholesky_ex_out(out[0], out[1], _r.tensor(0), _r.toBool(1), _r.toBool(2)));
}
Py_RETURN_NONE;
END_HANDLE_TH_ERRORS
}
```
</details>
Pull Request resolved: https://github.com/pytorch/pytorch/pull/66614
Reviewed By: H-Huang
Differential Revision: D32741134
Pulled By: zou3519
fbshipit-source-id: 27bada30d20e66333ca1be1775608d9f0cbf9f59
2021-12-06 17:03:11 +00:00
|
|
|
|
2021-08-25 22:05:14 +00:00
|
|
|
def group_filter_overloads(
|
|
|
|
|
pairs: Sequence[PythonSignatureNativeFunctionPair],
|
2022-04-20 12:51:02 +00:00
|
|
|
pred: Callable[[NativeFunction], bool],
|
2021-08-25 22:05:14 +00:00
|
|
|
) -> Dict[BaseOperatorName, List[PythonSignatureNativeFunctionPair]]:
|
2022-04-20 12:51:02 +00:00
|
|
|
grouped: Dict[
|
|
|
|
|
BaseOperatorName, List[PythonSignatureNativeFunctionPair]
|
|
|
|
|
] = defaultdict(list)
|
2021-08-25 22:05:14 +00:00
|
|
|
for pair in pairs:
|
|
|
|
|
if pred(pair.function):
|
|
|
|
|
grouped[pair.function.func.name.name].append(pair)
|
|
|
|
|
return grouped
|
|
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
|
2020-11-14 10:22:37 +00:00
|
|
|
def create_python_bindings(
|
|
|
|
|
fm: FileManager,
|
|
|
|
|
pairs: Sequence[PythonSignatureNativeFunctionPair],
|
|
|
|
|
pred: Callable[[NativeFunction], bool],
|
|
|
|
|
module: Optional[str],
|
|
|
|
|
filename: str,
|
|
|
|
|
*,
|
|
|
|
|
method: bool,
|
|
|
|
|
) -> None:
|
2018-01-17 23:27:42 +00:00
|
|
|
"""Generates Python bindings to ATen functions"""
|
2020-11-08 09:03:59 +00:00
|
|
|
py_methods: List[str] = []
|
2022-01-21 15:32:59 +00:00
|
|
|
ops_headers: List[str] = []
|
2020-11-08 09:03:59 +00:00
|
|
|
py_method_defs: List[str] = []
|
|
|
|
|
py_forwards: List[str] = []
|
2020-01-30 08:26:16 +00:00
|
|
|
|
2021-08-25 22:05:14 +00:00
|
|
|
grouped = group_filter_overloads(pairs, pred)
|
2020-11-14 10:22:37 +00:00
|
|
|
|
2020-11-18 20:17:37 +00:00
|
|
|
for name in sorted(grouped.keys(), key=lambda x: str(x)):
|
2020-11-14 10:22:37 +00:00
|
|
|
overloads = grouped[name]
|
|
|
|
|
py_methods.append(method_impl(name, module, overloads, method=method))
|
|
|
|
|
py_method_defs.append(method_def(name, module, overloads, method=method))
|
|
|
|
|
py_forwards.extend(forward_decls(name, overloads, method=method))
|
2022-04-20 12:51:02 +00:00
|
|
|
ops_headers.append(f"#include <ATen/ops/{name.base}.h>")
|
|
|
|
|
|
|
|
|
|
fm.write_with_template(
|
|
|
|
|
filename,
|
|
|
|
|
filename,
|
|
|
|
|
lambda: {
|
|
|
|
|
"generated_comment": "@" + f"generated from {fm.template_dir}/{filename}",
|
|
|
|
|
"ops_headers": ops_headers,
|
|
|
|
|
"py_forwards": py_forwards,
|
|
|
|
|
"py_methods": py_methods,
|
|
|
|
|
"py_method_defs": py_method_defs,
|
|
|
|
|
},
|
|
|
|
|
)
|
2017-10-06 16:12:50 +00:00
|
|
|
|
2020-11-08 09:03:59 +00:00
|
|
|
|
expose return_types in Python (#66614)
Summary:
https://github.com/facebookresearch/functorch/issues/87
TODO:
* [x] Add comments
* [x] Add test
* [x] Fix XLA
<details>
<summary>Generated python_return_types.cpp</summary>
```cpp
#include <Python.h>
#include <vector>
#include <map>
#include <string>
#include "torch/csrc/autograd/python_return_types.h"
#include "torch/csrc/utils/structseq.h"
#include "torch/csrc/Exceptions.h"
namespace {
PyTypeObject* get__det_lu_based_helper_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"det", ""}, {"lu", ""}, {"pivs", ""}, {nullptr} };
static PyTypeObject _det_lu_based_helperNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._det_lu_based_helper", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&_det_lu_based_helperNamedTuple, &desc);
_det_lu_based_helperNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_det_lu_based_helperNamedTuple;
}
PyTypeObject* get__fake_quantize_per_tensor_affine_cachemask_tensor_qparams_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"output", ""}, {"mask", ""}, {nullptr} };
static PyTypeObject _fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._fake_quantize_per_tensor_affine_cachemask_tensor_qparams", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple, &desc);
_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple;
}
PyTypeObject* get__fused_moving_avg_obs_fq_helper_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"output", ""}, {"mask", ""}, {nullptr} };
static PyTypeObject _fused_moving_avg_obs_fq_helperNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._fused_moving_avg_obs_fq_helper", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_fused_moving_avg_obs_fq_helperNamedTuple, &desc);
_fused_moving_avg_obs_fq_helperNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_fused_moving_avg_obs_fq_helperNamedTuple;
}
PyTypeObject* get__lu_with_info_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"LU", ""}, {"pivots", ""}, {"info", ""}, {nullptr} };
static PyTypeObject _lu_with_infoNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._lu_with_info", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&_lu_with_infoNamedTuple, &desc);
_lu_with_infoNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_lu_with_infoNamedTuple;
}
PyTypeObject* get__unpack_dual_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"primal", ""}, {"tangent", ""}, {nullptr} };
static PyTypeObject _unpack_dualNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._unpack_dual", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_unpack_dualNamedTuple, &desc);
_unpack_dualNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_unpack_dualNamedTuple;
}
PyTypeObject* get_aminmax_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"min", ""}, {"max", ""}, {nullptr} };
static PyTypeObject aminmaxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.aminmax", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&aminmaxNamedTuple, &desc);
aminmaxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &aminmaxNamedTuple;
}
PyTypeObject* get_aminmax_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"min", ""}, {"max", ""}, {nullptr} };
static PyTypeObject aminmax_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.aminmax_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&aminmax_outNamedTuple1, &desc);
aminmax_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &aminmax_outNamedTuple1;
}
PyTypeObject* get_cummax_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummaxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummax", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummaxNamedTuple, &desc);
cummaxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummaxNamedTuple;
}
PyTypeObject* get_cummax_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummax_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummax_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummax_outNamedTuple1, &desc);
cummax_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummax_outNamedTuple1;
}
PyTypeObject* get_cummin_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cumminNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummin", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cumminNamedTuple, &desc);
cumminNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cumminNamedTuple;
}
PyTypeObject* get_cummin_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummin_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummin_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummin_outNamedTuple1, &desc);
cummin_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummin_outNamedTuple1;
}
PyTypeObject* get_eig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject eig_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.eig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&eig_outNamedTuple, &desc);
eig_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &eig_outNamedTuple;
}
PyTypeObject* get_eig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject eigNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.eig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&eigNamedTuple1, &desc);
eigNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &eigNamedTuple1;
}
PyTypeObject* get_frexp_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"mantissa", ""}, {"exponent", ""}, {nullptr} };
static PyTypeObject frexpNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.frexp", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&frexpNamedTuple, &desc);
frexpNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &frexpNamedTuple;
}
PyTypeObject* get_frexp_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"mantissa", ""}, {"exponent", ""}, {nullptr} };
static PyTypeObject frexp_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.frexp_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&frexp_outNamedTuple1, &desc);
frexp_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &frexp_outNamedTuple1;
}
PyTypeObject* get_geqrf_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"a", ""}, {"tau", ""}, {nullptr} };
static PyTypeObject geqrf_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.geqrf_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&geqrf_outNamedTuple, &desc);
geqrf_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &geqrf_outNamedTuple;
}
PyTypeObject* get_geqrf_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"a", ""}, {"tau", ""}, {nullptr} };
static PyTypeObject geqrfNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.geqrf", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&geqrfNamedTuple1, &desc);
geqrfNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &geqrfNamedTuple1;
}
PyTypeObject* get_histogram_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"hist", ""}, {"bin_edges", ""}, {nullptr} };
static PyTypeObject histogram_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.histogram_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&histogram_outNamedTuple, &desc);
histogram_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &histogram_outNamedTuple;
}
PyTypeObject* get_histogram_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"hist", ""}, {"bin_edges", ""}, {nullptr} };
static PyTypeObject histogramNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.histogram", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&histogramNamedTuple1, &desc);
histogramNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &histogramNamedTuple1;
}
PyTypeObject* get_kthvalue_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject kthvalueNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.kthvalue", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&kthvalueNamedTuple, &desc);
kthvalueNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &kthvalueNamedTuple;
}
PyTypeObject* get_kthvalue_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject kthvalue_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.kthvalue_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&kthvalue_outNamedTuple1, &desc);
kthvalue_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &kthvalue_outNamedTuple1;
}
PyTypeObject* get_linalg_cholesky_ex_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"L", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_cholesky_exNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_cholesky_ex", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_cholesky_exNamedTuple, &desc);
linalg_cholesky_exNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_cholesky_exNamedTuple;
}
PyTypeObject* get_linalg_cholesky_ex_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"L", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_cholesky_ex_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_cholesky_ex_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_cholesky_ex_outNamedTuple1, &desc);
linalg_cholesky_ex_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_cholesky_ex_outNamedTuple1;
}
PyTypeObject* get_linalg_eig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eigNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eigNamedTuple, &desc);
linalg_eigNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eigNamedTuple;
}
PyTypeObject* get_linalg_eig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eig_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eig_outNamedTuple1, &desc);
linalg_eig_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eig_outNamedTuple1;
}
PyTypeObject* get_linalg_eigh_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eighNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eigh", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eighNamedTuple, &desc);
linalg_eighNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eighNamedTuple;
}
PyTypeObject* get_linalg_eigh_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eigh_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eigh_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eigh_outNamedTuple1, &desc);
linalg_eigh_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eigh_outNamedTuple1;
}
PyTypeObject* get_linalg_inv_ex_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"inverse", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_inv_exNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_inv_ex", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_inv_exNamedTuple, &desc);
linalg_inv_exNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_inv_exNamedTuple;
}
PyTypeObject* get_linalg_inv_ex_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"inverse", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_inv_ex_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_inv_ex_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_inv_ex_outNamedTuple1, &desc);
linalg_inv_ex_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_inv_ex_outNamedTuple1;
}
PyTypeObject* get_linalg_lstsq_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"residuals", ""}, {"rank", ""}, {"singular_values", ""}, {nullptr} };
static PyTypeObject linalg_lstsqNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_lstsq", nullptr, NamedTuple_fields, 4 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_lstsqNamedTuple, &desc);
linalg_lstsqNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_lstsqNamedTuple;
}
PyTypeObject* get_linalg_lstsq_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"residuals", ""}, {"rank", ""}, {"singular_values", ""}, {nullptr} };
static PyTypeObject linalg_lstsq_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_lstsq_out", nullptr, NamedTuple_fields, 4 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_lstsq_outNamedTuple1, &desc);
linalg_lstsq_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_lstsq_outNamedTuple1;
}
PyTypeObject* get_linalg_qr_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject linalg_qrNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_qr", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_qrNamedTuple, &desc);
linalg_qrNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_qrNamedTuple;
}
PyTypeObject* get_linalg_qr_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject linalg_qr_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_qr_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_qr_outNamedTuple1, &desc);
linalg_qr_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_qr_outNamedTuple1;
}
PyTypeObject* get_linalg_slogdet_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject linalg_slogdetNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_slogdet", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_slogdetNamedTuple, &desc);
linalg_slogdetNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_slogdetNamedTuple;
}
PyTypeObject* get_linalg_slogdet_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject linalg_slogdet_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_slogdet_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_slogdet_outNamedTuple1, &desc);
linalg_slogdet_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_slogdet_outNamedTuple1;
}
PyTypeObject* get_linalg_svd_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"Vh", ""}, {nullptr} };
static PyTypeObject linalg_svd_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_svd_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_svd_outNamedTuple, &desc);
linalg_svd_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_svd_outNamedTuple;
}
PyTypeObject* get_linalg_svd_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"Vh", ""}, {nullptr} };
static PyTypeObject linalg_svdNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_svd", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_svdNamedTuple1, &desc);
linalg_svdNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_svdNamedTuple1;
}
PyTypeObject* get_lstsq_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"QR", ""}, {nullptr} };
static PyTypeObject lstsq_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lstsq_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&lstsq_outNamedTuple, &desc);
lstsq_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lstsq_outNamedTuple;
}
PyTypeObject* get_lstsq_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"QR", ""}, {nullptr} };
static PyTypeObject lstsqNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lstsq", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&lstsqNamedTuple1, &desc);
lstsqNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lstsqNamedTuple1;
}
PyTypeObject* get_lu_unpack_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"P", ""}, {"L", ""}, {"U", ""}, {nullptr} };
static PyTypeObject lu_unpackNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lu_unpack", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&lu_unpackNamedTuple, &desc);
lu_unpackNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lu_unpackNamedTuple;
}
PyTypeObject* get_lu_unpack_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"P", ""}, {"L", ""}, {"U", ""}, {nullptr} };
static PyTypeObject lu_unpack_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lu_unpack_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&lu_unpack_outNamedTuple1, &desc);
lu_unpack_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lu_unpack_outNamedTuple1;
}
PyTypeObject* get_max_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject maxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.max", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&maxNamedTuple, &desc);
maxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &maxNamedTuple;
}
PyTypeObject* get_max_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject max_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.max_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&max_outNamedTuple1, &desc);
max_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &max_outNamedTuple1;
}
PyTypeObject* get_median_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject medianNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.median", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&medianNamedTuple, &desc);
medianNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &medianNamedTuple;
}
PyTypeObject* get_median_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject median_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.median_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&median_outNamedTuple1, &desc);
median_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &median_outNamedTuple1;
}
PyTypeObject* get_min_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject minNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.min", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&minNamedTuple, &desc);
minNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &minNamedTuple;
}
PyTypeObject* get_min_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject min_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.min_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&min_outNamedTuple1, &desc);
min_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &min_outNamedTuple1;
}
PyTypeObject* get_mode_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject modeNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.mode", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&modeNamedTuple, &desc);
modeNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &modeNamedTuple;
}
PyTypeObject* get_mode_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject mode_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.mode_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&mode_outNamedTuple1, &desc);
mode_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &mode_outNamedTuple1;
}
PyTypeObject* get_nanmedian_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject nanmedianNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.nanmedian", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&nanmedianNamedTuple, &desc);
nanmedianNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &nanmedianNamedTuple;
}
PyTypeObject* get_nanmedian_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject nanmedian_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.nanmedian_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&nanmedian_outNamedTuple1, &desc);
nanmedian_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &nanmedian_outNamedTuple1;
}
PyTypeObject* get_qr_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject qr_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.qr_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&qr_outNamedTuple, &desc);
qr_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &qr_outNamedTuple;
}
PyTypeObject* get_qr_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject qrNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.qr", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&qrNamedTuple1, &desc);
qrNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &qrNamedTuple1;
}
PyTypeObject* get_slogdet_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject slogdetNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.slogdet", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&slogdetNamedTuple, &desc);
slogdetNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &slogdetNamedTuple;
}
PyTypeObject* get_solve_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"LU", ""}, {nullptr} };
static PyTypeObject solveNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.solve", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&solveNamedTuple, &desc);
solveNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &solveNamedTuple;
}
PyTypeObject* get_solve_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"LU", ""}, {nullptr} };
static PyTypeObject solve_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.solve_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&solve_outNamedTuple1, &desc);
solve_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &solve_outNamedTuple1;
}
PyTypeObject* get_sort_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject sort_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.sort_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&sort_outNamedTuple, &desc);
sort_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &sort_outNamedTuple;
}
PyTypeObject* get_sort_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject sortNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.sort", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&sortNamedTuple1, &desc);
sortNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &sortNamedTuple1;
}
PyTypeObject* get_svd_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"V", ""}, {nullptr} };
static PyTypeObject svd_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.svd_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&svd_outNamedTuple, &desc);
svd_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &svd_outNamedTuple;
}
PyTypeObject* get_svd_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"V", ""}, {nullptr} };
static PyTypeObject svdNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.svd", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&svdNamedTuple1, &desc);
svdNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &svdNamedTuple1;
}
PyTypeObject* get_symeig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject symeig_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.symeig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&symeig_outNamedTuple, &desc);
symeig_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &symeig_outNamedTuple;
}
PyTypeObject* get_symeig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject symeigNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.symeig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&symeigNamedTuple1, &desc);
symeigNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &symeigNamedTuple1;
}
PyTypeObject* get_topk_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject topk_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.topk_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&topk_outNamedTuple, &desc);
topk_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &topk_outNamedTuple;
}
PyTypeObject* get_topk_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject topkNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.topk", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&topkNamedTuple1, &desc);
topkNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &topkNamedTuple1;
}
PyTypeObject* get_triangular_solve_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"cloned_coefficient", ""}, {nullptr} };
static PyTypeObject triangular_solve_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.triangular_solve_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&triangular_solve_outNamedTuple, &desc);
triangular_solve_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &triangular_solve_outNamedTuple;
}
PyTypeObject* get_triangular_solve_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"cloned_coefficient", ""}, {nullptr} };
static PyTypeObject triangular_solveNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.triangular_solve", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&triangular_solveNamedTuple1, &desc);
triangular_solveNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &triangular_solveNamedTuple1;
}
}
namespace torch {
namespace autograd {
std::map<std::string, PyTypeObject*>& get_namedtuple_types_map() {
// [NOTE] Non-global map
// This map calls Python functions during its initialization.
// If it is a global static variable and in case it is loaded
// before Python interpreter is ready, then the calls it makes during
// initialization will SEGFAULT.
// To avoid this we make it function static variable so that it is
// initialized only after the Python interpreter is ready.
static std::map<std::string, PyTypeObject*> namedtuple_types_map = {
{"_det_lu_based_helper", get__det_lu_based_helper_namedtuple()},
{"_fake_quantize_per_tensor_affine_cachemask_tensor_qparams", get__fake_quantize_per_tensor_affine_cachemask_tensor_qparams_namedtuple()},
{"_fused_moving_avg_obs_fq_helper", get__fused_moving_avg_obs_fq_helper_namedtuple()},
{"_lu_with_info", get__lu_with_info_namedtuple()},
{"_unpack_dual", get__unpack_dual_namedtuple()},
{"aminmax", get_aminmax_namedtuple()},
{"aminmax_out", get_aminmax_out_namedtuple()},
{"cummax", get_cummax_namedtuple()},
{"cummax_out", get_cummax_out_namedtuple()},
{"cummin", get_cummin_namedtuple()},
{"cummin_out", get_cummin_out_namedtuple()},
{"eig_out", get_eig_out_namedtuple()},
{"eig", get_eig_namedtuple()},
{"frexp", get_frexp_namedtuple()},
{"frexp_out", get_frexp_out_namedtuple()},
{"geqrf_out", get_geqrf_out_namedtuple()},
{"geqrf", get_geqrf_namedtuple()},
{"histogram_out", get_histogram_out_namedtuple()},
{"histogram", get_histogram_namedtuple()},
{"kthvalue", get_kthvalue_namedtuple()},
{"kthvalue_out", get_kthvalue_out_namedtuple()},
{"linalg_cholesky_ex", get_linalg_cholesky_ex_namedtuple()},
{"linalg_cholesky_ex_out", get_linalg_cholesky_ex_out_namedtuple()},
{"linalg_eig", get_linalg_eig_namedtuple()},
{"linalg_eig_out", get_linalg_eig_out_namedtuple()},
{"linalg_eigh", get_linalg_eigh_namedtuple()},
{"linalg_eigh_out", get_linalg_eigh_out_namedtuple()},
{"linalg_inv_ex", get_linalg_inv_ex_namedtuple()},
{"linalg_inv_ex_out", get_linalg_inv_ex_out_namedtuple()},
{"linalg_lstsq", get_linalg_lstsq_namedtuple()},
{"linalg_lstsq_out", get_linalg_lstsq_out_namedtuple()},
{"linalg_qr", get_linalg_qr_namedtuple()},
{"linalg_qr_out", get_linalg_qr_out_namedtuple()},
{"linalg_slogdet", get_linalg_slogdet_namedtuple()},
{"linalg_slogdet_out", get_linalg_slogdet_out_namedtuple()},
{"linalg_svd_out", get_linalg_svd_out_namedtuple()},
{"linalg_svd", get_linalg_svd_namedtuple()},
{"lstsq_out", get_lstsq_out_namedtuple()},
{"lstsq", get_lstsq_namedtuple()},
{"lu_unpack", get_lu_unpack_namedtuple()},
{"lu_unpack_out", get_lu_unpack_out_namedtuple()},
{"max", get_max_namedtuple()},
{"max_out", get_max_out_namedtuple()},
{"median", get_median_namedtuple()},
{"median_out", get_median_out_namedtuple()},
{"min", get_min_namedtuple()},
{"min_out", get_min_out_namedtuple()},
{"mode", get_mode_namedtuple()},
{"mode_out", get_mode_out_namedtuple()},
{"nanmedian", get_nanmedian_namedtuple()},
{"nanmedian_out", get_nanmedian_out_namedtuple()},
{"qr_out", get_qr_out_namedtuple()},
{"qr", get_qr_namedtuple()},
{"slogdet", get_slogdet_namedtuple()},
{"solve", get_solve_namedtuple()},
{"solve_out", get_solve_out_namedtuple()},
{"sort_out", get_sort_out_namedtuple()},
{"sort", get_sort_namedtuple()},
{"svd_out", get_svd_out_namedtuple()},
{"svd", get_svd_namedtuple()},
{"symeig_out", get_symeig_out_namedtuple()},
{"symeig", get_symeig_namedtuple()},
{"topk_out", get_topk_out_namedtuple()},
{"topk", get_topk_namedtuple()},
{"triangular_solve_out", get_triangular_solve_out_namedtuple()},
{"triangular_solve", get_triangular_solve_namedtuple()},
};
return namedtuple_types_map;
}
PyTypeObject* get_namedtuple(std::string name) {
static auto& namedtuple_types_map = get_namedtuple_types_map();
return namedtuple_types_map[name];
}
void initReturnTypes(PyObject* module) {
static struct PyModuleDef def = {
PyModuleDef_HEAD_INIT, "torch._C._return_types", nullptr, -1, {}};
PyObject* return_types_module = PyModule_Create(&def);
if (!return_types_module) {
throw python_error();
}
for (const auto& return_type_pair : get_namedtuple_types_map()) {
// hold onto the TypeObject for the unlikely case of user
// deleting or overriding it.
Py_INCREF(return_type_pair.second);
if (PyModule_AddObject(
return_types_module,
return_type_pair.first.c_str(),
(PyObject*)return_type_pair.second) != 0) {
Py_DECREF((PyObject*)return_type_pair.second);
throw python_error();
}
}
// steals a reference to return_types on success
if (PyModule_AddObject(module, "_return_types", return_types_module) != 0) {
Py_DECREF(return_types_module);
throw python_error();
}
}
} // namespace autograd
} // namespace torch
```
</details>
<details>
<summary>Eg. updated call in other python_*_functions</summary>
```cpp
// linalg_cholesky_ex
static PyObject * THPVariable_linalg_cholesky_ex(PyObject* self_, PyObject* args, PyObject* kwargs)
{
HANDLE_TH_ERRORS
static PyTypeObject* NamedTuple = get_namedtuple("linalg_cholesky_ex");
static PyTypeObject* NamedTuple1 = get_namedtuple("linalg_cholesky_ex_out");
static PythonArgParser parser({
"linalg_cholesky_ex(Tensor input, *, bool upper=False, bool check_errors=False, TensorList[2] out=None)",
}, /*traceable=*/true);
ParsedArgs<4> parsed_args;
auto _r = parser.parse(nullptr, args, kwargs, parsed_args);
if(_r.has_torch_function()) {
return handle_torch_function(_r, nullptr, args, kwargs, THPLinalgVariableFunctionsModule, "torch.linalg");
}
if (_r.isNone(3)) {
// aten::linalg_cholesky_ex(Tensor self, *, bool upper=False, bool check_errors=False) -> (Tensor L, Tensor info)
auto dispatch_linalg_cholesky_ex = [](const at::Tensor & self, bool upper, bool check_errors) -> ::std::tuple<at::Tensor,at::Tensor> {
pybind11::gil_scoped_release no_gil;
return at::linalg_cholesky_ex(self, upper, check_errors);
};
return wrap(NamedTuple, dispatch_linalg_cholesky_ex(_r.tensor(0), _r.toBool(1), _r.toBool(2)));
} else {
// aten::linalg_cholesky_ex.L(Tensor self, *, bool upper=False, bool check_errors=False, Tensor(a!) L, Tensor(b!) info) -> (Tensor(a!) L, Tensor(b!) info)
auto out = _r.tensorlist_n<2>(3);
auto dispatch_linalg_cholesky_ex_out = [](at::Tensor & L, at::Tensor & info, const at::Tensor & self, bool upper, bool check_errors) -> ::std::tuple<at::Tensor,at::Tensor> {
pybind11::gil_scoped_release no_gil;
return at::linalg_cholesky_ex_out(L, info, self, upper, check_errors);
};
return wrap(NamedTuple1, dispatch_linalg_cholesky_ex_out(out[0], out[1], _r.tensor(0), _r.toBool(1), _r.toBool(2)));
}
Py_RETURN_NONE;
END_HANDLE_TH_ERRORS
}
```
</details>
Pull Request resolved: https://github.com/pytorch/pytorch/pull/66614
Reviewed By: H-Huang
Differential Revision: D32741134
Pulled By: zou3519
fbshipit-source-id: 27bada30d20e66333ca1be1775608d9f0cbf9f59
2021-12-06 17:03:11 +00:00
|
|
|
def create_python_return_type_bindings(
|
|
|
|
|
fm: FileManager,
|
|
|
|
|
pairs: Sequence[PythonSignatureNativeFunctionPair],
|
|
|
|
|
pred: Callable[[NativeFunction], bool],
|
|
|
|
|
filename: str,
|
|
|
|
|
) -> None:
|
|
|
|
|
"""
|
|
|
|
|
Generate function to initialize and return named tuple for native functions
|
|
|
|
|
which returns named tuple and relevant entry for the map in `python_return_types.cpp`.
|
|
|
|
|
"""
|
|
|
|
|
py_return_types_definition: List[str] = []
|
|
|
|
|
py_return_types_map: List[str] = []
|
|
|
|
|
|
|
|
|
|
grouped = group_filter_overloads(pairs, pred)
|
|
|
|
|
|
|
|
|
|
for name in sorted(grouped.keys(), key=lambda x: str(x)):
|
|
|
|
|
overloads = grouped[name]
|
2022-04-20 12:51:02 +00:00
|
|
|
definitions, map_entries = generate_return_type_definition_and_map_entry(
|
|
|
|
|
overloads
|
|
|
|
|
)
|
|
|
|
|
py_return_types_definition.append(
|
|
|
|
|
"" if not definitions else "\n".join(definitions)
|
|
|
|
|
)
|
expose return_types in Python (#66614)
Summary:
https://github.com/facebookresearch/functorch/issues/87
TODO:
* [x] Add comments
* [x] Add test
* [x] Fix XLA
<details>
<summary>Generated python_return_types.cpp</summary>
```cpp
#include <Python.h>
#include <vector>
#include <map>
#include <string>
#include "torch/csrc/autograd/python_return_types.h"
#include "torch/csrc/utils/structseq.h"
#include "torch/csrc/Exceptions.h"
namespace {
PyTypeObject* get__det_lu_based_helper_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"det", ""}, {"lu", ""}, {"pivs", ""}, {nullptr} };
static PyTypeObject _det_lu_based_helperNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._det_lu_based_helper", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&_det_lu_based_helperNamedTuple, &desc);
_det_lu_based_helperNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_det_lu_based_helperNamedTuple;
}
PyTypeObject* get__fake_quantize_per_tensor_affine_cachemask_tensor_qparams_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"output", ""}, {"mask", ""}, {nullptr} };
static PyTypeObject _fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._fake_quantize_per_tensor_affine_cachemask_tensor_qparams", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple, &desc);
_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple;
}
PyTypeObject* get__fused_moving_avg_obs_fq_helper_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"output", ""}, {"mask", ""}, {nullptr} };
static PyTypeObject _fused_moving_avg_obs_fq_helperNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._fused_moving_avg_obs_fq_helper", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_fused_moving_avg_obs_fq_helperNamedTuple, &desc);
_fused_moving_avg_obs_fq_helperNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_fused_moving_avg_obs_fq_helperNamedTuple;
}
PyTypeObject* get__lu_with_info_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"LU", ""}, {"pivots", ""}, {"info", ""}, {nullptr} };
static PyTypeObject _lu_with_infoNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._lu_with_info", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&_lu_with_infoNamedTuple, &desc);
_lu_with_infoNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_lu_with_infoNamedTuple;
}
PyTypeObject* get__unpack_dual_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"primal", ""}, {"tangent", ""}, {nullptr} };
static PyTypeObject _unpack_dualNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._unpack_dual", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_unpack_dualNamedTuple, &desc);
_unpack_dualNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_unpack_dualNamedTuple;
}
PyTypeObject* get_aminmax_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"min", ""}, {"max", ""}, {nullptr} };
static PyTypeObject aminmaxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.aminmax", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&aminmaxNamedTuple, &desc);
aminmaxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &aminmaxNamedTuple;
}
PyTypeObject* get_aminmax_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"min", ""}, {"max", ""}, {nullptr} };
static PyTypeObject aminmax_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.aminmax_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&aminmax_outNamedTuple1, &desc);
aminmax_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &aminmax_outNamedTuple1;
}
PyTypeObject* get_cummax_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummaxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummax", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummaxNamedTuple, &desc);
cummaxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummaxNamedTuple;
}
PyTypeObject* get_cummax_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummax_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummax_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummax_outNamedTuple1, &desc);
cummax_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummax_outNamedTuple1;
}
PyTypeObject* get_cummin_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cumminNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummin", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cumminNamedTuple, &desc);
cumminNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cumminNamedTuple;
}
PyTypeObject* get_cummin_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummin_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummin_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummin_outNamedTuple1, &desc);
cummin_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummin_outNamedTuple1;
}
PyTypeObject* get_eig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject eig_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.eig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&eig_outNamedTuple, &desc);
eig_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &eig_outNamedTuple;
}
PyTypeObject* get_eig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject eigNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.eig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&eigNamedTuple1, &desc);
eigNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &eigNamedTuple1;
}
PyTypeObject* get_frexp_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"mantissa", ""}, {"exponent", ""}, {nullptr} };
static PyTypeObject frexpNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.frexp", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&frexpNamedTuple, &desc);
frexpNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &frexpNamedTuple;
}
PyTypeObject* get_frexp_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"mantissa", ""}, {"exponent", ""}, {nullptr} };
static PyTypeObject frexp_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.frexp_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&frexp_outNamedTuple1, &desc);
frexp_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &frexp_outNamedTuple1;
}
PyTypeObject* get_geqrf_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"a", ""}, {"tau", ""}, {nullptr} };
static PyTypeObject geqrf_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.geqrf_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&geqrf_outNamedTuple, &desc);
geqrf_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &geqrf_outNamedTuple;
}
PyTypeObject* get_geqrf_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"a", ""}, {"tau", ""}, {nullptr} };
static PyTypeObject geqrfNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.geqrf", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&geqrfNamedTuple1, &desc);
geqrfNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &geqrfNamedTuple1;
}
PyTypeObject* get_histogram_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"hist", ""}, {"bin_edges", ""}, {nullptr} };
static PyTypeObject histogram_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.histogram_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&histogram_outNamedTuple, &desc);
histogram_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &histogram_outNamedTuple;
}
PyTypeObject* get_histogram_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"hist", ""}, {"bin_edges", ""}, {nullptr} };
static PyTypeObject histogramNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.histogram", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&histogramNamedTuple1, &desc);
histogramNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &histogramNamedTuple1;
}
PyTypeObject* get_kthvalue_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject kthvalueNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.kthvalue", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&kthvalueNamedTuple, &desc);
kthvalueNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &kthvalueNamedTuple;
}
PyTypeObject* get_kthvalue_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject kthvalue_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.kthvalue_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&kthvalue_outNamedTuple1, &desc);
kthvalue_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &kthvalue_outNamedTuple1;
}
PyTypeObject* get_linalg_cholesky_ex_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"L", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_cholesky_exNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_cholesky_ex", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_cholesky_exNamedTuple, &desc);
linalg_cholesky_exNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_cholesky_exNamedTuple;
}
PyTypeObject* get_linalg_cholesky_ex_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"L", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_cholesky_ex_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_cholesky_ex_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_cholesky_ex_outNamedTuple1, &desc);
linalg_cholesky_ex_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_cholesky_ex_outNamedTuple1;
}
PyTypeObject* get_linalg_eig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eigNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eigNamedTuple, &desc);
linalg_eigNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eigNamedTuple;
}
PyTypeObject* get_linalg_eig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eig_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eig_outNamedTuple1, &desc);
linalg_eig_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eig_outNamedTuple1;
}
PyTypeObject* get_linalg_eigh_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eighNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eigh", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eighNamedTuple, &desc);
linalg_eighNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eighNamedTuple;
}
PyTypeObject* get_linalg_eigh_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eigh_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eigh_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eigh_outNamedTuple1, &desc);
linalg_eigh_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eigh_outNamedTuple1;
}
PyTypeObject* get_linalg_inv_ex_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"inverse", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_inv_exNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_inv_ex", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_inv_exNamedTuple, &desc);
linalg_inv_exNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_inv_exNamedTuple;
}
PyTypeObject* get_linalg_inv_ex_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"inverse", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_inv_ex_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_inv_ex_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_inv_ex_outNamedTuple1, &desc);
linalg_inv_ex_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_inv_ex_outNamedTuple1;
}
PyTypeObject* get_linalg_lstsq_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"residuals", ""}, {"rank", ""}, {"singular_values", ""}, {nullptr} };
static PyTypeObject linalg_lstsqNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_lstsq", nullptr, NamedTuple_fields, 4 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_lstsqNamedTuple, &desc);
linalg_lstsqNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_lstsqNamedTuple;
}
PyTypeObject* get_linalg_lstsq_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"residuals", ""}, {"rank", ""}, {"singular_values", ""}, {nullptr} };
static PyTypeObject linalg_lstsq_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_lstsq_out", nullptr, NamedTuple_fields, 4 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_lstsq_outNamedTuple1, &desc);
linalg_lstsq_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_lstsq_outNamedTuple1;
}
PyTypeObject* get_linalg_qr_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject linalg_qrNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_qr", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_qrNamedTuple, &desc);
linalg_qrNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_qrNamedTuple;
}
PyTypeObject* get_linalg_qr_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject linalg_qr_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_qr_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_qr_outNamedTuple1, &desc);
linalg_qr_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_qr_outNamedTuple1;
}
PyTypeObject* get_linalg_slogdet_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject linalg_slogdetNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_slogdet", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_slogdetNamedTuple, &desc);
linalg_slogdetNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_slogdetNamedTuple;
}
PyTypeObject* get_linalg_slogdet_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject linalg_slogdet_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_slogdet_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_slogdet_outNamedTuple1, &desc);
linalg_slogdet_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_slogdet_outNamedTuple1;
}
PyTypeObject* get_linalg_svd_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"Vh", ""}, {nullptr} };
static PyTypeObject linalg_svd_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_svd_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_svd_outNamedTuple, &desc);
linalg_svd_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_svd_outNamedTuple;
}
PyTypeObject* get_linalg_svd_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"Vh", ""}, {nullptr} };
static PyTypeObject linalg_svdNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_svd", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_svdNamedTuple1, &desc);
linalg_svdNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_svdNamedTuple1;
}
PyTypeObject* get_lstsq_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"QR", ""}, {nullptr} };
static PyTypeObject lstsq_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lstsq_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&lstsq_outNamedTuple, &desc);
lstsq_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lstsq_outNamedTuple;
}
PyTypeObject* get_lstsq_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"QR", ""}, {nullptr} };
static PyTypeObject lstsqNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lstsq", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&lstsqNamedTuple1, &desc);
lstsqNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lstsqNamedTuple1;
}
PyTypeObject* get_lu_unpack_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"P", ""}, {"L", ""}, {"U", ""}, {nullptr} };
static PyTypeObject lu_unpackNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lu_unpack", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&lu_unpackNamedTuple, &desc);
lu_unpackNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lu_unpackNamedTuple;
}
PyTypeObject* get_lu_unpack_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"P", ""}, {"L", ""}, {"U", ""}, {nullptr} };
static PyTypeObject lu_unpack_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lu_unpack_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&lu_unpack_outNamedTuple1, &desc);
lu_unpack_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lu_unpack_outNamedTuple1;
}
PyTypeObject* get_max_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject maxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.max", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&maxNamedTuple, &desc);
maxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &maxNamedTuple;
}
PyTypeObject* get_max_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject max_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.max_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&max_outNamedTuple1, &desc);
max_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &max_outNamedTuple1;
}
PyTypeObject* get_median_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject medianNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.median", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&medianNamedTuple, &desc);
medianNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &medianNamedTuple;
}
PyTypeObject* get_median_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject median_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.median_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&median_outNamedTuple1, &desc);
median_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &median_outNamedTuple1;
}
PyTypeObject* get_min_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject minNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.min", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&minNamedTuple, &desc);
minNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &minNamedTuple;
}
PyTypeObject* get_min_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject min_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.min_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&min_outNamedTuple1, &desc);
min_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &min_outNamedTuple1;
}
PyTypeObject* get_mode_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject modeNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.mode", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&modeNamedTuple, &desc);
modeNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &modeNamedTuple;
}
PyTypeObject* get_mode_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject mode_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.mode_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&mode_outNamedTuple1, &desc);
mode_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &mode_outNamedTuple1;
}
PyTypeObject* get_nanmedian_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject nanmedianNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.nanmedian", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&nanmedianNamedTuple, &desc);
nanmedianNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &nanmedianNamedTuple;
}
PyTypeObject* get_nanmedian_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject nanmedian_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.nanmedian_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&nanmedian_outNamedTuple1, &desc);
nanmedian_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &nanmedian_outNamedTuple1;
}
PyTypeObject* get_qr_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject qr_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.qr_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&qr_outNamedTuple, &desc);
qr_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &qr_outNamedTuple;
}
PyTypeObject* get_qr_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject qrNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.qr", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&qrNamedTuple1, &desc);
qrNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &qrNamedTuple1;
}
PyTypeObject* get_slogdet_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject slogdetNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.slogdet", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&slogdetNamedTuple, &desc);
slogdetNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &slogdetNamedTuple;
}
PyTypeObject* get_solve_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"LU", ""}, {nullptr} };
static PyTypeObject solveNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.solve", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&solveNamedTuple, &desc);
solveNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &solveNamedTuple;
}
PyTypeObject* get_solve_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"LU", ""}, {nullptr} };
static PyTypeObject solve_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.solve_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&solve_outNamedTuple1, &desc);
solve_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &solve_outNamedTuple1;
}
PyTypeObject* get_sort_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject sort_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.sort_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&sort_outNamedTuple, &desc);
sort_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &sort_outNamedTuple;
}
PyTypeObject* get_sort_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject sortNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.sort", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&sortNamedTuple1, &desc);
sortNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &sortNamedTuple1;
}
PyTypeObject* get_svd_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"V", ""}, {nullptr} };
static PyTypeObject svd_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.svd_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&svd_outNamedTuple, &desc);
svd_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &svd_outNamedTuple;
}
PyTypeObject* get_svd_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"V", ""}, {nullptr} };
static PyTypeObject svdNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.svd", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&svdNamedTuple1, &desc);
svdNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &svdNamedTuple1;
}
PyTypeObject* get_symeig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject symeig_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.symeig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&symeig_outNamedTuple, &desc);
symeig_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &symeig_outNamedTuple;
}
PyTypeObject* get_symeig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject symeigNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.symeig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&symeigNamedTuple1, &desc);
symeigNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &symeigNamedTuple1;
}
PyTypeObject* get_topk_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject topk_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.topk_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&topk_outNamedTuple, &desc);
topk_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &topk_outNamedTuple;
}
PyTypeObject* get_topk_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject topkNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.topk", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&topkNamedTuple1, &desc);
topkNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &topkNamedTuple1;
}
PyTypeObject* get_triangular_solve_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"cloned_coefficient", ""}, {nullptr} };
static PyTypeObject triangular_solve_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.triangular_solve_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&triangular_solve_outNamedTuple, &desc);
triangular_solve_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &triangular_solve_outNamedTuple;
}
PyTypeObject* get_triangular_solve_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"cloned_coefficient", ""}, {nullptr} };
static PyTypeObject triangular_solveNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.triangular_solve", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&triangular_solveNamedTuple1, &desc);
triangular_solveNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &triangular_solveNamedTuple1;
}
}
namespace torch {
namespace autograd {
std::map<std::string, PyTypeObject*>& get_namedtuple_types_map() {
// [NOTE] Non-global map
// This map calls Python functions during its initialization.
// If it is a global static variable and in case it is loaded
// before Python interpreter is ready, then the calls it makes during
// initialization will SEGFAULT.
// To avoid this we make it function static variable so that it is
// initialized only after the Python interpreter is ready.
static std::map<std::string, PyTypeObject*> namedtuple_types_map = {
{"_det_lu_based_helper", get__det_lu_based_helper_namedtuple()},
{"_fake_quantize_per_tensor_affine_cachemask_tensor_qparams", get__fake_quantize_per_tensor_affine_cachemask_tensor_qparams_namedtuple()},
{"_fused_moving_avg_obs_fq_helper", get__fused_moving_avg_obs_fq_helper_namedtuple()},
{"_lu_with_info", get__lu_with_info_namedtuple()},
{"_unpack_dual", get__unpack_dual_namedtuple()},
{"aminmax", get_aminmax_namedtuple()},
{"aminmax_out", get_aminmax_out_namedtuple()},
{"cummax", get_cummax_namedtuple()},
{"cummax_out", get_cummax_out_namedtuple()},
{"cummin", get_cummin_namedtuple()},
{"cummin_out", get_cummin_out_namedtuple()},
{"eig_out", get_eig_out_namedtuple()},
{"eig", get_eig_namedtuple()},
{"frexp", get_frexp_namedtuple()},
{"frexp_out", get_frexp_out_namedtuple()},
{"geqrf_out", get_geqrf_out_namedtuple()},
{"geqrf", get_geqrf_namedtuple()},
{"histogram_out", get_histogram_out_namedtuple()},
{"histogram", get_histogram_namedtuple()},
{"kthvalue", get_kthvalue_namedtuple()},
{"kthvalue_out", get_kthvalue_out_namedtuple()},
{"linalg_cholesky_ex", get_linalg_cholesky_ex_namedtuple()},
{"linalg_cholesky_ex_out", get_linalg_cholesky_ex_out_namedtuple()},
{"linalg_eig", get_linalg_eig_namedtuple()},
{"linalg_eig_out", get_linalg_eig_out_namedtuple()},
{"linalg_eigh", get_linalg_eigh_namedtuple()},
{"linalg_eigh_out", get_linalg_eigh_out_namedtuple()},
{"linalg_inv_ex", get_linalg_inv_ex_namedtuple()},
{"linalg_inv_ex_out", get_linalg_inv_ex_out_namedtuple()},
{"linalg_lstsq", get_linalg_lstsq_namedtuple()},
{"linalg_lstsq_out", get_linalg_lstsq_out_namedtuple()},
{"linalg_qr", get_linalg_qr_namedtuple()},
{"linalg_qr_out", get_linalg_qr_out_namedtuple()},
{"linalg_slogdet", get_linalg_slogdet_namedtuple()},
{"linalg_slogdet_out", get_linalg_slogdet_out_namedtuple()},
{"linalg_svd_out", get_linalg_svd_out_namedtuple()},
{"linalg_svd", get_linalg_svd_namedtuple()},
{"lstsq_out", get_lstsq_out_namedtuple()},
{"lstsq", get_lstsq_namedtuple()},
{"lu_unpack", get_lu_unpack_namedtuple()},
{"lu_unpack_out", get_lu_unpack_out_namedtuple()},
{"max", get_max_namedtuple()},
{"max_out", get_max_out_namedtuple()},
{"median", get_median_namedtuple()},
{"median_out", get_median_out_namedtuple()},
{"min", get_min_namedtuple()},
{"min_out", get_min_out_namedtuple()},
{"mode", get_mode_namedtuple()},
{"mode_out", get_mode_out_namedtuple()},
{"nanmedian", get_nanmedian_namedtuple()},
{"nanmedian_out", get_nanmedian_out_namedtuple()},
{"qr_out", get_qr_out_namedtuple()},
{"qr", get_qr_namedtuple()},
{"slogdet", get_slogdet_namedtuple()},
{"solve", get_solve_namedtuple()},
{"solve_out", get_solve_out_namedtuple()},
{"sort_out", get_sort_out_namedtuple()},
{"sort", get_sort_namedtuple()},
{"svd_out", get_svd_out_namedtuple()},
{"svd", get_svd_namedtuple()},
{"symeig_out", get_symeig_out_namedtuple()},
{"symeig", get_symeig_namedtuple()},
{"topk_out", get_topk_out_namedtuple()},
{"topk", get_topk_namedtuple()},
{"triangular_solve_out", get_triangular_solve_out_namedtuple()},
{"triangular_solve", get_triangular_solve_namedtuple()},
};
return namedtuple_types_map;
}
PyTypeObject* get_namedtuple(std::string name) {
static auto& namedtuple_types_map = get_namedtuple_types_map();
return namedtuple_types_map[name];
}
void initReturnTypes(PyObject* module) {
static struct PyModuleDef def = {
PyModuleDef_HEAD_INIT, "torch._C._return_types", nullptr, -1, {}};
PyObject* return_types_module = PyModule_Create(&def);
if (!return_types_module) {
throw python_error();
}
for (const auto& return_type_pair : get_namedtuple_types_map()) {
// hold onto the TypeObject for the unlikely case of user
// deleting or overriding it.
Py_INCREF(return_type_pair.second);
if (PyModule_AddObject(
return_types_module,
return_type_pair.first.c_str(),
(PyObject*)return_type_pair.second) != 0) {
Py_DECREF((PyObject*)return_type_pair.second);
throw python_error();
}
}
// steals a reference to return_types on success
if (PyModule_AddObject(module, "_return_types", return_types_module) != 0) {
Py_DECREF(return_types_module);
throw python_error();
}
}
} // namespace autograd
} // namespace torch
```
</details>
<details>
<summary>Eg. updated call in other python_*_functions</summary>
```cpp
// linalg_cholesky_ex
static PyObject * THPVariable_linalg_cholesky_ex(PyObject* self_, PyObject* args, PyObject* kwargs)
{
HANDLE_TH_ERRORS
static PyTypeObject* NamedTuple = get_namedtuple("linalg_cholesky_ex");
static PyTypeObject* NamedTuple1 = get_namedtuple("linalg_cholesky_ex_out");
static PythonArgParser parser({
"linalg_cholesky_ex(Tensor input, *, bool upper=False, bool check_errors=False, TensorList[2] out=None)",
}, /*traceable=*/true);
ParsedArgs<4> parsed_args;
auto _r = parser.parse(nullptr, args, kwargs, parsed_args);
if(_r.has_torch_function()) {
return handle_torch_function(_r, nullptr, args, kwargs, THPLinalgVariableFunctionsModule, "torch.linalg");
}
if (_r.isNone(3)) {
// aten::linalg_cholesky_ex(Tensor self, *, bool upper=False, bool check_errors=False) -> (Tensor L, Tensor info)
auto dispatch_linalg_cholesky_ex = [](const at::Tensor & self, bool upper, bool check_errors) -> ::std::tuple<at::Tensor,at::Tensor> {
pybind11::gil_scoped_release no_gil;
return at::linalg_cholesky_ex(self, upper, check_errors);
};
return wrap(NamedTuple, dispatch_linalg_cholesky_ex(_r.tensor(0), _r.toBool(1), _r.toBool(2)));
} else {
// aten::linalg_cholesky_ex.L(Tensor self, *, bool upper=False, bool check_errors=False, Tensor(a!) L, Tensor(b!) info) -> (Tensor(a!) L, Tensor(b!) info)
auto out = _r.tensorlist_n<2>(3);
auto dispatch_linalg_cholesky_ex_out = [](at::Tensor & L, at::Tensor & info, const at::Tensor & self, bool upper, bool check_errors) -> ::std::tuple<at::Tensor,at::Tensor> {
pybind11::gil_scoped_release no_gil;
return at::linalg_cholesky_ex_out(L, info, self, upper, check_errors);
};
return wrap(NamedTuple1, dispatch_linalg_cholesky_ex_out(out[0], out[1], _r.tensor(0), _r.toBool(1), _r.toBool(2)));
}
Py_RETURN_NONE;
END_HANDLE_TH_ERRORS
}
```
</details>
Pull Request resolved: https://github.com/pytorch/pytorch/pull/66614
Reviewed By: H-Huang
Differential Revision: D32741134
Pulled By: zou3519
fbshipit-source-id: 27bada30d20e66333ca1be1775608d9f0cbf9f59
2021-12-06 17:03:11 +00:00
|
|
|
py_return_types_map.append("" if not map_entries else "\n".join(map_entries))
|
|
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
fm.write_with_template(
|
|
|
|
|
filename,
|
|
|
|
|
filename,
|
|
|
|
|
lambda: {
|
|
|
|
|
"generated_comment": "@" + f"generated from {fm.template_dir}/{filename}",
|
|
|
|
|
"py_return_types": py_return_types_definition,
|
|
|
|
|
"py_return_types_map": py_return_types_map,
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
expose return_types in Python (#66614)
Summary:
https://github.com/facebookresearch/functorch/issues/87
TODO:
* [x] Add comments
* [x] Add test
* [x] Fix XLA
<details>
<summary>Generated python_return_types.cpp</summary>
```cpp
#include <Python.h>
#include <vector>
#include <map>
#include <string>
#include "torch/csrc/autograd/python_return_types.h"
#include "torch/csrc/utils/structseq.h"
#include "torch/csrc/Exceptions.h"
namespace {
PyTypeObject* get__det_lu_based_helper_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"det", ""}, {"lu", ""}, {"pivs", ""}, {nullptr} };
static PyTypeObject _det_lu_based_helperNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._det_lu_based_helper", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&_det_lu_based_helperNamedTuple, &desc);
_det_lu_based_helperNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_det_lu_based_helperNamedTuple;
}
PyTypeObject* get__fake_quantize_per_tensor_affine_cachemask_tensor_qparams_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"output", ""}, {"mask", ""}, {nullptr} };
static PyTypeObject _fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._fake_quantize_per_tensor_affine_cachemask_tensor_qparams", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple, &desc);
_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple;
}
PyTypeObject* get__fused_moving_avg_obs_fq_helper_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"output", ""}, {"mask", ""}, {nullptr} };
static PyTypeObject _fused_moving_avg_obs_fq_helperNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._fused_moving_avg_obs_fq_helper", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_fused_moving_avg_obs_fq_helperNamedTuple, &desc);
_fused_moving_avg_obs_fq_helperNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_fused_moving_avg_obs_fq_helperNamedTuple;
}
PyTypeObject* get__lu_with_info_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"LU", ""}, {"pivots", ""}, {"info", ""}, {nullptr} };
static PyTypeObject _lu_with_infoNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._lu_with_info", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&_lu_with_infoNamedTuple, &desc);
_lu_with_infoNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_lu_with_infoNamedTuple;
}
PyTypeObject* get__unpack_dual_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"primal", ""}, {"tangent", ""}, {nullptr} };
static PyTypeObject _unpack_dualNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._unpack_dual", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_unpack_dualNamedTuple, &desc);
_unpack_dualNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_unpack_dualNamedTuple;
}
PyTypeObject* get_aminmax_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"min", ""}, {"max", ""}, {nullptr} };
static PyTypeObject aminmaxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.aminmax", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&aminmaxNamedTuple, &desc);
aminmaxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &aminmaxNamedTuple;
}
PyTypeObject* get_aminmax_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"min", ""}, {"max", ""}, {nullptr} };
static PyTypeObject aminmax_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.aminmax_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&aminmax_outNamedTuple1, &desc);
aminmax_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &aminmax_outNamedTuple1;
}
PyTypeObject* get_cummax_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummaxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummax", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummaxNamedTuple, &desc);
cummaxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummaxNamedTuple;
}
PyTypeObject* get_cummax_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummax_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummax_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummax_outNamedTuple1, &desc);
cummax_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummax_outNamedTuple1;
}
PyTypeObject* get_cummin_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cumminNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummin", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cumminNamedTuple, &desc);
cumminNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cumminNamedTuple;
}
PyTypeObject* get_cummin_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummin_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummin_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummin_outNamedTuple1, &desc);
cummin_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummin_outNamedTuple1;
}
PyTypeObject* get_eig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject eig_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.eig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&eig_outNamedTuple, &desc);
eig_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &eig_outNamedTuple;
}
PyTypeObject* get_eig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject eigNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.eig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&eigNamedTuple1, &desc);
eigNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &eigNamedTuple1;
}
PyTypeObject* get_frexp_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"mantissa", ""}, {"exponent", ""}, {nullptr} };
static PyTypeObject frexpNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.frexp", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&frexpNamedTuple, &desc);
frexpNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &frexpNamedTuple;
}
PyTypeObject* get_frexp_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"mantissa", ""}, {"exponent", ""}, {nullptr} };
static PyTypeObject frexp_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.frexp_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&frexp_outNamedTuple1, &desc);
frexp_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &frexp_outNamedTuple1;
}
PyTypeObject* get_geqrf_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"a", ""}, {"tau", ""}, {nullptr} };
static PyTypeObject geqrf_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.geqrf_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&geqrf_outNamedTuple, &desc);
geqrf_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &geqrf_outNamedTuple;
}
PyTypeObject* get_geqrf_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"a", ""}, {"tau", ""}, {nullptr} };
static PyTypeObject geqrfNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.geqrf", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&geqrfNamedTuple1, &desc);
geqrfNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &geqrfNamedTuple1;
}
PyTypeObject* get_histogram_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"hist", ""}, {"bin_edges", ""}, {nullptr} };
static PyTypeObject histogram_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.histogram_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&histogram_outNamedTuple, &desc);
histogram_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &histogram_outNamedTuple;
}
PyTypeObject* get_histogram_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"hist", ""}, {"bin_edges", ""}, {nullptr} };
static PyTypeObject histogramNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.histogram", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&histogramNamedTuple1, &desc);
histogramNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &histogramNamedTuple1;
}
PyTypeObject* get_kthvalue_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject kthvalueNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.kthvalue", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&kthvalueNamedTuple, &desc);
kthvalueNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &kthvalueNamedTuple;
}
PyTypeObject* get_kthvalue_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject kthvalue_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.kthvalue_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&kthvalue_outNamedTuple1, &desc);
kthvalue_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &kthvalue_outNamedTuple1;
}
PyTypeObject* get_linalg_cholesky_ex_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"L", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_cholesky_exNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_cholesky_ex", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_cholesky_exNamedTuple, &desc);
linalg_cholesky_exNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_cholesky_exNamedTuple;
}
PyTypeObject* get_linalg_cholesky_ex_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"L", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_cholesky_ex_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_cholesky_ex_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_cholesky_ex_outNamedTuple1, &desc);
linalg_cholesky_ex_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_cholesky_ex_outNamedTuple1;
}
PyTypeObject* get_linalg_eig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eigNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eigNamedTuple, &desc);
linalg_eigNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eigNamedTuple;
}
PyTypeObject* get_linalg_eig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eig_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eig_outNamedTuple1, &desc);
linalg_eig_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eig_outNamedTuple1;
}
PyTypeObject* get_linalg_eigh_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eighNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eigh", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eighNamedTuple, &desc);
linalg_eighNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eighNamedTuple;
}
PyTypeObject* get_linalg_eigh_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eigh_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eigh_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eigh_outNamedTuple1, &desc);
linalg_eigh_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eigh_outNamedTuple1;
}
PyTypeObject* get_linalg_inv_ex_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"inverse", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_inv_exNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_inv_ex", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_inv_exNamedTuple, &desc);
linalg_inv_exNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_inv_exNamedTuple;
}
PyTypeObject* get_linalg_inv_ex_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"inverse", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_inv_ex_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_inv_ex_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_inv_ex_outNamedTuple1, &desc);
linalg_inv_ex_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_inv_ex_outNamedTuple1;
}
PyTypeObject* get_linalg_lstsq_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"residuals", ""}, {"rank", ""}, {"singular_values", ""}, {nullptr} };
static PyTypeObject linalg_lstsqNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_lstsq", nullptr, NamedTuple_fields, 4 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_lstsqNamedTuple, &desc);
linalg_lstsqNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_lstsqNamedTuple;
}
PyTypeObject* get_linalg_lstsq_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"residuals", ""}, {"rank", ""}, {"singular_values", ""}, {nullptr} };
static PyTypeObject linalg_lstsq_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_lstsq_out", nullptr, NamedTuple_fields, 4 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_lstsq_outNamedTuple1, &desc);
linalg_lstsq_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_lstsq_outNamedTuple1;
}
PyTypeObject* get_linalg_qr_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject linalg_qrNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_qr", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_qrNamedTuple, &desc);
linalg_qrNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_qrNamedTuple;
}
PyTypeObject* get_linalg_qr_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject linalg_qr_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_qr_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_qr_outNamedTuple1, &desc);
linalg_qr_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_qr_outNamedTuple1;
}
PyTypeObject* get_linalg_slogdet_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject linalg_slogdetNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_slogdet", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_slogdetNamedTuple, &desc);
linalg_slogdetNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_slogdetNamedTuple;
}
PyTypeObject* get_linalg_slogdet_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject linalg_slogdet_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_slogdet_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_slogdet_outNamedTuple1, &desc);
linalg_slogdet_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_slogdet_outNamedTuple1;
}
PyTypeObject* get_linalg_svd_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"Vh", ""}, {nullptr} };
static PyTypeObject linalg_svd_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_svd_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_svd_outNamedTuple, &desc);
linalg_svd_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_svd_outNamedTuple;
}
PyTypeObject* get_linalg_svd_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"Vh", ""}, {nullptr} };
static PyTypeObject linalg_svdNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_svd", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_svdNamedTuple1, &desc);
linalg_svdNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_svdNamedTuple1;
}
PyTypeObject* get_lstsq_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"QR", ""}, {nullptr} };
static PyTypeObject lstsq_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lstsq_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&lstsq_outNamedTuple, &desc);
lstsq_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lstsq_outNamedTuple;
}
PyTypeObject* get_lstsq_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"QR", ""}, {nullptr} };
static PyTypeObject lstsqNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lstsq", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&lstsqNamedTuple1, &desc);
lstsqNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lstsqNamedTuple1;
}
PyTypeObject* get_lu_unpack_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"P", ""}, {"L", ""}, {"U", ""}, {nullptr} };
static PyTypeObject lu_unpackNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lu_unpack", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&lu_unpackNamedTuple, &desc);
lu_unpackNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lu_unpackNamedTuple;
}
PyTypeObject* get_lu_unpack_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"P", ""}, {"L", ""}, {"U", ""}, {nullptr} };
static PyTypeObject lu_unpack_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lu_unpack_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&lu_unpack_outNamedTuple1, &desc);
lu_unpack_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lu_unpack_outNamedTuple1;
}
PyTypeObject* get_max_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject maxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.max", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&maxNamedTuple, &desc);
maxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &maxNamedTuple;
}
PyTypeObject* get_max_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject max_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.max_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&max_outNamedTuple1, &desc);
max_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &max_outNamedTuple1;
}
PyTypeObject* get_median_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject medianNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.median", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&medianNamedTuple, &desc);
medianNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &medianNamedTuple;
}
PyTypeObject* get_median_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject median_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.median_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&median_outNamedTuple1, &desc);
median_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &median_outNamedTuple1;
}
PyTypeObject* get_min_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject minNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.min", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&minNamedTuple, &desc);
minNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &minNamedTuple;
}
PyTypeObject* get_min_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject min_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.min_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&min_outNamedTuple1, &desc);
min_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &min_outNamedTuple1;
}
PyTypeObject* get_mode_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject modeNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.mode", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&modeNamedTuple, &desc);
modeNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &modeNamedTuple;
}
PyTypeObject* get_mode_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject mode_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.mode_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&mode_outNamedTuple1, &desc);
mode_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &mode_outNamedTuple1;
}
PyTypeObject* get_nanmedian_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject nanmedianNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.nanmedian", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&nanmedianNamedTuple, &desc);
nanmedianNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &nanmedianNamedTuple;
}
PyTypeObject* get_nanmedian_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject nanmedian_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.nanmedian_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&nanmedian_outNamedTuple1, &desc);
nanmedian_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &nanmedian_outNamedTuple1;
}
PyTypeObject* get_qr_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject qr_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.qr_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&qr_outNamedTuple, &desc);
qr_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &qr_outNamedTuple;
}
PyTypeObject* get_qr_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject qrNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.qr", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&qrNamedTuple1, &desc);
qrNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &qrNamedTuple1;
}
PyTypeObject* get_slogdet_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject slogdetNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.slogdet", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&slogdetNamedTuple, &desc);
slogdetNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &slogdetNamedTuple;
}
PyTypeObject* get_solve_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"LU", ""}, {nullptr} };
static PyTypeObject solveNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.solve", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&solveNamedTuple, &desc);
solveNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &solveNamedTuple;
}
PyTypeObject* get_solve_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"LU", ""}, {nullptr} };
static PyTypeObject solve_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.solve_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&solve_outNamedTuple1, &desc);
solve_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &solve_outNamedTuple1;
}
PyTypeObject* get_sort_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject sort_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.sort_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&sort_outNamedTuple, &desc);
sort_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &sort_outNamedTuple;
}
PyTypeObject* get_sort_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject sortNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.sort", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&sortNamedTuple1, &desc);
sortNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &sortNamedTuple1;
}
PyTypeObject* get_svd_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"V", ""}, {nullptr} };
static PyTypeObject svd_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.svd_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&svd_outNamedTuple, &desc);
svd_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &svd_outNamedTuple;
}
PyTypeObject* get_svd_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"V", ""}, {nullptr} };
static PyTypeObject svdNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.svd", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&svdNamedTuple1, &desc);
svdNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &svdNamedTuple1;
}
PyTypeObject* get_symeig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject symeig_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.symeig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&symeig_outNamedTuple, &desc);
symeig_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &symeig_outNamedTuple;
}
PyTypeObject* get_symeig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject symeigNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.symeig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&symeigNamedTuple1, &desc);
symeigNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &symeigNamedTuple1;
}
PyTypeObject* get_topk_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject topk_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.topk_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&topk_outNamedTuple, &desc);
topk_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &topk_outNamedTuple;
}
PyTypeObject* get_topk_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject topkNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.topk", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&topkNamedTuple1, &desc);
topkNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &topkNamedTuple1;
}
PyTypeObject* get_triangular_solve_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"cloned_coefficient", ""}, {nullptr} };
static PyTypeObject triangular_solve_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.triangular_solve_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&triangular_solve_outNamedTuple, &desc);
triangular_solve_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &triangular_solve_outNamedTuple;
}
PyTypeObject* get_triangular_solve_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"cloned_coefficient", ""}, {nullptr} };
static PyTypeObject triangular_solveNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.triangular_solve", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&triangular_solveNamedTuple1, &desc);
triangular_solveNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &triangular_solveNamedTuple1;
}
}
namespace torch {
namespace autograd {
std::map<std::string, PyTypeObject*>& get_namedtuple_types_map() {
// [NOTE] Non-global map
// This map calls Python functions during its initialization.
// If it is a global static variable and in case it is loaded
// before Python interpreter is ready, then the calls it makes during
// initialization will SEGFAULT.
// To avoid this we make it function static variable so that it is
// initialized only after the Python interpreter is ready.
static std::map<std::string, PyTypeObject*> namedtuple_types_map = {
{"_det_lu_based_helper", get__det_lu_based_helper_namedtuple()},
{"_fake_quantize_per_tensor_affine_cachemask_tensor_qparams", get__fake_quantize_per_tensor_affine_cachemask_tensor_qparams_namedtuple()},
{"_fused_moving_avg_obs_fq_helper", get__fused_moving_avg_obs_fq_helper_namedtuple()},
{"_lu_with_info", get__lu_with_info_namedtuple()},
{"_unpack_dual", get__unpack_dual_namedtuple()},
{"aminmax", get_aminmax_namedtuple()},
{"aminmax_out", get_aminmax_out_namedtuple()},
{"cummax", get_cummax_namedtuple()},
{"cummax_out", get_cummax_out_namedtuple()},
{"cummin", get_cummin_namedtuple()},
{"cummin_out", get_cummin_out_namedtuple()},
{"eig_out", get_eig_out_namedtuple()},
{"eig", get_eig_namedtuple()},
{"frexp", get_frexp_namedtuple()},
{"frexp_out", get_frexp_out_namedtuple()},
{"geqrf_out", get_geqrf_out_namedtuple()},
{"geqrf", get_geqrf_namedtuple()},
{"histogram_out", get_histogram_out_namedtuple()},
{"histogram", get_histogram_namedtuple()},
{"kthvalue", get_kthvalue_namedtuple()},
{"kthvalue_out", get_kthvalue_out_namedtuple()},
{"linalg_cholesky_ex", get_linalg_cholesky_ex_namedtuple()},
{"linalg_cholesky_ex_out", get_linalg_cholesky_ex_out_namedtuple()},
{"linalg_eig", get_linalg_eig_namedtuple()},
{"linalg_eig_out", get_linalg_eig_out_namedtuple()},
{"linalg_eigh", get_linalg_eigh_namedtuple()},
{"linalg_eigh_out", get_linalg_eigh_out_namedtuple()},
{"linalg_inv_ex", get_linalg_inv_ex_namedtuple()},
{"linalg_inv_ex_out", get_linalg_inv_ex_out_namedtuple()},
{"linalg_lstsq", get_linalg_lstsq_namedtuple()},
{"linalg_lstsq_out", get_linalg_lstsq_out_namedtuple()},
{"linalg_qr", get_linalg_qr_namedtuple()},
{"linalg_qr_out", get_linalg_qr_out_namedtuple()},
{"linalg_slogdet", get_linalg_slogdet_namedtuple()},
{"linalg_slogdet_out", get_linalg_slogdet_out_namedtuple()},
{"linalg_svd_out", get_linalg_svd_out_namedtuple()},
{"linalg_svd", get_linalg_svd_namedtuple()},
{"lstsq_out", get_lstsq_out_namedtuple()},
{"lstsq", get_lstsq_namedtuple()},
{"lu_unpack", get_lu_unpack_namedtuple()},
{"lu_unpack_out", get_lu_unpack_out_namedtuple()},
{"max", get_max_namedtuple()},
{"max_out", get_max_out_namedtuple()},
{"median", get_median_namedtuple()},
{"median_out", get_median_out_namedtuple()},
{"min", get_min_namedtuple()},
{"min_out", get_min_out_namedtuple()},
{"mode", get_mode_namedtuple()},
{"mode_out", get_mode_out_namedtuple()},
{"nanmedian", get_nanmedian_namedtuple()},
{"nanmedian_out", get_nanmedian_out_namedtuple()},
{"qr_out", get_qr_out_namedtuple()},
{"qr", get_qr_namedtuple()},
{"slogdet", get_slogdet_namedtuple()},
{"solve", get_solve_namedtuple()},
{"solve_out", get_solve_out_namedtuple()},
{"sort_out", get_sort_out_namedtuple()},
{"sort", get_sort_namedtuple()},
{"svd_out", get_svd_out_namedtuple()},
{"svd", get_svd_namedtuple()},
{"symeig_out", get_symeig_out_namedtuple()},
{"symeig", get_symeig_namedtuple()},
{"topk_out", get_topk_out_namedtuple()},
{"topk", get_topk_namedtuple()},
{"triangular_solve_out", get_triangular_solve_out_namedtuple()},
{"triangular_solve", get_triangular_solve_namedtuple()},
};
return namedtuple_types_map;
}
PyTypeObject* get_namedtuple(std::string name) {
static auto& namedtuple_types_map = get_namedtuple_types_map();
return namedtuple_types_map[name];
}
void initReturnTypes(PyObject* module) {
static struct PyModuleDef def = {
PyModuleDef_HEAD_INIT, "torch._C._return_types", nullptr, -1, {}};
PyObject* return_types_module = PyModule_Create(&def);
if (!return_types_module) {
throw python_error();
}
for (const auto& return_type_pair : get_namedtuple_types_map()) {
// hold onto the TypeObject for the unlikely case of user
// deleting or overriding it.
Py_INCREF(return_type_pair.second);
if (PyModule_AddObject(
return_types_module,
return_type_pair.first.c_str(),
(PyObject*)return_type_pair.second) != 0) {
Py_DECREF((PyObject*)return_type_pair.second);
throw python_error();
}
}
// steals a reference to return_types on success
if (PyModule_AddObject(module, "_return_types", return_types_module) != 0) {
Py_DECREF(return_types_module);
throw python_error();
}
}
} // namespace autograd
} // namespace torch
```
</details>
<details>
<summary>Eg. updated call in other python_*_functions</summary>
```cpp
// linalg_cholesky_ex
static PyObject * THPVariable_linalg_cholesky_ex(PyObject* self_, PyObject* args, PyObject* kwargs)
{
HANDLE_TH_ERRORS
static PyTypeObject* NamedTuple = get_namedtuple("linalg_cholesky_ex");
static PyTypeObject* NamedTuple1 = get_namedtuple("linalg_cholesky_ex_out");
static PythonArgParser parser({
"linalg_cholesky_ex(Tensor input, *, bool upper=False, bool check_errors=False, TensorList[2] out=None)",
}, /*traceable=*/true);
ParsedArgs<4> parsed_args;
auto _r = parser.parse(nullptr, args, kwargs, parsed_args);
if(_r.has_torch_function()) {
return handle_torch_function(_r, nullptr, args, kwargs, THPLinalgVariableFunctionsModule, "torch.linalg");
}
if (_r.isNone(3)) {
// aten::linalg_cholesky_ex(Tensor self, *, bool upper=False, bool check_errors=False) -> (Tensor L, Tensor info)
auto dispatch_linalg_cholesky_ex = [](const at::Tensor & self, bool upper, bool check_errors) -> ::std::tuple<at::Tensor,at::Tensor> {
pybind11::gil_scoped_release no_gil;
return at::linalg_cholesky_ex(self, upper, check_errors);
};
return wrap(NamedTuple, dispatch_linalg_cholesky_ex(_r.tensor(0), _r.toBool(1), _r.toBool(2)));
} else {
// aten::linalg_cholesky_ex.L(Tensor self, *, bool upper=False, bool check_errors=False, Tensor(a!) L, Tensor(b!) info) -> (Tensor(a!) L, Tensor(b!) info)
auto out = _r.tensorlist_n<2>(3);
auto dispatch_linalg_cholesky_ex_out = [](at::Tensor & L, at::Tensor & info, const at::Tensor & self, bool upper, bool check_errors) -> ::std::tuple<at::Tensor,at::Tensor> {
pybind11::gil_scoped_release no_gil;
return at::linalg_cholesky_ex_out(L, info, self, upper, check_errors);
};
return wrap(NamedTuple1, dispatch_linalg_cholesky_ex_out(out[0], out[1], _r.tensor(0), _r.toBool(1), _r.toBool(2)));
}
Py_RETURN_NONE;
END_HANDLE_TH_ERRORS
}
```
</details>
Pull Request resolved: https://github.com/pytorch/pytorch/pull/66614
Reviewed By: H-Huang
Differential Revision: D32741134
Pulled By: zou3519
fbshipit-source-id: 27bada30d20e66333ca1be1775608d9f0cbf9f59
2021-12-06 17:03:11 +00:00
|
|
|
|
2021-08-25 22:05:14 +00:00
|
|
|
def create_python_bindings_sharded(
|
|
|
|
|
fm: FileManager,
|
|
|
|
|
pairs: Sequence[PythonSignatureNativeFunctionPair],
|
|
|
|
|
pred: Callable[[NativeFunction], bool],
|
|
|
|
|
module: Optional[str],
|
|
|
|
|
filename: str,
|
|
|
|
|
*,
|
|
|
|
|
method: bool,
|
2022-04-20 12:51:02 +00:00
|
|
|
num_shards: int,
|
2021-08-25 22:05:14 +00:00
|
|
|
) -> None:
|
|
|
|
|
"""Generates Python bindings to ATen functions"""
|
|
|
|
|
grouped = group_filter_overloads(pairs, pred)
|
|
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
def key_func(
|
|
|
|
|
kv: Tuple[BaseOperatorName, List[PythonSignatureNativeFunctionPair]]
|
|
|
|
|
) -> str:
|
2022-01-21 15:32:59 +00:00
|
|
|
return kv[0].base
|
2021-08-25 22:05:14 +00:00
|
|
|
|
|
|
|
|
def env_func(
|
|
|
|
|
kv: Tuple[BaseOperatorName, List[PythonSignatureNativeFunctionPair]]
|
|
|
|
|
) -> Dict[str, List[str]]:
|
2022-01-21 15:32:59 +00:00
|
|
|
name, fn_pairs = kv
|
2021-08-25 22:05:14 +00:00
|
|
|
return {
|
2022-04-20 12:51:02 +00:00
|
|
|
"ops_headers": [f"#include <ATen/ops/{name.base}.h>"],
|
|
|
|
|
"py_forwards": list(forward_decls(name, fn_pairs, method=method)),
|
|
|
|
|
"py_methods": [method_impl(name, module, fn_pairs, method=method)],
|
|
|
|
|
"py_method_defs": [method_def(name, module, fn_pairs, method=method)],
|
2021-08-25 22:05:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fm.write_sharded(
|
|
|
|
|
filename,
|
|
|
|
|
grouped.items(),
|
|
|
|
|
base_env={
|
2022-04-20 12:51:02 +00:00
|
|
|
"generated_comment": "@" + f"generated from {fm.template_dir}/{filename}",
|
2021-08-25 22:05:14 +00:00
|
|
|
},
|
|
|
|
|
key_fn=key_func,
|
|
|
|
|
env_callable=env_func,
|
|
|
|
|
num_shards=num_shards,
|
2022-04-20 12:51:02 +00:00
|
|
|
sharded_keys={"ops_headers", "py_forwards", "py_methods", "py_method_defs"},
|
2021-08-25 22:05:14 +00:00
|
|
|
)
|
|
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
|
2020-11-14 10:22:37 +00:00
|
|
|
def load_signatures(
|
2021-06-12 13:55:44 +00:00
|
|
|
native_functions: List[NativeFunction],
|
2020-11-14 10:22:37 +00:00
|
|
|
deprecated_yaml_path: str,
|
|
|
|
|
*,
|
|
|
|
|
method: bool,
|
pyi codegen update - remove Declarations.yaml (#48754)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/48754
The goal of this PR is to kill Declarations.yaml in the pyi codegen, in favor of native_functions + the existing python object model.
**High-level design**
Since the python signatures used by the `python_arg_parser` are “supposed” to resemble the corresponding pyi type hint signatures, I re-used the existing python object model that Jiakai defined in `tools/codegen/api/python.py`. This means that the pyi codegen now reads `native_functions.yaml`, parses it into a bunch of `PythonSignatureGroup` objects, and emits corresponding method + function variants of type-hint signatures for each one, respectively into `__init__.pyi` and `_VariableFunctions.pyi`.
What makes this uglier is that pyi and the python arg parser have a number of differences in how they’re emitted. I expressed that through a `pyi` flag on the `PythonSignature` dataclass, that tells it whether or not to print itself as a pyi vs. arg_parser signature.
One thing worth noting is how pyi generates signatures differently for native / deprecated op signatures.
For native ops:
- The pyi codegen fuses functional and out variants of each op into a single signature with an optional `out` argument. Ops without an `out` variant just get an ordinary functional signature.
- Some ops that fit certain criteria also get a second “varargs” signature - basically ops with a single positional argument of type List[int].
For deprecated signatures:
- Functional and out variants are not fused - they each get their own signature entry
- There are no varargs signatures
This is currently implemented through the `signature_str()` and `signature_str_vararg()` methods on the `PythonSignature`/`PythonSignatureDeprecated` classes. `signature_str()` knows how to print itself with/without out arguments, differently for native/deprecated ops. `signature_str_vararg()` optionally returns a vararg variant of the signature if one exists.
**Calling out the gap between python_arg_parser vs. pyi**
The two formats are notably different, so I don’t think we can expect to unify them completely. That said, I encountered a number of differences in the pyi codegen that looked wrong- I tried to call them out in the PR, to be removed later. Just as an example, looking at the `svd` signature in the python_arg_parser vs. the pyi type hint:
python_arg_parser
```
Static PythonArgParser parser({
“svd(Tensor input, bool some=True, bool compute_uv=True, *, TensorList[3] out=None”,
}, /*traceable=*/true);
```
Pyi
```
def svd(input: Tensor, some: _bool=True, compute_uv: _bool=True, *, out: Optional[Tensor]=None) -> namedtuple_U_S_V: …
```
The two have obvious syntactic differences that we probably don’t plan on changing: the python_arg_parser doesn’t include `def` or return types, and it includes the type hint before the variable name. But the type of `out` in pyi is probably wrong, since `svd` has multiple output params. I tried to clearly call out any instances of the pyi codegen diverging in a way that looks buggy, so we can clean it up in a later PR (see the comments for details).
Another particularly ugly “bug” that I kept in to maintain byte-for-byte compatibility is the fact that the pyi codegen groups operator overloads together. It turns out that the only reason it does this (as far as I can tell) is because is tacks on an out argument to signatures that don’t have one, if ANY overloads of that op have an out variant.
E.g. consider the pyi type hints generated for `nanmedian` in `_VF.pyi`:
```
overload
def nanmedian(input: Tensor, *, out: Optional[Tensor]=None) -> Tensor: ...
overload
def nanmedian(input: Tensor, dim: _int, keepdim: _bool=False, *, out: Optional[Tensor]=None) -> namedtuple_values_indices: ...
overload
def nanmedian(input: Tensor, dim: Union[str, ellipsis, None], keepdim: _bool=False, *, out: Optional[Tensor]=None) -> namedtuple_values_indices: ...
```
And the corresponding native_functions.yaml entries:
```
- func: nanmedian(Tensor self) -> Tensor
- func: nanmedian.dim(Tensor self, int dim, bool keepdim=False) -> (Tensor values, Tensor indices)
- func: nanmedian.dim_values(Tensor self, int dim, bool keepdim=False, *, Tensor(a!) values, Tensor(b!) indices) -> (Tensor(a!) values, Tensor(b!) indices)
- func: nanmedian.names_dim(Tensor self, Dimname dim, bool keepdim=False) -> (Tensor values, Tensor indices)
- func: nanmedian.names_dim_values(Tensor self, Dimname dim, bool keepdim=False, *, Tensor(a!) values, Tensor(b!) indices) -> (Tensor(a!) values, Tensor(b!)
```
Signature 2 corresponds to entries 2 and 3 in native_functions, and Signature 3 corresponds to entries 4 and 5. But signature 1 has an optional out argument, even though entry 1 in native_functions.yaml has no out variant.
I’d like to delete that logic in a later PR- that will also have the added benefit no longer requiring to group overloads together in the pyi codegen. We can just operate independently on each PythonSignatureGroup.
**More detailed accounting of the changes**
Per file:
gen_python_functions.py
- `load_signatures()` can now skip deprecated signatures. Needed because pyi only includes deprecated functions, and skips their method variants (maybe we should add them in…?)
- Moved `namedtuple_fieldnames` into python.cpp
- `group_overloads()` can now opt to not sort the overloads (needed for byte-for-byte compact, pyi doesn’t sort for some reason)
Python.py:
- Gave `PythonSignature`and `PythonSignatureDeprecated` a `pyi` flag that tells it whether or not to print itself in pyi vs. python_arg_parser format
- Added a `PythonReturns` dataclass , which is now a member of PythonSignature. It is only used by pyi. I found this useful because python returns need to know how to deal with named tuple returns properly. I also moved `namedtuple_fieldnames` into this file from gen_python_functions
gen_pyi.py
- Merged `get_py_torch_functions` and `get_py_variable_methods` into a single function, since they’re very similar
- Lifted out all of the pyi type hint type-mapping mess and dropped it into python.py. This required updating the mapping to deal with NativeFunction objects instead of the outputs of Declarations.yaml (this was most of the logic in `type_to_python`, `arg_to_type_hint`, and `generate_type_hints`). `generate_type_hints` is now a small orchestration function that gathers the different signatures for each PythonSignatureGroup.
- NamedTuples are now generated by calling `PythonReturn.named_tuple()` (in `generate_named_tuples()`), rather than appending to a global list
A lot of hardcoded pyi signatures still live in `gen_pyi.py`. I didn’t look to closely into whether or not any of that can be removed as part of this PR.
Test Plan: Imported from OSS
Reviewed By: ljk53
Differential Revision: D25343802
Pulled By: bdhirsh
fbshipit-source-id: f73e99e1afef934ff41e4aca3dabf34273459a52
2020-12-07 18:37:38 +00:00
|
|
|
skip_deprecated: bool = False,
|
|
|
|
|
pyi: bool = False,
|
2020-11-14 10:22:37 +00:00
|
|
|
) -> Sequence[PythonSignatureNativeFunctionPair]:
|
|
|
|
|
@with_native_function
|
|
|
|
|
def gen_signature_pairs(f: NativeFunction) -> PythonSignatureNativeFunctionPair:
|
|
|
|
|
return PythonSignatureNativeFunctionPair(
|
pyi codegen update - remove Declarations.yaml (#48754)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/48754
The goal of this PR is to kill Declarations.yaml in the pyi codegen, in favor of native_functions + the existing python object model.
**High-level design**
Since the python signatures used by the `python_arg_parser` are “supposed” to resemble the corresponding pyi type hint signatures, I re-used the existing python object model that Jiakai defined in `tools/codegen/api/python.py`. This means that the pyi codegen now reads `native_functions.yaml`, parses it into a bunch of `PythonSignatureGroup` objects, and emits corresponding method + function variants of type-hint signatures for each one, respectively into `__init__.pyi` and `_VariableFunctions.pyi`.
What makes this uglier is that pyi and the python arg parser have a number of differences in how they’re emitted. I expressed that through a `pyi` flag on the `PythonSignature` dataclass, that tells it whether or not to print itself as a pyi vs. arg_parser signature.
One thing worth noting is how pyi generates signatures differently for native / deprecated op signatures.
For native ops:
- The pyi codegen fuses functional and out variants of each op into a single signature with an optional `out` argument. Ops without an `out` variant just get an ordinary functional signature.
- Some ops that fit certain criteria also get a second “varargs” signature - basically ops with a single positional argument of type List[int].
For deprecated signatures:
- Functional and out variants are not fused - they each get their own signature entry
- There are no varargs signatures
This is currently implemented through the `signature_str()` and `signature_str_vararg()` methods on the `PythonSignature`/`PythonSignatureDeprecated` classes. `signature_str()` knows how to print itself with/without out arguments, differently for native/deprecated ops. `signature_str_vararg()` optionally returns a vararg variant of the signature if one exists.
**Calling out the gap between python_arg_parser vs. pyi**
The two formats are notably different, so I don’t think we can expect to unify them completely. That said, I encountered a number of differences in the pyi codegen that looked wrong- I tried to call them out in the PR, to be removed later. Just as an example, looking at the `svd` signature in the python_arg_parser vs. the pyi type hint:
python_arg_parser
```
Static PythonArgParser parser({
“svd(Tensor input, bool some=True, bool compute_uv=True, *, TensorList[3] out=None”,
}, /*traceable=*/true);
```
Pyi
```
def svd(input: Tensor, some: _bool=True, compute_uv: _bool=True, *, out: Optional[Tensor]=None) -> namedtuple_U_S_V: …
```
The two have obvious syntactic differences that we probably don’t plan on changing: the python_arg_parser doesn’t include `def` or return types, and it includes the type hint before the variable name. But the type of `out` in pyi is probably wrong, since `svd` has multiple output params. I tried to clearly call out any instances of the pyi codegen diverging in a way that looks buggy, so we can clean it up in a later PR (see the comments for details).
Another particularly ugly “bug” that I kept in to maintain byte-for-byte compatibility is the fact that the pyi codegen groups operator overloads together. It turns out that the only reason it does this (as far as I can tell) is because is tacks on an out argument to signatures that don’t have one, if ANY overloads of that op have an out variant.
E.g. consider the pyi type hints generated for `nanmedian` in `_VF.pyi`:
```
overload
def nanmedian(input: Tensor, *, out: Optional[Tensor]=None) -> Tensor: ...
overload
def nanmedian(input: Tensor, dim: _int, keepdim: _bool=False, *, out: Optional[Tensor]=None) -> namedtuple_values_indices: ...
overload
def nanmedian(input: Tensor, dim: Union[str, ellipsis, None], keepdim: _bool=False, *, out: Optional[Tensor]=None) -> namedtuple_values_indices: ...
```
And the corresponding native_functions.yaml entries:
```
- func: nanmedian(Tensor self) -> Tensor
- func: nanmedian.dim(Tensor self, int dim, bool keepdim=False) -> (Tensor values, Tensor indices)
- func: nanmedian.dim_values(Tensor self, int dim, bool keepdim=False, *, Tensor(a!) values, Tensor(b!) indices) -> (Tensor(a!) values, Tensor(b!) indices)
- func: nanmedian.names_dim(Tensor self, Dimname dim, bool keepdim=False) -> (Tensor values, Tensor indices)
- func: nanmedian.names_dim_values(Tensor self, Dimname dim, bool keepdim=False, *, Tensor(a!) values, Tensor(b!) indices) -> (Tensor(a!) values, Tensor(b!)
```
Signature 2 corresponds to entries 2 and 3 in native_functions, and Signature 3 corresponds to entries 4 and 5. But signature 1 has an optional out argument, even though entry 1 in native_functions.yaml has no out variant.
I’d like to delete that logic in a later PR- that will also have the added benefit no longer requiring to group overloads together in the pyi codegen. We can just operate independently on each PythonSignatureGroup.
**More detailed accounting of the changes**
Per file:
gen_python_functions.py
- `load_signatures()` can now skip deprecated signatures. Needed because pyi only includes deprecated functions, and skips their method variants (maybe we should add them in…?)
- Moved `namedtuple_fieldnames` into python.cpp
- `group_overloads()` can now opt to not sort the overloads (needed for byte-for-byte compact, pyi doesn’t sort for some reason)
Python.py:
- Gave `PythonSignature`and `PythonSignatureDeprecated` a `pyi` flag that tells it whether or not to print itself in pyi vs. python_arg_parser format
- Added a `PythonReturns` dataclass , which is now a member of PythonSignature. It is only used by pyi. I found this useful because python returns need to know how to deal with named tuple returns properly. I also moved `namedtuple_fieldnames` into this file from gen_python_functions
gen_pyi.py
- Merged `get_py_torch_functions` and `get_py_variable_methods` into a single function, since they’re very similar
- Lifted out all of the pyi type hint type-mapping mess and dropped it into python.py. This required updating the mapping to deal with NativeFunction objects instead of the outputs of Declarations.yaml (this was most of the logic in `type_to_python`, `arg_to_type_hint`, and `generate_type_hints`). `generate_type_hints` is now a small orchestration function that gathers the different signatures for each PythonSignatureGroup.
- NamedTuples are now generated by calling `PythonReturn.named_tuple()` (in `generate_named_tuples()`), rather than appending to a global list
A lot of hardcoded pyi signatures still live in `gen_pyi.py`. I didn’t look to closely into whether or not any of that can be removed as part of this PR.
Test Plan: Imported from OSS
Reviewed By: ljk53
Differential Revision: D25343802
Pulled By: bdhirsh
fbshipit-source-id: f73e99e1afef934ff41e4aca3dabf34273459a52
2020-12-07 18:37:38 +00:00
|
|
|
signature=signature(f, method=method, pyi=pyi),
|
2020-11-14 10:22:37 +00:00
|
|
|
function=f,
|
|
|
|
|
)
|
2020-11-14 10:22:37 +00:00
|
|
|
|
2020-11-14 10:22:37 +00:00
|
|
|
pairs = list(map(gen_signature_pairs, native_functions))
|
2022-04-20 12:51:02 +00:00
|
|
|
deprecated = load_deprecated_signatures(
|
|
|
|
|
pairs, deprecated_yaml_path, method=method, pyi=pyi
|
|
|
|
|
)
|
pyi codegen update - remove Declarations.yaml (#48754)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/48754
The goal of this PR is to kill Declarations.yaml in the pyi codegen, in favor of native_functions + the existing python object model.
**High-level design**
Since the python signatures used by the `python_arg_parser` are “supposed” to resemble the corresponding pyi type hint signatures, I re-used the existing python object model that Jiakai defined in `tools/codegen/api/python.py`. This means that the pyi codegen now reads `native_functions.yaml`, parses it into a bunch of `PythonSignatureGroup` objects, and emits corresponding method + function variants of type-hint signatures for each one, respectively into `__init__.pyi` and `_VariableFunctions.pyi`.
What makes this uglier is that pyi and the python arg parser have a number of differences in how they’re emitted. I expressed that through a `pyi` flag on the `PythonSignature` dataclass, that tells it whether or not to print itself as a pyi vs. arg_parser signature.
One thing worth noting is how pyi generates signatures differently for native / deprecated op signatures.
For native ops:
- The pyi codegen fuses functional and out variants of each op into a single signature with an optional `out` argument. Ops without an `out` variant just get an ordinary functional signature.
- Some ops that fit certain criteria also get a second “varargs” signature - basically ops with a single positional argument of type List[int].
For deprecated signatures:
- Functional and out variants are not fused - they each get their own signature entry
- There are no varargs signatures
This is currently implemented through the `signature_str()` and `signature_str_vararg()` methods on the `PythonSignature`/`PythonSignatureDeprecated` classes. `signature_str()` knows how to print itself with/without out arguments, differently for native/deprecated ops. `signature_str_vararg()` optionally returns a vararg variant of the signature if one exists.
**Calling out the gap between python_arg_parser vs. pyi**
The two formats are notably different, so I don’t think we can expect to unify them completely. That said, I encountered a number of differences in the pyi codegen that looked wrong- I tried to call them out in the PR, to be removed later. Just as an example, looking at the `svd` signature in the python_arg_parser vs. the pyi type hint:
python_arg_parser
```
Static PythonArgParser parser({
“svd(Tensor input, bool some=True, bool compute_uv=True, *, TensorList[3] out=None”,
}, /*traceable=*/true);
```
Pyi
```
def svd(input: Tensor, some: _bool=True, compute_uv: _bool=True, *, out: Optional[Tensor]=None) -> namedtuple_U_S_V: …
```
The two have obvious syntactic differences that we probably don’t plan on changing: the python_arg_parser doesn’t include `def` or return types, and it includes the type hint before the variable name. But the type of `out` in pyi is probably wrong, since `svd` has multiple output params. I tried to clearly call out any instances of the pyi codegen diverging in a way that looks buggy, so we can clean it up in a later PR (see the comments for details).
Another particularly ugly “bug” that I kept in to maintain byte-for-byte compatibility is the fact that the pyi codegen groups operator overloads together. It turns out that the only reason it does this (as far as I can tell) is because is tacks on an out argument to signatures that don’t have one, if ANY overloads of that op have an out variant.
E.g. consider the pyi type hints generated for `nanmedian` in `_VF.pyi`:
```
overload
def nanmedian(input: Tensor, *, out: Optional[Tensor]=None) -> Tensor: ...
overload
def nanmedian(input: Tensor, dim: _int, keepdim: _bool=False, *, out: Optional[Tensor]=None) -> namedtuple_values_indices: ...
overload
def nanmedian(input: Tensor, dim: Union[str, ellipsis, None], keepdim: _bool=False, *, out: Optional[Tensor]=None) -> namedtuple_values_indices: ...
```
And the corresponding native_functions.yaml entries:
```
- func: nanmedian(Tensor self) -> Tensor
- func: nanmedian.dim(Tensor self, int dim, bool keepdim=False) -> (Tensor values, Tensor indices)
- func: nanmedian.dim_values(Tensor self, int dim, bool keepdim=False, *, Tensor(a!) values, Tensor(b!) indices) -> (Tensor(a!) values, Tensor(b!) indices)
- func: nanmedian.names_dim(Tensor self, Dimname dim, bool keepdim=False) -> (Tensor values, Tensor indices)
- func: nanmedian.names_dim_values(Tensor self, Dimname dim, bool keepdim=False, *, Tensor(a!) values, Tensor(b!) indices) -> (Tensor(a!) values, Tensor(b!)
```
Signature 2 corresponds to entries 2 and 3 in native_functions, and Signature 3 corresponds to entries 4 and 5. But signature 1 has an optional out argument, even though entry 1 in native_functions.yaml has no out variant.
I’d like to delete that logic in a later PR- that will also have the added benefit no longer requiring to group overloads together in the pyi codegen. We can just operate independently on each PythonSignatureGroup.
**More detailed accounting of the changes**
Per file:
gen_python_functions.py
- `load_signatures()` can now skip deprecated signatures. Needed because pyi only includes deprecated functions, and skips their method variants (maybe we should add them in…?)
- Moved `namedtuple_fieldnames` into python.cpp
- `group_overloads()` can now opt to not sort the overloads (needed for byte-for-byte compact, pyi doesn’t sort for some reason)
Python.py:
- Gave `PythonSignature`and `PythonSignatureDeprecated` a `pyi` flag that tells it whether or not to print itself in pyi vs. python_arg_parser format
- Added a `PythonReturns` dataclass , which is now a member of PythonSignature. It is only used by pyi. I found this useful because python returns need to know how to deal with named tuple returns properly. I also moved `namedtuple_fieldnames` into this file from gen_python_functions
gen_pyi.py
- Merged `get_py_torch_functions` and `get_py_variable_methods` into a single function, since they’re very similar
- Lifted out all of the pyi type hint type-mapping mess and dropped it into python.py. This required updating the mapping to deal with NativeFunction objects instead of the outputs of Declarations.yaml (this was most of the logic in `type_to_python`, `arg_to_type_hint`, and `generate_type_hints`). `generate_type_hints` is now a small orchestration function that gathers the different signatures for each PythonSignatureGroup.
- NamedTuples are now generated by calling `PythonReturn.named_tuple()` (in `generate_named_tuples()`), rather than appending to a global list
A lot of hardcoded pyi signatures still live in `gen_pyi.py`. I didn’t look to closely into whether or not any of that can be removed as part of this PR.
Test Plan: Imported from OSS
Reviewed By: ljk53
Differential Revision: D25343802
Pulled By: bdhirsh
fbshipit-source-id: f73e99e1afef934ff41e4aca3dabf34273459a52
2020-12-07 18:37:38 +00:00
|
|
|
return pairs if skip_deprecated else pairs + deprecated
|
2020-11-14 10:22:37 +00:00
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
|
2020-11-14 10:22:37 +00:00
|
|
|
def load_deprecated_signatures(
|
|
|
|
|
pairs: Sequence[PythonSignatureNativeFunctionPair],
|
|
|
|
|
deprecated_yaml_path: str,
|
|
|
|
|
*,
|
|
|
|
|
method: bool,
|
pyi codegen update - remove Declarations.yaml (#48754)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/48754
The goal of this PR is to kill Declarations.yaml in the pyi codegen, in favor of native_functions + the existing python object model.
**High-level design**
Since the python signatures used by the `python_arg_parser` are “supposed” to resemble the corresponding pyi type hint signatures, I re-used the existing python object model that Jiakai defined in `tools/codegen/api/python.py`. This means that the pyi codegen now reads `native_functions.yaml`, parses it into a bunch of `PythonSignatureGroup` objects, and emits corresponding method + function variants of type-hint signatures for each one, respectively into `__init__.pyi` and `_VariableFunctions.pyi`.
What makes this uglier is that pyi and the python arg parser have a number of differences in how they’re emitted. I expressed that through a `pyi` flag on the `PythonSignature` dataclass, that tells it whether or not to print itself as a pyi vs. arg_parser signature.
One thing worth noting is how pyi generates signatures differently for native / deprecated op signatures.
For native ops:
- The pyi codegen fuses functional and out variants of each op into a single signature with an optional `out` argument. Ops without an `out` variant just get an ordinary functional signature.
- Some ops that fit certain criteria also get a second “varargs” signature - basically ops with a single positional argument of type List[int].
For deprecated signatures:
- Functional and out variants are not fused - they each get their own signature entry
- There are no varargs signatures
This is currently implemented through the `signature_str()` and `signature_str_vararg()` methods on the `PythonSignature`/`PythonSignatureDeprecated` classes. `signature_str()` knows how to print itself with/without out arguments, differently for native/deprecated ops. `signature_str_vararg()` optionally returns a vararg variant of the signature if one exists.
**Calling out the gap between python_arg_parser vs. pyi**
The two formats are notably different, so I don’t think we can expect to unify them completely. That said, I encountered a number of differences in the pyi codegen that looked wrong- I tried to call them out in the PR, to be removed later. Just as an example, looking at the `svd` signature in the python_arg_parser vs. the pyi type hint:
python_arg_parser
```
Static PythonArgParser parser({
“svd(Tensor input, bool some=True, bool compute_uv=True, *, TensorList[3] out=None”,
}, /*traceable=*/true);
```
Pyi
```
def svd(input: Tensor, some: _bool=True, compute_uv: _bool=True, *, out: Optional[Tensor]=None) -> namedtuple_U_S_V: …
```
The two have obvious syntactic differences that we probably don’t plan on changing: the python_arg_parser doesn’t include `def` or return types, and it includes the type hint before the variable name. But the type of `out` in pyi is probably wrong, since `svd` has multiple output params. I tried to clearly call out any instances of the pyi codegen diverging in a way that looks buggy, so we can clean it up in a later PR (see the comments for details).
Another particularly ugly “bug” that I kept in to maintain byte-for-byte compatibility is the fact that the pyi codegen groups operator overloads together. It turns out that the only reason it does this (as far as I can tell) is because is tacks on an out argument to signatures that don’t have one, if ANY overloads of that op have an out variant.
E.g. consider the pyi type hints generated for `nanmedian` in `_VF.pyi`:
```
overload
def nanmedian(input: Tensor, *, out: Optional[Tensor]=None) -> Tensor: ...
overload
def nanmedian(input: Tensor, dim: _int, keepdim: _bool=False, *, out: Optional[Tensor]=None) -> namedtuple_values_indices: ...
overload
def nanmedian(input: Tensor, dim: Union[str, ellipsis, None], keepdim: _bool=False, *, out: Optional[Tensor]=None) -> namedtuple_values_indices: ...
```
And the corresponding native_functions.yaml entries:
```
- func: nanmedian(Tensor self) -> Tensor
- func: nanmedian.dim(Tensor self, int dim, bool keepdim=False) -> (Tensor values, Tensor indices)
- func: nanmedian.dim_values(Tensor self, int dim, bool keepdim=False, *, Tensor(a!) values, Tensor(b!) indices) -> (Tensor(a!) values, Tensor(b!) indices)
- func: nanmedian.names_dim(Tensor self, Dimname dim, bool keepdim=False) -> (Tensor values, Tensor indices)
- func: nanmedian.names_dim_values(Tensor self, Dimname dim, bool keepdim=False, *, Tensor(a!) values, Tensor(b!) indices) -> (Tensor(a!) values, Tensor(b!)
```
Signature 2 corresponds to entries 2 and 3 in native_functions, and Signature 3 corresponds to entries 4 and 5. But signature 1 has an optional out argument, even though entry 1 in native_functions.yaml has no out variant.
I’d like to delete that logic in a later PR- that will also have the added benefit no longer requiring to group overloads together in the pyi codegen. We can just operate independently on each PythonSignatureGroup.
**More detailed accounting of the changes**
Per file:
gen_python_functions.py
- `load_signatures()` can now skip deprecated signatures. Needed because pyi only includes deprecated functions, and skips their method variants (maybe we should add them in…?)
- Moved `namedtuple_fieldnames` into python.cpp
- `group_overloads()` can now opt to not sort the overloads (needed for byte-for-byte compact, pyi doesn’t sort for some reason)
Python.py:
- Gave `PythonSignature`and `PythonSignatureDeprecated` a `pyi` flag that tells it whether or not to print itself in pyi vs. python_arg_parser format
- Added a `PythonReturns` dataclass , which is now a member of PythonSignature. It is only used by pyi. I found this useful because python returns need to know how to deal with named tuple returns properly. I also moved `namedtuple_fieldnames` into this file from gen_python_functions
gen_pyi.py
- Merged `get_py_torch_functions` and `get_py_variable_methods` into a single function, since they’re very similar
- Lifted out all of the pyi type hint type-mapping mess and dropped it into python.py. This required updating the mapping to deal with NativeFunction objects instead of the outputs of Declarations.yaml (this was most of the logic in `type_to_python`, `arg_to_type_hint`, and `generate_type_hints`). `generate_type_hints` is now a small orchestration function that gathers the different signatures for each PythonSignatureGroup.
- NamedTuples are now generated by calling `PythonReturn.named_tuple()` (in `generate_named_tuples()`), rather than appending to a global list
A lot of hardcoded pyi signatures still live in `gen_pyi.py`. I didn’t look to closely into whether or not any of that can be removed as part of this PR.
Test Plan: Imported from OSS
Reviewed By: ljk53
Differential Revision: D25343802
Pulled By: bdhirsh
fbshipit-source-id: f73e99e1afef934ff41e4aca3dabf34273459a52
2020-12-07 18:37:38 +00:00
|
|
|
pyi: bool,
|
2020-11-14 10:22:37 +00:00
|
|
|
) -> List[PythonSignatureNativeFunctionPair]:
|
|
|
|
|
# The deprecated.yaml doesn't have complete type information, we need
|
|
|
|
|
# find and leverage the original ATen signature (to which it delegates
|
|
|
|
|
# the call) to generate the full python signature.
|
|
|
|
|
# We join the deprecated and the original signatures using type-only form.
|
|
|
|
|
|
|
|
|
|
# native function -> type-only signature
|
|
|
|
|
@with_native_function
|
|
|
|
|
def signature_original(f: NativeFunction) -> str:
|
|
|
|
|
# remove inplace suffix but keep outplace suffix
|
|
|
|
|
opname = str(f.func.name.name.base)
|
|
|
|
|
if f.func.is_out_fn():
|
2022-04-20 12:51:02 +00:00
|
|
|
opname += "_out"
|
pyi codegen update - remove Declarations.yaml (#48754)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/48754
The goal of this PR is to kill Declarations.yaml in the pyi codegen, in favor of native_functions + the existing python object model.
**High-level design**
Since the python signatures used by the `python_arg_parser` are “supposed” to resemble the corresponding pyi type hint signatures, I re-used the existing python object model that Jiakai defined in `tools/codegen/api/python.py`. This means that the pyi codegen now reads `native_functions.yaml`, parses it into a bunch of `PythonSignatureGroup` objects, and emits corresponding method + function variants of type-hint signatures for each one, respectively into `__init__.pyi` and `_VariableFunctions.pyi`.
What makes this uglier is that pyi and the python arg parser have a number of differences in how they’re emitted. I expressed that through a `pyi` flag on the `PythonSignature` dataclass, that tells it whether or not to print itself as a pyi vs. arg_parser signature.
One thing worth noting is how pyi generates signatures differently for native / deprecated op signatures.
For native ops:
- The pyi codegen fuses functional and out variants of each op into a single signature with an optional `out` argument. Ops without an `out` variant just get an ordinary functional signature.
- Some ops that fit certain criteria also get a second “varargs” signature - basically ops with a single positional argument of type List[int].
For deprecated signatures:
- Functional and out variants are not fused - they each get their own signature entry
- There are no varargs signatures
This is currently implemented through the `signature_str()` and `signature_str_vararg()` methods on the `PythonSignature`/`PythonSignatureDeprecated` classes. `signature_str()` knows how to print itself with/without out arguments, differently for native/deprecated ops. `signature_str_vararg()` optionally returns a vararg variant of the signature if one exists.
**Calling out the gap between python_arg_parser vs. pyi**
The two formats are notably different, so I don’t think we can expect to unify them completely. That said, I encountered a number of differences in the pyi codegen that looked wrong- I tried to call them out in the PR, to be removed later. Just as an example, looking at the `svd` signature in the python_arg_parser vs. the pyi type hint:
python_arg_parser
```
Static PythonArgParser parser({
“svd(Tensor input, bool some=True, bool compute_uv=True, *, TensorList[3] out=None”,
}, /*traceable=*/true);
```
Pyi
```
def svd(input: Tensor, some: _bool=True, compute_uv: _bool=True, *, out: Optional[Tensor]=None) -> namedtuple_U_S_V: …
```
The two have obvious syntactic differences that we probably don’t plan on changing: the python_arg_parser doesn’t include `def` or return types, and it includes the type hint before the variable name. But the type of `out` in pyi is probably wrong, since `svd` has multiple output params. I tried to clearly call out any instances of the pyi codegen diverging in a way that looks buggy, so we can clean it up in a later PR (see the comments for details).
Another particularly ugly “bug” that I kept in to maintain byte-for-byte compatibility is the fact that the pyi codegen groups operator overloads together. It turns out that the only reason it does this (as far as I can tell) is because is tacks on an out argument to signatures that don’t have one, if ANY overloads of that op have an out variant.
E.g. consider the pyi type hints generated for `nanmedian` in `_VF.pyi`:
```
overload
def nanmedian(input: Tensor, *, out: Optional[Tensor]=None) -> Tensor: ...
overload
def nanmedian(input: Tensor, dim: _int, keepdim: _bool=False, *, out: Optional[Tensor]=None) -> namedtuple_values_indices: ...
overload
def nanmedian(input: Tensor, dim: Union[str, ellipsis, None], keepdim: _bool=False, *, out: Optional[Tensor]=None) -> namedtuple_values_indices: ...
```
And the corresponding native_functions.yaml entries:
```
- func: nanmedian(Tensor self) -> Tensor
- func: nanmedian.dim(Tensor self, int dim, bool keepdim=False) -> (Tensor values, Tensor indices)
- func: nanmedian.dim_values(Tensor self, int dim, bool keepdim=False, *, Tensor(a!) values, Tensor(b!) indices) -> (Tensor(a!) values, Tensor(b!) indices)
- func: nanmedian.names_dim(Tensor self, Dimname dim, bool keepdim=False) -> (Tensor values, Tensor indices)
- func: nanmedian.names_dim_values(Tensor self, Dimname dim, bool keepdim=False, *, Tensor(a!) values, Tensor(b!) indices) -> (Tensor(a!) values, Tensor(b!)
```
Signature 2 corresponds to entries 2 and 3 in native_functions, and Signature 3 corresponds to entries 4 and 5. But signature 1 has an optional out argument, even though entry 1 in native_functions.yaml has no out variant.
I’d like to delete that logic in a later PR- that will also have the added benefit no longer requiring to group overloads together in the pyi codegen. We can just operate independently on each PythonSignatureGroup.
**More detailed accounting of the changes**
Per file:
gen_python_functions.py
- `load_signatures()` can now skip deprecated signatures. Needed because pyi only includes deprecated functions, and skips their method variants (maybe we should add them in…?)
- Moved `namedtuple_fieldnames` into python.cpp
- `group_overloads()` can now opt to not sort the overloads (needed for byte-for-byte compact, pyi doesn’t sort for some reason)
Python.py:
- Gave `PythonSignature`and `PythonSignatureDeprecated` a `pyi` flag that tells it whether or not to print itself in pyi vs. python_arg_parser format
- Added a `PythonReturns` dataclass , which is now a member of PythonSignature. It is only used by pyi. I found this useful because python returns need to know how to deal with named tuple returns properly. I also moved `namedtuple_fieldnames` into this file from gen_python_functions
gen_pyi.py
- Merged `get_py_torch_functions` and `get_py_variable_methods` into a single function, since they’re very similar
- Lifted out all of the pyi type hint type-mapping mess and dropped it into python.py. This required updating the mapping to deal with NativeFunction objects instead of the outputs of Declarations.yaml (this was most of the logic in `type_to_python`, `arg_to_type_hint`, and `generate_type_hints`). `generate_type_hints` is now a small orchestration function that gathers the different signatures for each PythonSignatureGroup.
- NamedTuples are now generated by calling `PythonReturn.named_tuple()` (in `generate_named_tuples()`), rather than appending to a global list
A lot of hardcoded pyi signatures still live in `gen_pyi.py`. I didn’t look to closely into whether or not any of that can be removed as part of this PR.
Test Plan: Imported from OSS
Reviewed By: ljk53
Differential Revision: D25343802
Pulled By: bdhirsh
fbshipit-source-id: f73e99e1afef934ff41e4aca3dabf34273459a52
2020-12-07 18:37:38 +00:00
|
|
|
if f.func.name.name.inplace and pyi:
|
2022-04-20 12:51:02 +00:00
|
|
|
opname += "_"
|
|
|
|
|
args = CppSignatureGroup.from_native_function(
|
|
|
|
|
f, method=False
|
|
|
|
|
).signature.arguments()
|
2020-11-14 10:22:37 +00:00
|
|
|
# Simply ignore TensorOptionsArguments as it does not exist in deprecated.yaml.
|
2022-04-20 12:51:02 +00:00
|
|
|
types = ", ".join(
|
|
|
|
|
argument_type_str(a.argument.type)
|
|
|
|
|
for a in args
|
|
|
|
|
if isinstance(a.argument, Argument)
|
|
|
|
|
)
|
|
|
|
|
return f"{opname}({types})"
|
2020-11-14 10:22:37 +00:00
|
|
|
|
|
|
|
|
# deprecated -> type-only native signature (according to the call order)
|
2022-04-20 12:51:02 +00:00
|
|
|
def signature_deprecated(
|
|
|
|
|
opname: str, params: List[str], call_args: List[str]
|
|
|
|
|
) -> str:
|
2020-11-14 10:22:37 +00:00
|
|
|
# create a mapping of parameter name to parameter type
|
|
|
|
|
types: Dict[str, str] = {}
|
|
|
|
|
for param in params:
|
2022-04-20 12:51:02 +00:00
|
|
|
if param == "*":
|
2020-11-14 10:22:37 +00:00
|
|
|
continue
|
2022-04-20 12:51:02 +00:00
|
|
|
type, name = param.split(" ")
|
2020-11-14 10:22:37 +00:00
|
|
|
types[name] = type
|
|
|
|
|
# if the name in the call is not in the parameter list, assume it's
|
|
|
|
|
# a literal Scalar
|
2022-04-20 12:51:02 +00:00
|
|
|
rearranged_types = ", ".join(types.get(arg, "Scalar") for arg in call_args)
|
|
|
|
|
return f"{opname}({rearranged_types})"
|
2020-11-14 10:22:37 +00:00
|
|
|
|
|
|
|
|
# group the original ATen signatures by type-only signature
|
|
|
|
|
grouped: Dict[str, List[PythonSignatureNativeFunctionPair]] = defaultdict(list)
|
|
|
|
|
for pair in pairs:
|
|
|
|
|
grouped[signature_original(pair.function)].append(pair)
|
|
|
|
|
|
|
|
|
|
# find matching original signatures for each deprecated signature
|
|
|
|
|
results: List[PythonSignatureNativeFunctionPair] = []
|
|
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
with open(deprecated_yaml_path, "r") as f:
|
2021-06-12 13:55:44 +00:00
|
|
|
deprecated_defs = yaml.load(f, Loader=YamlLoader)
|
2020-11-14 10:22:37 +00:00
|
|
|
|
|
|
|
|
for deprecated in deprecated_defs:
|
2022-04-20 12:51:02 +00:00
|
|
|
_, params = split_name_params(deprecated["name"])
|
|
|
|
|
aten_name, call_args = split_name_params(deprecated["aten"])
|
2020-11-14 10:22:37 +00:00
|
|
|
|
|
|
|
|
for pair in grouped[signature_deprecated(aten_name, params, call_args)]:
|
|
|
|
|
# It uses the types from the original ATen declaration, but the
|
|
|
|
|
# ordering and parameter names from the deprecated overload. Any
|
|
|
|
|
# default parameter values from the original ATen declaration are
|
|
|
|
|
# ignored.
|
|
|
|
|
# Deprecated signature might reorder input_args and input_kwargs,
|
|
|
|
|
# but never changes output_args nor TensorOptions (if any?),
|
|
|
|
|
# so here we only look into these two types of args.
|
|
|
|
|
python_sig = pair.signature
|
2022-04-20 12:51:02 +00:00
|
|
|
src_args: Dict[str, PythonArgument] = {
|
|
|
|
|
a.name: PythonArgument(
|
|
|
|
|
name=a.name,
|
|
|
|
|
type=a.type,
|
|
|
|
|
default=None,
|
|
|
|
|
default_init=None,
|
|
|
|
|
)
|
|
|
|
|
for a in itertools.chain(python_sig.input_args, python_sig.input_kwargs)
|
|
|
|
|
}
|
2020-11-14 10:22:37 +00:00
|
|
|
|
|
|
|
|
args: List[str] = []
|
|
|
|
|
input_args: List[PythonArgument] = []
|
|
|
|
|
input_kwargs: List[PythonArgument] = []
|
|
|
|
|
|
|
|
|
|
kwarg_only = False
|
|
|
|
|
for param in params:
|
2022-04-20 12:51:02 +00:00
|
|
|
if param == "*":
|
2020-11-14 10:22:37 +00:00
|
|
|
kwarg_only = True
|
|
|
|
|
continue
|
2022-04-20 12:51:02 +00:00
|
|
|
_, param_name = param.split(" ")
|
2020-11-14 10:22:37 +00:00
|
|
|
args.append(param_name)
|
|
|
|
|
|
|
|
|
|
if param_name not in src_args:
|
|
|
|
|
# output argument
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
if not kwarg_only:
|
2022-04-20 12:51:02 +00:00
|
|
|
if not method or param_name != "self":
|
2020-11-14 10:22:37 +00:00
|
|
|
input_args.append(src_args[param_name])
|
|
|
|
|
else:
|
|
|
|
|
input_kwargs.append(src_args[param_name])
|
|
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
results.append(
|
|
|
|
|
PythonSignatureNativeFunctionPair(
|
|
|
|
|
signature=PythonSignatureDeprecated(
|
|
|
|
|
name=python_sig.name,
|
|
|
|
|
input_args=tuple(input_args),
|
|
|
|
|
input_kwargs=tuple(input_kwargs),
|
|
|
|
|
output_args=python_sig.output_args,
|
|
|
|
|
tensor_options_args=python_sig.tensor_options_args,
|
|
|
|
|
method=python_sig.method,
|
|
|
|
|
deprecated_args_names=tuple(args),
|
|
|
|
|
deprecated_args_exprs=tuple(call_args),
|
|
|
|
|
returns=python_sig.returns,
|
|
|
|
|
),
|
|
|
|
|
function=pair.function,
|
|
|
|
|
)
|
|
|
|
|
)
|
2020-11-14 10:22:37 +00:00
|
|
|
|
|
|
|
|
return results
|
2020-11-14 10:22:37 +00:00
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
|
2020-11-08 09:03:59 +00:00
|
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
|
2020-01-30 08:26:16 +00:00
|
|
|
#
|
2020-11-08 09:03:59 +00:00
|
|
|
# Named Tuple Codegen
|
2020-01-30 08:26:16 +00:00
|
|
|
#
|
2020-11-08 09:03:59 +00:00
|
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
|
2020-01-30 08:26:16 +00:00
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
|
2020-11-08 09:03:59 +00:00
|
|
|
@with_native_function
|
|
|
|
|
def gen_namedtuple_typename_key(f: NativeFunction) -> str:
|
|
|
|
|
name = cpp.name(f.func)
|
pyi codegen update - remove Declarations.yaml (#48754)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/48754
The goal of this PR is to kill Declarations.yaml in the pyi codegen, in favor of native_functions + the existing python object model.
**High-level design**
Since the python signatures used by the `python_arg_parser` are “supposed” to resemble the corresponding pyi type hint signatures, I re-used the existing python object model that Jiakai defined in `tools/codegen/api/python.py`. This means that the pyi codegen now reads `native_functions.yaml`, parses it into a bunch of `PythonSignatureGroup` objects, and emits corresponding method + function variants of type-hint signatures for each one, respectively into `__init__.pyi` and `_VariableFunctions.pyi`.
What makes this uglier is that pyi and the python arg parser have a number of differences in how they’re emitted. I expressed that through a `pyi` flag on the `PythonSignature` dataclass, that tells it whether or not to print itself as a pyi vs. arg_parser signature.
One thing worth noting is how pyi generates signatures differently for native / deprecated op signatures.
For native ops:
- The pyi codegen fuses functional and out variants of each op into a single signature with an optional `out` argument. Ops without an `out` variant just get an ordinary functional signature.
- Some ops that fit certain criteria also get a second “varargs” signature - basically ops with a single positional argument of type List[int].
For deprecated signatures:
- Functional and out variants are not fused - they each get their own signature entry
- There are no varargs signatures
This is currently implemented through the `signature_str()` and `signature_str_vararg()` methods on the `PythonSignature`/`PythonSignatureDeprecated` classes. `signature_str()` knows how to print itself with/without out arguments, differently for native/deprecated ops. `signature_str_vararg()` optionally returns a vararg variant of the signature if one exists.
**Calling out the gap between python_arg_parser vs. pyi**
The two formats are notably different, so I don’t think we can expect to unify them completely. That said, I encountered a number of differences in the pyi codegen that looked wrong- I tried to call them out in the PR, to be removed later. Just as an example, looking at the `svd` signature in the python_arg_parser vs. the pyi type hint:
python_arg_parser
```
Static PythonArgParser parser({
“svd(Tensor input, bool some=True, bool compute_uv=True, *, TensorList[3] out=None”,
}, /*traceable=*/true);
```
Pyi
```
def svd(input: Tensor, some: _bool=True, compute_uv: _bool=True, *, out: Optional[Tensor]=None) -> namedtuple_U_S_V: …
```
The two have obvious syntactic differences that we probably don’t plan on changing: the python_arg_parser doesn’t include `def` or return types, and it includes the type hint before the variable name. But the type of `out` in pyi is probably wrong, since `svd` has multiple output params. I tried to clearly call out any instances of the pyi codegen diverging in a way that looks buggy, so we can clean it up in a later PR (see the comments for details).
Another particularly ugly “bug” that I kept in to maintain byte-for-byte compatibility is the fact that the pyi codegen groups operator overloads together. It turns out that the only reason it does this (as far as I can tell) is because is tacks on an out argument to signatures that don’t have one, if ANY overloads of that op have an out variant.
E.g. consider the pyi type hints generated for `nanmedian` in `_VF.pyi`:
```
overload
def nanmedian(input: Tensor, *, out: Optional[Tensor]=None) -> Tensor: ...
overload
def nanmedian(input: Tensor, dim: _int, keepdim: _bool=False, *, out: Optional[Tensor]=None) -> namedtuple_values_indices: ...
overload
def nanmedian(input: Tensor, dim: Union[str, ellipsis, None], keepdim: _bool=False, *, out: Optional[Tensor]=None) -> namedtuple_values_indices: ...
```
And the corresponding native_functions.yaml entries:
```
- func: nanmedian(Tensor self) -> Tensor
- func: nanmedian.dim(Tensor self, int dim, bool keepdim=False) -> (Tensor values, Tensor indices)
- func: nanmedian.dim_values(Tensor self, int dim, bool keepdim=False, *, Tensor(a!) values, Tensor(b!) indices) -> (Tensor(a!) values, Tensor(b!) indices)
- func: nanmedian.names_dim(Tensor self, Dimname dim, bool keepdim=False) -> (Tensor values, Tensor indices)
- func: nanmedian.names_dim_values(Tensor self, Dimname dim, bool keepdim=False, *, Tensor(a!) values, Tensor(b!) indices) -> (Tensor(a!) values, Tensor(b!)
```
Signature 2 corresponds to entries 2 and 3 in native_functions, and Signature 3 corresponds to entries 4 and 5. But signature 1 has an optional out argument, even though entry 1 in native_functions.yaml has no out variant.
I’d like to delete that logic in a later PR- that will also have the added benefit no longer requiring to group overloads together in the pyi codegen. We can just operate independently on each PythonSignatureGroup.
**More detailed accounting of the changes**
Per file:
gen_python_functions.py
- `load_signatures()` can now skip deprecated signatures. Needed because pyi only includes deprecated functions, and skips their method variants (maybe we should add them in…?)
- Moved `namedtuple_fieldnames` into python.cpp
- `group_overloads()` can now opt to not sort the overloads (needed for byte-for-byte compact, pyi doesn’t sort for some reason)
Python.py:
- Gave `PythonSignature`and `PythonSignatureDeprecated` a `pyi` flag that tells it whether or not to print itself in pyi vs. python_arg_parser format
- Added a `PythonReturns` dataclass , which is now a member of PythonSignature. It is only used by pyi. I found this useful because python returns need to know how to deal with named tuple returns properly. I also moved `namedtuple_fieldnames` into this file from gen_python_functions
gen_pyi.py
- Merged `get_py_torch_functions` and `get_py_variable_methods` into a single function, since they’re very similar
- Lifted out all of the pyi type hint type-mapping mess and dropped it into python.py. This required updating the mapping to deal with NativeFunction objects instead of the outputs of Declarations.yaml (this was most of the logic in `type_to_python`, `arg_to_type_hint`, and `generate_type_hints`). `generate_type_hints` is now a small orchestration function that gathers the different signatures for each PythonSignatureGroup.
- NamedTuples are now generated by calling `PythonReturn.named_tuple()` (in `generate_named_tuples()`), rather than appending to a global list
A lot of hardcoded pyi signatures still live in `gen_pyi.py`. I didn’t look to closely into whether or not any of that can be removed as part of this PR.
Test Plan: Imported from OSS
Reviewed By: ljk53
Differential Revision: D25343802
Pulled By: bdhirsh
fbshipit-source-id: f73e99e1afef934ff41e4aca3dabf34273459a52
2020-12-07 18:37:38 +00:00
|
|
|
fieldnames = namedtuple_fieldnames(f.func.returns)
|
2022-04-20 12:51:02 +00:00
|
|
|
return "_".join([name] + fieldnames)
|
|
|
|
|
|
2020-11-08 09:03:59 +00:00
|
|
|
|
expose return_types in Python (#66614)
Summary:
https://github.com/facebookresearch/functorch/issues/87
TODO:
* [x] Add comments
* [x] Add test
* [x] Fix XLA
<details>
<summary>Generated python_return_types.cpp</summary>
```cpp
#include <Python.h>
#include <vector>
#include <map>
#include <string>
#include "torch/csrc/autograd/python_return_types.h"
#include "torch/csrc/utils/structseq.h"
#include "torch/csrc/Exceptions.h"
namespace {
PyTypeObject* get__det_lu_based_helper_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"det", ""}, {"lu", ""}, {"pivs", ""}, {nullptr} };
static PyTypeObject _det_lu_based_helperNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._det_lu_based_helper", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&_det_lu_based_helperNamedTuple, &desc);
_det_lu_based_helperNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_det_lu_based_helperNamedTuple;
}
PyTypeObject* get__fake_quantize_per_tensor_affine_cachemask_tensor_qparams_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"output", ""}, {"mask", ""}, {nullptr} };
static PyTypeObject _fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._fake_quantize_per_tensor_affine_cachemask_tensor_qparams", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple, &desc);
_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple;
}
PyTypeObject* get__fused_moving_avg_obs_fq_helper_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"output", ""}, {"mask", ""}, {nullptr} };
static PyTypeObject _fused_moving_avg_obs_fq_helperNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._fused_moving_avg_obs_fq_helper", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_fused_moving_avg_obs_fq_helperNamedTuple, &desc);
_fused_moving_avg_obs_fq_helperNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_fused_moving_avg_obs_fq_helperNamedTuple;
}
PyTypeObject* get__lu_with_info_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"LU", ""}, {"pivots", ""}, {"info", ""}, {nullptr} };
static PyTypeObject _lu_with_infoNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._lu_with_info", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&_lu_with_infoNamedTuple, &desc);
_lu_with_infoNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_lu_with_infoNamedTuple;
}
PyTypeObject* get__unpack_dual_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"primal", ""}, {"tangent", ""}, {nullptr} };
static PyTypeObject _unpack_dualNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._unpack_dual", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_unpack_dualNamedTuple, &desc);
_unpack_dualNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_unpack_dualNamedTuple;
}
PyTypeObject* get_aminmax_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"min", ""}, {"max", ""}, {nullptr} };
static PyTypeObject aminmaxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.aminmax", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&aminmaxNamedTuple, &desc);
aminmaxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &aminmaxNamedTuple;
}
PyTypeObject* get_aminmax_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"min", ""}, {"max", ""}, {nullptr} };
static PyTypeObject aminmax_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.aminmax_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&aminmax_outNamedTuple1, &desc);
aminmax_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &aminmax_outNamedTuple1;
}
PyTypeObject* get_cummax_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummaxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummax", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummaxNamedTuple, &desc);
cummaxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummaxNamedTuple;
}
PyTypeObject* get_cummax_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummax_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummax_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummax_outNamedTuple1, &desc);
cummax_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummax_outNamedTuple1;
}
PyTypeObject* get_cummin_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cumminNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummin", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cumminNamedTuple, &desc);
cumminNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cumminNamedTuple;
}
PyTypeObject* get_cummin_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummin_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummin_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummin_outNamedTuple1, &desc);
cummin_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummin_outNamedTuple1;
}
PyTypeObject* get_eig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject eig_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.eig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&eig_outNamedTuple, &desc);
eig_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &eig_outNamedTuple;
}
PyTypeObject* get_eig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject eigNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.eig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&eigNamedTuple1, &desc);
eigNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &eigNamedTuple1;
}
PyTypeObject* get_frexp_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"mantissa", ""}, {"exponent", ""}, {nullptr} };
static PyTypeObject frexpNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.frexp", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&frexpNamedTuple, &desc);
frexpNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &frexpNamedTuple;
}
PyTypeObject* get_frexp_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"mantissa", ""}, {"exponent", ""}, {nullptr} };
static PyTypeObject frexp_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.frexp_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&frexp_outNamedTuple1, &desc);
frexp_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &frexp_outNamedTuple1;
}
PyTypeObject* get_geqrf_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"a", ""}, {"tau", ""}, {nullptr} };
static PyTypeObject geqrf_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.geqrf_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&geqrf_outNamedTuple, &desc);
geqrf_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &geqrf_outNamedTuple;
}
PyTypeObject* get_geqrf_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"a", ""}, {"tau", ""}, {nullptr} };
static PyTypeObject geqrfNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.geqrf", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&geqrfNamedTuple1, &desc);
geqrfNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &geqrfNamedTuple1;
}
PyTypeObject* get_histogram_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"hist", ""}, {"bin_edges", ""}, {nullptr} };
static PyTypeObject histogram_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.histogram_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&histogram_outNamedTuple, &desc);
histogram_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &histogram_outNamedTuple;
}
PyTypeObject* get_histogram_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"hist", ""}, {"bin_edges", ""}, {nullptr} };
static PyTypeObject histogramNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.histogram", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&histogramNamedTuple1, &desc);
histogramNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &histogramNamedTuple1;
}
PyTypeObject* get_kthvalue_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject kthvalueNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.kthvalue", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&kthvalueNamedTuple, &desc);
kthvalueNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &kthvalueNamedTuple;
}
PyTypeObject* get_kthvalue_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject kthvalue_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.kthvalue_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&kthvalue_outNamedTuple1, &desc);
kthvalue_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &kthvalue_outNamedTuple1;
}
PyTypeObject* get_linalg_cholesky_ex_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"L", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_cholesky_exNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_cholesky_ex", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_cholesky_exNamedTuple, &desc);
linalg_cholesky_exNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_cholesky_exNamedTuple;
}
PyTypeObject* get_linalg_cholesky_ex_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"L", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_cholesky_ex_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_cholesky_ex_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_cholesky_ex_outNamedTuple1, &desc);
linalg_cholesky_ex_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_cholesky_ex_outNamedTuple1;
}
PyTypeObject* get_linalg_eig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eigNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eigNamedTuple, &desc);
linalg_eigNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eigNamedTuple;
}
PyTypeObject* get_linalg_eig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eig_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eig_outNamedTuple1, &desc);
linalg_eig_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eig_outNamedTuple1;
}
PyTypeObject* get_linalg_eigh_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eighNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eigh", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eighNamedTuple, &desc);
linalg_eighNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eighNamedTuple;
}
PyTypeObject* get_linalg_eigh_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eigh_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eigh_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eigh_outNamedTuple1, &desc);
linalg_eigh_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eigh_outNamedTuple1;
}
PyTypeObject* get_linalg_inv_ex_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"inverse", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_inv_exNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_inv_ex", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_inv_exNamedTuple, &desc);
linalg_inv_exNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_inv_exNamedTuple;
}
PyTypeObject* get_linalg_inv_ex_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"inverse", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_inv_ex_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_inv_ex_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_inv_ex_outNamedTuple1, &desc);
linalg_inv_ex_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_inv_ex_outNamedTuple1;
}
PyTypeObject* get_linalg_lstsq_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"residuals", ""}, {"rank", ""}, {"singular_values", ""}, {nullptr} };
static PyTypeObject linalg_lstsqNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_lstsq", nullptr, NamedTuple_fields, 4 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_lstsqNamedTuple, &desc);
linalg_lstsqNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_lstsqNamedTuple;
}
PyTypeObject* get_linalg_lstsq_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"residuals", ""}, {"rank", ""}, {"singular_values", ""}, {nullptr} };
static PyTypeObject linalg_lstsq_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_lstsq_out", nullptr, NamedTuple_fields, 4 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_lstsq_outNamedTuple1, &desc);
linalg_lstsq_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_lstsq_outNamedTuple1;
}
PyTypeObject* get_linalg_qr_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject linalg_qrNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_qr", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_qrNamedTuple, &desc);
linalg_qrNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_qrNamedTuple;
}
PyTypeObject* get_linalg_qr_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject linalg_qr_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_qr_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_qr_outNamedTuple1, &desc);
linalg_qr_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_qr_outNamedTuple1;
}
PyTypeObject* get_linalg_slogdet_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject linalg_slogdetNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_slogdet", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_slogdetNamedTuple, &desc);
linalg_slogdetNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_slogdetNamedTuple;
}
PyTypeObject* get_linalg_slogdet_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject linalg_slogdet_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_slogdet_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_slogdet_outNamedTuple1, &desc);
linalg_slogdet_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_slogdet_outNamedTuple1;
}
PyTypeObject* get_linalg_svd_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"Vh", ""}, {nullptr} };
static PyTypeObject linalg_svd_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_svd_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_svd_outNamedTuple, &desc);
linalg_svd_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_svd_outNamedTuple;
}
PyTypeObject* get_linalg_svd_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"Vh", ""}, {nullptr} };
static PyTypeObject linalg_svdNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_svd", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_svdNamedTuple1, &desc);
linalg_svdNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_svdNamedTuple1;
}
PyTypeObject* get_lstsq_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"QR", ""}, {nullptr} };
static PyTypeObject lstsq_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lstsq_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&lstsq_outNamedTuple, &desc);
lstsq_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lstsq_outNamedTuple;
}
PyTypeObject* get_lstsq_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"QR", ""}, {nullptr} };
static PyTypeObject lstsqNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lstsq", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&lstsqNamedTuple1, &desc);
lstsqNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lstsqNamedTuple1;
}
PyTypeObject* get_lu_unpack_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"P", ""}, {"L", ""}, {"U", ""}, {nullptr} };
static PyTypeObject lu_unpackNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lu_unpack", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&lu_unpackNamedTuple, &desc);
lu_unpackNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lu_unpackNamedTuple;
}
PyTypeObject* get_lu_unpack_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"P", ""}, {"L", ""}, {"U", ""}, {nullptr} };
static PyTypeObject lu_unpack_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lu_unpack_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&lu_unpack_outNamedTuple1, &desc);
lu_unpack_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lu_unpack_outNamedTuple1;
}
PyTypeObject* get_max_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject maxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.max", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&maxNamedTuple, &desc);
maxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &maxNamedTuple;
}
PyTypeObject* get_max_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject max_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.max_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&max_outNamedTuple1, &desc);
max_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &max_outNamedTuple1;
}
PyTypeObject* get_median_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject medianNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.median", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&medianNamedTuple, &desc);
medianNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &medianNamedTuple;
}
PyTypeObject* get_median_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject median_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.median_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&median_outNamedTuple1, &desc);
median_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &median_outNamedTuple1;
}
PyTypeObject* get_min_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject minNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.min", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&minNamedTuple, &desc);
minNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &minNamedTuple;
}
PyTypeObject* get_min_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject min_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.min_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&min_outNamedTuple1, &desc);
min_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &min_outNamedTuple1;
}
PyTypeObject* get_mode_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject modeNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.mode", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&modeNamedTuple, &desc);
modeNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &modeNamedTuple;
}
PyTypeObject* get_mode_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject mode_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.mode_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&mode_outNamedTuple1, &desc);
mode_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &mode_outNamedTuple1;
}
PyTypeObject* get_nanmedian_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject nanmedianNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.nanmedian", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&nanmedianNamedTuple, &desc);
nanmedianNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &nanmedianNamedTuple;
}
PyTypeObject* get_nanmedian_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject nanmedian_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.nanmedian_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&nanmedian_outNamedTuple1, &desc);
nanmedian_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &nanmedian_outNamedTuple1;
}
PyTypeObject* get_qr_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject qr_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.qr_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&qr_outNamedTuple, &desc);
qr_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &qr_outNamedTuple;
}
PyTypeObject* get_qr_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject qrNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.qr", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&qrNamedTuple1, &desc);
qrNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &qrNamedTuple1;
}
PyTypeObject* get_slogdet_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject slogdetNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.slogdet", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&slogdetNamedTuple, &desc);
slogdetNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &slogdetNamedTuple;
}
PyTypeObject* get_solve_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"LU", ""}, {nullptr} };
static PyTypeObject solveNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.solve", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&solveNamedTuple, &desc);
solveNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &solveNamedTuple;
}
PyTypeObject* get_solve_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"LU", ""}, {nullptr} };
static PyTypeObject solve_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.solve_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&solve_outNamedTuple1, &desc);
solve_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &solve_outNamedTuple1;
}
PyTypeObject* get_sort_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject sort_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.sort_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&sort_outNamedTuple, &desc);
sort_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &sort_outNamedTuple;
}
PyTypeObject* get_sort_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject sortNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.sort", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&sortNamedTuple1, &desc);
sortNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &sortNamedTuple1;
}
PyTypeObject* get_svd_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"V", ""}, {nullptr} };
static PyTypeObject svd_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.svd_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&svd_outNamedTuple, &desc);
svd_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &svd_outNamedTuple;
}
PyTypeObject* get_svd_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"V", ""}, {nullptr} };
static PyTypeObject svdNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.svd", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&svdNamedTuple1, &desc);
svdNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &svdNamedTuple1;
}
PyTypeObject* get_symeig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject symeig_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.symeig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&symeig_outNamedTuple, &desc);
symeig_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &symeig_outNamedTuple;
}
PyTypeObject* get_symeig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject symeigNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.symeig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&symeigNamedTuple1, &desc);
symeigNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &symeigNamedTuple1;
}
PyTypeObject* get_topk_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject topk_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.topk_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&topk_outNamedTuple, &desc);
topk_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &topk_outNamedTuple;
}
PyTypeObject* get_topk_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject topkNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.topk", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&topkNamedTuple1, &desc);
topkNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &topkNamedTuple1;
}
PyTypeObject* get_triangular_solve_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"cloned_coefficient", ""}, {nullptr} };
static PyTypeObject triangular_solve_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.triangular_solve_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&triangular_solve_outNamedTuple, &desc);
triangular_solve_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &triangular_solve_outNamedTuple;
}
PyTypeObject* get_triangular_solve_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"cloned_coefficient", ""}, {nullptr} };
static PyTypeObject triangular_solveNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.triangular_solve", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&triangular_solveNamedTuple1, &desc);
triangular_solveNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &triangular_solveNamedTuple1;
}
}
namespace torch {
namespace autograd {
std::map<std::string, PyTypeObject*>& get_namedtuple_types_map() {
// [NOTE] Non-global map
// This map calls Python functions during its initialization.
// If it is a global static variable and in case it is loaded
// before Python interpreter is ready, then the calls it makes during
// initialization will SEGFAULT.
// To avoid this we make it function static variable so that it is
// initialized only after the Python interpreter is ready.
static std::map<std::string, PyTypeObject*> namedtuple_types_map = {
{"_det_lu_based_helper", get__det_lu_based_helper_namedtuple()},
{"_fake_quantize_per_tensor_affine_cachemask_tensor_qparams", get__fake_quantize_per_tensor_affine_cachemask_tensor_qparams_namedtuple()},
{"_fused_moving_avg_obs_fq_helper", get__fused_moving_avg_obs_fq_helper_namedtuple()},
{"_lu_with_info", get__lu_with_info_namedtuple()},
{"_unpack_dual", get__unpack_dual_namedtuple()},
{"aminmax", get_aminmax_namedtuple()},
{"aminmax_out", get_aminmax_out_namedtuple()},
{"cummax", get_cummax_namedtuple()},
{"cummax_out", get_cummax_out_namedtuple()},
{"cummin", get_cummin_namedtuple()},
{"cummin_out", get_cummin_out_namedtuple()},
{"eig_out", get_eig_out_namedtuple()},
{"eig", get_eig_namedtuple()},
{"frexp", get_frexp_namedtuple()},
{"frexp_out", get_frexp_out_namedtuple()},
{"geqrf_out", get_geqrf_out_namedtuple()},
{"geqrf", get_geqrf_namedtuple()},
{"histogram_out", get_histogram_out_namedtuple()},
{"histogram", get_histogram_namedtuple()},
{"kthvalue", get_kthvalue_namedtuple()},
{"kthvalue_out", get_kthvalue_out_namedtuple()},
{"linalg_cholesky_ex", get_linalg_cholesky_ex_namedtuple()},
{"linalg_cholesky_ex_out", get_linalg_cholesky_ex_out_namedtuple()},
{"linalg_eig", get_linalg_eig_namedtuple()},
{"linalg_eig_out", get_linalg_eig_out_namedtuple()},
{"linalg_eigh", get_linalg_eigh_namedtuple()},
{"linalg_eigh_out", get_linalg_eigh_out_namedtuple()},
{"linalg_inv_ex", get_linalg_inv_ex_namedtuple()},
{"linalg_inv_ex_out", get_linalg_inv_ex_out_namedtuple()},
{"linalg_lstsq", get_linalg_lstsq_namedtuple()},
{"linalg_lstsq_out", get_linalg_lstsq_out_namedtuple()},
{"linalg_qr", get_linalg_qr_namedtuple()},
{"linalg_qr_out", get_linalg_qr_out_namedtuple()},
{"linalg_slogdet", get_linalg_slogdet_namedtuple()},
{"linalg_slogdet_out", get_linalg_slogdet_out_namedtuple()},
{"linalg_svd_out", get_linalg_svd_out_namedtuple()},
{"linalg_svd", get_linalg_svd_namedtuple()},
{"lstsq_out", get_lstsq_out_namedtuple()},
{"lstsq", get_lstsq_namedtuple()},
{"lu_unpack", get_lu_unpack_namedtuple()},
{"lu_unpack_out", get_lu_unpack_out_namedtuple()},
{"max", get_max_namedtuple()},
{"max_out", get_max_out_namedtuple()},
{"median", get_median_namedtuple()},
{"median_out", get_median_out_namedtuple()},
{"min", get_min_namedtuple()},
{"min_out", get_min_out_namedtuple()},
{"mode", get_mode_namedtuple()},
{"mode_out", get_mode_out_namedtuple()},
{"nanmedian", get_nanmedian_namedtuple()},
{"nanmedian_out", get_nanmedian_out_namedtuple()},
{"qr_out", get_qr_out_namedtuple()},
{"qr", get_qr_namedtuple()},
{"slogdet", get_slogdet_namedtuple()},
{"solve", get_solve_namedtuple()},
{"solve_out", get_solve_out_namedtuple()},
{"sort_out", get_sort_out_namedtuple()},
{"sort", get_sort_namedtuple()},
{"svd_out", get_svd_out_namedtuple()},
{"svd", get_svd_namedtuple()},
{"symeig_out", get_symeig_out_namedtuple()},
{"symeig", get_symeig_namedtuple()},
{"topk_out", get_topk_out_namedtuple()},
{"topk", get_topk_namedtuple()},
{"triangular_solve_out", get_triangular_solve_out_namedtuple()},
{"triangular_solve", get_triangular_solve_namedtuple()},
};
return namedtuple_types_map;
}
PyTypeObject* get_namedtuple(std::string name) {
static auto& namedtuple_types_map = get_namedtuple_types_map();
return namedtuple_types_map[name];
}
void initReturnTypes(PyObject* module) {
static struct PyModuleDef def = {
PyModuleDef_HEAD_INIT, "torch._C._return_types", nullptr, -1, {}};
PyObject* return_types_module = PyModule_Create(&def);
if (!return_types_module) {
throw python_error();
}
for (const auto& return_type_pair : get_namedtuple_types_map()) {
// hold onto the TypeObject for the unlikely case of user
// deleting or overriding it.
Py_INCREF(return_type_pair.second);
if (PyModule_AddObject(
return_types_module,
return_type_pair.first.c_str(),
(PyObject*)return_type_pair.second) != 0) {
Py_DECREF((PyObject*)return_type_pair.second);
throw python_error();
}
}
// steals a reference to return_types on success
if (PyModule_AddObject(module, "_return_types", return_types_module) != 0) {
Py_DECREF(return_types_module);
throw python_error();
}
}
} // namespace autograd
} // namespace torch
```
</details>
<details>
<summary>Eg. updated call in other python_*_functions</summary>
```cpp
// linalg_cholesky_ex
static PyObject * THPVariable_linalg_cholesky_ex(PyObject* self_, PyObject* args, PyObject* kwargs)
{
HANDLE_TH_ERRORS
static PyTypeObject* NamedTuple = get_namedtuple("linalg_cholesky_ex");
static PyTypeObject* NamedTuple1 = get_namedtuple("linalg_cholesky_ex_out");
static PythonArgParser parser({
"linalg_cholesky_ex(Tensor input, *, bool upper=False, bool check_errors=False, TensorList[2] out=None)",
}, /*traceable=*/true);
ParsedArgs<4> parsed_args;
auto _r = parser.parse(nullptr, args, kwargs, parsed_args);
if(_r.has_torch_function()) {
return handle_torch_function(_r, nullptr, args, kwargs, THPLinalgVariableFunctionsModule, "torch.linalg");
}
if (_r.isNone(3)) {
// aten::linalg_cholesky_ex(Tensor self, *, bool upper=False, bool check_errors=False) -> (Tensor L, Tensor info)
auto dispatch_linalg_cholesky_ex = [](const at::Tensor & self, bool upper, bool check_errors) -> ::std::tuple<at::Tensor,at::Tensor> {
pybind11::gil_scoped_release no_gil;
return at::linalg_cholesky_ex(self, upper, check_errors);
};
return wrap(NamedTuple, dispatch_linalg_cholesky_ex(_r.tensor(0), _r.toBool(1), _r.toBool(2)));
} else {
// aten::linalg_cholesky_ex.L(Tensor self, *, bool upper=False, bool check_errors=False, Tensor(a!) L, Tensor(b!) info) -> (Tensor(a!) L, Tensor(b!) info)
auto out = _r.tensorlist_n<2>(3);
auto dispatch_linalg_cholesky_ex_out = [](at::Tensor & L, at::Tensor & info, const at::Tensor & self, bool upper, bool check_errors) -> ::std::tuple<at::Tensor,at::Tensor> {
pybind11::gil_scoped_release no_gil;
return at::linalg_cholesky_ex_out(L, info, self, upper, check_errors);
};
return wrap(NamedTuple1, dispatch_linalg_cholesky_ex_out(out[0], out[1], _r.tensor(0), _r.toBool(1), _r.toBool(2)));
}
Py_RETURN_NONE;
END_HANDLE_TH_ERRORS
}
```
</details>
Pull Request resolved: https://github.com/pytorch/pytorch/pull/66614
Reviewed By: H-Huang
Differential Revision: D32741134
Pulled By: zou3519
fbshipit-source-id: 27bada30d20e66333ca1be1775608d9f0cbf9f59
2021-12-06 17:03:11 +00:00
|
|
|
def emit_namedtuple_call(
|
2022-04-20 12:51:02 +00:00
|
|
|
overloads: Sequence[PythonSignatureNativeFunctionPair],
|
2020-11-08 09:03:59 +00:00
|
|
|
) -> Tuple[List[str], Dict[str, str]]:
|
2020-01-30 08:26:16 +00:00
|
|
|
"""
|
|
|
|
|
Generate block of named tuple type def inits, and add typeref snippets
|
|
|
|
|
to declarations that use them
|
|
|
|
|
"""
|
2022-04-20 12:51:02 +00:00
|
|
|
typenames: Dict[
|
|
|
|
|
str, str
|
|
|
|
|
] = {} # map from unique name + field name lists to typedef name
|
|
|
|
|
typedefs: List[str] = [] # typedef declarations and init code
|
2020-11-08 09:03:59 +00:00
|
|
|
|
|
|
|
|
for overload in overloads:
|
pyi codegen update - remove Declarations.yaml (#48754)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/48754
The goal of this PR is to kill Declarations.yaml in the pyi codegen, in favor of native_functions + the existing python object model.
**High-level design**
Since the python signatures used by the `python_arg_parser` are “supposed” to resemble the corresponding pyi type hint signatures, I re-used the existing python object model that Jiakai defined in `tools/codegen/api/python.py`. This means that the pyi codegen now reads `native_functions.yaml`, parses it into a bunch of `PythonSignatureGroup` objects, and emits corresponding method + function variants of type-hint signatures for each one, respectively into `__init__.pyi` and `_VariableFunctions.pyi`.
What makes this uglier is that pyi and the python arg parser have a number of differences in how they’re emitted. I expressed that through a `pyi` flag on the `PythonSignature` dataclass, that tells it whether or not to print itself as a pyi vs. arg_parser signature.
One thing worth noting is how pyi generates signatures differently for native / deprecated op signatures.
For native ops:
- The pyi codegen fuses functional and out variants of each op into a single signature with an optional `out` argument. Ops without an `out` variant just get an ordinary functional signature.
- Some ops that fit certain criteria also get a second “varargs” signature - basically ops with a single positional argument of type List[int].
For deprecated signatures:
- Functional and out variants are not fused - they each get their own signature entry
- There are no varargs signatures
This is currently implemented through the `signature_str()` and `signature_str_vararg()` methods on the `PythonSignature`/`PythonSignatureDeprecated` classes. `signature_str()` knows how to print itself with/without out arguments, differently for native/deprecated ops. `signature_str_vararg()` optionally returns a vararg variant of the signature if one exists.
**Calling out the gap between python_arg_parser vs. pyi**
The two formats are notably different, so I don’t think we can expect to unify them completely. That said, I encountered a number of differences in the pyi codegen that looked wrong- I tried to call them out in the PR, to be removed later. Just as an example, looking at the `svd` signature in the python_arg_parser vs. the pyi type hint:
python_arg_parser
```
Static PythonArgParser parser({
“svd(Tensor input, bool some=True, bool compute_uv=True, *, TensorList[3] out=None”,
}, /*traceable=*/true);
```
Pyi
```
def svd(input: Tensor, some: _bool=True, compute_uv: _bool=True, *, out: Optional[Tensor]=None) -> namedtuple_U_S_V: …
```
The two have obvious syntactic differences that we probably don’t plan on changing: the python_arg_parser doesn’t include `def` or return types, and it includes the type hint before the variable name. But the type of `out` in pyi is probably wrong, since `svd` has multiple output params. I tried to clearly call out any instances of the pyi codegen diverging in a way that looks buggy, so we can clean it up in a later PR (see the comments for details).
Another particularly ugly “bug” that I kept in to maintain byte-for-byte compatibility is the fact that the pyi codegen groups operator overloads together. It turns out that the only reason it does this (as far as I can tell) is because is tacks on an out argument to signatures that don’t have one, if ANY overloads of that op have an out variant.
E.g. consider the pyi type hints generated for `nanmedian` in `_VF.pyi`:
```
overload
def nanmedian(input: Tensor, *, out: Optional[Tensor]=None) -> Tensor: ...
overload
def nanmedian(input: Tensor, dim: _int, keepdim: _bool=False, *, out: Optional[Tensor]=None) -> namedtuple_values_indices: ...
overload
def nanmedian(input: Tensor, dim: Union[str, ellipsis, None], keepdim: _bool=False, *, out: Optional[Tensor]=None) -> namedtuple_values_indices: ...
```
And the corresponding native_functions.yaml entries:
```
- func: nanmedian(Tensor self) -> Tensor
- func: nanmedian.dim(Tensor self, int dim, bool keepdim=False) -> (Tensor values, Tensor indices)
- func: nanmedian.dim_values(Tensor self, int dim, bool keepdim=False, *, Tensor(a!) values, Tensor(b!) indices) -> (Tensor(a!) values, Tensor(b!) indices)
- func: nanmedian.names_dim(Tensor self, Dimname dim, bool keepdim=False) -> (Tensor values, Tensor indices)
- func: nanmedian.names_dim_values(Tensor self, Dimname dim, bool keepdim=False, *, Tensor(a!) values, Tensor(b!) indices) -> (Tensor(a!) values, Tensor(b!)
```
Signature 2 corresponds to entries 2 and 3 in native_functions, and Signature 3 corresponds to entries 4 and 5. But signature 1 has an optional out argument, even though entry 1 in native_functions.yaml has no out variant.
I’d like to delete that logic in a later PR- that will also have the added benefit no longer requiring to group overloads together in the pyi codegen. We can just operate independently on each PythonSignatureGroup.
**More detailed accounting of the changes**
Per file:
gen_python_functions.py
- `load_signatures()` can now skip deprecated signatures. Needed because pyi only includes deprecated functions, and skips their method variants (maybe we should add them in…?)
- Moved `namedtuple_fieldnames` into python.cpp
- `group_overloads()` can now opt to not sort the overloads (needed for byte-for-byte compact, pyi doesn’t sort for some reason)
Python.py:
- Gave `PythonSignature`and `PythonSignatureDeprecated` a `pyi` flag that tells it whether or not to print itself in pyi vs. python_arg_parser format
- Added a `PythonReturns` dataclass , which is now a member of PythonSignature. It is only used by pyi. I found this useful because python returns need to know how to deal with named tuple returns properly. I also moved `namedtuple_fieldnames` into this file from gen_python_functions
gen_pyi.py
- Merged `get_py_torch_functions` and `get_py_variable_methods` into a single function, since they’re very similar
- Lifted out all of the pyi type hint type-mapping mess and dropped it into python.py. This required updating the mapping to deal with NativeFunction objects instead of the outputs of Declarations.yaml (this was most of the logic in `type_to_python`, `arg_to_type_hint`, and `generate_type_hints`). `generate_type_hints` is now a small orchestration function that gathers the different signatures for each PythonSignatureGroup.
- NamedTuples are now generated by calling `PythonReturn.named_tuple()` (in `generate_named_tuples()`), rather than appending to a global list
A lot of hardcoded pyi signatures still live in `gen_pyi.py`. I didn’t look to closely into whether or not any of that can be removed as part of this PR.
Test Plan: Imported from OSS
Reviewed By: ljk53
Differential Revision: D25343802
Pulled By: bdhirsh
fbshipit-source-id: f73e99e1afef934ff41e4aca3dabf34273459a52
2020-12-07 18:37:38 +00:00
|
|
|
fieldnames = namedtuple_fieldnames(overload.function.func.returns)
|
2020-11-08 09:03:59 +00:00
|
|
|
if not fieldnames:
|
2020-01-30 08:26:16 +00:00
|
|
|
continue
|
|
|
|
|
|
2020-11-08 09:03:59 +00:00
|
|
|
name = cpp.name(overload.function.func) # use @with_native_function?
|
|
|
|
|
tn_key = gen_namedtuple_typename_key(overload.function)
|
|
|
|
|
typename = typenames.get(tn_key)
|
2020-01-30 08:26:16 +00:00
|
|
|
if typename is None:
|
2020-11-08 09:03:59 +00:00
|
|
|
typename = f'NamedTuple{"" if not typedefs else len(typedefs)}'
|
|
|
|
|
typenames[tn_key] = typename
|
2022-04-20 12:51:02 +00:00
|
|
|
typedefs.append(
|
|
|
|
|
f"""\
|
|
|
|
|
static PyTypeObject* {typename} = get_namedtuple("{name}");"""
|
|
|
|
|
)
|
expose return_types in Python (#66614)
Summary:
https://github.com/facebookresearch/functorch/issues/87
TODO:
* [x] Add comments
* [x] Add test
* [x] Fix XLA
<details>
<summary>Generated python_return_types.cpp</summary>
```cpp
#include <Python.h>
#include <vector>
#include <map>
#include <string>
#include "torch/csrc/autograd/python_return_types.h"
#include "torch/csrc/utils/structseq.h"
#include "torch/csrc/Exceptions.h"
namespace {
PyTypeObject* get__det_lu_based_helper_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"det", ""}, {"lu", ""}, {"pivs", ""}, {nullptr} };
static PyTypeObject _det_lu_based_helperNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._det_lu_based_helper", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&_det_lu_based_helperNamedTuple, &desc);
_det_lu_based_helperNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_det_lu_based_helperNamedTuple;
}
PyTypeObject* get__fake_quantize_per_tensor_affine_cachemask_tensor_qparams_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"output", ""}, {"mask", ""}, {nullptr} };
static PyTypeObject _fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._fake_quantize_per_tensor_affine_cachemask_tensor_qparams", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple, &desc);
_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple;
}
PyTypeObject* get__fused_moving_avg_obs_fq_helper_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"output", ""}, {"mask", ""}, {nullptr} };
static PyTypeObject _fused_moving_avg_obs_fq_helperNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._fused_moving_avg_obs_fq_helper", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_fused_moving_avg_obs_fq_helperNamedTuple, &desc);
_fused_moving_avg_obs_fq_helperNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_fused_moving_avg_obs_fq_helperNamedTuple;
}
PyTypeObject* get__lu_with_info_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"LU", ""}, {"pivots", ""}, {"info", ""}, {nullptr} };
static PyTypeObject _lu_with_infoNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._lu_with_info", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&_lu_with_infoNamedTuple, &desc);
_lu_with_infoNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_lu_with_infoNamedTuple;
}
PyTypeObject* get__unpack_dual_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"primal", ""}, {"tangent", ""}, {nullptr} };
static PyTypeObject _unpack_dualNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._unpack_dual", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_unpack_dualNamedTuple, &desc);
_unpack_dualNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_unpack_dualNamedTuple;
}
PyTypeObject* get_aminmax_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"min", ""}, {"max", ""}, {nullptr} };
static PyTypeObject aminmaxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.aminmax", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&aminmaxNamedTuple, &desc);
aminmaxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &aminmaxNamedTuple;
}
PyTypeObject* get_aminmax_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"min", ""}, {"max", ""}, {nullptr} };
static PyTypeObject aminmax_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.aminmax_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&aminmax_outNamedTuple1, &desc);
aminmax_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &aminmax_outNamedTuple1;
}
PyTypeObject* get_cummax_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummaxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummax", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummaxNamedTuple, &desc);
cummaxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummaxNamedTuple;
}
PyTypeObject* get_cummax_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummax_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummax_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummax_outNamedTuple1, &desc);
cummax_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummax_outNamedTuple1;
}
PyTypeObject* get_cummin_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cumminNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummin", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cumminNamedTuple, &desc);
cumminNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cumminNamedTuple;
}
PyTypeObject* get_cummin_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummin_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummin_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummin_outNamedTuple1, &desc);
cummin_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummin_outNamedTuple1;
}
PyTypeObject* get_eig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject eig_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.eig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&eig_outNamedTuple, &desc);
eig_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &eig_outNamedTuple;
}
PyTypeObject* get_eig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject eigNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.eig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&eigNamedTuple1, &desc);
eigNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &eigNamedTuple1;
}
PyTypeObject* get_frexp_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"mantissa", ""}, {"exponent", ""}, {nullptr} };
static PyTypeObject frexpNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.frexp", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&frexpNamedTuple, &desc);
frexpNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &frexpNamedTuple;
}
PyTypeObject* get_frexp_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"mantissa", ""}, {"exponent", ""}, {nullptr} };
static PyTypeObject frexp_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.frexp_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&frexp_outNamedTuple1, &desc);
frexp_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &frexp_outNamedTuple1;
}
PyTypeObject* get_geqrf_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"a", ""}, {"tau", ""}, {nullptr} };
static PyTypeObject geqrf_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.geqrf_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&geqrf_outNamedTuple, &desc);
geqrf_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &geqrf_outNamedTuple;
}
PyTypeObject* get_geqrf_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"a", ""}, {"tau", ""}, {nullptr} };
static PyTypeObject geqrfNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.geqrf", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&geqrfNamedTuple1, &desc);
geqrfNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &geqrfNamedTuple1;
}
PyTypeObject* get_histogram_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"hist", ""}, {"bin_edges", ""}, {nullptr} };
static PyTypeObject histogram_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.histogram_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&histogram_outNamedTuple, &desc);
histogram_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &histogram_outNamedTuple;
}
PyTypeObject* get_histogram_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"hist", ""}, {"bin_edges", ""}, {nullptr} };
static PyTypeObject histogramNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.histogram", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&histogramNamedTuple1, &desc);
histogramNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &histogramNamedTuple1;
}
PyTypeObject* get_kthvalue_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject kthvalueNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.kthvalue", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&kthvalueNamedTuple, &desc);
kthvalueNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &kthvalueNamedTuple;
}
PyTypeObject* get_kthvalue_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject kthvalue_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.kthvalue_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&kthvalue_outNamedTuple1, &desc);
kthvalue_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &kthvalue_outNamedTuple1;
}
PyTypeObject* get_linalg_cholesky_ex_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"L", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_cholesky_exNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_cholesky_ex", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_cholesky_exNamedTuple, &desc);
linalg_cholesky_exNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_cholesky_exNamedTuple;
}
PyTypeObject* get_linalg_cholesky_ex_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"L", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_cholesky_ex_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_cholesky_ex_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_cholesky_ex_outNamedTuple1, &desc);
linalg_cholesky_ex_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_cholesky_ex_outNamedTuple1;
}
PyTypeObject* get_linalg_eig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eigNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eigNamedTuple, &desc);
linalg_eigNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eigNamedTuple;
}
PyTypeObject* get_linalg_eig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eig_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eig_outNamedTuple1, &desc);
linalg_eig_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eig_outNamedTuple1;
}
PyTypeObject* get_linalg_eigh_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eighNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eigh", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eighNamedTuple, &desc);
linalg_eighNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eighNamedTuple;
}
PyTypeObject* get_linalg_eigh_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eigh_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eigh_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eigh_outNamedTuple1, &desc);
linalg_eigh_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eigh_outNamedTuple1;
}
PyTypeObject* get_linalg_inv_ex_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"inverse", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_inv_exNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_inv_ex", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_inv_exNamedTuple, &desc);
linalg_inv_exNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_inv_exNamedTuple;
}
PyTypeObject* get_linalg_inv_ex_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"inverse", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_inv_ex_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_inv_ex_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_inv_ex_outNamedTuple1, &desc);
linalg_inv_ex_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_inv_ex_outNamedTuple1;
}
PyTypeObject* get_linalg_lstsq_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"residuals", ""}, {"rank", ""}, {"singular_values", ""}, {nullptr} };
static PyTypeObject linalg_lstsqNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_lstsq", nullptr, NamedTuple_fields, 4 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_lstsqNamedTuple, &desc);
linalg_lstsqNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_lstsqNamedTuple;
}
PyTypeObject* get_linalg_lstsq_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"residuals", ""}, {"rank", ""}, {"singular_values", ""}, {nullptr} };
static PyTypeObject linalg_lstsq_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_lstsq_out", nullptr, NamedTuple_fields, 4 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_lstsq_outNamedTuple1, &desc);
linalg_lstsq_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_lstsq_outNamedTuple1;
}
PyTypeObject* get_linalg_qr_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject linalg_qrNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_qr", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_qrNamedTuple, &desc);
linalg_qrNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_qrNamedTuple;
}
PyTypeObject* get_linalg_qr_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject linalg_qr_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_qr_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_qr_outNamedTuple1, &desc);
linalg_qr_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_qr_outNamedTuple1;
}
PyTypeObject* get_linalg_slogdet_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject linalg_slogdetNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_slogdet", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_slogdetNamedTuple, &desc);
linalg_slogdetNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_slogdetNamedTuple;
}
PyTypeObject* get_linalg_slogdet_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject linalg_slogdet_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_slogdet_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_slogdet_outNamedTuple1, &desc);
linalg_slogdet_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_slogdet_outNamedTuple1;
}
PyTypeObject* get_linalg_svd_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"Vh", ""}, {nullptr} };
static PyTypeObject linalg_svd_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_svd_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_svd_outNamedTuple, &desc);
linalg_svd_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_svd_outNamedTuple;
}
PyTypeObject* get_linalg_svd_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"Vh", ""}, {nullptr} };
static PyTypeObject linalg_svdNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_svd", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_svdNamedTuple1, &desc);
linalg_svdNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_svdNamedTuple1;
}
PyTypeObject* get_lstsq_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"QR", ""}, {nullptr} };
static PyTypeObject lstsq_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lstsq_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&lstsq_outNamedTuple, &desc);
lstsq_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lstsq_outNamedTuple;
}
PyTypeObject* get_lstsq_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"QR", ""}, {nullptr} };
static PyTypeObject lstsqNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lstsq", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&lstsqNamedTuple1, &desc);
lstsqNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lstsqNamedTuple1;
}
PyTypeObject* get_lu_unpack_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"P", ""}, {"L", ""}, {"U", ""}, {nullptr} };
static PyTypeObject lu_unpackNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lu_unpack", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&lu_unpackNamedTuple, &desc);
lu_unpackNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lu_unpackNamedTuple;
}
PyTypeObject* get_lu_unpack_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"P", ""}, {"L", ""}, {"U", ""}, {nullptr} };
static PyTypeObject lu_unpack_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lu_unpack_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&lu_unpack_outNamedTuple1, &desc);
lu_unpack_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lu_unpack_outNamedTuple1;
}
PyTypeObject* get_max_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject maxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.max", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&maxNamedTuple, &desc);
maxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &maxNamedTuple;
}
PyTypeObject* get_max_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject max_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.max_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&max_outNamedTuple1, &desc);
max_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &max_outNamedTuple1;
}
PyTypeObject* get_median_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject medianNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.median", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&medianNamedTuple, &desc);
medianNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &medianNamedTuple;
}
PyTypeObject* get_median_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject median_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.median_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&median_outNamedTuple1, &desc);
median_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &median_outNamedTuple1;
}
PyTypeObject* get_min_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject minNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.min", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&minNamedTuple, &desc);
minNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &minNamedTuple;
}
PyTypeObject* get_min_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject min_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.min_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&min_outNamedTuple1, &desc);
min_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &min_outNamedTuple1;
}
PyTypeObject* get_mode_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject modeNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.mode", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&modeNamedTuple, &desc);
modeNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &modeNamedTuple;
}
PyTypeObject* get_mode_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject mode_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.mode_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&mode_outNamedTuple1, &desc);
mode_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &mode_outNamedTuple1;
}
PyTypeObject* get_nanmedian_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject nanmedianNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.nanmedian", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&nanmedianNamedTuple, &desc);
nanmedianNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &nanmedianNamedTuple;
}
PyTypeObject* get_nanmedian_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject nanmedian_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.nanmedian_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&nanmedian_outNamedTuple1, &desc);
nanmedian_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &nanmedian_outNamedTuple1;
}
PyTypeObject* get_qr_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject qr_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.qr_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&qr_outNamedTuple, &desc);
qr_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &qr_outNamedTuple;
}
PyTypeObject* get_qr_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject qrNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.qr", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&qrNamedTuple1, &desc);
qrNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &qrNamedTuple1;
}
PyTypeObject* get_slogdet_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject slogdetNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.slogdet", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&slogdetNamedTuple, &desc);
slogdetNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &slogdetNamedTuple;
}
PyTypeObject* get_solve_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"LU", ""}, {nullptr} };
static PyTypeObject solveNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.solve", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&solveNamedTuple, &desc);
solveNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &solveNamedTuple;
}
PyTypeObject* get_solve_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"LU", ""}, {nullptr} };
static PyTypeObject solve_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.solve_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&solve_outNamedTuple1, &desc);
solve_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &solve_outNamedTuple1;
}
PyTypeObject* get_sort_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject sort_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.sort_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&sort_outNamedTuple, &desc);
sort_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &sort_outNamedTuple;
}
PyTypeObject* get_sort_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject sortNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.sort", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&sortNamedTuple1, &desc);
sortNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &sortNamedTuple1;
}
PyTypeObject* get_svd_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"V", ""}, {nullptr} };
static PyTypeObject svd_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.svd_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&svd_outNamedTuple, &desc);
svd_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &svd_outNamedTuple;
}
PyTypeObject* get_svd_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"V", ""}, {nullptr} };
static PyTypeObject svdNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.svd", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&svdNamedTuple1, &desc);
svdNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &svdNamedTuple1;
}
PyTypeObject* get_symeig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject symeig_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.symeig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&symeig_outNamedTuple, &desc);
symeig_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &symeig_outNamedTuple;
}
PyTypeObject* get_symeig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject symeigNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.symeig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&symeigNamedTuple1, &desc);
symeigNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &symeigNamedTuple1;
}
PyTypeObject* get_topk_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject topk_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.topk_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&topk_outNamedTuple, &desc);
topk_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &topk_outNamedTuple;
}
PyTypeObject* get_topk_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject topkNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.topk", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&topkNamedTuple1, &desc);
topkNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &topkNamedTuple1;
}
PyTypeObject* get_triangular_solve_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"cloned_coefficient", ""}, {nullptr} };
static PyTypeObject triangular_solve_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.triangular_solve_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&triangular_solve_outNamedTuple, &desc);
triangular_solve_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &triangular_solve_outNamedTuple;
}
PyTypeObject* get_triangular_solve_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"cloned_coefficient", ""}, {nullptr} };
static PyTypeObject triangular_solveNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.triangular_solve", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&triangular_solveNamedTuple1, &desc);
triangular_solveNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &triangular_solveNamedTuple1;
}
}
namespace torch {
namespace autograd {
std::map<std::string, PyTypeObject*>& get_namedtuple_types_map() {
// [NOTE] Non-global map
// This map calls Python functions during its initialization.
// If it is a global static variable and in case it is loaded
// before Python interpreter is ready, then the calls it makes during
// initialization will SEGFAULT.
// To avoid this we make it function static variable so that it is
// initialized only after the Python interpreter is ready.
static std::map<std::string, PyTypeObject*> namedtuple_types_map = {
{"_det_lu_based_helper", get__det_lu_based_helper_namedtuple()},
{"_fake_quantize_per_tensor_affine_cachemask_tensor_qparams", get__fake_quantize_per_tensor_affine_cachemask_tensor_qparams_namedtuple()},
{"_fused_moving_avg_obs_fq_helper", get__fused_moving_avg_obs_fq_helper_namedtuple()},
{"_lu_with_info", get__lu_with_info_namedtuple()},
{"_unpack_dual", get__unpack_dual_namedtuple()},
{"aminmax", get_aminmax_namedtuple()},
{"aminmax_out", get_aminmax_out_namedtuple()},
{"cummax", get_cummax_namedtuple()},
{"cummax_out", get_cummax_out_namedtuple()},
{"cummin", get_cummin_namedtuple()},
{"cummin_out", get_cummin_out_namedtuple()},
{"eig_out", get_eig_out_namedtuple()},
{"eig", get_eig_namedtuple()},
{"frexp", get_frexp_namedtuple()},
{"frexp_out", get_frexp_out_namedtuple()},
{"geqrf_out", get_geqrf_out_namedtuple()},
{"geqrf", get_geqrf_namedtuple()},
{"histogram_out", get_histogram_out_namedtuple()},
{"histogram", get_histogram_namedtuple()},
{"kthvalue", get_kthvalue_namedtuple()},
{"kthvalue_out", get_kthvalue_out_namedtuple()},
{"linalg_cholesky_ex", get_linalg_cholesky_ex_namedtuple()},
{"linalg_cholesky_ex_out", get_linalg_cholesky_ex_out_namedtuple()},
{"linalg_eig", get_linalg_eig_namedtuple()},
{"linalg_eig_out", get_linalg_eig_out_namedtuple()},
{"linalg_eigh", get_linalg_eigh_namedtuple()},
{"linalg_eigh_out", get_linalg_eigh_out_namedtuple()},
{"linalg_inv_ex", get_linalg_inv_ex_namedtuple()},
{"linalg_inv_ex_out", get_linalg_inv_ex_out_namedtuple()},
{"linalg_lstsq", get_linalg_lstsq_namedtuple()},
{"linalg_lstsq_out", get_linalg_lstsq_out_namedtuple()},
{"linalg_qr", get_linalg_qr_namedtuple()},
{"linalg_qr_out", get_linalg_qr_out_namedtuple()},
{"linalg_slogdet", get_linalg_slogdet_namedtuple()},
{"linalg_slogdet_out", get_linalg_slogdet_out_namedtuple()},
{"linalg_svd_out", get_linalg_svd_out_namedtuple()},
{"linalg_svd", get_linalg_svd_namedtuple()},
{"lstsq_out", get_lstsq_out_namedtuple()},
{"lstsq", get_lstsq_namedtuple()},
{"lu_unpack", get_lu_unpack_namedtuple()},
{"lu_unpack_out", get_lu_unpack_out_namedtuple()},
{"max", get_max_namedtuple()},
{"max_out", get_max_out_namedtuple()},
{"median", get_median_namedtuple()},
{"median_out", get_median_out_namedtuple()},
{"min", get_min_namedtuple()},
{"min_out", get_min_out_namedtuple()},
{"mode", get_mode_namedtuple()},
{"mode_out", get_mode_out_namedtuple()},
{"nanmedian", get_nanmedian_namedtuple()},
{"nanmedian_out", get_nanmedian_out_namedtuple()},
{"qr_out", get_qr_out_namedtuple()},
{"qr", get_qr_namedtuple()},
{"slogdet", get_slogdet_namedtuple()},
{"solve", get_solve_namedtuple()},
{"solve_out", get_solve_out_namedtuple()},
{"sort_out", get_sort_out_namedtuple()},
{"sort", get_sort_namedtuple()},
{"svd_out", get_svd_out_namedtuple()},
{"svd", get_svd_namedtuple()},
{"symeig_out", get_symeig_out_namedtuple()},
{"symeig", get_symeig_namedtuple()},
{"topk_out", get_topk_out_namedtuple()},
{"topk", get_topk_namedtuple()},
{"triangular_solve_out", get_triangular_solve_out_namedtuple()},
{"triangular_solve", get_triangular_solve_namedtuple()},
};
return namedtuple_types_map;
}
PyTypeObject* get_namedtuple(std::string name) {
static auto& namedtuple_types_map = get_namedtuple_types_map();
return namedtuple_types_map[name];
}
void initReturnTypes(PyObject* module) {
static struct PyModuleDef def = {
PyModuleDef_HEAD_INIT, "torch._C._return_types", nullptr, -1, {}};
PyObject* return_types_module = PyModule_Create(&def);
if (!return_types_module) {
throw python_error();
}
for (const auto& return_type_pair : get_namedtuple_types_map()) {
// hold onto the TypeObject for the unlikely case of user
// deleting or overriding it.
Py_INCREF(return_type_pair.second);
if (PyModule_AddObject(
return_types_module,
return_type_pair.first.c_str(),
(PyObject*)return_type_pair.second) != 0) {
Py_DECREF((PyObject*)return_type_pair.second);
throw python_error();
}
}
// steals a reference to return_types on success
if (PyModule_AddObject(module, "_return_types", return_types_module) != 0) {
Py_DECREF(return_types_module);
throw python_error();
}
}
} // namespace autograd
} // namespace torch
```
</details>
<details>
<summary>Eg. updated call in other python_*_functions</summary>
```cpp
// linalg_cholesky_ex
static PyObject * THPVariable_linalg_cholesky_ex(PyObject* self_, PyObject* args, PyObject* kwargs)
{
HANDLE_TH_ERRORS
static PyTypeObject* NamedTuple = get_namedtuple("linalg_cholesky_ex");
static PyTypeObject* NamedTuple1 = get_namedtuple("linalg_cholesky_ex_out");
static PythonArgParser parser({
"linalg_cholesky_ex(Tensor input, *, bool upper=False, bool check_errors=False, TensorList[2] out=None)",
}, /*traceable=*/true);
ParsedArgs<4> parsed_args;
auto _r = parser.parse(nullptr, args, kwargs, parsed_args);
if(_r.has_torch_function()) {
return handle_torch_function(_r, nullptr, args, kwargs, THPLinalgVariableFunctionsModule, "torch.linalg");
}
if (_r.isNone(3)) {
// aten::linalg_cholesky_ex(Tensor self, *, bool upper=False, bool check_errors=False) -> (Tensor L, Tensor info)
auto dispatch_linalg_cholesky_ex = [](const at::Tensor & self, bool upper, bool check_errors) -> ::std::tuple<at::Tensor,at::Tensor> {
pybind11::gil_scoped_release no_gil;
return at::linalg_cholesky_ex(self, upper, check_errors);
};
return wrap(NamedTuple, dispatch_linalg_cholesky_ex(_r.tensor(0), _r.toBool(1), _r.toBool(2)));
} else {
// aten::linalg_cholesky_ex.L(Tensor self, *, bool upper=False, bool check_errors=False, Tensor(a!) L, Tensor(b!) info) -> (Tensor(a!) L, Tensor(b!) info)
auto out = _r.tensorlist_n<2>(3);
auto dispatch_linalg_cholesky_ex_out = [](at::Tensor & L, at::Tensor & info, const at::Tensor & self, bool upper, bool check_errors) -> ::std::tuple<at::Tensor,at::Tensor> {
pybind11::gil_scoped_release no_gil;
return at::linalg_cholesky_ex_out(L, info, self, upper, check_errors);
};
return wrap(NamedTuple1, dispatch_linalg_cholesky_ex_out(out[0], out[1], _r.tensor(0), _r.toBool(1), _r.toBool(2)));
}
Py_RETURN_NONE;
END_HANDLE_TH_ERRORS
}
```
</details>
Pull Request resolved: https://github.com/pytorch/pytorch/pull/66614
Reviewed By: H-Huang
Differential Revision: D32741134
Pulled By: zou3519
fbshipit-source-id: 27bada30d20e66333ca1be1775608d9f0cbf9f59
2021-12-06 17:03:11 +00:00
|
|
|
|
|
|
|
|
return typedefs, typenames
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def generate_return_type_definition_and_map_entry(
|
|
|
|
|
overloads: Sequence[PythonSignatureNativeFunctionPair],
|
|
|
|
|
) -> Tuple[List[str], List[str]]:
|
|
|
|
|
"""
|
|
|
|
|
Generate block of function in `python_return_types.cpp` to initialize
|
|
|
|
|
and return named tuple for a native function which returns named tuple
|
|
|
|
|
and relevant entry for the map in same file.
|
|
|
|
|
"""
|
2022-04-20 12:51:02 +00:00
|
|
|
typenames: Dict[
|
|
|
|
|
str, str
|
|
|
|
|
] = {} # map from unique name + field name lists to typedef name
|
expose return_types in Python (#66614)
Summary:
https://github.com/facebookresearch/functorch/issues/87
TODO:
* [x] Add comments
* [x] Add test
* [x] Fix XLA
<details>
<summary>Generated python_return_types.cpp</summary>
```cpp
#include <Python.h>
#include <vector>
#include <map>
#include <string>
#include "torch/csrc/autograd/python_return_types.h"
#include "torch/csrc/utils/structseq.h"
#include "torch/csrc/Exceptions.h"
namespace {
PyTypeObject* get__det_lu_based_helper_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"det", ""}, {"lu", ""}, {"pivs", ""}, {nullptr} };
static PyTypeObject _det_lu_based_helperNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._det_lu_based_helper", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&_det_lu_based_helperNamedTuple, &desc);
_det_lu_based_helperNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_det_lu_based_helperNamedTuple;
}
PyTypeObject* get__fake_quantize_per_tensor_affine_cachemask_tensor_qparams_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"output", ""}, {"mask", ""}, {nullptr} };
static PyTypeObject _fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._fake_quantize_per_tensor_affine_cachemask_tensor_qparams", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple, &desc);
_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple;
}
PyTypeObject* get__fused_moving_avg_obs_fq_helper_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"output", ""}, {"mask", ""}, {nullptr} };
static PyTypeObject _fused_moving_avg_obs_fq_helperNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._fused_moving_avg_obs_fq_helper", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_fused_moving_avg_obs_fq_helperNamedTuple, &desc);
_fused_moving_avg_obs_fq_helperNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_fused_moving_avg_obs_fq_helperNamedTuple;
}
PyTypeObject* get__lu_with_info_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"LU", ""}, {"pivots", ""}, {"info", ""}, {nullptr} };
static PyTypeObject _lu_with_infoNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._lu_with_info", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&_lu_with_infoNamedTuple, &desc);
_lu_with_infoNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_lu_with_infoNamedTuple;
}
PyTypeObject* get__unpack_dual_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"primal", ""}, {"tangent", ""}, {nullptr} };
static PyTypeObject _unpack_dualNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._unpack_dual", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_unpack_dualNamedTuple, &desc);
_unpack_dualNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_unpack_dualNamedTuple;
}
PyTypeObject* get_aminmax_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"min", ""}, {"max", ""}, {nullptr} };
static PyTypeObject aminmaxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.aminmax", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&aminmaxNamedTuple, &desc);
aminmaxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &aminmaxNamedTuple;
}
PyTypeObject* get_aminmax_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"min", ""}, {"max", ""}, {nullptr} };
static PyTypeObject aminmax_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.aminmax_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&aminmax_outNamedTuple1, &desc);
aminmax_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &aminmax_outNamedTuple1;
}
PyTypeObject* get_cummax_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummaxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummax", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummaxNamedTuple, &desc);
cummaxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummaxNamedTuple;
}
PyTypeObject* get_cummax_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummax_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummax_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummax_outNamedTuple1, &desc);
cummax_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummax_outNamedTuple1;
}
PyTypeObject* get_cummin_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cumminNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummin", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cumminNamedTuple, &desc);
cumminNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cumminNamedTuple;
}
PyTypeObject* get_cummin_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummin_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummin_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummin_outNamedTuple1, &desc);
cummin_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummin_outNamedTuple1;
}
PyTypeObject* get_eig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject eig_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.eig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&eig_outNamedTuple, &desc);
eig_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &eig_outNamedTuple;
}
PyTypeObject* get_eig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject eigNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.eig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&eigNamedTuple1, &desc);
eigNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &eigNamedTuple1;
}
PyTypeObject* get_frexp_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"mantissa", ""}, {"exponent", ""}, {nullptr} };
static PyTypeObject frexpNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.frexp", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&frexpNamedTuple, &desc);
frexpNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &frexpNamedTuple;
}
PyTypeObject* get_frexp_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"mantissa", ""}, {"exponent", ""}, {nullptr} };
static PyTypeObject frexp_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.frexp_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&frexp_outNamedTuple1, &desc);
frexp_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &frexp_outNamedTuple1;
}
PyTypeObject* get_geqrf_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"a", ""}, {"tau", ""}, {nullptr} };
static PyTypeObject geqrf_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.geqrf_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&geqrf_outNamedTuple, &desc);
geqrf_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &geqrf_outNamedTuple;
}
PyTypeObject* get_geqrf_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"a", ""}, {"tau", ""}, {nullptr} };
static PyTypeObject geqrfNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.geqrf", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&geqrfNamedTuple1, &desc);
geqrfNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &geqrfNamedTuple1;
}
PyTypeObject* get_histogram_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"hist", ""}, {"bin_edges", ""}, {nullptr} };
static PyTypeObject histogram_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.histogram_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&histogram_outNamedTuple, &desc);
histogram_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &histogram_outNamedTuple;
}
PyTypeObject* get_histogram_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"hist", ""}, {"bin_edges", ""}, {nullptr} };
static PyTypeObject histogramNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.histogram", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&histogramNamedTuple1, &desc);
histogramNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &histogramNamedTuple1;
}
PyTypeObject* get_kthvalue_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject kthvalueNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.kthvalue", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&kthvalueNamedTuple, &desc);
kthvalueNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &kthvalueNamedTuple;
}
PyTypeObject* get_kthvalue_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject kthvalue_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.kthvalue_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&kthvalue_outNamedTuple1, &desc);
kthvalue_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &kthvalue_outNamedTuple1;
}
PyTypeObject* get_linalg_cholesky_ex_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"L", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_cholesky_exNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_cholesky_ex", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_cholesky_exNamedTuple, &desc);
linalg_cholesky_exNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_cholesky_exNamedTuple;
}
PyTypeObject* get_linalg_cholesky_ex_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"L", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_cholesky_ex_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_cholesky_ex_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_cholesky_ex_outNamedTuple1, &desc);
linalg_cholesky_ex_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_cholesky_ex_outNamedTuple1;
}
PyTypeObject* get_linalg_eig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eigNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eigNamedTuple, &desc);
linalg_eigNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eigNamedTuple;
}
PyTypeObject* get_linalg_eig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eig_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eig_outNamedTuple1, &desc);
linalg_eig_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eig_outNamedTuple1;
}
PyTypeObject* get_linalg_eigh_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eighNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eigh", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eighNamedTuple, &desc);
linalg_eighNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eighNamedTuple;
}
PyTypeObject* get_linalg_eigh_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eigh_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eigh_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eigh_outNamedTuple1, &desc);
linalg_eigh_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eigh_outNamedTuple1;
}
PyTypeObject* get_linalg_inv_ex_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"inverse", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_inv_exNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_inv_ex", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_inv_exNamedTuple, &desc);
linalg_inv_exNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_inv_exNamedTuple;
}
PyTypeObject* get_linalg_inv_ex_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"inverse", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_inv_ex_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_inv_ex_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_inv_ex_outNamedTuple1, &desc);
linalg_inv_ex_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_inv_ex_outNamedTuple1;
}
PyTypeObject* get_linalg_lstsq_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"residuals", ""}, {"rank", ""}, {"singular_values", ""}, {nullptr} };
static PyTypeObject linalg_lstsqNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_lstsq", nullptr, NamedTuple_fields, 4 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_lstsqNamedTuple, &desc);
linalg_lstsqNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_lstsqNamedTuple;
}
PyTypeObject* get_linalg_lstsq_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"residuals", ""}, {"rank", ""}, {"singular_values", ""}, {nullptr} };
static PyTypeObject linalg_lstsq_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_lstsq_out", nullptr, NamedTuple_fields, 4 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_lstsq_outNamedTuple1, &desc);
linalg_lstsq_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_lstsq_outNamedTuple1;
}
PyTypeObject* get_linalg_qr_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject linalg_qrNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_qr", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_qrNamedTuple, &desc);
linalg_qrNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_qrNamedTuple;
}
PyTypeObject* get_linalg_qr_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject linalg_qr_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_qr_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_qr_outNamedTuple1, &desc);
linalg_qr_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_qr_outNamedTuple1;
}
PyTypeObject* get_linalg_slogdet_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject linalg_slogdetNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_slogdet", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_slogdetNamedTuple, &desc);
linalg_slogdetNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_slogdetNamedTuple;
}
PyTypeObject* get_linalg_slogdet_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject linalg_slogdet_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_slogdet_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_slogdet_outNamedTuple1, &desc);
linalg_slogdet_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_slogdet_outNamedTuple1;
}
PyTypeObject* get_linalg_svd_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"Vh", ""}, {nullptr} };
static PyTypeObject linalg_svd_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_svd_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_svd_outNamedTuple, &desc);
linalg_svd_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_svd_outNamedTuple;
}
PyTypeObject* get_linalg_svd_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"Vh", ""}, {nullptr} };
static PyTypeObject linalg_svdNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_svd", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_svdNamedTuple1, &desc);
linalg_svdNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_svdNamedTuple1;
}
PyTypeObject* get_lstsq_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"QR", ""}, {nullptr} };
static PyTypeObject lstsq_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lstsq_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&lstsq_outNamedTuple, &desc);
lstsq_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lstsq_outNamedTuple;
}
PyTypeObject* get_lstsq_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"QR", ""}, {nullptr} };
static PyTypeObject lstsqNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lstsq", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&lstsqNamedTuple1, &desc);
lstsqNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lstsqNamedTuple1;
}
PyTypeObject* get_lu_unpack_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"P", ""}, {"L", ""}, {"U", ""}, {nullptr} };
static PyTypeObject lu_unpackNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lu_unpack", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&lu_unpackNamedTuple, &desc);
lu_unpackNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lu_unpackNamedTuple;
}
PyTypeObject* get_lu_unpack_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"P", ""}, {"L", ""}, {"U", ""}, {nullptr} };
static PyTypeObject lu_unpack_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lu_unpack_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&lu_unpack_outNamedTuple1, &desc);
lu_unpack_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lu_unpack_outNamedTuple1;
}
PyTypeObject* get_max_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject maxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.max", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&maxNamedTuple, &desc);
maxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &maxNamedTuple;
}
PyTypeObject* get_max_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject max_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.max_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&max_outNamedTuple1, &desc);
max_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &max_outNamedTuple1;
}
PyTypeObject* get_median_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject medianNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.median", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&medianNamedTuple, &desc);
medianNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &medianNamedTuple;
}
PyTypeObject* get_median_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject median_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.median_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&median_outNamedTuple1, &desc);
median_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &median_outNamedTuple1;
}
PyTypeObject* get_min_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject minNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.min", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&minNamedTuple, &desc);
minNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &minNamedTuple;
}
PyTypeObject* get_min_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject min_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.min_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&min_outNamedTuple1, &desc);
min_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &min_outNamedTuple1;
}
PyTypeObject* get_mode_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject modeNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.mode", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&modeNamedTuple, &desc);
modeNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &modeNamedTuple;
}
PyTypeObject* get_mode_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject mode_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.mode_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&mode_outNamedTuple1, &desc);
mode_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &mode_outNamedTuple1;
}
PyTypeObject* get_nanmedian_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject nanmedianNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.nanmedian", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&nanmedianNamedTuple, &desc);
nanmedianNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &nanmedianNamedTuple;
}
PyTypeObject* get_nanmedian_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject nanmedian_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.nanmedian_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&nanmedian_outNamedTuple1, &desc);
nanmedian_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &nanmedian_outNamedTuple1;
}
PyTypeObject* get_qr_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject qr_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.qr_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&qr_outNamedTuple, &desc);
qr_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &qr_outNamedTuple;
}
PyTypeObject* get_qr_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject qrNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.qr", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&qrNamedTuple1, &desc);
qrNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &qrNamedTuple1;
}
PyTypeObject* get_slogdet_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject slogdetNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.slogdet", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&slogdetNamedTuple, &desc);
slogdetNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &slogdetNamedTuple;
}
PyTypeObject* get_solve_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"LU", ""}, {nullptr} };
static PyTypeObject solveNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.solve", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&solveNamedTuple, &desc);
solveNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &solveNamedTuple;
}
PyTypeObject* get_solve_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"LU", ""}, {nullptr} };
static PyTypeObject solve_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.solve_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&solve_outNamedTuple1, &desc);
solve_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &solve_outNamedTuple1;
}
PyTypeObject* get_sort_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject sort_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.sort_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&sort_outNamedTuple, &desc);
sort_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &sort_outNamedTuple;
}
PyTypeObject* get_sort_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject sortNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.sort", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&sortNamedTuple1, &desc);
sortNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &sortNamedTuple1;
}
PyTypeObject* get_svd_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"V", ""}, {nullptr} };
static PyTypeObject svd_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.svd_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&svd_outNamedTuple, &desc);
svd_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &svd_outNamedTuple;
}
PyTypeObject* get_svd_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"V", ""}, {nullptr} };
static PyTypeObject svdNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.svd", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&svdNamedTuple1, &desc);
svdNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &svdNamedTuple1;
}
PyTypeObject* get_symeig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject symeig_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.symeig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&symeig_outNamedTuple, &desc);
symeig_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &symeig_outNamedTuple;
}
PyTypeObject* get_symeig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject symeigNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.symeig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&symeigNamedTuple1, &desc);
symeigNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &symeigNamedTuple1;
}
PyTypeObject* get_topk_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject topk_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.topk_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&topk_outNamedTuple, &desc);
topk_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &topk_outNamedTuple;
}
PyTypeObject* get_topk_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject topkNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.topk", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&topkNamedTuple1, &desc);
topkNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &topkNamedTuple1;
}
PyTypeObject* get_triangular_solve_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"cloned_coefficient", ""}, {nullptr} };
static PyTypeObject triangular_solve_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.triangular_solve_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&triangular_solve_outNamedTuple, &desc);
triangular_solve_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &triangular_solve_outNamedTuple;
}
PyTypeObject* get_triangular_solve_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"cloned_coefficient", ""}, {nullptr} };
static PyTypeObject triangular_solveNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.triangular_solve", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&triangular_solveNamedTuple1, &desc);
triangular_solveNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &triangular_solveNamedTuple1;
}
}
namespace torch {
namespace autograd {
std::map<std::string, PyTypeObject*>& get_namedtuple_types_map() {
// [NOTE] Non-global map
// This map calls Python functions during its initialization.
// If it is a global static variable and in case it is loaded
// before Python interpreter is ready, then the calls it makes during
// initialization will SEGFAULT.
// To avoid this we make it function static variable so that it is
// initialized only after the Python interpreter is ready.
static std::map<std::string, PyTypeObject*> namedtuple_types_map = {
{"_det_lu_based_helper", get__det_lu_based_helper_namedtuple()},
{"_fake_quantize_per_tensor_affine_cachemask_tensor_qparams", get__fake_quantize_per_tensor_affine_cachemask_tensor_qparams_namedtuple()},
{"_fused_moving_avg_obs_fq_helper", get__fused_moving_avg_obs_fq_helper_namedtuple()},
{"_lu_with_info", get__lu_with_info_namedtuple()},
{"_unpack_dual", get__unpack_dual_namedtuple()},
{"aminmax", get_aminmax_namedtuple()},
{"aminmax_out", get_aminmax_out_namedtuple()},
{"cummax", get_cummax_namedtuple()},
{"cummax_out", get_cummax_out_namedtuple()},
{"cummin", get_cummin_namedtuple()},
{"cummin_out", get_cummin_out_namedtuple()},
{"eig_out", get_eig_out_namedtuple()},
{"eig", get_eig_namedtuple()},
{"frexp", get_frexp_namedtuple()},
{"frexp_out", get_frexp_out_namedtuple()},
{"geqrf_out", get_geqrf_out_namedtuple()},
{"geqrf", get_geqrf_namedtuple()},
{"histogram_out", get_histogram_out_namedtuple()},
{"histogram", get_histogram_namedtuple()},
{"kthvalue", get_kthvalue_namedtuple()},
{"kthvalue_out", get_kthvalue_out_namedtuple()},
{"linalg_cholesky_ex", get_linalg_cholesky_ex_namedtuple()},
{"linalg_cholesky_ex_out", get_linalg_cholesky_ex_out_namedtuple()},
{"linalg_eig", get_linalg_eig_namedtuple()},
{"linalg_eig_out", get_linalg_eig_out_namedtuple()},
{"linalg_eigh", get_linalg_eigh_namedtuple()},
{"linalg_eigh_out", get_linalg_eigh_out_namedtuple()},
{"linalg_inv_ex", get_linalg_inv_ex_namedtuple()},
{"linalg_inv_ex_out", get_linalg_inv_ex_out_namedtuple()},
{"linalg_lstsq", get_linalg_lstsq_namedtuple()},
{"linalg_lstsq_out", get_linalg_lstsq_out_namedtuple()},
{"linalg_qr", get_linalg_qr_namedtuple()},
{"linalg_qr_out", get_linalg_qr_out_namedtuple()},
{"linalg_slogdet", get_linalg_slogdet_namedtuple()},
{"linalg_slogdet_out", get_linalg_slogdet_out_namedtuple()},
{"linalg_svd_out", get_linalg_svd_out_namedtuple()},
{"linalg_svd", get_linalg_svd_namedtuple()},
{"lstsq_out", get_lstsq_out_namedtuple()},
{"lstsq", get_lstsq_namedtuple()},
{"lu_unpack", get_lu_unpack_namedtuple()},
{"lu_unpack_out", get_lu_unpack_out_namedtuple()},
{"max", get_max_namedtuple()},
{"max_out", get_max_out_namedtuple()},
{"median", get_median_namedtuple()},
{"median_out", get_median_out_namedtuple()},
{"min", get_min_namedtuple()},
{"min_out", get_min_out_namedtuple()},
{"mode", get_mode_namedtuple()},
{"mode_out", get_mode_out_namedtuple()},
{"nanmedian", get_nanmedian_namedtuple()},
{"nanmedian_out", get_nanmedian_out_namedtuple()},
{"qr_out", get_qr_out_namedtuple()},
{"qr", get_qr_namedtuple()},
{"slogdet", get_slogdet_namedtuple()},
{"solve", get_solve_namedtuple()},
{"solve_out", get_solve_out_namedtuple()},
{"sort_out", get_sort_out_namedtuple()},
{"sort", get_sort_namedtuple()},
{"svd_out", get_svd_out_namedtuple()},
{"svd", get_svd_namedtuple()},
{"symeig_out", get_symeig_out_namedtuple()},
{"symeig", get_symeig_namedtuple()},
{"topk_out", get_topk_out_namedtuple()},
{"topk", get_topk_namedtuple()},
{"triangular_solve_out", get_triangular_solve_out_namedtuple()},
{"triangular_solve", get_triangular_solve_namedtuple()},
};
return namedtuple_types_map;
}
PyTypeObject* get_namedtuple(std::string name) {
static auto& namedtuple_types_map = get_namedtuple_types_map();
return namedtuple_types_map[name];
}
void initReturnTypes(PyObject* module) {
static struct PyModuleDef def = {
PyModuleDef_HEAD_INIT, "torch._C._return_types", nullptr, -1, {}};
PyObject* return_types_module = PyModule_Create(&def);
if (!return_types_module) {
throw python_error();
}
for (const auto& return_type_pair : get_namedtuple_types_map()) {
// hold onto the TypeObject for the unlikely case of user
// deleting or overriding it.
Py_INCREF(return_type_pair.second);
if (PyModule_AddObject(
return_types_module,
return_type_pair.first.c_str(),
(PyObject*)return_type_pair.second) != 0) {
Py_DECREF((PyObject*)return_type_pair.second);
throw python_error();
}
}
// steals a reference to return_types on success
if (PyModule_AddObject(module, "_return_types", return_types_module) != 0) {
Py_DECREF(return_types_module);
throw python_error();
}
}
} // namespace autograd
} // namespace torch
```
</details>
<details>
<summary>Eg. updated call in other python_*_functions</summary>
```cpp
// linalg_cholesky_ex
static PyObject * THPVariable_linalg_cholesky_ex(PyObject* self_, PyObject* args, PyObject* kwargs)
{
HANDLE_TH_ERRORS
static PyTypeObject* NamedTuple = get_namedtuple("linalg_cholesky_ex");
static PyTypeObject* NamedTuple1 = get_namedtuple("linalg_cholesky_ex_out");
static PythonArgParser parser({
"linalg_cholesky_ex(Tensor input, *, bool upper=False, bool check_errors=False, TensorList[2] out=None)",
}, /*traceable=*/true);
ParsedArgs<4> parsed_args;
auto _r = parser.parse(nullptr, args, kwargs, parsed_args);
if(_r.has_torch_function()) {
return handle_torch_function(_r, nullptr, args, kwargs, THPLinalgVariableFunctionsModule, "torch.linalg");
}
if (_r.isNone(3)) {
// aten::linalg_cholesky_ex(Tensor self, *, bool upper=False, bool check_errors=False) -> (Tensor L, Tensor info)
auto dispatch_linalg_cholesky_ex = [](const at::Tensor & self, bool upper, bool check_errors) -> ::std::tuple<at::Tensor,at::Tensor> {
pybind11::gil_scoped_release no_gil;
return at::linalg_cholesky_ex(self, upper, check_errors);
};
return wrap(NamedTuple, dispatch_linalg_cholesky_ex(_r.tensor(0), _r.toBool(1), _r.toBool(2)));
} else {
// aten::linalg_cholesky_ex.L(Tensor self, *, bool upper=False, bool check_errors=False, Tensor(a!) L, Tensor(b!) info) -> (Tensor(a!) L, Tensor(b!) info)
auto out = _r.tensorlist_n<2>(3);
auto dispatch_linalg_cholesky_ex_out = [](at::Tensor & L, at::Tensor & info, const at::Tensor & self, bool upper, bool check_errors) -> ::std::tuple<at::Tensor,at::Tensor> {
pybind11::gil_scoped_release no_gil;
return at::linalg_cholesky_ex_out(L, info, self, upper, check_errors);
};
return wrap(NamedTuple1, dispatch_linalg_cholesky_ex_out(out[0], out[1], _r.tensor(0), _r.toBool(1), _r.toBool(2)));
}
Py_RETURN_NONE;
END_HANDLE_TH_ERRORS
}
```
</details>
Pull Request resolved: https://github.com/pytorch/pytorch/pull/66614
Reviewed By: H-Huang
Differential Revision: D32741134
Pulled By: zou3519
fbshipit-source-id: 27bada30d20e66333ca1be1775608d9f0cbf9f59
2021-12-06 17:03:11 +00:00
|
|
|
definitions: List[str] = [] # function defintion to register the typedef
|
2022-04-20 12:51:02 +00:00
|
|
|
map_entries: List[
|
|
|
|
|
str
|
|
|
|
|
] = [] # C++ map entry of <function_name, function creates it namedtuple>
|
expose return_types in Python (#66614)
Summary:
https://github.com/facebookresearch/functorch/issues/87
TODO:
* [x] Add comments
* [x] Add test
* [x] Fix XLA
<details>
<summary>Generated python_return_types.cpp</summary>
```cpp
#include <Python.h>
#include <vector>
#include <map>
#include <string>
#include "torch/csrc/autograd/python_return_types.h"
#include "torch/csrc/utils/structseq.h"
#include "torch/csrc/Exceptions.h"
namespace {
PyTypeObject* get__det_lu_based_helper_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"det", ""}, {"lu", ""}, {"pivs", ""}, {nullptr} };
static PyTypeObject _det_lu_based_helperNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._det_lu_based_helper", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&_det_lu_based_helperNamedTuple, &desc);
_det_lu_based_helperNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_det_lu_based_helperNamedTuple;
}
PyTypeObject* get__fake_quantize_per_tensor_affine_cachemask_tensor_qparams_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"output", ""}, {"mask", ""}, {nullptr} };
static PyTypeObject _fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._fake_quantize_per_tensor_affine_cachemask_tensor_qparams", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple, &desc);
_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple;
}
PyTypeObject* get__fused_moving_avg_obs_fq_helper_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"output", ""}, {"mask", ""}, {nullptr} };
static PyTypeObject _fused_moving_avg_obs_fq_helperNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._fused_moving_avg_obs_fq_helper", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_fused_moving_avg_obs_fq_helperNamedTuple, &desc);
_fused_moving_avg_obs_fq_helperNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_fused_moving_avg_obs_fq_helperNamedTuple;
}
PyTypeObject* get__lu_with_info_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"LU", ""}, {"pivots", ""}, {"info", ""}, {nullptr} };
static PyTypeObject _lu_with_infoNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._lu_with_info", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&_lu_with_infoNamedTuple, &desc);
_lu_with_infoNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_lu_with_infoNamedTuple;
}
PyTypeObject* get__unpack_dual_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"primal", ""}, {"tangent", ""}, {nullptr} };
static PyTypeObject _unpack_dualNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._unpack_dual", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_unpack_dualNamedTuple, &desc);
_unpack_dualNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_unpack_dualNamedTuple;
}
PyTypeObject* get_aminmax_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"min", ""}, {"max", ""}, {nullptr} };
static PyTypeObject aminmaxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.aminmax", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&aminmaxNamedTuple, &desc);
aminmaxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &aminmaxNamedTuple;
}
PyTypeObject* get_aminmax_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"min", ""}, {"max", ""}, {nullptr} };
static PyTypeObject aminmax_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.aminmax_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&aminmax_outNamedTuple1, &desc);
aminmax_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &aminmax_outNamedTuple1;
}
PyTypeObject* get_cummax_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummaxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummax", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummaxNamedTuple, &desc);
cummaxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummaxNamedTuple;
}
PyTypeObject* get_cummax_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummax_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummax_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummax_outNamedTuple1, &desc);
cummax_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummax_outNamedTuple1;
}
PyTypeObject* get_cummin_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cumminNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummin", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cumminNamedTuple, &desc);
cumminNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cumminNamedTuple;
}
PyTypeObject* get_cummin_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummin_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummin_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummin_outNamedTuple1, &desc);
cummin_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummin_outNamedTuple1;
}
PyTypeObject* get_eig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject eig_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.eig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&eig_outNamedTuple, &desc);
eig_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &eig_outNamedTuple;
}
PyTypeObject* get_eig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject eigNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.eig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&eigNamedTuple1, &desc);
eigNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &eigNamedTuple1;
}
PyTypeObject* get_frexp_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"mantissa", ""}, {"exponent", ""}, {nullptr} };
static PyTypeObject frexpNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.frexp", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&frexpNamedTuple, &desc);
frexpNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &frexpNamedTuple;
}
PyTypeObject* get_frexp_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"mantissa", ""}, {"exponent", ""}, {nullptr} };
static PyTypeObject frexp_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.frexp_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&frexp_outNamedTuple1, &desc);
frexp_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &frexp_outNamedTuple1;
}
PyTypeObject* get_geqrf_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"a", ""}, {"tau", ""}, {nullptr} };
static PyTypeObject geqrf_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.geqrf_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&geqrf_outNamedTuple, &desc);
geqrf_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &geqrf_outNamedTuple;
}
PyTypeObject* get_geqrf_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"a", ""}, {"tau", ""}, {nullptr} };
static PyTypeObject geqrfNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.geqrf", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&geqrfNamedTuple1, &desc);
geqrfNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &geqrfNamedTuple1;
}
PyTypeObject* get_histogram_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"hist", ""}, {"bin_edges", ""}, {nullptr} };
static PyTypeObject histogram_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.histogram_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&histogram_outNamedTuple, &desc);
histogram_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &histogram_outNamedTuple;
}
PyTypeObject* get_histogram_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"hist", ""}, {"bin_edges", ""}, {nullptr} };
static PyTypeObject histogramNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.histogram", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&histogramNamedTuple1, &desc);
histogramNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &histogramNamedTuple1;
}
PyTypeObject* get_kthvalue_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject kthvalueNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.kthvalue", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&kthvalueNamedTuple, &desc);
kthvalueNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &kthvalueNamedTuple;
}
PyTypeObject* get_kthvalue_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject kthvalue_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.kthvalue_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&kthvalue_outNamedTuple1, &desc);
kthvalue_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &kthvalue_outNamedTuple1;
}
PyTypeObject* get_linalg_cholesky_ex_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"L", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_cholesky_exNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_cholesky_ex", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_cholesky_exNamedTuple, &desc);
linalg_cholesky_exNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_cholesky_exNamedTuple;
}
PyTypeObject* get_linalg_cholesky_ex_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"L", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_cholesky_ex_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_cholesky_ex_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_cholesky_ex_outNamedTuple1, &desc);
linalg_cholesky_ex_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_cholesky_ex_outNamedTuple1;
}
PyTypeObject* get_linalg_eig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eigNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eigNamedTuple, &desc);
linalg_eigNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eigNamedTuple;
}
PyTypeObject* get_linalg_eig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eig_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eig_outNamedTuple1, &desc);
linalg_eig_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eig_outNamedTuple1;
}
PyTypeObject* get_linalg_eigh_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eighNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eigh", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eighNamedTuple, &desc);
linalg_eighNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eighNamedTuple;
}
PyTypeObject* get_linalg_eigh_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eigh_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eigh_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eigh_outNamedTuple1, &desc);
linalg_eigh_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eigh_outNamedTuple1;
}
PyTypeObject* get_linalg_inv_ex_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"inverse", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_inv_exNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_inv_ex", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_inv_exNamedTuple, &desc);
linalg_inv_exNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_inv_exNamedTuple;
}
PyTypeObject* get_linalg_inv_ex_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"inverse", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_inv_ex_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_inv_ex_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_inv_ex_outNamedTuple1, &desc);
linalg_inv_ex_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_inv_ex_outNamedTuple1;
}
PyTypeObject* get_linalg_lstsq_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"residuals", ""}, {"rank", ""}, {"singular_values", ""}, {nullptr} };
static PyTypeObject linalg_lstsqNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_lstsq", nullptr, NamedTuple_fields, 4 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_lstsqNamedTuple, &desc);
linalg_lstsqNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_lstsqNamedTuple;
}
PyTypeObject* get_linalg_lstsq_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"residuals", ""}, {"rank", ""}, {"singular_values", ""}, {nullptr} };
static PyTypeObject linalg_lstsq_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_lstsq_out", nullptr, NamedTuple_fields, 4 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_lstsq_outNamedTuple1, &desc);
linalg_lstsq_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_lstsq_outNamedTuple1;
}
PyTypeObject* get_linalg_qr_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject linalg_qrNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_qr", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_qrNamedTuple, &desc);
linalg_qrNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_qrNamedTuple;
}
PyTypeObject* get_linalg_qr_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject linalg_qr_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_qr_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_qr_outNamedTuple1, &desc);
linalg_qr_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_qr_outNamedTuple1;
}
PyTypeObject* get_linalg_slogdet_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject linalg_slogdetNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_slogdet", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_slogdetNamedTuple, &desc);
linalg_slogdetNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_slogdetNamedTuple;
}
PyTypeObject* get_linalg_slogdet_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject linalg_slogdet_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_slogdet_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_slogdet_outNamedTuple1, &desc);
linalg_slogdet_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_slogdet_outNamedTuple1;
}
PyTypeObject* get_linalg_svd_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"Vh", ""}, {nullptr} };
static PyTypeObject linalg_svd_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_svd_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_svd_outNamedTuple, &desc);
linalg_svd_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_svd_outNamedTuple;
}
PyTypeObject* get_linalg_svd_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"Vh", ""}, {nullptr} };
static PyTypeObject linalg_svdNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_svd", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_svdNamedTuple1, &desc);
linalg_svdNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_svdNamedTuple1;
}
PyTypeObject* get_lstsq_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"QR", ""}, {nullptr} };
static PyTypeObject lstsq_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lstsq_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&lstsq_outNamedTuple, &desc);
lstsq_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lstsq_outNamedTuple;
}
PyTypeObject* get_lstsq_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"QR", ""}, {nullptr} };
static PyTypeObject lstsqNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lstsq", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&lstsqNamedTuple1, &desc);
lstsqNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lstsqNamedTuple1;
}
PyTypeObject* get_lu_unpack_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"P", ""}, {"L", ""}, {"U", ""}, {nullptr} };
static PyTypeObject lu_unpackNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lu_unpack", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&lu_unpackNamedTuple, &desc);
lu_unpackNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lu_unpackNamedTuple;
}
PyTypeObject* get_lu_unpack_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"P", ""}, {"L", ""}, {"U", ""}, {nullptr} };
static PyTypeObject lu_unpack_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lu_unpack_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&lu_unpack_outNamedTuple1, &desc);
lu_unpack_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lu_unpack_outNamedTuple1;
}
PyTypeObject* get_max_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject maxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.max", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&maxNamedTuple, &desc);
maxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &maxNamedTuple;
}
PyTypeObject* get_max_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject max_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.max_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&max_outNamedTuple1, &desc);
max_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &max_outNamedTuple1;
}
PyTypeObject* get_median_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject medianNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.median", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&medianNamedTuple, &desc);
medianNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &medianNamedTuple;
}
PyTypeObject* get_median_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject median_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.median_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&median_outNamedTuple1, &desc);
median_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &median_outNamedTuple1;
}
PyTypeObject* get_min_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject minNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.min", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&minNamedTuple, &desc);
minNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &minNamedTuple;
}
PyTypeObject* get_min_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject min_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.min_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&min_outNamedTuple1, &desc);
min_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &min_outNamedTuple1;
}
PyTypeObject* get_mode_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject modeNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.mode", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&modeNamedTuple, &desc);
modeNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &modeNamedTuple;
}
PyTypeObject* get_mode_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject mode_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.mode_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&mode_outNamedTuple1, &desc);
mode_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &mode_outNamedTuple1;
}
PyTypeObject* get_nanmedian_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject nanmedianNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.nanmedian", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&nanmedianNamedTuple, &desc);
nanmedianNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &nanmedianNamedTuple;
}
PyTypeObject* get_nanmedian_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject nanmedian_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.nanmedian_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&nanmedian_outNamedTuple1, &desc);
nanmedian_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &nanmedian_outNamedTuple1;
}
PyTypeObject* get_qr_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject qr_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.qr_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&qr_outNamedTuple, &desc);
qr_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &qr_outNamedTuple;
}
PyTypeObject* get_qr_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject qrNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.qr", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&qrNamedTuple1, &desc);
qrNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &qrNamedTuple1;
}
PyTypeObject* get_slogdet_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject slogdetNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.slogdet", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&slogdetNamedTuple, &desc);
slogdetNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &slogdetNamedTuple;
}
PyTypeObject* get_solve_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"LU", ""}, {nullptr} };
static PyTypeObject solveNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.solve", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&solveNamedTuple, &desc);
solveNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &solveNamedTuple;
}
PyTypeObject* get_solve_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"LU", ""}, {nullptr} };
static PyTypeObject solve_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.solve_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&solve_outNamedTuple1, &desc);
solve_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &solve_outNamedTuple1;
}
PyTypeObject* get_sort_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject sort_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.sort_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&sort_outNamedTuple, &desc);
sort_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &sort_outNamedTuple;
}
PyTypeObject* get_sort_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject sortNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.sort", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&sortNamedTuple1, &desc);
sortNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &sortNamedTuple1;
}
PyTypeObject* get_svd_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"V", ""}, {nullptr} };
static PyTypeObject svd_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.svd_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&svd_outNamedTuple, &desc);
svd_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &svd_outNamedTuple;
}
PyTypeObject* get_svd_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"V", ""}, {nullptr} };
static PyTypeObject svdNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.svd", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&svdNamedTuple1, &desc);
svdNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &svdNamedTuple1;
}
PyTypeObject* get_symeig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject symeig_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.symeig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&symeig_outNamedTuple, &desc);
symeig_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &symeig_outNamedTuple;
}
PyTypeObject* get_symeig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject symeigNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.symeig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&symeigNamedTuple1, &desc);
symeigNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &symeigNamedTuple1;
}
PyTypeObject* get_topk_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject topk_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.topk_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&topk_outNamedTuple, &desc);
topk_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &topk_outNamedTuple;
}
PyTypeObject* get_topk_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject topkNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.topk", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&topkNamedTuple1, &desc);
topkNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &topkNamedTuple1;
}
PyTypeObject* get_triangular_solve_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"cloned_coefficient", ""}, {nullptr} };
static PyTypeObject triangular_solve_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.triangular_solve_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&triangular_solve_outNamedTuple, &desc);
triangular_solve_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &triangular_solve_outNamedTuple;
}
PyTypeObject* get_triangular_solve_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"cloned_coefficient", ""}, {nullptr} };
static PyTypeObject triangular_solveNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.triangular_solve", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&triangular_solveNamedTuple1, &desc);
triangular_solveNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &triangular_solveNamedTuple1;
}
}
namespace torch {
namespace autograd {
std::map<std::string, PyTypeObject*>& get_namedtuple_types_map() {
// [NOTE] Non-global map
// This map calls Python functions during its initialization.
// If it is a global static variable and in case it is loaded
// before Python interpreter is ready, then the calls it makes during
// initialization will SEGFAULT.
// To avoid this we make it function static variable so that it is
// initialized only after the Python interpreter is ready.
static std::map<std::string, PyTypeObject*> namedtuple_types_map = {
{"_det_lu_based_helper", get__det_lu_based_helper_namedtuple()},
{"_fake_quantize_per_tensor_affine_cachemask_tensor_qparams", get__fake_quantize_per_tensor_affine_cachemask_tensor_qparams_namedtuple()},
{"_fused_moving_avg_obs_fq_helper", get__fused_moving_avg_obs_fq_helper_namedtuple()},
{"_lu_with_info", get__lu_with_info_namedtuple()},
{"_unpack_dual", get__unpack_dual_namedtuple()},
{"aminmax", get_aminmax_namedtuple()},
{"aminmax_out", get_aminmax_out_namedtuple()},
{"cummax", get_cummax_namedtuple()},
{"cummax_out", get_cummax_out_namedtuple()},
{"cummin", get_cummin_namedtuple()},
{"cummin_out", get_cummin_out_namedtuple()},
{"eig_out", get_eig_out_namedtuple()},
{"eig", get_eig_namedtuple()},
{"frexp", get_frexp_namedtuple()},
{"frexp_out", get_frexp_out_namedtuple()},
{"geqrf_out", get_geqrf_out_namedtuple()},
{"geqrf", get_geqrf_namedtuple()},
{"histogram_out", get_histogram_out_namedtuple()},
{"histogram", get_histogram_namedtuple()},
{"kthvalue", get_kthvalue_namedtuple()},
{"kthvalue_out", get_kthvalue_out_namedtuple()},
{"linalg_cholesky_ex", get_linalg_cholesky_ex_namedtuple()},
{"linalg_cholesky_ex_out", get_linalg_cholesky_ex_out_namedtuple()},
{"linalg_eig", get_linalg_eig_namedtuple()},
{"linalg_eig_out", get_linalg_eig_out_namedtuple()},
{"linalg_eigh", get_linalg_eigh_namedtuple()},
{"linalg_eigh_out", get_linalg_eigh_out_namedtuple()},
{"linalg_inv_ex", get_linalg_inv_ex_namedtuple()},
{"linalg_inv_ex_out", get_linalg_inv_ex_out_namedtuple()},
{"linalg_lstsq", get_linalg_lstsq_namedtuple()},
{"linalg_lstsq_out", get_linalg_lstsq_out_namedtuple()},
{"linalg_qr", get_linalg_qr_namedtuple()},
{"linalg_qr_out", get_linalg_qr_out_namedtuple()},
{"linalg_slogdet", get_linalg_slogdet_namedtuple()},
{"linalg_slogdet_out", get_linalg_slogdet_out_namedtuple()},
{"linalg_svd_out", get_linalg_svd_out_namedtuple()},
{"linalg_svd", get_linalg_svd_namedtuple()},
{"lstsq_out", get_lstsq_out_namedtuple()},
{"lstsq", get_lstsq_namedtuple()},
{"lu_unpack", get_lu_unpack_namedtuple()},
{"lu_unpack_out", get_lu_unpack_out_namedtuple()},
{"max", get_max_namedtuple()},
{"max_out", get_max_out_namedtuple()},
{"median", get_median_namedtuple()},
{"median_out", get_median_out_namedtuple()},
{"min", get_min_namedtuple()},
{"min_out", get_min_out_namedtuple()},
{"mode", get_mode_namedtuple()},
{"mode_out", get_mode_out_namedtuple()},
{"nanmedian", get_nanmedian_namedtuple()},
{"nanmedian_out", get_nanmedian_out_namedtuple()},
{"qr_out", get_qr_out_namedtuple()},
{"qr", get_qr_namedtuple()},
{"slogdet", get_slogdet_namedtuple()},
{"solve", get_solve_namedtuple()},
{"solve_out", get_solve_out_namedtuple()},
{"sort_out", get_sort_out_namedtuple()},
{"sort", get_sort_namedtuple()},
{"svd_out", get_svd_out_namedtuple()},
{"svd", get_svd_namedtuple()},
{"symeig_out", get_symeig_out_namedtuple()},
{"symeig", get_symeig_namedtuple()},
{"topk_out", get_topk_out_namedtuple()},
{"topk", get_topk_namedtuple()},
{"triangular_solve_out", get_triangular_solve_out_namedtuple()},
{"triangular_solve", get_triangular_solve_namedtuple()},
};
return namedtuple_types_map;
}
PyTypeObject* get_namedtuple(std::string name) {
static auto& namedtuple_types_map = get_namedtuple_types_map();
return namedtuple_types_map[name];
}
void initReturnTypes(PyObject* module) {
static struct PyModuleDef def = {
PyModuleDef_HEAD_INIT, "torch._C._return_types", nullptr, -1, {}};
PyObject* return_types_module = PyModule_Create(&def);
if (!return_types_module) {
throw python_error();
}
for (const auto& return_type_pair : get_namedtuple_types_map()) {
// hold onto the TypeObject for the unlikely case of user
// deleting or overriding it.
Py_INCREF(return_type_pair.second);
if (PyModule_AddObject(
return_types_module,
return_type_pair.first.c_str(),
(PyObject*)return_type_pair.second) != 0) {
Py_DECREF((PyObject*)return_type_pair.second);
throw python_error();
}
}
// steals a reference to return_types on success
if (PyModule_AddObject(module, "_return_types", return_types_module) != 0) {
Py_DECREF(return_types_module);
throw python_error();
}
}
} // namespace autograd
} // namespace torch
```
</details>
<details>
<summary>Eg. updated call in other python_*_functions</summary>
```cpp
// linalg_cholesky_ex
static PyObject * THPVariable_linalg_cholesky_ex(PyObject* self_, PyObject* args, PyObject* kwargs)
{
HANDLE_TH_ERRORS
static PyTypeObject* NamedTuple = get_namedtuple("linalg_cholesky_ex");
static PyTypeObject* NamedTuple1 = get_namedtuple("linalg_cholesky_ex_out");
static PythonArgParser parser({
"linalg_cholesky_ex(Tensor input, *, bool upper=False, bool check_errors=False, TensorList[2] out=None)",
}, /*traceable=*/true);
ParsedArgs<4> parsed_args;
auto _r = parser.parse(nullptr, args, kwargs, parsed_args);
if(_r.has_torch_function()) {
return handle_torch_function(_r, nullptr, args, kwargs, THPLinalgVariableFunctionsModule, "torch.linalg");
}
if (_r.isNone(3)) {
// aten::linalg_cholesky_ex(Tensor self, *, bool upper=False, bool check_errors=False) -> (Tensor L, Tensor info)
auto dispatch_linalg_cholesky_ex = [](const at::Tensor & self, bool upper, bool check_errors) -> ::std::tuple<at::Tensor,at::Tensor> {
pybind11::gil_scoped_release no_gil;
return at::linalg_cholesky_ex(self, upper, check_errors);
};
return wrap(NamedTuple, dispatch_linalg_cholesky_ex(_r.tensor(0), _r.toBool(1), _r.toBool(2)));
} else {
// aten::linalg_cholesky_ex.L(Tensor self, *, bool upper=False, bool check_errors=False, Tensor(a!) L, Tensor(b!) info) -> (Tensor(a!) L, Tensor(b!) info)
auto out = _r.tensorlist_n<2>(3);
auto dispatch_linalg_cholesky_ex_out = [](at::Tensor & L, at::Tensor & info, const at::Tensor & self, bool upper, bool check_errors) -> ::std::tuple<at::Tensor,at::Tensor> {
pybind11::gil_scoped_release no_gil;
return at::linalg_cholesky_ex_out(L, info, self, upper, check_errors);
};
return wrap(NamedTuple1, dispatch_linalg_cholesky_ex_out(out[0], out[1], _r.tensor(0), _r.toBool(1), _r.toBool(2)));
}
Py_RETURN_NONE;
END_HANDLE_TH_ERRORS
}
```
</details>
Pull Request resolved: https://github.com/pytorch/pytorch/pull/66614
Reviewed By: H-Huang
Differential Revision: D32741134
Pulled By: zou3519
fbshipit-source-id: 27bada30d20e66333ca1be1775608d9f0cbf9f59
2021-12-06 17:03:11 +00:00
|
|
|
|
|
|
|
|
for overload in overloads:
|
|
|
|
|
fieldnames = namedtuple_fieldnames(overload.function.func.returns)
|
|
|
|
|
if not fieldnames:
|
|
|
|
|
continue
|
|
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
fields = ", ".join(f'{{"{fn}", ""}}' for fn in fieldnames)
|
expose return_types in Python (#66614)
Summary:
https://github.com/facebookresearch/functorch/issues/87
TODO:
* [x] Add comments
* [x] Add test
* [x] Fix XLA
<details>
<summary>Generated python_return_types.cpp</summary>
```cpp
#include <Python.h>
#include <vector>
#include <map>
#include <string>
#include "torch/csrc/autograd/python_return_types.h"
#include "torch/csrc/utils/structseq.h"
#include "torch/csrc/Exceptions.h"
namespace {
PyTypeObject* get__det_lu_based_helper_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"det", ""}, {"lu", ""}, {"pivs", ""}, {nullptr} };
static PyTypeObject _det_lu_based_helperNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._det_lu_based_helper", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&_det_lu_based_helperNamedTuple, &desc);
_det_lu_based_helperNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_det_lu_based_helperNamedTuple;
}
PyTypeObject* get__fake_quantize_per_tensor_affine_cachemask_tensor_qparams_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"output", ""}, {"mask", ""}, {nullptr} };
static PyTypeObject _fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._fake_quantize_per_tensor_affine_cachemask_tensor_qparams", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple, &desc);
_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple;
}
PyTypeObject* get__fused_moving_avg_obs_fq_helper_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"output", ""}, {"mask", ""}, {nullptr} };
static PyTypeObject _fused_moving_avg_obs_fq_helperNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._fused_moving_avg_obs_fq_helper", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_fused_moving_avg_obs_fq_helperNamedTuple, &desc);
_fused_moving_avg_obs_fq_helperNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_fused_moving_avg_obs_fq_helperNamedTuple;
}
PyTypeObject* get__lu_with_info_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"LU", ""}, {"pivots", ""}, {"info", ""}, {nullptr} };
static PyTypeObject _lu_with_infoNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._lu_with_info", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&_lu_with_infoNamedTuple, &desc);
_lu_with_infoNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_lu_with_infoNamedTuple;
}
PyTypeObject* get__unpack_dual_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"primal", ""}, {"tangent", ""}, {nullptr} };
static PyTypeObject _unpack_dualNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._unpack_dual", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_unpack_dualNamedTuple, &desc);
_unpack_dualNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_unpack_dualNamedTuple;
}
PyTypeObject* get_aminmax_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"min", ""}, {"max", ""}, {nullptr} };
static PyTypeObject aminmaxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.aminmax", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&aminmaxNamedTuple, &desc);
aminmaxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &aminmaxNamedTuple;
}
PyTypeObject* get_aminmax_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"min", ""}, {"max", ""}, {nullptr} };
static PyTypeObject aminmax_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.aminmax_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&aminmax_outNamedTuple1, &desc);
aminmax_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &aminmax_outNamedTuple1;
}
PyTypeObject* get_cummax_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummaxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummax", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummaxNamedTuple, &desc);
cummaxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummaxNamedTuple;
}
PyTypeObject* get_cummax_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummax_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummax_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummax_outNamedTuple1, &desc);
cummax_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummax_outNamedTuple1;
}
PyTypeObject* get_cummin_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cumminNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummin", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cumminNamedTuple, &desc);
cumminNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cumminNamedTuple;
}
PyTypeObject* get_cummin_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummin_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummin_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummin_outNamedTuple1, &desc);
cummin_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummin_outNamedTuple1;
}
PyTypeObject* get_eig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject eig_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.eig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&eig_outNamedTuple, &desc);
eig_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &eig_outNamedTuple;
}
PyTypeObject* get_eig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject eigNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.eig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&eigNamedTuple1, &desc);
eigNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &eigNamedTuple1;
}
PyTypeObject* get_frexp_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"mantissa", ""}, {"exponent", ""}, {nullptr} };
static PyTypeObject frexpNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.frexp", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&frexpNamedTuple, &desc);
frexpNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &frexpNamedTuple;
}
PyTypeObject* get_frexp_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"mantissa", ""}, {"exponent", ""}, {nullptr} };
static PyTypeObject frexp_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.frexp_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&frexp_outNamedTuple1, &desc);
frexp_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &frexp_outNamedTuple1;
}
PyTypeObject* get_geqrf_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"a", ""}, {"tau", ""}, {nullptr} };
static PyTypeObject geqrf_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.geqrf_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&geqrf_outNamedTuple, &desc);
geqrf_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &geqrf_outNamedTuple;
}
PyTypeObject* get_geqrf_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"a", ""}, {"tau", ""}, {nullptr} };
static PyTypeObject geqrfNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.geqrf", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&geqrfNamedTuple1, &desc);
geqrfNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &geqrfNamedTuple1;
}
PyTypeObject* get_histogram_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"hist", ""}, {"bin_edges", ""}, {nullptr} };
static PyTypeObject histogram_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.histogram_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&histogram_outNamedTuple, &desc);
histogram_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &histogram_outNamedTuple;
}
PyTypeObject* get_histogram_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"hist", ""}, {"bin_edges", ""}, {nullptr} };
static PyTypeObject histogramNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.histogram", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&histogramNamedTuple1, &desc);
histogramNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &histogramNamedTuple1;
}
PyTypeObject* get_kthvalue_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject kthvalueNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.kthvalue", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&kthvalueNamedTuple, &desc);
kthvalueNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &kthvalueNamedTuple;
}
PyTypeObject* get_kthvalue_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject kthvalue_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.kthvalue_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&kthvalue_outNamedTuple1, &desc);
kthvalue_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &kthvalue_outNamedTuple1;
}
PyTypeObject* get_linalg_cholesky_ex_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"L", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_cholesky_exNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_cholesky_ex", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_cholesky_exNamedTuple, &desc);
linalg_cholesky_exNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_cholesky_exNamedTuple;
}
PyTypeObject* get_linalg_cholesky_ex_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"L", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_cholesky_ex_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_cholesky_ex_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_cholesky_ex_outNamedTuple1, &desc);
linalg_cholesky_ex_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_cholesky_ex_outNamedTuple1;
}
PyTypeObject* get_linalg_eig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eigNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eigNamedTuple, &desc);
linalg_eigNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eigNamedTuple;
}
PyTypeObject* get_linalg_eig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eig_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eig_outNamedTuple1, &desc);
linalg_eig_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eig_outNamedTuple1;
}
PyTypeObject* get_linalg_eigh_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eighNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eigh", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eighNamedTuple, &desc);
linalg_eighNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eighNamedTuple;
}
PyTypeObject* get_linalg_eigh_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eigh_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eigh_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eigh_outNamedTuple1, &desc);
linalg_eigh_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eigh_outNamedTuple1;
}
PyTypeObject* get_linalg_inv_ex_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"inverse", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_inv_exNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_inv_ex", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_inv_exNamedTuple, &desc);
linalg_inv_exNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_inv_exNamedTuple;
}
PyTypeObject* get_linalg_inv_ex_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"inverse", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_inv_ex_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_inv_ex_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_inv_ex_outNamedTuple1, &desc);
linalg_inv_ex_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_inv_ex_outNamedTuple1;
}
PyTypeObject* get_linalg_lstsq_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"residuals", ""}, {"rank", ""}, {"singular_values", ""}, {nullptr} };
static PyTypeObject linalg_lstsqNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_lstsq", nullptr, NamedTuple_fields, 4 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_lstsqNamedTuple, &desc);
linalg_lstsqNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_lstsqNamedTuple;
}
PyTypeObject* get_linalg_lstsq_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"residuals", ""}, {"rank", ""}, {"singular_values", ""}, {nullptr} };
static PyTypeObject linalg_lstsq_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_lstsq_out", nullptr, NamedTuple_fields, 4 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_lstsq_outNamedTuple1, &desc);
linalg_lstsq_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_lstsq_outNamedTuple1;
}
PyTypeObject* get_linalg_qr_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject linalg_qrNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_qr", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_qrNamedTuple, &desc);
linalg_qrNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_qrNamedTuple;
}
PyTypeObject* get_linalg_qr_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject linalg_qr_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_qr_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_qr_outNamedTuple1, &desc);
linalg_qr_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_qr_outNamedTuple1;
}
PyTypeObject* get_linalg_slogdet_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject linalg_slogdetNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_slogdet", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_slogdetNamedTuple, &desc);
linalg_slogdetNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_slogdetNamedTuple;
}
PyTypeObject* get_linalg_slogdet_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject linalg_slogdet_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_slogdet_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_slogdet_outNamedTuple1, &desc);
linalg_slogdet_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_slogdet_outNamedTuple1;
}
PyTypeObject* get_linalg_svd_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"Vh", ""}, {nullptr} };
static PyTypeObject linalg_svd_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_svd_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_svd_outNamedTuple, &desc);
linalg_svd_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_svd_outNamedTuple;
}
PyTypeObject* get_linalg_svd_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"Vh", ""}, {nullptr} };
static PyTypeObject linalg_svdNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_svd", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_svdNamedTuple1, &desc);
linalg_svdNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_svdNamedTuple1;
}
PyTypeObject* get_lstsq_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"QR", ""}, {nullptr} };
static PyTypeObject lstsq_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lstsq_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&lstsq_outNamedTuple, &desc);
lstsq_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lstsq_outNamedTuple;
}
PyTypeObject* get_lstsq_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"QR", ""}, {nullptr} };
static PyTypeObject lstsqNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lstsq", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&lstsqNamedTuple1, &desc);
lstsqNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lstsqNamedTuple1;
}
PyTypeObject* get_lu_unpack_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"P", ""}, {"L", ""}, {"U", ""}, {nullptr} };
static PyTypeObject lu_unpackNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lu_unpack", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&lu_unpackNamedTuple, &desc);
lu_unpackNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lu_unpackNamedTuple;
}
PyTypeObject* get_lu_unpack_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"P", ""}, {"L", ""}, {"U", ""}, {nullptr} };
static PyTypeObject lu_unpack_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lu_unpack_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&lu_unpack_outNamedTuple1, &desc);
lu_unpack_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lu_unpack_outNamedTuple1;
}
PyTypeObject* get_max_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject maxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.max", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&maxNamedTuple, &desc);
maxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &maxNamedTuple;
}
PyTypeObject* get_max_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject max_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.max_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&max_outNamedTuple1, &desc);
max_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &max_outNamedTuple1;
}
PyTypeObject* get_median_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject medianNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.median", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&medianNamedTuple, &desc);
medianNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &medianNamedTuple;
}
PyTypeObject* get_median_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject median_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.median_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&median_outNamedTuple1, &desc);
median_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &median_outNamedTuple1;
}
PyTypeObject* get_min_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject minNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.min", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&minNamedTuple, &desc);
minNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &minNamedTuple;
}
PyTypeObject* get_min_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject min_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.min_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&min_outNamedTuple1, &desc);
min_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &min_outNamedTuple1;
}
PyTypeObject* get_mode_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject modeNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.mode", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&modeNamedTuple, &desc);
modeNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &modeNamedTuple;
}
PyTypeObject* get_mode_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject mode_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.mode_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&mode_outNamedTuple1, &desc);
mode_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &mode_outNamedTuple1;
}
PyTypeObject* get_nanmedian_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject nanmedianNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.nanmedian", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&nanmedianNamedTuple, &desc);
nanmedianNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &nanmedianNamedTuple;
}
PyTypeObject* get_nanmedian_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject nanmedian_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.nanmedian_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&nanmedian_outNamedTuple1, &desc);
nanmedian_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &nanmedian_outNamedTuple1;
}
PyTypeObject* get_qr_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject qr_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.qr_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&qr_outNamedTuple, &desc);
qr_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &qr_outNamedTuple;
}
PyTypeObject* get_qr_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject qrNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.qr", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&qrNamedTuple1, &desc);
qrNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &qrNamedTuple1;
}
PyTypeObject* get_slogdet_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject slogdetNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.slogdet", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&slogdetNamedTuple, &desc);
slogdetNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &slogdetNamedTuple;
}
PyTypeObject* get_solve_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"LU", ""}, {nullptr} };
static PyTypeObject solveNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.solve", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&solveNamedTuple, &desc);
solveNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &solveNamedTuple;
}
PyTypeObject* get_solve_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"LU", ""}, {nullptr} };
static PyTypeObject solve_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.solve_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&solve_outNamedTuple1, &desc);
solve_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &solve_outNamedTuple1;
}
PyTypeObject* get_sort_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject sort_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.sort_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&sort_outNamedTuple, &desc);
sort_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &sort_outNamedTuple;
}
PyTypeObject* get_sort_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject sortNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.sort", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&sortNamedTuple1, &desc);
sortNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &sortNamedTuple1;
}
PyTypeObject* get_svd_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"V", ""}, {nullptr} };
static PyTypeObject svd_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.svd_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&svd_outNamedTuple, &desc);
svd_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &svd_outNamedTuple;
}
PyTypeObject* get_svd_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"V", ""}, {nullptr} };
static PyTypeObject svdNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.svd", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&svdNamedTuple1, &desc);
svdNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &svdNamedTuple1;
}
PyTypeObject* get_symeig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject symeig_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.symeig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&symeig_outNamedTuple, &desc);
symeig_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &symeig_outNamedTuple;
}
PyTypeObject* get_symeig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject symeigNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.symeig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&symeigNamedTuple1, &desc);
symeigNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &symeigNamedTuple1;
}
PyTypeObject* get_topk_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject topk_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.topk_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&topk_outNamedTuple, &desc);
topk_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &topk_outNamedTuple;
}
PyTypeObject* get_topk_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject topkNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.topk", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&topkNamedTuple1, &desc);
topkNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &topkNamedTuple1;
}
PyTypeObject* get_triangular_solve_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"cloned_coefficient", ""}, {nullptr} };
static PyTypeObject triangular_solve_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.triangular_solve_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&triangular_solve_outNamedTuple, &desc);
triangular_solve_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &triangular_solve_outNamedTuple;
}
PyTypeObject* get_triangular_solve_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"cloned_coefficient", ""}, {nullptr} };
static PyTypeObject triangular_solveNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.triangular_solve", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&triangular_solveNamedTuple1, &desc);
triangular_solveNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &triangular_solveNamedTuple1;
}
}
namespace torch {
namespace autograd {
std::map<std::string, PyTypeObject*>& get_namedtuple_types_map() {
// [NOTE] Non-global map
// This map calls Python functions during its initialization.
// If it is a global static variable and in case it is loaded
// before Python interpreter is ready, then the calls it makes during
// initialization will SEGFAULT.
// To avoid this we make it function static variable so that it is
// initialized only after the Python interpreter is ready.
static std::map<std::string, PyTypeObject*> namedtuple_types_map = {
{"_det_lu_based_helper", get__det_lu_based_helper_namedtuple()},
{"_fake_quantize_per_tensor_affine_cachemask_tensor_qparams", get__fake_quantize_per_tensor_affine_cachemask_tensor_qparams_namedtuple()},
{"_fused_moving_avg_obs_fq_helper", get__fused_moving_avg_obs_fq_helper_namedtuple()},
{"_lu_with_info", get__lu_with_info_namedtuple()},
{"_unpack_dual", get__unpack_dual_namedtuple()},
{"aminmax", get_aminmax_namedtuple()},
{"aminmax_out", get_aminmax_out_namedtuple()},
{"cummax", get_cummax_namedtuple()},
{"cummax_out", get_cummax_out_namedtuple()},
{"cummin", get_cummin_namedtuple()},
{"cummin_out", get_cummin_out_namedtuple()},
{"eig_out", get_eig_out_namedtuple()},
{"eig", get_eig_namedtuple()},
{"frexp", get_frexp_namedtuple()},
{"frexp_out", get_frexp_out_namedtuple()},
{"geqrf_out", get_geqrf_out_namedtuple()},
{"geqrf", get_geqrf_namedtuple()},
{"histogram_out", get_histogram_out_namedtuple()},
{"histogram", get_histogram_namedtuple()},
{"kthvalue", get_kthvalue_namedtuple()},
{"kthvalue_out", get_kthvalue_out_namedtuple()},
{"linalg_cholesky_ex", get_linalg_cholesky_ex_namedtuple()},
{"linalg_cholesky_ex_out", get_linalg_cholesky_ex_out_namedtuple()},
{"linalg_eig", get_linalg_eig_namedtuple()},
{"linalg_eig_out", get_linalg_eig_out_namedtuple()},
{"linalg_eigh", get_linalg_eigh_namedtuple()},
{"linalg_eigh_out", get_linalg_eigh_out_namedtuple()},
{"linalg_inv_ex", get_linalg_inv_ex_namedtuple()},
{"linalg_inv_ex_out", get_linalg_inv_ex_out_namedtuple()},
{"linalg_lstsq", get_linalg_lstsq_namedtuple()},
{"linalg_lstsq_out", get_linalg_lstsq_out_namedtuple()},
{"linalg_qr", get_linalg_qr_namedtuple()},
{"linalg_qr_out", get_linalg_qr_out_namedtuple()},
{"linalg_slogdet", get_linalg_slogdet_namedtuple()},
{"linalg_slogdet_out", get_linalg_slogdet_out_namedtuple()},
{"linalg_svd_out", get_linalg_svd_out_namedtuple()},
{"linalg_svd", get_linalg_svd_namedtuple()},
{"lstsq_out", get_lstsq_out_namedtuple()},
{"lstsq", get_lstsq_namedtuple()},
{"lu_unpack", get_lu_unpack_namedtuple()},
{"lu_unpack_out", get_lu_unpack_out_namedtuple()},
{"max", get_max_namedtuple()},
{"max_out", get_max_out_namedtuple()},
{"median", get_median_namedtuple()},
{"median_out", get_median_out_namedtuple()},
{"min", get_min_namedtuple()},
{"min_out", get_min_out_namedtuple()},
{"mode", get_mode_namedtuple()},
{"mode_out", get_mode_out_namedtuple()},
{"nanmedian", get_nanmedian_namedtuple()},
{"nanmedian_out", get_nanmedian_out_namedtuple()},
{"qr_out", get_qr_out_namedtuple()},
{"qr", get_qr_namedtuple()},
{"slogdet", get_slogdet_namedtuple()},
{"solve", get_solve_namedtuple()},
{"solve_out", get_solve_out_namedtuple()},
{"sort_out", get_sort_out_namedtuple()},
{"sort", get_sort_namedtuple()},
{"svd_out", get_svd_out_namedtuple()},
{"svd", get_svd_namedtuple()},
{"symeig_out", get_symeig_out_namedtuple()},
{"symeig", get_symeig_namedtuple()},
{"topk_out", get_topk_out_namedtuple()},
{"topk", get_topk_namedtuple()},
{"triangular_solve_out", get_triangular_solve_out_namedtuple()},
{"triangular_solve", get_triangular_solve_namedtuple()},
};
return namedtuple_types_map;
}
PyTypeObject* get_namedtuple(std::string name) {
static auto& namedtuple_types_map = get_namedtuple_types_map();
return namedtuple_types_map[name];
}
void initReturnTypes(PyObject* module) {
static struct PyModuleDef def = {
PyModuleDef_HEAD_INIT, "torch._C._return_types", nullptr, -1, {}};
PyObject* return_types_module = PyModule_Create(&def);
if (!return_types_module) {
throw python_error();
}
for (const auto& return_type_pair : get_namedtuple_types_map()) {
// hold onto the TypeObject for the unlikely case of user
// deleting or overriding it.
Py_INCREF(return_type_pair.second);
if (PyModule_AddObject(
return_types_module,
return_type_pair.first.c_str(),
(PyObject*)return_type_pair.second) != 0) {
Py_DECREF((PyObject*)return_type_pair.second);
throw python_error();
}
}
// steals a reference to return_types on success
if (PyModule_AddObject(module, "_return_types", return_types_module) != 0) {
Py_DECREF(return_types_module);
throw python_error();
}
}
} // namespace autograd
} // namespace torch
```
</details>
<details>
<summary>Eg. updated call in other python_*_functions</summary>
```cpp
// linalg_cholesky_ex
static PyObject * THPVariable_linalg_cholesky_ex(PyObject* self_, PyObject* args, PyObject* kwargs)
{
HANDLE_TH_ERRORS
static PyTypeObject* NamedTuple = get_namedtuple("linalg_cholesky_ex");
static PyTypeObject* NamedTuple1 = get_namedtuple("linalg_cholesky_ex_out");
static PythonArgParser parser({
"linalg_cholesky_ex(Tensor input, *, bool upper=False, bool check_errors=False, TensorList[2] out=None)",
}, /*traceable=*/true);
ParsedArgs<4> parsed_args;
auto _r = parser.parse(nullptr, args, kwargs, parsed_args);
if(_r.has_torch_function()) {
return handle_torch_function(_r, nullptr, args, kwargs, THPLinalgVariableFunctionsModule, "torch.linalg");
}
if (_r.isNone(3)) {
// aten::linalg_cholesky_ex(Tensor self, *, bool upper=False, bool check_errors=False) -> (Tensor L, Tensor info)
auto dispatch_linalg_cholesky_ex = [](const at::Tensor & self, bool upper, bool check_errors) -> ::std::tuple<at::Tensor,at::Tensor> {
pybind11::gil_scoped_release no_gil;
return at::linalg_cholesky_ex(self, upper, check_errors);
};
return wrap(NamedTuple, dispatch_linalg_cholesky_ex(_r.tensor(0), _r.toBool(1), _r.toBool(2)));
} else {
// aten::linalg_cholesky_ex.L(Tensor self, *, bool upper=False, bool check_errors=False, Tensor(a!) L, Tensor(b!) info) -> (Tensor(a!) L, Tensor(b!) info)
auto out = _r.tensorlist_n<2>(3);
auto dispatch_linalg_cholesky_ex_out = [](at::Tensor & L, at::Tensor & info, const at::Tensor & self, bool upper, bool check_errors) -> ::std::tuple<at::Tensor,at::Tensor> {
pybind11::gil_scoped_release no_gil;
return at::linalg_cholesky_ex_out(L, info, self, upper, check_errors);
};
return wrap(NamedTuple1, dispatch_linalg_cholesky_ex_out(out[0], out[1], _r.tensor(0), _r.toBool(1), _r.toBool(2)));
}
Py_RETURN_NONE;
END_HANDLE_TH_ERRORS
}
```
</details>
Pull Request resolved: https://github.com/pytorch/pytorch/pull/66614
Reviewed By: H-Huang
Differential Revision: D32741134
Pulled By: zou3519
fbshipit-source-id: 27bada30d20e66333ca1be1775608d9f0cbf9f59
2021-12-06 17:03:11 +00:00
|
|
|
|
|
|
|
|
name = cpp.name(overload.function.func) # use @with_native_function?
|
|
|
|
|
tn_key = gen_namedtuple_typename_key(overload.function)
|
|
|
|
|
typename = typenames.get(tn_key)
|
|
|
|
|
|
|
|
|
|
if typename is None:
|
|
|
|
|
typename = f'{name}NamedTuple{"" if not definitions else len(definitions)}'
|
|
|
|
|
typenames[tn_key] = typename
|
2022-04-20 12:51:02 +00:00
|
|
|
definitions.append(
|
|
|
|
|
f"""\
|
expose return_types in Python (#66614)
Summary:
https://github.com/facebookresearch/functorch/issues/87
TODO:
* [x] Add comments
* [x] Add test
* [x] Fix XLA
<details>
<summary>Generated python_return_types.cpp</summary>
```cpp
#include <Python.h>
#include <vector>
#include <map>
#include <string>
#include "torch/csrc/autograd/python_return_types.h"
#include "torch/csrc/utils/structseq.h"
#include "torch/csrc/Exceptions.h"
namespace {
PyTypeObject* get__det_lu_based_helper_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"det", ""}, {"lu", ""}, {"pivs", ""}, {nullptr} };
static PyTypeObject _det_lu_based_helperNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._det_lu_based_helper", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&_det_lu_based_helperNamedTuple, &desc);
_det_lu_based_helperNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_det_lu_based_helperNamedTuple;
}
PyTypeObject* get__fake_quantize_per_tensor_affine_cachemask_tensor_qparams_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"output", ""}, {"mask", ""}, {nullptr} };
static PyTypeObject _fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._fake_quantize_per_tensor_affine_cachemask_tensor_qparams", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple, &desc);
_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple;
}
PyTypeObject* get__fused_moving_avg_obs_fq_helper_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"output", ""}, {"mask", ""}, {nullptr} };
static PyTypeObject _fused_moving_avg_obs_fq_helperNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._fused_moving_avg_obs_fq_helper", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_fused_moving_avg_obs_fq_helperNamedTuple, &desc);
_fused_moving_avg_obs_fq_helperNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_fused_moving_avg_obs_fq_helperNamedTuple;
}
PyTypeObject* get__lu_with_info_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"LU", ""}, {"pivots", ""}, {"info", ""}, {nullptr} };
static PyTypeObject _lu_with_infoNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._lu_with_info", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&_lu_with_infoNamedTuple, &desc);
_lu_with_infoNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_lu_with_infoNamedTuple;
}
PyTypeObject* get__unpack_dual_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"primal", ""}, {"tangent", ""}, {nullptr} };
static PyTypeObject _unpack_dualNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._unpack_dual", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_unpack_dualNamedTuple, &desc);
_unpack_dualNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_unpack_dualNamedTuple;
}
PyTypeObject* get_aminmax_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"min", ""}, {"max", ""}, {nullptr} };
static PyTypeObject aminmaxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.aminmax", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&aminmaxNamedTuple, &desc);
aminmaxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &aminmaxNamedTuple;
}
PyTypeObject* get_aminmax_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"min", ""}, {"max", ""}, {nullptr} };
static PyTypeObject aminmax_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.aminmax_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&aminmax_outNamedTuple1, &desc);
aminmax_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &aminmax_outNamedTuple1;
}
PyTypeObject* get_cummax_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummaxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummax", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummaxNamedTuple, &desc);
cummaxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummaxNamedTuple;
}
PyTypeObject* get_cummax_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummax_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummax_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummax_outNamedTuple1, &desc);
cummax_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummax_outNamedTuple1;
}
PyTypeObject* get_cummin_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cumminNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummin", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cumminNamedTuple, &desc);
cumminNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cumminNamedTuple;
}
PyTypeObject* get_cummin_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummin_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummin_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummin_outNamedTuple1, &desc);
cummin_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummin_outNamedTuple1;
}
PyTypeObject* get_eig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject eig_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.eig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&eig_outNamedTuple, &desc);
eig_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &eig_outNamedTuple;
}
PyTypeObject* get_eig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject eigNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.eig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&eigNamedTuple1, &desc);
eigNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &eigNamedTuple1;
}
PyTypeObject* get_frexp_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"mantissa", ""}, {"exponent", ""}, {nullptr} };
static PyTypeObject frexpNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.frexp", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&frexpNamedTuple, &desc);
frexpNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &frexpNamedTuple;
}
PyTypeObject* get_frexp_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"mantissa", ""}, {"exponent", ""}, {nullptr} };
static PyTypeObject frexp_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.frexp_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&frexp_outNamedTuple1, &desc);
frexp_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &frexp_outNamedTuple1;
}
PyTypeObject* get_geqrf_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"a", ""}, {"tau", ""}, {nullptr} };
static PyTypeObject geqrf_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.geqrf_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&geqrf_outNamedTuple, &desc);
geqrf_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &geqrf_outNamedTuple;
}
PyTypeObject* get_geqrf_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"a", ""}, {"tau", ""}, {nullptr} };
static PyTypeObject geqrfNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.geqrf", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&geqrfNamedTuple1, &desc);
geqrfNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &geqrfNamedTuple1;
}
PyTypeObject* get_histogram_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"hist", ""}, {"bin_edges", ""}, {nullptr} };
static PyTypeObject histogram_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.histogram_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&histogram_outNamedTuple, &desc);
histogram_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &histogram_outNamedTuple;
}
PyTypeObject* get_histogram_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"hist", ""}, {"bin_edges", ""}, {nullptr} };
static PyTypeObject histogramNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.histogram", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&histogramNamedTuple1, &desc);
histogramNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &histogramNamedTuple1;
}
PyTypeObject* get_kthvalue_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject kthvalueNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.kthvalue", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&kthvalueNamedTuple, &desc);
kthvalueNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &kthvalueNamedTuple;
}
PyTypeObject* get_kthvalue_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject kthvalue_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.kthvalue_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&kthvalue_outNamedTuple1, &desc);
kthvalue_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &kthvalue_outNamedTuple1;
}
PyTypeObject* get_linalg_cholesky_ex_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"L", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_cholesky_exNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_cholesky_ex", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_cholesky_exNamedTuple, &desc);
linalg_cholesky_exNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_cholesky_exNamedTuple;
}
PyTypeObject* get_linalg_cholesky_ex_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"L", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_cholesky_ex_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_cholesky_ex_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_cholesky_ex_outNamedTuple1, &desc);
linalg_cholesky_ex_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_cholesky_ex_outNamedTuple1;
}
PyTypeObject* get_linalg_eig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eigNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eigNamedTuple, &desc);
linalg_eigNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eigNamedTuple;
}
PyTypeObject* get_linalg_eig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eig_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eig_outNamedTuple1, &desc);
linalg_eig_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eig_outNamedTuple1;
}
PyTypeObject* get_linalg_eigh_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eighNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eigh", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eighNamedTuple, &desc);
linalg_eighNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eighNamedTuple;
}
PyTypeObject* get_linalg_eigh_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eigh_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eigh_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eigh_outNamedTuple1, &desc);
linalg_eigh_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eigh_outNamedTuple1;
}
PyTypeObject* get_linalg_inv_ex_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"inverse", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_inv_exNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_inv_ex", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_inv_exNamedTuple, &desc);
linalg_inv_exNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_inv_exNamedTuple;
}
PyTypeObject* get_linalg_inv_ex_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"inverse", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_inv_ex_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_inv_ex_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_inv_ex_outNamedTuple1, &desc);
linalg_inv_ex_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_inv_ex_outNamedTuple1;
}
PyTypeObject* get_linalg_lstsq_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"residuals", ""}, {"rank", ""}, {"singular_values", ""}, {nullptr} };
static PyTypeObject linalg_lstsqNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_lstsq", nullptr, NamedTuple_fields, 4 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_lstsqNamedTuple, &desc);
linalg_lstsqNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_lstsqNamedTuple;
}
PyTypeObject* get_linalg_lstsq_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"residuals", ""}, {"rank", ""}, {"singular_values", ""}, {nullptr} };
static PyTypeObject linalg_lstsq_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_lstsq_out", nullptr, NamedTuple_fields, 4 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_lstsq_outNamedTuple1, &desc);
linalg_lstsq_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_lstsq_outNamedTuple1;
}
PyTypeObject* get_linalg_qr_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject linalg_qrNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_qr", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_qrNamedTuple, &desc);
linalg_qrNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_qrNamedTuple;
}
PyTypeObject* get_linalg_qr_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject linalg_qr_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_qr_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_qr_outNamedTuple1, &desc);
linalg_qr_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_qr_outNamedTuple1;
}
PyTypeObject* get_linalg_slogdet_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject linalg_slogdetNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_slogdet", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_slogdetNamedTuple, &desc);
linalg_slogdetNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_slogdetNamedTuple;
}
PyTypeObject* get_linalg_slogdet_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject linalg_slogdet_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_slogdet_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_slogdet_outNamedTuple1, &desc);
linalg_slogdet_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_slogdet_outNamedTuple1;
}
PyTypeObject* get_linalg_svd_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"Vh", ""}, {nullptr} };
static PyTypeObject linalg_svd_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_svd_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_svd_outNamedTuple, &desc);
linalg_svd_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_svd_outNamedTuple;
}
PyTypeObject* get_linalg_svd_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"Vh", ""}, {nullptr} };
static PyTypeObject linalg_svdNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_svd", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_svdNamedTuple1, &desc);
linalg_svdNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_svdNamedTuple1;
}
PyTypeObject* get_lstsq_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"QR", ""}, {nullptr} };
static PyTypeObject lstsq_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lstsq_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&lstsq_outNamedTuple, &desc);
lstsq_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lstsq_outNamedTuple;
}
PyTypeObject* get_lstsq_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"QR", ""}, {nullptr} };
static PyTypeObject lstsqNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lstsq", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&lstsqNamedTuple1, &desc);
lstsqNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lstsqNamedTuple1;
}
PyTypeObject* get_lu_unpack_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"P", ""}, {"L", ""}, {"U", ""}, {nullptr} };
static PyTypeObject lu_unpackNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lu_unpack", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&lu_unpackNamedTuple, &desc);
lu_unpackNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lu_unpackNamedTuple;
}
PyTypeObject* get_lu_unpack_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"P", ""}, {"L", ""}, {"U", ""}, {nullptr} };
static PyTypeObject lu_unpack_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lu_unpack_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&lu_unpack_outNamedTuple1, &desc);
lu_unpack_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lu_unpack_outNamedTuple1;
}
PyTypeObject* get_max_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject maxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.max", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&maxNamedTuple, &desc);
maxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &maxNamedTuple;
}
PyTypeObject* get_max_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject max_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.max_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&max_outNamedTuple1, &desc);
max_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &max_outNamedTuple1;
}
PyTypeObject* get_median_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject medianNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.median", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&medianNamedTuple, &desc);
medianNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &medianNamedTuple;
}
PyTypeObject* get_median_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject median_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.median_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&median_outNamedTuple1, &desc);
median_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &median_outNamedTuple1;
}
PyTypeObject* get_min_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject minNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.min", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&minNamedTuple, &desc);
minNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &minNamedTuple;
}
PyTypeObject* get_min_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject min_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.min_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&min_outNamedTuple1, &desc);
min_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &min_outNamedTuple1;
}
PyTypeObject* get_mode_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject modeNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.mode", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&modeNamedTuple, &desc);
modeNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &modeNamedTuple;
}
PyTypeObject* get_mode_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject mode_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.mode_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&mode_outNamedTuple1, &desc);
mode_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &mode_outNamedTuple1;
}
PyTypeObject* get_nanmedian_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject nanmedianNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.nanmedian", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&nanmedianNamedTuple, &desc);
nanmedianNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &nanmedianNamedTuple;
}
PyTypeObject* get_nanmedian_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject nanmedian_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.nanmedian_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&nanmedian_outNamedTuple1, &desc);
nanmedian_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &nanmedian_outNamedTuple1;
}
PyTypeObject* get_qr_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject qr_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.qr_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&qr_outNamedTuple, &desc);
qr_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &qr_outNamedTuple;
}
PyTypeObject* get_qr_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject qrNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.qr", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&qrNamedTuple1, &desc);
qrNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &qrNamedTuple1;
}
PyTypeObject* get_slogdet_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject slogdetNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.slogdet", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&slogdetNamedTuple, &desc);
slogdetNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &slogdetNamedTuple;
}
PyTypeObject* get_solve_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"LU", ""}, {nullptr} };
static PyTypeObject solveNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.solve", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&solveNamedTuple, &desc);
solveNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &solveNamedTuple;
}
PyTypeObject* get_solve_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"LU", ""}, {nullptr} };
static PyTypeObject solve_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.solve_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&solve_outNamedTuple1, &desc);
solve_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &solve_outNamedTuple1;
}
PyTypeObject* get_sort_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject sort_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.sort_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&sort_outNamedTuple, &desc);
sort_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &sort_outNamedTuple;
}
PyTypeObject* get_sort_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject sortNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.sort", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&sortNamedTuple1, &desc);
sortNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &sortNamedTuple1;
}
PyTypeObject* get_svd_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"V", ""}, {nullptr} };
static PyTypeObject svd_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.svd_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&svd_outNamedTuple, &desc);
svd_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &svd_outNamedTuple;
}
PyTypeObject* get_svd_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"V", ""}, {nullptr} };
static PyTypeObject svdNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.svd", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&svdNamedTuple1, &desc);
svdNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &svdNamedTuple1;
}
PyTypeObject* get_symeig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject symeig_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.symeig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&symeig_outNamedTuple, &desc);
symeig_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &symeig_outNamedTuple;
}
PyTypeObject* get_symeig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject symeigNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.symeig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&symeigNamedTuple1, &desc);
symeigNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &symeigNamedTuple1;
}
PyTypeObject* get_topk_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject topk_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.topk_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&topk_outNamedTuple, &desc);
topk_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &topk_outNamedTuple;
}
PyTypeObject* get_topk_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject topkNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.topk", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&topkNamedTuple1, &desc);
topkNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &topkNamedTuple1;
}
PyTypeObject* get_triangular_solve_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"cloned_coefficient", ""}, {nullptr} };
static PyTypeObject triangular_solve_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.triangular_solve_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&triangular_solve_outNamedTuple, &desc);
triangular_solve_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &triangular_solve_outNamedTuple;
}
PyTypeObject* get_triangular_solve_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"cloned_coefficient", ""}, {nullptr} };
static PyTypeObject triangular_solveNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.triangular_solve", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&triangular_solveNamedTuple1, &desc);
triangular_solveNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &triangular_solveNamedTuple1;
}
}
namespace torch {
namespace autograd {
std::map<std::string, PyTypeObject*>& get_namedtuple_types_map() {
// [NOTE] Non-global map
// This map calls Python functions during its initialization.
// If it is a global static variable and in case it is loaded
// before Python interpreter is ready, then the calls it makes during
// initialization will SEGFAULT.
// To avoid this we make it function static variable so that it is
// initialized only after the Python interpreter is ready.
static std::map<std::string, PyTypeObject*> namedtuple_types_map = {
{"_det_lu_based_helper", get__det_lu_based_helper_namedtuple()},
{"_fake_quantize_per_tensor_affine_cachemask_tensor_qparams", get__fake_quantize_per_tensor_affine_cachemask_tensor_qparams_namedtuple()},
{"_fused_moving_avg_obs_fq_helper", get__fused_moving_avg_obs_fq_helper_namedtuple()},
{"_lu_with_info", get__lu_with_info_namedtuple()},
{"_unpack_dual", get__unpack_dual_namedtuple()},
{"aminmax", get_aminmax_namedtuple()},
{"aminmax_out", get_aminmax_out_namedtuple()},
{"cummax", get_cummax_namedtuple()},
{"cummax_out", get_cummax_out_namedtuple()},
{"cummin", get_cummin_namedtuple()},
{"cummin_out", get_cummin_out_namedtuple()},
{"eig_out", get_eig_out_namedtuple()},
{"eig", get_eig_namedtuple()},
{"frexp", get_frexp_namedtuple()},
{"frexp_out", get_frexp_out_namedtuple()},
{"geqrf_out", get_geqrf_out_namedtuple()},
{"geqrf", get_geqrf_namedtuple()},
{"histogram_out", get_histogram_out_namedtuple()},
{"histogram", get_histogram_namedtuple()},
{"kthvalue", get_kthvalue_namedtuple()},
{"kthvalue_out", get_kthvalue_out_namedtuple()},
{"linalg_cholesky_ex", get_linalg_cholesky_ex_namedtuple()},
{"linalg_cholesky_ex_out", get_linalg_cholesky_ex_out_namedtuple()},
{"linalg_eig", get_linalg_eig_namedtuple()},
{"linalg_eig_out", get_linalg_eig_out_namedtuple()},
{"linalg_eigh", get_linalg_eigh_namedtuple()},
{"linalg_eigh_out", get_linalg_eigh_out_namedtuple()},
{"linalg_inv_ex", get_linalg_inv_ex_namedtuple()},
{"linalg_inv_ex_out", get_linalg_inv_ex_out_namedtuple()},
{"linalg_lstsq", get_linalg_lstsq_namedtuple()},
{"linalg_lstsq_out", get_linalg_lstsq_out_namedtuple()},
{"linalg_qr", get_linalg_qr_namedtuple()},
{"linalg_qr_out", get_linalg_qr_out_namedtuple()},
{"linalg_slogdet", get_linalg_slogdet_namedtuple()},
{"linalg_slogdet_out", get_linalg_slogdet_out_namedtuple()},
{"linalg_svd_out", get_linalg_svd_out_namedtuple()},
{"linalg_svd", get_linalg_svd_namedtuple()},
{"lstsq_out", get_lstsq_out_namedtuple()},
{"lstsq", get_lstsq_namedtuple()},
{"lu_unpack", get_lu_unpack_namedtuple()},
{"lu_unpack_out", get_lu_unpack_out_namedtuple()},
{"max", get_max_namedtuple()},
{"max_out", get_max_out_namedtuple()},
{"median", get_median_namedtuple()},
{"median_out", get_median_out_namedtuple()},
{"min", get_min_namedtuple()},
{"min_out", get_min_out_namedtuple()},
{"mode", get_mode_namedtuple()},
{"mode_out", get_mode_out_namedtuple()},
{"nanmedian", get_nanmedian_namedtuple()},
{"nanmedian_out", get_nanmedian_out_namedtuple()},
{"qr_out", get_qr_out_namedtuple()},
{"qr", get_qr_namedtuple()},
{"slogdet", get_slogdet_namedtuple()},
{"solve", get_solve_namedtuple()},
{"solve_out", get_solve_out_namedtuple()},
{"sort_out", get_sort_out_namedtuple()},
{"sort", get_sort_namedtuple()},
{"svd_out", get_svd_out_namedtuple()},
{"svd", get_svd_namedtuple()},
{"symeig_out", get_symeig_out_namedtuple()},
{"symeig", get_symeig_namedtuple()},
{"topk_out", get_topk_out_namedtuple()},
{"topk", get_topk_namedtuple()},
{"triangular_solve_out", get_triangular_solve_out_namedtuple()},
{"triangular_solve", get_triangular_solve_namedtuple()},
};
return namedtuple_types_map;
}
PyTypeObject* get_namedtuple(std::string name) {
static auto& namedtuple_types_map = get_namedtuple_types_map();
return namedtuple_types_map[name];
}
void initReturnTypes(PyObject* module) {
static struct PyModuleDef def = {
PyModuleDef_HEAD_INIT, "torch._C._return_types", nullptr, -1, {}};
PyObject* return_types_module = PyModule_Create(&def);
if (!return_types_module) {
throw python_error();
}
for (const auto& return_type_pair : get_namedtuple_types_map()) {
// hold onto the TypeObject for the unlikely case of user
// deleting or overriding it.
Py_INCREF(return_type_pair.second);
if (PyModule_AddObject(
return_types_module,
return_type_pair.first.c_str(),
(PyObject*)return_type_pair.second) != 0) {
Py_DECREF((PyObject*)return_type_pair.second);
throw python_error();
}
}
// steals a reference to return_types on success
if (PyModule_AddObject(module, "_return_types", return_types_module) != 0) {
Py_DECREF(return_types_module);
throw python_error();
}
}
} // namespace autograd
} // namespace torch
```
</details>
<details>
<summary>Eg. updated call in other python_*_functions</summary>
```cpp
// linalg_cholesky_ex
static PyObject * THPVariable_linalg_cholesky_ex(PyObject* self_, PyObject* args, PyObject* kwargs)
{
HANDLE_TH_ERRORS
static PyTypeObject* NamedTuple = get_namedtuple("linalg_cholesky_ex");
static PyTypeObject* NamedTuple1 = get_namedtuple("linalg_cholesky_ex_out");
static PythonArgParser parser({
"linalg_cholesky_ex(Tensor input, *, bool upper=False, bool check_errors=False, TensorList[2] out=None)",
}, /*traceable=*/true);
ParsedArgs<4> parsed_args;
auto _r = parser.parse(nullptr, args, kwargs, parsed_args);
if(_r.has_torch_function()) {
return handle_torch_function(_r, nullptr, args, kwargs, THPLinalgVariableFunctionsModule, "torch.linalg");
}
if (_r.isNone(3)) {
// aten::linalg_cholesky_ex(Tensor self, *, bool upper=False, bool check_errors=False) -> (Tensor L, Tensor info)
auto dispatch_linalg_cholesky_ex = [](const at::Tensor & self, bool upper, bool check_errors) -> ::std::tuple<at::Tensor,at::Tensor> {
pybind11::gil_scoped_release no_gil;
return at::linalg_cholesky_ex(self, upper, check_errors);
};
return wrap(NamedTuple, dispatch_linalg_cholesky_ex(_r.tensor(0), _r.toBool(1), _r.toBool(2)));
} else {
// aten::linalg_cholesky_ex.L(Tensor self, *, bool upper=False, bool check_errors=False, Tensor(a!) L, Tensor(b!) info) -> (Tensor(a!) L, Tensor(b!) info)
auto out = _r.tensorlist_n<2>(3);
auto dispatch_linalg_cholesky_ex_out = [](at::Tensor & L, at::Tensor & info, const at::Tensor & self, bool upper, bool check_errors) -> ::std::tuple<at::Tensor,at::Tensor> {
pybind11::gil_scoped_release no_gil;
return at::linalg_cholesky_ex_out(L, info, self, upper, check_errors);
};
return wrap(NamedTuple1, dispatch_linalg_cholesky_ex_out(out[0], out[1], _r.tensor(0), _r.toBool(1), _r.toBool(2)));
}
Py_RETURN_NONE;
END_HANDLE_TH_ERRORS
}
```
</details>
Pull Request resolved: https://github.com/pytorch/pytorch/pull/66614
Reviewed By: H-Huang
Differential Revision: D32741134
Pulled By: zou3519
fbshipit-source-id: 27bada30d20e66333ca1be1775608d9f0cbf9f59
2021-12-06 17:03:11 +00:00
|
|
|
PyTypeObject* get_{name}_namedtuple() {{
|
|
|
|
|
static PyStructSequence_Field NamedTuple_fields[] = {{ {fields}, {{nullptr}} }};
|
|
|
|
|
static PyTypeObject {typename};
|
|
|
|
|
static bool is_initialized = false;
|
|
|
|
|
static PyStructSequence_Desc desc = {{ "torch.return_types.{name}", nullptr, NamedTuple_fields, {len(fieldnames)} }};
|
|
|
|
|
if (!is_initialized) {{
|
|
|
|
|
PyStructSequence_InitType(&{typename}, &desc);
|
|
|
|
|
{typename}.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
|
|
|
|
|
is_initialized = true;
|
|
|
|
|
}}
|
|
|
|
|
return &{typename};
|
2020-11-08 09:03:59 +00:00
|
|
|
}}
|
2022-04-20 12:51:02 +00:00
|
|
|
"""
|
|
|
|
|
)
|
expose return_types in Python (#66614)
Summary:
https://github.com/facebookresearch/functorch/issues/87
TODO:
* [x] Add comments
* [x] Add test
* [x] Fix XLA
<details>
<summary>Generated python_return_types.cpp</summary>
```cpp
#include <Python.h>
#include <vector>
#include <map>
#include <string>
#include "torch/csrc/autograd/python_return_types.h"
#include "torch/csrc/utils/structseq.h"
#include "torch/csrc/Exceptions.h"
namespace {
PyTypeObject* get__det_lu_based_helper_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"det", ""}, {"lu", ""}, {"pivs", ""}, {nullptr} };
static PyTypeObject _det_lu_based_helperNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._det_lu_based_helper", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&_det_lu_based_helperNamedTuple, &desc);
_det_lu_based_helperNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_det_lu_based_helperNamedTuple;
}
PyTypeObject* get__fake_quantize_per_tensor_affine_cachemask_tensor_qparams_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"output", ""}, {"mask", ""}, {nullptr} };
static PyTypeObject _fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._fake_quantize_per_tensor_affine_cachemask_tensor_qparams", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple, &desc);
_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple;
}
PyTypeObject* get__fused_moving_avg_obs_fq_helper_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"output", ""}, {"mask", ""}, {nullptr} };
static PyTypeObject _fused_moving_avg_obs_fq_helperNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._fused_moving_avg_obs_fq_helper", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_fused_moving_avg_obs_fq_helperNamedTuple, &desc);
_fused_moving_avg_obs_fq_helperNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_fused_moving_avg_obs_fq_helperNamedTuple;
}
PyTypeObject* get__lu_with_info_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"LU", ""}, {"pivots", ""}, {"info", ""}, {nullptr} };
static PyTypeObject _lu_with_infoNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._lu_with_info", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&_lu_with_infoNamedTuple, &desc);
_lu_with_infoNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_lu_with_infoNamedTuple;
}
PyTypeObject* get__unpack_dual_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"primal", ""}, {"tangent", ""}, {nullptr} };
static PyTypeObject _unpack_dualNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._unpack_dual", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_unpack_dualNamedTuple, &desc);
_unpack_dualNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_unpack_dualNamedTuple;
}
PyTypeObject* get_aminmax_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"min", ""}, {"max", ""}, {nullptr} };
static PyTypeObject aminmaxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.aminmax", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&aminmaxNamedTuple, &desc);
aminmaxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &aminmaxNamedTuple;
}
PyTypeObject* get_aminmax_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"min", ""}, {"max", ""}, {nullptr} };
static PyTypeObject aminmax_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.aminmax_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&aminmax_outNamedTuple1, &desc);
aminmax_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &aminmax_outNamedTuple1;
}
PyTypeObject* get_cummax_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummaxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummax", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummaxNamedTuple, &desc);
cummaxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummaxNamedTuple;
}
PyTypeObject* get_cummax_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummax_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummax_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummax_outNamedTuple1, &desc);
cummax_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummax_outNamedTuple1;
}
PyTypeObject* get_cummin_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cumminNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummin", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cumminNamedTuple, &desc);
cumminNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cumminNamedTuple;
}
PyTypeObject* get_cummin_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummin_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummin_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummin_outNamedTuple1, &desc);
cummin_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummin_outNamedTuple1;
}
PyTypeObject* get_eig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject eig_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.eig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&eig_outNamedTuple, &desc);
eig_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &eig_outNamedTuple;
}
PyTypeObject* get_eig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject eigNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.eig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&eigNamedTuple1, &desc);
eigNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &eigNamedTuple1;
}
PyTypeObject* get_frexp_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"mantissa", ""}, {"exponent", ""}, {nullptr} };
static PyTypeObject frexpNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.frexp", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&frexpNamedTuple, &desc);
frexpNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &frexpNamedTuple;
}
PyTypeObject* get_frexp_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"mantissa", ""}, {"exponent", ""}, {nullptr} };
static PyTypeObject frexp_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.frexp_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&frexp_outNamedTuple1, &desc);
frexp_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &frexp_outNamedTuple1;
}
PyTypeObject* get_geqrf_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"a", ""}, {"tau", ""}, {nullptr} };
static PyTypeObject geqrf_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.geqrf_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&geqrf_outNamedTuple, &desc);
geqrf_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &geqrf_outNamedTuple;
}
PyTypeObject* get_geqrf_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"a", ""}, {"tau", ""}, {nullptr} };
static PyTypeObject geqrfNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.geqrf", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&geqrfNamedTuple1, &desc);
geqrfNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &geqrfNamedTuple1;
}
PyTypeObject* get_histogram_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"hist", ""}, {"bin_edges", ""}, {nullptr} };
static PyTypeObject histogram_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.histogram_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&histogram_outNamedTuple, &desc);
histogram_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &histogram_outNamedTuple;
}
PyTypeObject* get_histogram_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"hist", ""}, {"bin_edges", ""}, {nullptr} };
static PyTypeObject histogramNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.histogram", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&histogramNamedTuple1, &desc);
histogramNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &histogramNamedTuple1;
}
PyTypeObject* get_kthvalue_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject kthvalueNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.kthvalue", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&kthvalueNamedTuple, &desc);
kthvalueNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &kthvalueNamedTuple;
}
PyTypeObject* get_kthvalue_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject kthvalue_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.kthvalue_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&kthvalue_outNamedTuple1, &desc);
kthvalue_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &kthvalue_outNamedTuple1;
}
PyTypeObject* get_linalg_cholesky_ex_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"L", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_cholesky_exNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_cholesky_ex", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_cholesky_exNamedTuple, &desc);
linalg_cholesky_exNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_cholesky_exNamedTuple;
}
PyTypeObject* get_linalg_cholesky_ex_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"L", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_cholesky_ex_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_cholesky_ex_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_cholesky_ex_outNamedTuple1, &desc);
linalg_cholesky_ex_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_cholesky_ex_outNamedTuple1;
}
PyTypeObject* get_linalg_eig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eigNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eigNamedTuple, &desc);
linalg_eigNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eigNamedTuple;
}
PyTypeObject* get_linalg_eig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eig_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eig_outNamedTuple1, &desc);
linalg_eig_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eig_outNamedTuple1;
}
PyTypeObject* get_linalg_eigh_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eighNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eigh", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eighNamedTuple, &desc);
linalg_eighNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eighNamedTuple;
}
PyTypeObject* get_linalg_eigh_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eigh_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eigh_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eigh_outNamedTuple1, &desc);
linalg_eigh_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eigh_outNamedTuple1;
}
PyTypeObject* get_linalg_inv_ex_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"inverse", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_inv_exNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_inv_ex", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_inv_exNamedTuple, &desc);
linalg_inv_exNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_inv_exNamedTuple;
}
PyTypeObject* get_linalg_inv_ex_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"inverse", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_inv_ex_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_inv_ex_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_inv_ex_outNamedTuple1, &desc);
linalg_inv_ex_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_inv_ex_outNamedTuple1;
}
PyTypeObject* get_linalg_lstsq_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"residuals", ""}, {"rank", ""}, {"singular_values", ""}, {nullptr} };
static PyTypeObject linalg_lstsqNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_lstsq", nullptr, NamedTuple_fields, 4 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_lstsqNamedTuple, &desc);
linalg_lstsqNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_lstsqNamedTuple;
}
PyTypeObject* get_linalg_lstsq_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"residuals", ""}, {"rank", ""}, {"singular_values", ""}, {nullptr} };
static PyTypeObject linalg_lstsq_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_lstsq_out", nullptr, NamedTuple_fields, 4 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_lstsq_outNamedTuple1, &desc);
linalg_lstsq_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_lstsq_outNamedTuple1;
}
PyTypeObject* get_linalg_qr_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject linalg_qrNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_qr", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_qrNamedTuple, &desc);
linalg_qrNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_qrNamedTuple;
}
PyTypeObject* get_linalg_qr_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject linalg_qr_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_qr_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_qr_outNamedTuple1, &desc);
linalg_qr_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_qr_outNamedTuple1;
}
PyTypeObject* get_linalg_slogdet_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject linalg_slogdetNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_slogdet", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_slogdetNamedTuple, &desc);
linalg_slogdetNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_slogdetNamedTuple;
}
PyTypeObject* get_linalg_slogdet_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject linalg_slogdet_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_slogdet_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_slogdet_outNamedTuple1, &desc);
linalg_slogdet_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_slogdet_outNamedTuple1;
}
PyTypeObject* get_linalg_svd_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"Vh", ""}, {nullptr} };
static PyTypeObject linalg_svd_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_svd_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_svd_outNamedTuple, &desc);
linalg_svd_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_svd_outNamedTuple;
}
PyTypeObject* get_linalg_svd_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"Vh", ""}, {nullptr} };
static PyTypeObject linalg_svdNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_svd", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_svdNamedTuple1, &desc);
linalg_svdNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_svdNamedTuple1;
}
PyTypeObject* get_lstsq_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"QR", ""}, {nullptr} };
static PyTypeObject lstsq_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lstsq_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&lstsq_outNamedTuple, &desc);
lstsq_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lstsq_outNamedTuple;
}
PyTypeObject* get_lstsq_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"QR", ""}, {nullptr} };
static PyTypeObject lstsqNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lstsq", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&lstsqNamedTuple1, &desc);
lstsqNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lstsqNamedTuple1;
}
PyTypeObject* get_lu_unpack_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"P", ""}, {"L", ""}, {"U", ""}, {nullptr} };
static PyTypeObject lu_unpackNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lu_unpack", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&lu_unpackNamedTuple, &desc);
lu_unpackNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lu_unpackNamedTuple;
}
PyTypeObject* get_lu_unpack_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"P", ""}, {"L", ""}, {"U", ""}, {nullptr} };
static PyTypeObject lu_unpack_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lu_unpack_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&lu_unpack_outNamedTuple1, &desc);
lu_unpack_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lu_unpack_outNamedTuple1;
}
PyTypeObject* get_max_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject maxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.max", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&maxNamedTuple, &desc);
maxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &maxNamedTuple;
}
PyTypeObject* get_max_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject max_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.max_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&max_outNamedTuple1, &desc);
max_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &max_outNamedTuple1;
}
PyTypeObject* get_median_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject medianNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.median", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&medianNamedTuple, &desc);
medianNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &medianNamedTuple;
}
PyTypeObject* get_median_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject median_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.median_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&median_outNamedTuple1, &desc);
median_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &median_outNamedTuple1;
}
PyTypeObject* get_min_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject minNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.min", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&minNamedTuple, &desc);
minNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &minNamedTuple;
}
PyTypeObject* get_min_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject min_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.min_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&min_outNamedTuple1, &desc);
min_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &min_outNamedTuple1;
}
PyTypeObject* get_mode_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject modeNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.mode", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&modeNamedTuple, &desc);
modeNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &modeNamedTuple;
}
PyTypeObject* get_mode_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject mode_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.mode_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&mode_outNamedTuple1, &desc);
mode_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &mode_outNamedTuple1;
}
PyTypeObject* get_nanmedian_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject nanmedianNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.nanmedian", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&nanmedianNamedTuple, &desc);
nanmedianNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &nanmedianNamedTuple;
}
PyTypeObject* get_nanmedian_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject nanmedian_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.nanmedian_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&nanmedian_outNamedTuple1, &desc);
nanmedian_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &nanmedian_outNamedTuple1;
}
PyTypeObject* get_qr_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject qr_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.qr_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&qr_outNamedTuple, &desc);
qr_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &qr_outNamedTuple;
}
PyTypeObject* get_qr_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject qrNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.qr", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&qrNamedTuple1, &desc);
qrNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &qrNamedTuple1;
}
PyTypeObject* get_slogdet_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject slogdetNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.slogdet", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&slogdetNamedTuple, &desc);
slogdetNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &slogdetNamedTuple;
}
PyTypeObject* get_solve_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"LU", ""}, {nullptr} };
static PyTypeObject solveNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.solve", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&solveNamedTuple, &desc);
solveNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &solveNamedTuple;
}
PyTypeObject* get_solve_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"LU", ""}, {nullptr} };
static PyTypeObject solve_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.solve_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&solve_outNamedTuple1, &desc);
solve_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &solve_outNamedTuple1;
}
PyTypeObject* get_sort_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject sort_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.sort_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&sort_outNamedTuple, &desc);
sort_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &sort_outNamedTuple;
}
PyTypeObject* get_sort_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject sortNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.sort", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&sortNamedTuple1, &desc);
sortNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &sortNamedTuple1;
}
PyTypeObject* get_svd_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"V", ""}, {nullptr} };
static PyTypeObject svd_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.svd_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&svd_outNamedTuple, &desc);
svd_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &svd_outNamedTuple;
}
PyTypeObject* get_svd_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"V", ""}, {nullptr} };
static PyTypeObject svdNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.svd", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&svdNamedTuple1, &desc);
svdNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &svdNamedTuple1;
}
PyTypeObject* get_symeig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject symeig_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.symeig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&symeig_outNamedTuple, &desc);
symeig_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &symeig_outNamedTuple;
}
PyTypeObject* get_symeig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject symeigNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.symeig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&symeigNamedTuple1, &desc);
symeigNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &symeigNamedTuple1;
}
PyTypeObject* get_topk_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject topk_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.topk_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&topk_outNamedTuple, &desc);
topk_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &topk_outNamedTuple;
}
PyTypeObject* get_topk_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject topkNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.topk", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&topkNamedTuple1, &desc);
topkNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &topkNamedTuple1;
}
PyTypeObject* get_triangular_solve_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"cloned_coefficient", ""}, {nullptr} };
static PyTypeObject triangular_solve_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.triangular_solve_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&triangular_solve_outNamedTuple, &desc);
triangular_solve_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &triangular_solve_outNamedTuple;
}
PyTypeObject* get_triangular_solve_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"cloned_coefficient", ""}, {nullptr} };
static PyTypeObject triangular_solveNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.triangular_solve", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&triangular_solveNamedTuple1, &desc);
triangular_solveNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &triangular_solveNamedTuple1;
}
}
namespace torch {
namespace autograd {
std::map<std::string, PyTypeObject*>& get_namedtuple_types_map() {
// [NOTE] Non-global map
// This map calls Python functions during its initialization.
// If it is a global static variable and in case it is loaded
// before Python interpreter is ready, then the calls it makes during
// initialization will SEGFAULT.
// To avoid this we make it function static variable so that it is
// initialized only after the Python interpreter is ready.
static std::map<std::string, PyTypeObject*> namedtuple_types_map = {
{"_det_lu_based_helper", get__det_lu_based_helper_namedtuple()},
{"_fake_quantize_per_tensor_affine_cachemask_tensor_qparams", get__fake_quantize_per_tensor_affine_cachemask_tensor_qparams_namedtuple()},
{"_fused_moving_avg_obs_fq_helper", get__fused_moving_avg_obs_fq_helper_namedtuple()},
{"_lu_with_info", get__lu_with_info_namedtuple()},
{"_unpack_dual", get__unpack_dual_namedtuple()},
{"aminmax", get_aminmax_namedtuple()},
{"aminmax_out", get_aminmax_out_namedtuple()},
{"cummax", get_cummax_namedtuple()},
{"cummax_out", get_cummax_out_namedtuple()},
{"cummin", get_cummin_namedtuple()},
{"cummin_out", get_cummin_out_namedtuple()},
{"eig_out", get_eig_out_namedtuple()},
{"eig", get_eig_namedtuple()},
{"frexp", get_frexp_namedtuple()},
{"frexp_out", get_frexp_out_namedtuple()},
{"geqrf_out", get_geqrf_out_namedtuple()},
{"geqrf", get_geqrf_namedtuple()},
{"histogram_out", get_histogram_out_namedtuple()},
{"histogram", get_histogram_namedtuple()},
{"kthvalue", get_kthvalue_namedtuple()},
{"kthvalue_out", get_kthvalue_out_namedtuple()},
{"linalg_cholesky_ex", get_linalg_cholesky_ex_namedtuple()},
{"linalg_cholesky_ex_out", get_linalg_cholesky_ex_out_namedtuple()},
{"linalg_eig", get_linalg_eig_namedtuple()},
{"linalg_eig_out", get_linalg_eig_out_namedtuple()},
{"linalg_eigh", get_linalg_eigh_namedtuple()},
{"linalg_eigh_out", get_linalg_eigh_out_namedtuple()},
{"linalg_inv_ex", get_linalg_inv_ex_namedtuple()},
{"linalg_inv_ex_out", get_linalg_inv_ex_out_namedtuple()},
{"linalg_lstsq", get_linalg_lstsq_namedtuple()},
{"linalg_lstsq_out", get_linalg_lstsq_out_namedtuple()},
{"linalg_qr", get_linalg_qr_namedtuple()},
{"linalg_qr_out", get_linalg_qr_out_namedtuple()},
{"linalg_slogdet", get_linalg_slogdet_namedtuple()},
{"linalg_slogdet_out", get_linalg_slogdet_out_namedtuple()},
{"linalg_svd_out", get_linalg_svd_out_namedtuple()},
{"linalg_svd", get_linalg_svd_namedtuple()},
{"lstsq_out", get_lstsq_out_namedtuple()},
{"lstsq", get_lstsq_namedtuple()},
{"lu_unpack", get_lu_unpack_namedtuple()},
{"lu_unpack_out", get_lu_unpack_out_namedtuple()},
{"max", get_max_namedtuple()},
{"max_out", get_max_out_namedtuple()},
{"median", get_median_namedtuple()},
{"median_out", get_median_out_namedtuple()},
{"min", get_min_namedtuple()},
{"min_out", get_min_out_namedtuple()},
{"mode", get_mode_namedtuple()},
{"mode_out", get_mode_out_namedtuple()},
{"nanmedian", get_nanmedian_namedtuple()},
{"nanmedian_out", get_nanmedian_out_namedtuple()},
{"qr_out", get_qr_out_namedtuple()},
{"qr", get_qr_namedtuple()},
{"slogdet", get_slogdet_namedtuple()},
{"solve", get_solve_namedtuple()},
{"solve_out", get_solve_out_namedtuple()},
{"sort_out", get_sort_out_namedtuple()},
{"sort", get_sort_namedtuple()},
{"svd_out", get_svd_out_namedtuple()},
{"svd", get_svd_namedtuple()},
{"symeig_out", get_symeig_out_namedtuple()},
{"symeig", get_symeig_namedtuple()},
{"topk_out", get_topk_out_namedtuple()},
{"topk", get_topk_namedtuple()},
{"triangular_solve_out", get_triangular_solve_out_namedtuple()},
{"triangular_solve", get_triangular_solve_namedtuple()},
};
return namedtuple_types_map;
}
PyTypeObject* get_namedtuple(std::string name) {
static auto& namedtuple_types_map = get_namedtuple_types_map();
return namedtuple_types_map[name];
}
void initReturnTypes(PyObject* module) {
static struct PyModuleDef def = {
PyModuleDef_HEAD_INIT, "torch._C._return_types", nullptr, -1, {}};
PyObject* return_types_module = PyModule_Create(&def);
if (!return_types_module) {
throw python_error();
}
for (const auto& return_type_pair : get_namedtuple_types_map()) {
// hold onto the TypeObject for the unlikely case of user
// deleting or overriding it.
Py_INCREF(return_type_pair.second);
if (PyModule_AddObject(
return_types_module,
return_type_pair.first.c_str(),
(PyObject*)return_type_pair.second) != 0) {
Py_DECREF((PyObject*)return_type_pair.second);
throw python_error();
}
}
// steals a reference to return_types on success
if (PyModule_AddObject(module, "_return_types", return_types_module) != 0) {
Py_DECREF(return_types_module);
throw python_error();
}
}
} // namespace autograd
} // namespace torch
```
</details>
<details>
<summary>Eg. updated call in other python_*_functions</summary>
```cpp
// linalg_cholesky_ex
static PyObject * THPVariable_linalg_cholesky_ex(PyObject* self_, PyObject* args, PyObject* kwargs)
{
HANDLE_TH_ERRORS
static PyTypeObject* NamedTuple = get_namedtuple("linalg_cholesky_ex");
static PyTypeObject* NamedTuple1 = get_namedtuple("linalg_cholesky_ex_out");
static PythonArgParser parser({
"linalg_cholesky_ex(Tensor input, *, bool upper=False, bool check_errors=False, TensorList[2] out=None)",
}, /*traceable=*/true);
ParsedArgs<4> parsed_args;
auto _r = parser.parse(nullptr, args, kwargs, parsed_args);
if(_r.has_torch_function()) {
return handle_torch_function(_r, nullptr, args, kwargs, THPLinalgVariableFunctionsModule, "torch.linalg");
}
if (_r.isNone(3)) {
// aten::linalg_cholesky_ex(Tensor self, *, bool upper=False, bool check_errors=False) -> (Tensor L, Tensor info)
auto dispatch_linalg_cholesky_ex = [](const at::Tensor & self, bool upper, bool check_errors) -> ::std::tuple<at::Tensor,at::Tensor> {
pybind11::gil_scoped_release no_gil;
return at::linalg_cholesky_ex(self, upper, check_errors);
};
return wrap(NamedTuple, dispatch_linalg_cholesky_ex(_r.tensor(0), _r.toBool(1), _r.toBool(2)));
} else {
// aten::linalg_cholesky_ex.L(Tensor self, *, bool upper=False, bool check_errors=False, Tensor(a!) L, Tensor(b!) info) -> (Tensor(a!) L, Tensor(b!) info)
auto out = _r.tensorlist_n<2>(3);
auto dispatch_linalg_cholesky_ex_out = [](at::Tensor & L, at::Tensor & info, const at::Tensor & self, bool upper, bool check_errors) -> ::std::tuple<at::Tensor,at::Tensor> {
pybind11::gil_scoped_release no_gil;
return at::linalg_cholesky_ex_out(L, info, self, upper, check_errors);
};
return wrap(NamedTuple1, dispatch_linalg_cholesky_ex_out(out[0], out[1], _r.tensor(0), _r.toBool(1), _r.toBool(2)));
}
Py_RETURN_NONE;
END_HANDLE_TH_ERRORS
}
```
</details>
Pull Request resolved: https://github.com/pytorch/pytorch/pull/66614
Reviewed By: H-Huang
Differential Revision: D32741134
Pulled By: zou3519
fbshipit-source-id: 27bada30d20e66333ca1be1775608d9f0cbf9f59
2021-12-06 17:03:11 +00:00
|
|
|
map_entries.append(f'{{"{name}", get_{name}_namedtuple()}}, ')
|
2020-01-30 08:26:16 +00:00
|
|
|
|
expose return_types in Python (#66614)
Summary:
https://github.com/facebookresearch/functorch/issues/87
TODO:
* [x] Add comments
* [x] Add test
* [x] Fix XLA
<details>
<summary>Generated python_return_types.cpp</summary>
```cpp
#include <Python.h>
#include <vector>
#include <map>
#include <string>
#include "torch/csrc/autograd/python_return_types.h"
#include "torch/csrc/utils/structseq.h"
#include "torch/csrc/Exceptions.h"
namespace {
PyTypeObject* get__det_lu_based_helper_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"det", ""}, {"lu", ""}, {"pivs", ""}, {nullptr} };
static PyTypeObject _det_lu_based_helperNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._det_lu_based_helper", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&_det_lu_based_helperNamedTuple, &desc);
_det_lu_based_helperNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_det_lu_based_helperNamedTuple;
}
PyTypeObject* get__fake_quantize_per_tensor_affine_cachemask_tensor_qparams_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"output", ""}, {"mask", ""}, {nullptr} };
static PyTypeObject _fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._fake_quantize_per_tensor_affine_cachemask_tensor_qparams", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple, &desc);
_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple;
}
PyTypeObject* get__fused_moving_avg_obs_fq_helper_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"output", ""}, {"mask", ""}, {nullptr} };
static PyTypeObject _fused_moving_avg_obs_fq_helperNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._fused_moving_avg_obs_fq_helper", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_fused_moving_avg_obs_fq_helperNamedTuple, &desc);
_fused_moving_avg_obs_fq_helperNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_fused_moving_avg_obs_fq_helperNamedTuple;
}
PyTypeObject* get__lu_with_info_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"LU", ""}, {"pivots", ""}, {"info", ""}, {nullptr} };
static PyTypeObject _lu_with_infoNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._lu_with_info", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&_lu_with_infoNamedTuple, &desc);
_lu_with_infoNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_lu_with_infoNamedTuple;
}
PyTypeObject* get__unpack_dual_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"primal", ""}, {"tangent", ""}, {nullptr} };
static PyTypeObject _unpack_dualNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._unpack_dual", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_unpack_dualNamedTuple, &desc);
_unpack_dualNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_unpack_dualNamedTuple;
}
PyTypeObject* get_aminmax_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"min", ""}, {"max", ""}, {nullptr} };
static PyTypeObject aminmaxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.aminmax", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&aminmaxNamedTuple, &desc);
aminmaxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &aminmaxNamedTuple;
}
PyTypeObject* get_aminmax_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"min", ""}, {"max", ""}, {nullptr} };
static PyTypeObject aminmax_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.aminmax_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&aminmax_outNamedTuple1, &desc);
aminmax_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &aminmax_outNamedTuple1;
}
PyTypeObject* get_cummax_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummaxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummax", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummaxNamedTuple, &desc);
cummaxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummaxNamedTuple;
}
PyTypeObject* get_cummax_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummax_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummax_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummax_outNamedTuple1, &desc);
cummax_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummax_outNamedTuple1;
}
PyTypeObject* get_cummin_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cumminNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummin", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cumminNamedTuple, &desc);
cumminNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cumminNamedTuple;
}
PyTypeObject* get_cummin_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummin_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummin_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummin_outNamedTuple1, &desc);
cummin_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummin_outNamedTuple1;
}
PyTypeObject* get_eig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject eig_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.eig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&eig_outNamedTuple, &desc);
eig_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &eig_outNamedTuple;
}
PyTypeObject* get_eig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject eigNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.eig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&eigNamedTuple1, &desc);
eigNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &eigNamedTuple1;
}
PyTypeObject* get_frexp_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"mantissa", ""}, {"exponent", ""}, {nullptr} };
static PyTypeObject frexpNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.frexp", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&frexpNamedTuple, &desc);
frexpNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &frexpNamedTuple;
}
PyTypeObject* get_frexp_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"mantissa", ""}, {"exponent", ""}, {nullptr} };
static PyTypeObject frexp_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.frexp_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&frexp_outNamedTuple1, &desc);
frexp_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &frexp_outNamedTuple1;
}
PyTypeObject* get_geqrf_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"a", ""}, {"tau", ""}, {nullptr} };
static PyTypeObject geqrf_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.geqrf_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&geqrf_outNamedTuple, &desc);
geqrf_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &geqrf_outNamedTuple;
}
PyTypeObject* get_geqrf_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"a", ""}, {"tau", ""}, {nullptr} };
static PyTypeObject geqrfNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.geqrf", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&geqrfNamedTuple1, &desc);
geqrfNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &geqrfNamedTuple1;
}
PyTypeObject* get_histogram_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"hist", ""}, {"bin_edges", ""}, {nullptr} };
static PyTypeObject histogram_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.histogram_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&histogram_outNamedTuple, &desc);
histogram_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &histogram_outNamedTuple;
}
PyTypeObject* get_histogram_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"hist", ""}, {"bin_edges", ""}, {nullptr} };
static PyTypeObject histogramNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.histogram", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&histogramNamedTuple1, &desc);
histogramNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &histogramNamedTuple1;
}
PyTypeObject* get_kthvalue_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject kthvalueNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.kthvalue", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&kthvalueNamedTuple, &desc);
kthvalueNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &kthvalueNamedTuple;
}
PyTypeObject* get_kthvalue_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject kthvalue_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.kthvalue_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&kthvalue_outNamedTuple1, &desc);
kthvalue_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &kthvalue_outNamedTuple1;
}
PyTypeObject* get_linalg_cholesky_ex_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"L", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_cholesky_exNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_cholesky_ex", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_cholesky_exNamedTuple, &desc);
linalg_cholesky_exNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_cholesky_exNamedTuple;
}
PyTypeObject* get_linalg_cholesky_ex_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"L", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_cholesky_ex_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_cholesky_ex_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_cholesky_ex_outNamedTuple1, &desc);
linalg_cholesky_ex_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_cholesky_ex_outNamedTuple1;
}
PyTypeObject* get_linalg_eig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eigNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eigNamedTuple, &desc);
linalg_eigNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eigNamedTuple;
}
PyTypeObject* get_linalg_eig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eig_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eig_outNamedTuple1, &desc);
linalg_eig_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eig_outNamedTuple1;
}
PyTypeObject* get_linalg_eigh_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eighNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eigh", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eighNamedTuple, &desc);
linalg_eighNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eighNamedTuple;
}
PyTypeObject* get_linalg_eigh_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eigh_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eigh_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eigh_outNamedTuple1, &desc);
linalg_eigh_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eigh_outNamedTuple1;
}
PyTypeObject* get_linalg_inv_ex_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"inverse", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_inv_exNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_inv_ex", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_inv_exNamedTuple, &desc);
linalg_inv_exNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_inv_exNamedTuple;
}
PyTypeObject* get_linalg_inv_ex_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"inverse", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_inv_ex_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_inv_ex_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_inv_ex_outNamedTuple1, &desc);
linalg_inv_ex_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_inv_ex_outNamedTuple1;
}
PyTypeObject* get_linalg_lstsq_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"residuals", ""}, {"rank", ""}, {"singular_values", ""}, {nullptr} };
static PyTypeObject linalg_lstsqNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_lstsq", nullptr, NamedTuple_fields, 4 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_lstsqNamedTuple, &desc);
linalg_lstsqNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_lstsqNamedTuple;
}
PyTypeObject* get_linalg_lstsq_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"residuals", ""}, {"rank", ""}, {"singular_values", ""}, {nullptr} };
static PyTypeObject linalg_lstsq_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_lstsq_out", nullptr, NamedTuple_fields, 4 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_lstsq_outNamedTuple1, &desc);
linalg_lstsq_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_lstsq_outNamedTuple1;
}
PyTypeObject* get_linalg_qr_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject linalg_qrNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_qr", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_qrNamedTuple, &desc);
linalg_qrNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_qrNamedTuple;
}
PyTypeObject* get_linalg_qr_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject linalg_qr_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_qr_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_qr_outNamedTuple1, &desc);
linalg_qr_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_qr_outNamedTuple1;
}
PyTypeObject* get_linalg_slogdet_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject linalg_slogdetNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_slogdet", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_slogdetNamedTuple, &desc);
linalg_slogdetNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_slogdetNamedTuple;
}
PyTypeObject* get_linalg_slogdet_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject linalg_slogdet_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_slogdet_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_slogdet_outNamedTuple1, &desc);
linalg_slogdet_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_slogdet_outNamedTuple1;
}
PyTypeObject* get_linalg_svd_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"Vh", ""}, {nullptr} };
static PyTypeObject linalg_svd_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_svd_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_svd_outNamedTuple, &desc);
linalg_svd_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_svd_outNamedTuple;
}
PyTypeObject* get_linalg_svd_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"Vh", ""}, {nullptr} };
static PyTypeObject linalg_svdNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_svd", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_svdNamedTuple1, &desc);
linalg_svdNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_svdNamedTuple1;
}
PyTypeObject* get_lstsq_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"QR", ""}, {nullptr} };
static PyTypeObject lstsq_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lstsq_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&lstsq_outNamedTuple, &desc);
lstsq_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lstsq_outNamedTuple;
}
PyTypeObject* get_lstsq_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"QR", ""}, {nullptr} };
static PyTypeObject lstsqNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lstsq", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&lstsqNamedTuple1, &desc);
lstsqNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lstsqNamedTuple1;
}
PyTypeObject* get_lu_unpack_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"P", ""}, {"L", ""}, {"U", ""}, {nullptr} };
static PyTypeObject lu_unpackNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lu_unpack", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&lu_unpackNamedTuple, &desc);
lu_unpackNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lu_unpackNamedTuple;
}
PyTypeObject* get_lu_unpack_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"P", ""}, {"L", ""}, {"U", ""}, {nullptr} };
static PyTypeObject lu_unpack_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lu_unpack_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&lu_unpack_outNamedTuple1, &desc);
lu_unpack_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lu_unpack_outNamedTuple1;
}
PyTypeObject* get_max_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject maxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.max", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&maxNamedTuple, &desc);
maxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &maxNamedTuple;
}
PyTypeObject* get_max_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject max_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.max_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&max_outNamedTuple1, &desc);
max_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &max_outNamedTuple1;
}
PyTypeObject* get_median_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject medianNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.median", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&medianNamedTuple, &desc);
medianNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &medianNamedTuple;
}
PyTypeObject* get_median_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject median_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.median_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&median_outNamedTuple1, &desc);
median_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &median_outNamedTuple1;
}
PyTypeObject* get_min_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject minNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.min", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&minNamedTuple, &desc);
minNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &minNamedTuple;
}
PyTypeObject* get_min_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject min_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.min_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&min_outNamedTuple1, &desc);
min_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &min_outNamedTuple1;
}
PyTypeObject* get_mode_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject modeNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.mode", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&modeNamedTuple, &desc);
modeNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &modeNamedTuple;
}
PyTypeObject* get_mode_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject mode_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.mode_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&mode_outNamedTuple1, &desc);
mode_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &mode_outNamedTuple1;
}
PyTypeObject* get_nanmedian_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject nanmedianNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.nanmedian", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&nanmedianNamedTuple, &desc);
nanmedianNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &nanmedianNamedTuple;
}
PyTypeObject* get_nanmedian_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject nanmedian_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.nanmedian_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&nanmedian_outNamedTuple1, &desc);
nanmedian_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &nanmedian_outNamedTuple1;
}
PyTypeObject* get_qr_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject qr_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.qr_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&qr_outNamedTuple, &desc);
qr_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &qr_outNamedTuple;
}
PyTypeObject* get_qr_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject qrNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.qr", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&qrNamedTuple1, &desc);
qrNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &qrNamedTuple1;
}
PyTypeObject* get_slogdet_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject slogdetNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.slogdet", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&slogdetNamedTuple, &desc);
slogdetNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &slogdetNamedTuple;
}
PyTypeObject* get_solve_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"LU", ""}, {nullptr} };
static PyTypeObject solveNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.solve", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&solveNamedTuple, &desc);
solveNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &solveNamedTuple;
}
PyTypeObject* get_solve_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"LU", ""}, {nullptr} };
static PyTypeObject solve_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.solve_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&solve_outNamedTuple1, &desc);
solve_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &solve_outNamedTuple1;
}
PyTypeObject* get_sort_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject sort_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.sort_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&sort_outNamedTuple, &desc);
sort_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &sort_outNamedTuple;
}
PyTypeObject* get_sort_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject sortNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.sort", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&sortNamedTuple1, &desc);
sortNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &sortNamedTuple1;
}
PyTypeObject* get_svd_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"V", ""}, {nullptr} };
static PyTypeObject svd_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.svd_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&svd_outNamedTuple, &desc);
svd_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &svd_outNamedTuple;
}
PyTypeObject* get_svd_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"V", ""}, {nullptr} };
static PyTypeObject svdNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.svd", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&svdNamedTuple1, &desc);
svdNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &svdNamedTuple1;
}
PyTypeObject* get_symeig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject symeig_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.symeig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&symeig_outNamedTuple, &desc);
symeig_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &symeig_outNamedTuple;
}
PyTypeObject* get_symeig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject symeigNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.symeig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&symeigNamedTuple1, &desc);
symeigNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &symeigNamedTuple1;
}
PyTypeObject* get_topk_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject topk_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.topk_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&topk_outNamedTuple, &desc);
topk_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &topk_outNamedTuple;
}
PyTypeObject* get_topk_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject topkNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.topk", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&topkNamedTuple1, &desc);
topkNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &topkNamedTuple1;
}
PyTypeObject* get_triangular_solve_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"cloned_coefficient", ""}, {nullptr} };
static PyTypeObject triangular_solve_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.triangular_solve_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&triangular_solve_outNamedTuple, &desc);
triangular_solve_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &triangular_solve_outNamedTuple;
}
PyTypeObject* get_triangular_solve_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"cloned_coefficient", ""}, {nullptr} };
static PyTypeObject triangular_solveNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.triangular_solve", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&triangular_solveNamedTuple1, &desc);
triangular_solveNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &triangular_solveNamedTuple1;
}
}
namespace torch {
namespace autograd {
std::map<std::string, PyTypeObject*>& get_namedtuple_types_map() {
// [NOTE] Non-global map
// This map calls Python functions during its initialization.
// If it is a global static variable and in case it is loaded
// before Python interpreter is ready, then the calls it makes during
// initialization will SEGFAULT.
// To avoid this we make it function static variable so that it is
// initialized only after the Python interpreter is ready.
static std::map<std::string, PyTypeObject*> namedtuple_types_map = {
{"_det_lu_based_helper", get__det_lu_based_helper_namedtuple()},
{"_fake_quantize_per_tensor_affine_cachemask_tensor_qparams", get__fake_quantize_per_tensor_affine_cachemask_tensor_qparams_namedtuple()},
{"_fused_moving_avg_obs_fq_helper", get__fused_moving_avg_obs_fq_helper_namedtuple()},
{"_lu_with_info", get__lu_with_info_namedtuple()},
{"_unpack_dual", get__unpack_dual_namedtuple()},
{"aminmax", get_aminmax_namedtuple()},
{"aminmax_out", get_aminmax_out_namedtuple()},
{"cummax", get_cummax_namedtuple()},
{"cummax_out", get_cummax_out_namedtuple()},
{"cummin", get_cummin_namedtuple()},
{"cummin_out", get_cummin_out_namedtuple()},
{"eig_out", get_eig_out_namedtuple()},
{"eig", get_eig_namedtuple()},
{"frexp", get_frexp_namedtuple()},
{"frexp_out", get_frexp_out_namedtuple()},
{"geqrf_out", get_geqrf_out_namedtuple()},
{"geqrf", get_geqrf_namedtuple()},
{"histogram_out", get_histogram_out_namedtuple()},
{"histogram", get_histogram_namedtuple()},
{"kthvalue", get_kthvalue_namedtuple()},
{"kthvalue_out", get_kthvalue_out_namedtuple()},
{"linalg_cholesky_ex", get_linalg_cholesky_ex_namedtuple()},
{"linalg_cholesky_ex_out", get_linalg_cholesky_ex_out_namedtuple()},
{"linalg_eig", get_linalg_eig_namedtuple()},
{"linalg_eig_out", get_linalg_eig_out_namedtuple()},
{"linalg_eigh", get_linalg_eigh_namedtuple()},
{"linalg_eigh_out", get_linalg_eigh_out_namedtuple()},
{"linalg_inv_ex", get_linalg_inv_ex_namedtuple()},
{"linalg_inv_ex_out", get_linalg_inv_ex_out_namedtuple()},
{"linalg_lstsq", get_linalg_lstsq_namedtuple()},
{"linalg_lstsq_out", get_linalg_lstsq_out_namedtuple()},
{"linalg_qr", get_linalg_qr_namedtuple()},
{"linalg_qr_out", get_linalg_qr_out_namedtuple()},
{"linalg_slogdet", get_linalg_slogdet_namedtuple()},
{"linalg_slogdet_out", get_linalg_slogdet_out_namedtuple()},
{"linalg_svd_out", get_linalg_svd_out_namedtuple()},
{"linalg_svd", get_linalg_svd_namedtuple()},
{"lstsq_out", get_lstsq_out_namedtuple()},
{"lstsq", get_lstsq_namedtuple()},
{"lu_unpack", get_lu_unpack_namedtuple()},
{"lu_unpack_out", get_lu_unpack_out_namedtuple()},
{"max", get_max_namedtuple()},
{"max_out", get_max_out_namedtuple()},
{"median", get_median_namedtuple()},
{"median_out", get_median_out_namedtuple()},
{"min", get_min_namedtuple()},
{"min_out", get_min_out_namedtuple()},
{"mode", get_mode_namedtuple()},
{"mode_out", get_mode_out_namedtuple()},
{"nanmedian", get_nanmedian_namedtuple()},
{"nanmedian_out", get_nanmedian_out_namedtuple()},
{"qr_out", get_qr_out_namedtuple()},
{"qr", get_qr_namedtuple()},
{"slogdet", get_slogdet_namedtuple()},
{"solve", get_solve_namedtuple()},
{"solve_out", get_solve_out_namedtuple()},
{"sort_out", get_sort_out_namedtuple()},
{"sort", get_sort_namedtuple()},
{"svd_out", get_svd_out_namedtuple()},
{"svd", get_svd_namedtuple()},
{"symeig_out", get_symeig_out_namedtuple()},
{"symeig", get_symeig_namedtuple()},
{"topk_out", get_topk_out_namedtuple()},
{"topk", get_topk_namedtuple()},
{"triangular_solve_out", get_triangular_solve_out_namedtuple()},
{"triangular_solve", get_triangular_solve_namedtuple()},
};
return namedtuple_types_map;
}
PyTypeObject* get_namedtuple(std::string name) {
static auto& namedtuple_types_map = get_namedtuple_types_map();
return namedtuple_types_map[name];
}
void initReturnTypes(PyObject* module) {
static struct PyModuleDef def = {
PyModuleDef_HEAD_INIT, "torch._C._return_types", nullptr, -1, {}};
PyObject* return_types_module = PyModule_Create(&def);
if (!return_types_module) {
throw python_error();
}
for (const auto& return_type_pair : get_namedtuple_types_map()) {
// hold onto the TypeObject for the unlikely case of user
// deleting or overriding it.
Py_INCREF(return_type_pair.second);
if (PyModule_AddObject(
return_types_module,
return_type_pair.first.c_str(),
(PyObject*)return_type_pair.second) != 0) {
Py_DECREF((PyObject*)return_type_pair.second);
throw python_error();
}
}
// steals a reference to return_types on success
if (PyModule_AddObject(module, "_return_types", return_types_module) != 0) {
Py_DECREF(return_types_module);
throw python_error();
}
}
} // namespace autograd
} // namespace torch
```
</details>
<details>
<summary>Eg. updated call in other python_*_functions</summary>
```cpp
// linalg_cholesky_ex
static PyObject * THPVariable_linalg_cholesky_ex(PyObject* self_, PyObject* args, PyObject* kwargs)
{
HANDLE_TH_ERRORS
static PyTypeObject* NamedTuple = get_namedtuple("linalg_cholesky_ex");
static PyTypeObject* NamedTuple1 = get_namedtuple("linalg_cholesky_ex_out");
static PythonArgParser parser({
"linalg_cholesky_ex(Tensor input, *, bool upper=False, bool check_errors=False, TensorList[2] out=None)",
}, /*traceable=*/true);
ParsedArgs<4> parsed_args;
auto _r = parser.parse(nullptr, args, kwargs, parsed_args);
if(_r.has_torch_function()) {
return handle_torch_function(_r, nullptr, args, kwargs, THPLinalgVariableFunctionsModule, "torch.linalg");
}
if (_r.isNone(3)) {
// aten::linalg_cholesky_ex(Tensor self, *, bool upper=False, bool check_errors=False) -> (Tensor L, Tensor info)
auto dispatch_linalg_cholesky_ex = [](const at::Tensor & self, bool upper, bool check_errors) -> ::std::tuple<at::Tensor,at::Tensor> {
pybind11::gil_scoped_release no_gil;
return at::linalg_cholesky_ex(self, upper, check_errors);
};
return wrap(NamedTuple, dispatch_linalg_cholesky_ex(_r.tensor(0), _r.toBool(1), _r.toBool(2)));
} else {
// aten::linalg_cholesky_ex.L(Tensor self, *, bool upper=False, bool check_errors=False, Tensor(a!) L, Tensor(b!) info) -> (Tensor(a!) L, Tensor(b!) info)
auto out = _r.tensorlist_n<2>(3);
auto dispatch_linalg_cholesky_ex_out = [](at::Tensor & L, at::Tensor & info, const at::Tensor & self, bool upper, bool check_errors) -> ::std::tuple<at::Tensor,at::Tensor> {
pybind11::gil_scoped_release no_gil;
return at::linalg_cholesky_ex_out(L, info, self, upper, check_errors);
};
return wrap(NamedTuple1, dispatch_linalg_cholesky_ex_out(out[0], out[1], _r.tensor(0), _r.toBool(1), _r.toBool(2)));
}
Py_RETURN_NONE;
END_HANDLE_TH_ERRORS
}
```
</details>
Pull Request resolved: https://github.com/pytorch/pytorch/pull/66614
Reviewed By: H-Huang
Differential Revision: D32741134
Pulled By: zou3519
fbshipit-source-id: 27bada30d20e66333ca1be1775608d9f0cbf9f59
2021-12-06 17:03:11 +00:00
|
|
|
return definitions, map_entries
|
2020-01-30 08:26:16 +00:00
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
|
2020-11-08 09:03:59 +00:00
|
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
|
2020-01-30 08:26:16 +00:00
|
|
|
#
|
2020-11-08 09:03:59 +00:00
|
|
|
# Method Impl Codegen
|
2020-01-30 08:26:16 +00:00
|
|
|
#
|
2020-11-08 09:03:59 +00:00
|
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
|
2020-01-30 08:26:16 +00:00
|
|
|
|
|
|
|
|
# python binding for all overloads of a particular function/method
|
2022-04-20 12:51:02 +00:00
|
|
|
PY_VARIABLE_METHOD_VARARGS = CodeTemplate(
|
|
|
|
|
r"""\
|
2020-01-30 08:26:16 +00:00
|
|
|
// ${name}
|
|
|
|
|
static PyObject * ${pycname}(PyObject* self_, PyObject* args, PyObject* kwargs)
|
|
|
|
|
{
|
|
|
|
|
${method_header}
|
|
|
|
|
static PythonArgParser parser({
|
|
|
|
|
${signatures}
|
|
|
|
|
}, /*traceable=*/${traceable});
|
|
|
|
|
|
|
|
|
|
ParsedArgs<${max_args}> parsed_args;
|
2020-08-06 03:39:27 +00:00
|
|
|
auto _r = parser.parse(${self_}, args, kwargs, parsed_args);
|
2020-01-30 08:26:16 +00:00
|
|
|
${check_has_torch_function}
|
|
|
|
|
switch (_r.idx) {
|
|
|
|
|
${dispatch}
|
|
|
|
|
}
|
|
|
|
|
${method_footer}
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
"""
|
|
|
|
|
)
|
2020-01-30 08:26:16 +00:00
|
|
|
|
2020-11-08 09:03:59 +00:00
|
|
|
# handler for a single parsed signature - may be a single overload or
|
|
|
|
|
# a pair of overloads that whose signatures only differ in output params
|
|
|
|
|
# (plugged into PY_VARIABLE_METHOD_VARARGS as an item in ${dispatch})
|
2022-04-20 12:51:02 +00:00
|
|
|
PY_VARIABLE_CASE = CodeTemplate(
|
|
|
|
|
"""\
|
2020-11-08 09:03:59 +00:00
|
|
|
case ${overload_index}: {
|
|
|
|
|
${body}
|
|
|
|
|
}
|
2022-04-20 12:51:02 +00:00
|
|
|
"""
|
|
|
|
|
)
|
2020-11-08 09:03:59 +00:00
|
|
|
|
2020-01-30 08:26:16 +00:00
|
|
|
# python binding for single-overload function/method
|
2022-04-20 12:51:02 +00:00
|
|
|
PY_VARIABLE_METHOD_VARARGS_SINGLETON = CodeTemplate(
|
|
|
|
|
"""\
|
2020-01-30 08:26:16 +00:00
|
|
|
// ${name}
|
|
|
|
|
static PyObject * ${pycname}(PyObject* self_, PyObject* args, PyObject* kwargs)
|
|
|
|
|
{
|
|
|
|
|
${method_header}
|
|
|
|
|
static PythonArgParser parser({
|
|
|
|
|
${signatures}
|
|
|
|
|
}, /*traceable=*/${traceable});
|
|
|
|
|
|
|
|
|
|
ParsedArgs<${max_args}> parsed_args;
|
2020-08-06 03:39:27 +00:00
|
|
|
auto _r = parser.parse(${self_}, args, kwargs, parsed_args);
|
2020-01-30 08:26:16 +00:00
|
|
|
${check_has_torch_function}
|
|
|
|
|
${dispatch}
|
|
|
|
|
${method_footer}
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
"""
|
|
|
|
|
)
|
2020-01-30 08:26:16 +00:00
|
|
|
|
|
|
|
|
# python binding for a method with no args, shortcuts parsing
|
2022-04-20 12:51:02 +00:00
|
|
|
PY_VARIABLE_METHOD_NOARGS = CodeTemplate(
|
|
|
|
|
"""\
|
2020-01-30 08:26:16 +00:00
|
|
|
// ${name}
|
|
|
|
|
static PyObject * ${pycname}(PyObject* self_, PyObject* args)
|
|
|
|
|
{
|
|
|
|
|
${method_header}
|
2020-08-06 03:39:27 +00:00
|
|
|
${check_has_torch_function}
|
2020-01-30 08:26:16 +00:00
|
|
|
${dispatch}
|
|
|
|
|
${method_footer}
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
"""
|
|
|
|
|
)
|
|
|
|
|
|
2020-01-30 08:26:16 +00:00
|
|
|
|
2020-11-08 09:03:59 +00:00
|
|
|
def method_impl(
|
2020-11-18 20:17:37 +00:00
|
|
|
name: BaseOperatorName,
|
2020-11-14 10:22:37 +00:00
|
|
|
module: Optional[str],
|
2020-11-08 09:03:59 +00:00
|
|
|
overloads: Sequence[PythonSignatureNativeFunctionPair],
|
|
|
|
|
*,
|
2022-04-20 12:51:02 +00:00
|
|
|
method: bool,
|
2020-11-08 09:03:59 +00:00
|
|
|
) -> str:
|
2020-01-30 08:26:16 +00:00
|
|
|
"""
|
|
|
|
|
Generate a python binding for all overloads of an op.
|
|
|
|
|
"""
|
|
|
|
|
pycname = get_pycname(name)
|
2020-11-08 09:03:59 +00:00
|
|
|
noarg = is_noarg(overloads)
|
expose return_types in Python (#66614)
Summary:
https://github.com/facebookresearch/functorch/issues/87
TODO:
* [x] Add comments
* [x] Add test
* [x] Fix XLA
<details>
<summary>Generated python_return_types.cpp</summary>
```cpp
#include <Python.h>
#include <vector>
#include <map>
#include <string>
#include "torch/csrc/autograd/python_return_types.h"
#include "torch/csrc/utils/structseq.h"
#include "torch/csrc/Exceptions.h"
namespace {
PyTypeObject* get__det_lu_based_helper_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"det", ""}, {"lu", ""}, {"pivs", ""}, {nullptr} };
static PyTypeObject _det_lu_based_helperNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._det_lu_based_helper", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&_det_lu_based_helperNamedTuple, &desc);
_det_lu_based_helperNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_det_lu_based_helperNamedTuple;
}
PyTypeObject* get__fake_quantize_per_tensor_affine_cachemask_tensor_qparams_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"output", ""}, {"mask", ""}, {nullptr} };
static PyTypeObject _fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._fake_quantize_per_tensor_affine_cachemask_tensor_qparams", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple, &desc);
_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_fake_quantize_per_tensor_affine_cachemask_tensor_qparamsNamedTuple;
}
PyTypeObject* get__fused_moving_avg_obs_fq_helper_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"output", ""}, {"mask", ""}, {nullptr} };
static PyTypeObject _fused_moving_avg_obs_fq_helperNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._fused_moving_avg_obs_fq_helper", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_fused_moving_avg_obs_fq_helperNamedTuple, &desc);
_fused_moving_avg_obs_fq_helperNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_fused_moving_avg_obs_fq_helperNamedTuple;
}
PyTypeObject* get__lu_with_info_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"LU", ""}, {"pivots", ""}, {"info", ""}, {nullptr} };
static PyTypeObject _lu_with_infoNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._lu_with_info", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&_lu_with_infoNamedTuple, &desc);
_lu_with_infoNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_lu_with_infoNamedTuple;
}
PyTypeObject* get__unpack_dual_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"primal", ""}, {"tangent", ""}, {nullptr} };
static PyTypeObject _unpack_dualNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types._unpack_dual", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&_unpack_dualNamedTuple, &desc);
_unpack_dualNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &_unpack_dualNamedTuple;
}
PyTypeObject* get_aminmax_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"min", ""}, {"max", ""}, {nullptr} };
static PyTypeObject aminmaxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.aminmax", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&aminmaxNamedTuple, &desc);
aminmaxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &aminmaxNamedTuple;
}
PyTypeObject* get_aminmax_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"min", ""}, {"max", ""}, {nullptr} };
static PyTypeObject aminmax_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.aminmax_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&aminmax_outNamedTuple1, &desc);
aminmax_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &aminmax_outNamedTuple1;
}
PyTypeObject* get_cummax_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummaxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummax", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummaxNamedTuple, &desc);
cummaxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummaxNamedTuple;
}
PyTypeObject* get_cummax_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummax_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummax_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummax_outNamedTuple1, &desc);
cummax_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummax_outNamedTuple1;
}
PyTypeObject* get_cummin_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cumminNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummin", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cumminNamedTuple, &desc);
cumminNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cumminNamedTuple;
}
PyTypeObject* get_cummin_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject cummin_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.cummin_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&cummin_outNamedTuple1, &desc);
cummin_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &cummin_outNamedTuple1;
}
PyTypeObject* get_eig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject eig_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.eig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&eig_outNamedTuple, &desc);
eig_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &eig_outNamedTuple;
}
PyTypeObject* get_eig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject eigNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.eig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&eigNamedTuple1, &desc);
eigNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &eigNamedTuple1;
}
PyTypeObject* get_frexp_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"mantissa", ""}, {"exponent", ""}, {nullptr} };
static PyTypeObject frexpNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.frexp", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&frexpNamedTuple, &desc);
frexpNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &frexpNamedTuple;
}
PyTypeObject* get_frexp_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"mantissa", ""}, {"exponent", ""}, {nullptr} };
static PyTypeObject frexp_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.frexp_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&frexp_outNamedTuple1, &desc);
frexp_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &frexp_outNamedTuple1;
}
PyTypeObject* get_geqrf_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"a", ""}, {"tau", ""}, {nullptr} };
static PyTypeObject geqrf_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.geqrf_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&geqrf_outNamedTuple, &desc);
geqrf_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &geqrf_outNamedTuple;
}
PyTypeObject* get_geqrf_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"a", ""}, {"tau", ""}, {nullptr} };
static PyTypeObject geqrfNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.geqrf", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&geqrfNamedTuple1, &desc);
geqrfNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &geqrfNamedTuple1;
}
PyTypeObject* get_histogram_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"hist", ""}, {"bin_edges", ""}, {nullptr} };
static PyTypeObject histogram_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.histogram_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&histogram_outNamedTuple, &desc);
histogram_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &histogram_outNamedTuple;
}
PyTypeObject* get_histogram_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"hist", ""}, {"bin_edges", ""}, {nullptr} };
static PyTypeObject histogramNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.histogram", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&histogramNamedTuple1, &desc);
histogramNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &histogramNamedTuple1;
}
PyTypeObject* get_kthvalue_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject kthvalueNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.kthvalue", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&kthvalueNamedTuple, &desc);
kthvalueNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &kthvalueNamedTuple;
}
PyTypeObject* get_kthvalue_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject kthvalue_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.kthvalue_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&kthvalue_outNamedTuple1, &desc);
kthvalue_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &kthvalue_outNamedTuple1;
}
PyTypeObject* get_linalg_cholesky_ex_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"L", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_cholesky_exNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_cholesky_ex", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_cholesky_exNamedTuple, &desc);
linalg_cholesky_exNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_cholesky_exNamedTuple;
}
PyTypeObject* get_linalg_cholesky_ex_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"L", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_cholesky_ex_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_cholesky_ex_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_cholesky_ex_outNamedTuple1, &desc);
linalg_cholesky_ex_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_cholesky_ex_outNamedTuple1;
}
PyTypeObject* get_linalg_eig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eigNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eigNamedTuple, &desc);
linalg_eigNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eigNamedTuple;
}
PyTypeObject* get_linalg_eig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eig_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eig_outNamedTuple1, &desc);
linalg_eig_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eig_outNamedTuple1;
}
PyTypeObject* get_linalg_eigh_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eighNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eigh", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eighNamedTuple, &desc);
linalg_eighNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eighNamedTuple;
}
PyTypeObject* get_linalg_eigh_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject linalg_eigh_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_eigh_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_eigh_outNamedTuple1, &desc);
linalg_eigh_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_eigh_outNamedTuple1;
}
PyTypeObject* get_linalg_inv_ex_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"inverse", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_inv_exNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_inv_ex", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_inv_exNamedTuple, &desc);
linalg_inv_exNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_inv_exNamedTuple;
}
PyTypeObject* get_linalg_inv_ex_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"inverse", ""}, {"info", ""}, {nullptr} };
static PyTypeObject linalg_inv_ex_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_inv_ex_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_inv_ex_outNamedTuple1, &desc);
linalg_inv_ex_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_inv_ex_outNamedTuple1;
}
PyTypeObject* get_linalg_lstsq_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"residuals", ""}, {"rank", ""}, {"singular_values", ""}, {nullptr} };
static PyTypeObject linalg_lstsqNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_lstsq", nullptr, NamedTuple_fields, 4 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_lstsqNamedTuple, &desc);
linalg_lstsqNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_lstsqNamedTuple;
}
PyTypeObject* get_linalg_lstsq_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"residuals", ""}, {"rank", ""}, {"singular_values", ""}, {nullptr} };
static PyTypeObject linalg_lstsq_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_lstsq_out", nullptr, NamedTuple_fields, 4 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_lstsq_outNamedTuple1, &desc);
linalg_lstsq_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_lstsq_outNamedTuple1;
}
PyTypeObject* get_linalg_qr_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject linalg_qrNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_qr", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_qrNamedTuple, &desc);
linalg_qrNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_qrNamedTuple;
}
PyTypeObject* get_linalg_qr_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject linalg_qr_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_qr_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_qr_outNamedTuple1, &desc);
linalg_qr_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_qr_outNamedTuple1;
}
PyTypeObject* get_linalg_slogdet_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject linalg_slogdetNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_slogdet", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_slogdetNamedTuple, &desc);
linalg_slogdetNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_slogdetNamedTuple;
}
PyTypeObject* get_linalg_slogdet_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject linalg_slogdet_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_slogdet_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_slogdet_outNamedTuple1, &desc);
linalg_slogdet_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_slogdet_outNamedTuple1;
}
PyTypeObject* get_linalg_svd_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"Vh", ""}, {nullptr} };
static PyTypeObject linalg_svd_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_svd_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_svd_outNamedTuple, &desc);
linalg_svd_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_svd_outNamedTuple;
}
PyTypeObject* get_linalg_svd_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"Vh", ""}, {nullptr} };
static PyTypeObject linalg_svdNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.linalg_svd", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&linalg_svdNamedTuple1, &desc);
linalg_svdNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &linalg_svdNamedTuple1;
}
PyTypeObject* get_lstsq_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"QR", ""}, {nullptr} };
static PyTypeObject lstsq_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lstsq_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&lstsq_outNamedTuple, &desc);
lstsq_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lstsq_outNamedTuple;
}
PyTypeObject* get_lstsq_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"QR", ""}, {nullptr} };
static PyTypeObject lstsqNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lstsq", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&lstsqNamedTuple1, &desc);
lstsqNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lstsqNamedTuple1;
}
PyTypeObject* get_lu_unpack_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"P", ""}, {"L", ""}, {"U", ""}, {nullptr} };
static PyTypeObject lu_unpackNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lu_unpack", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&lu_unpackNamedTuple, &desc);
lu_unpackNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lu_unpackNamedTuple;
}
PyTypeObject* get_lu_unpack_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"P", ""}, {"L", ""}, {"U", ""}, {nullptr} };
static PyTypeObject lu_unpack_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.lu_unpack_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&lu_unpack_outNamedTuple1, &desc);
lu_unpack_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &lu_unpack_outNamedTuple1;
}
PyTypeObject* get_max_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject maxNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.max", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&maxNamedTuple, &desc);
maxNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &maxNamedTuple;
}
PyTypeObject* get_max_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject max_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.max_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&max_outNamedTuple1, &desc);
max_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &max_outNamedTuple1;
}
PyTypeObject* get_median_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject medianNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.median", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&medianNamedTuple, &desc);
medianNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &medianNamedTuple;
}
PyTypeObject* get_median_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject median_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.median_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&median_outNamedTuple1, &desc);
median_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &median_outNamedTuple1;
}
PyTypeObject* get_min_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject minNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.min", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&minNamedTuple, &desc);
minNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &minNamedTuple;
}
PyTypeObject* get_min_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject min_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.min_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&min_outNamedTuple1, &desc);
min_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &min_outNamedTuple1;
}
PyTypeObject* get_mode_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject modeNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.mode", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&modeNamedTuple, &desc);
modeNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &modeNamedTuple;
}
PyTypeObject* get_mode_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject mode_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.mode_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&mode_outNamedTuple1, &desc);
mode_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &mode_outNamedTuple1;
}
PyTypeObject* get_nanmedian_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject nanmedianNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.nanmedian", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&nanmedianNamedTuple, &desc);
nanmedianNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &nanmedianNamedTuple;
}
PyTypeObject* get_nanmedian_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject nanmedian_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.nanmedian_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&nanmedian_outNamedTuple1, &desc);
nanmedian_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &nanmedian_outNamedTuple1;
}
PyTypeObject* get_qr_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject qr_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.qr_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&qr_outNamedTuple, &desc);
qr_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &qr_outNamedTuple;
}
PyTypeObject* get_qr_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"Q", ""}, {"R", ""}, {nullptr} };
static PyTypeObject qrNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.qr", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&qrNamedTuple1, &desc);
qrNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &qrNamedTuple1;
}
PyTypeObject* get_slogdet_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"sign", ""}, {"logabsdet", ""}, {nullptr} };
static PyTypeObject slogdetNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.slogdet", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&slogdetNamedTuple, &desc);
slogdetNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &slogdetNamedTuple;
}
PyTypeObject* get_solve_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"LU", ""}, {nullptr} };
static PyTypeObject solveNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.solve", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&solveNamedTuple, &desc);
solveNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &solveNamedTuple;
}
PyTypeObject* get_solve_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"LU", ""}, {nullptr} };
static PyTypeObject solve_outNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.solve_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&solve_outNamedTuple1, &desc);
solve_outNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &solve_outNamedTuple1;
}
PyTypeObject* get_sort_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject sort_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.sort_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&sort_outNamedTuple, &desc);
sort_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &sort_outNamedTuple;
}
PyTypeObject* get_sort_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject sortNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.sort", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&sortNamedTuple1, &desc);
sortNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &sortNamedTuple1;
}
PyTypeObject* get_svd_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"V", ""}, {nullptr} };
static PyTypeObject svd_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.svd_out", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&svd_outNamedTuple, &desc);
svd_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &svd_outNamedTuple;
}
PyTypeObject* get_svd_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"U", ""}, {"S", ""}, {"V", ""}, {nullptr} };
static PyTypeObject svdNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.svd", nullptr, NamedTuple_fields, 3 };
if (!is_initialized) {
PyStructSequence_InitType(&svdNamedTuple1, &desc);
svdNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &svdNamedTuple1;
}
PyTypeObject* get_symeig_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject symeig_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.symeig_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&symeig_outNamedTuple, &desc);
symeig_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &symeig_outNamedTuple;
}
PyTypeObject* get_symeig_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"eigenvalues", ""}, {"eigenvectors", ""}, {nullptr} };
static PyTypeObject symeigNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.symeig", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&symeigNamedTuple1, &desc);
symeigNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &symeigNamedTuple1;
}
PyTypeObject* get_topk_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject topk_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.topk_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&topk_outNamedTuple, &desc);
topk_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &topk_outNamedTuple;
}
PyTypeObject* get_topk_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"values", ""}, {"indices", ""}, {nullptr} };
static PyTypeObject topkNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.topk", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&topkNamedTuple1, &desc);
topkNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &topkNamedTuple1;
}
PyTypeObject* get_triangular_solve_out_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"cloned_coefficient", ""}, {nullptr} };
static PyTypeObject triangular_solve_outNamedTuple;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.triangular_solve_out", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&triangular_solve_outNamedTuple, &desc);
triangular_solve_outNamedTuple.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &triangular_solve_outNamedTuple;
}
PyTypeObject* get_triangular_solve_namedtuple() {
static PyStructSequence_Field NamedTuple_fields[] = { {"solution", ""}, {"cloned_coefficient", ""}, {nullptr} };
static PyTypeObject triangular_solveNamedTuple1;
static bool is_initialized = false;
static PyStructSequence_Desc desc = { "torch.return_types.triangular_solve", nullptr, NamedTuple_fields, 2 };
if (!is_initialized) {
PyStructSequence_InitType(&triangular_solveNamedTuple1, &desc);
triangular_solveNamedTuple1.tp_repr = (reprfunc)torch::utils::returned_structseq_repr;
is_initialized = true;
}
return &triangular_solveNamedTuple1;
}
}
namespace torch {
namespace autograd {
std::map<std::string, PyTypeObject*>& get_namedtuple_types_map() {
// [NOTE] Non-global map
// This map calls Python functions during its initialization.
// If it is a global static variable and in case it is loaded
// before Python interpreter is ready, then the calls it makes during
// initialization will SEGFAULT.
// To avoid this we make it function static variable so that it is
// initialized only after the Python interpreter is ready.
static std::map<std::string, PyTypeObject*> namedtuple_types_map = {
{"_det_lu_based_helper", get__det_lu_based_helper_namedtuple()},
{"_fake_quantize_per_tensor_affine_cachemask_tensor_qparams", get__fake_quantize_per_tensor_affine_cachemask_tensor_qparams_namedtuple()},
{"_fused_moving_avg_obs_fq_helper", get__fused_moving_avg_obs_fq_helper_namedtuple()},
{"_lu_with_info", get__lu_with_info_namedtuple()},
{"_unpack_dual", get__unpack_dual_namedtuple()},
{"aminmax", get_aminmax_namedtuple()},
{"aminmax_out", get_aminmax_out_namedtuple()},
{"cummax", get_cummax_namedtuple()},
{"cummax_out", get_cummax_out_namedtuple()},
{"cummin", get_cummin_namedtuple()},
{"cummin_out", get_cummin_out_namedtuple()},
{"eig_out", get_eig_out_namedtuple()},
{"eig", get_eig_namedtuple()},
{"frexp", get_frexp_namedtuple()},
{"frexp_out", get_frexp_out_namedtuple()},
{"geqrf_out", get_geqrf_out_namedtuple()},
{"geqrf", get_geqrf_namedtuple()},
{"histogram_out", get_histogram_out_namedtuple()},
{"histogram", get_histogram_namedtuple()},
{"kthvalue", get_kthvalue_namedtuple()},
{"kthvalue_out", get_kthvalue_out_namedtuple()},
{"linalg_cholesky_ex", get_linalg_cholesky_ex_namedtuple()},
{"linalg_cholesky_ex_out", get_linalg_cholesky_ex_out_namedtuple()},
{"linalg_eig", get_linalg_eig_namedtuple()},
{"linalg_eig_out", get_linalg_eig_out_namedtuple()},
{"linalg_eigh", get_linalg_eigh_namedtuple()},
{"linalg_eigh_out", get_linalg_eigh_out_namedtuple()},
{"linalg_inv_ex", get_linalg_inv_ex_namedtuple()},
{"linalg_inv_ex_out", get_linalg_inv_ex_out_namedtuple()},
{"linalg_lstsq", get_linalg_lstsq_namedtuple()},
{"linalg_lstsq_out", get_linalg_lstsq_out_namedtuple()},
{"linalg_qr", get_linalg_qr_namedtuple()},
{"linalg_qr_out", get_linalg_qr_out_namedtuple()},
{"linalg_slogdet", get_linalg_slogdet_namedtuple()},
{"linalg_slogdet_out", get_linalg_slogdet_out_namedtuple()},
{"linalg_svd_out", get_linalg_svd_out_namedtuple()},
{"linalg_svd", get_linalg_svd_namedtuple()},
{"lstsq_out", get_lstsq_out_namedtuple()},
{"lstsq", get_lstsq_namedtuple()},
{"lu_unpack", get_lu_unpack_namedtuple()},
{"lu_unpack_out", get_lu_unpack_out_namedtuple()},
{"max", get_max_namedtuple()},
{"max_out", get_max_out_namedtuple()},
{"median", get_median_namedtuple()},
{"median_out", get_median_out_namedtuple()},
{"min", get_min_namedtuple()},
{"min_out", get_min_out_namedtuple()},
{"mode", get_mode_namedtuple()},
{"mode_out", get_mode_out_namedtuple()},
{"nanmedian", get_nanmedian_namedtuple()},
{"nanmedian_out", get_nanmedian_out_namedtuple()},
{"qr_out", get_qr_out_namedtuple()},
{"qr", get_qr_namedtuple()},
{"slogdet", get_slogdet_namedtuple()},
{"solve", get_solve_namedtuple()},
{"solve_out", get_solve_out_namedtuple()},
{"sort_out", get_sort_out_namedtuple()},
{"sort", get_sort_namedtuple()},
{"svd_out", get_svd_out_namedtuple()},
{"svd", get_svd_namedtuple()},
{"symeig_out", get_symeig_out_namedtuple()},
{"symeig", get_symeig_namedtuple()},
{"topk_out", get_topk_out_namedtuple()},
{"topk", get_topk_namedtuple()},
{"triangular_solve_out", get_triangular_solve_out_namedtuple()},
{"triangular_solve", get_triangular_solve_namedtuple()},
};
return namedtuple_types_map;
}
PyTypeObject* get_namedtuple(std::string name) {
static auto& namedtuple_types_map = get_namedtuple_types_map();
return namedtuple_types_map[name];
}
void initReturnTypes(PyObject* module) {
static struct PyModuleDef def = {
PyModuleDef_HEAD_INIT, "torch._C._return_types", nullptr, -1, {}};
PyObject* return_types_module = PyModule_Create(&def);
if (!return_types_module) {
throw python_error();
}
for (const auto& return_type_pair : get_namedtuple_types_map()) {
// hold onto the TypeObject for the unlikely case of user
// deleting or overriding it.
Py_INCREF(return_type_pair.second);
if (PyModule_AddObject(
return_types_module,
return_type_pair.first.c_str(),
(PyObject*)return_type_pair.second) != 0) {
Py_DECREF((PyObject*)return_type_pair.second);
throw python_error();
}
}
// steals a reference to return_types on success
if (PyModule_AddObject(module, "_return_types", return_types_module) != 0) {
Py_DECREF(return_types_module);
throw python_error();
}
}
} // namespace autograd
} // namespace torch
```
</details>
<details>
<summary>Eg. updated call in other python_*_functions</summary>
```cpp
// linalg_cholesky_ex
static PyObject * THPVariable_linalg_cholesky_ex(PyObject* self_, PyObject* args, PyObject* kwargs)
{
HANDLE_TH_ERRORS
static PyTypeObject* NamedTuple = get_namedtuple("linalg_cholesky_ex");
static PyTypeObject* NamedTuple1 = get_namedtuple("linalg_cholesky_ex_out");
static PythonArgParser parser({
"linalg_cholesky_ex(Tensor input, *, bool upper=False, bool check_errors=False, TensorList[2] out=None)",
}, /*traceable=*/true);
ParsedArgs<4> parsed_args;
auto _r = parser.parse(nullptr, args, kwargs, parsed_args);
if(_r.has_torch_function()) {
return handle_torch_function(_r, nullptr, args, kwargs, THPLinalgVariableFunctionsModule, "torch.linalg");
}
if (_r.isNone(3)) {
// aten::linalg_cholesky_ex(Tensor self, *, bool upper=False, bool check_errors=False) -> (Tensor L, Tensor info)
auto dispatch_linalg_cholesky_ex = [](const at::Tensor & self, bool upper, bool check_errors) -> ::std::tuple<at::Tensor,at::Tensor> {
pybind11::gil_scoped_release no_gil;
return at::linalg_cholesky_ex(self, upper, check_errors);
};
return wrap(NamedTuple, dispatch_linalg_cholesky_ex(_r.tensor(0), _r.toBool(1), _r.toBool(2)));
} else {
// aten::linalg_cholesky_ex.L(Tensor self, *, bool upper=False, bool check_errors=False, Tensor(a!) L, Tensor(b!) info) -> (Tensor(a!) L, Tensor(b!) info)
auto out = _r.tensorlist_n<2>(3);
auto dispatch_linalg_cholesky_ex_out = [](at::Tensor & L, at::Tensor & info, const at::Tensor & self, bool upper, bool check_errors) -> ::std::tuple<at::Tensor,at::Tensor> {
pybind11::gil_scoped_release no_gil;
return at::linalg_cholesky_ex_out(L, info, self, upper, check_errors);
};
return wrap(NamedTuple1, dispatch_linalg_cholesky_ex_out(out[0], out[1], _r.tensor(0), _r.toBool(1), _r.toBool(2)));
}
Py_RETURN_NONE;
END_HANDLE_TH_ERRORS
}
```
</details>
Pull Request resolved: https://github.com/pytorch/pytorch/pull/66614
Reviewed By: H-Huang
Differential Revision: D32741134
Pulled By: zou3519
fbshipit-source-id: 27bada30d20e66333ca1be1775608d9f0cbf9f59
2021-12-06 17:03:11 +00:00
|
|
|
namedtuple_inits, namedtuple_typenames = emit_namedtuple_call(overloads)
|
2020-01-30 08:26:16 +00:00
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
method_header = ["HANDLE_TH_ERRORS"]
|
2020-11-08 09:03:59 +00:00
|
|
|
method_header += namedtuple_inits
|
2022-04-20 12:51:02 +00:00
|
|
|
method_header += (
|
|
|
|
|
["const Tensor& self = THPVariable_Unpack(self_);"] if method else []
|
|
|
|
|
)
|
2020-01-30 08:26:16 +00:00
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
method_footer = ([] if noarg else ["Py_RETURN_NONE;"]) + ["END_HANDLE_TH_ERRORS"]
|
2020-01-30 08:26:16 +00:00
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
traceable = "true" if all(should_trace(o.function) for o in overloads) else "false"
|
2020-08-06 03:39:27 +00:00
|
|
|
|
2020-11-08 09:03:59 +00:00
|
|
|
grouped_overloads: Sequence[PythonSignatureGroup] = group_overloads(overloads)
|
|
|
|
|
is_singleton = len(grouped_overloads) == 1
|
|
|
|
|
signatures: List[str] = []
|
|
|
|
|
dispatch: List[str] = []
|
|
|
|
|
for overload_index, overload in enumerate(grouped_overloads):
|
|
|
|
|
signature = overload.signature.signature_str()
|
2022-04-20 12:51:02 +00:00
|
|
|
signatures.append(f"{cpp_string(str(signature))},")
|
2020-11-08 09:03:59 +00:00
|
|
|
dispatch_body = emit_dispatch_case(overload, namedtuple_typenames)
|
|
|
|
|
dispatch.append(
|
2022-04-20 12:51:02 +00:00
|
|
|
PY_VARIABLE_CASE.substitute(
|
|
|
|
|
overload_index=overload_index, body=dispatch_body
|
|
|
|
|
)
|
|
|
|
|
if not is_singleton
|
|
|
|
|
else dispatch_body
|
|
|
|
|
)
|
2020-11-08 09:03:59 +00:00
|
|
|
|
|
|
|
|
if noarg:
|
|
|
|
|
template = PY_VARIABLE_METHOD_NOARGS
|
|
|
|
|
elif is_singleton:
|
2020-01-30 08:26:16 +00:00
|
|
|
template = PY_VARIABLE_METHOD_VARARGS_SINGLETON
|
|
|
|
|
else:
|
|
|
|
|
template = PY_VARIABLE_METHOD_VARARGS
|
|
|
|
|
|
|
|
|
|
return template.substitute(
|
|
|
|
|
name=name,
|
|
|
|
|
pycname=pycname,
|
|
|
|
|
method_header=method_header,
|
2020-11-08 09:03:59 +00:00
|
|
|
max_args=max(map(lambda o: o.signature.arguments_count(), overloads)),
|
2020-01-30 08:26:16 +00:00
|
|
|
signatures=signatures,
|
|
|
|
|
traceable=traceable,
|
2020-11-08 09:03:59 +00:00
|
|
|
check_has_torch_function=gen_has_torch_function_check(
|
|
|
|
|
name=name,
|
|
|
|
|
module=module,
|
|
|
|
|
noarg=noarg,
|
|
|
|
|
method=method,
|
|
|
|
|
),
|
2020-01-30 08:26:16 +00:00
|
|
|
dispatch=dispatch,
|
|
|
|
|
method_footer=method_footer,
|
2020-11-08 09:03:59 +00:00
|
|
|
self_="self_" if method else "nullptr",
|
2020-01-30 08:26:16 +00:00
|
|
|
)
|
|
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
|
2020-11-14 10:22:37 +00:00
|
|
|
def gen_has_torch_function_check(
|
2020-11-18 20:17:37 +00:00
|
|
|
name: BaseOperatorName, module: Optional[str], *, noarg: bool, method: bool
|
2020-11-14 10:22:37 +00:00
|
|
|
) -> str:
|
2020-11-08 09:03:59 +00:00
|
|
|
if noarg:
|
|
|
|
|
if method:
|
|
|
|
|
return f"""\
|
|
|
|
|
if(check_has_torch_function(self_)) {{
|
|
|
|
|
return handle_torch_function(self_, "{name}");
|
|
|
|
|
}}
|
|
|
|
|
"""
|
|
|
|
|
else:
|
2022-04-20 12:51:02 +00:00
|
|
|
return ""
|
2020-11-08 09:03:59 +00:00
|
|
|
|
|
|
|
|
self_ = "self_" if method else "nullptr"
|
2022-04-20 12:51:02 +00:00
|
|
|
namespace = (
|
|
|
|
|
{
|
|
|
|
|
"torch": "THPVariableFunctionsModule",
|
|
|
|
|
"torch.nn": "THPNNVariableFunctionsModule",
|
|
|
|
|
"torch.fft": "THPFFTVariableFunctionsModule",
|
|
|
|
|
"torch.linalg": "THPLinalgVariableFunctionsModule",
|
|
|
|
|
"torch.sparse": "THPSparseVariableFunctionsModule",
|
|
|
|
|
"torch.special": "THPSpecialVariableFunctionsModule",
|
|
|
|
|
}[module]
|
|
|
|
|
if module
|
|
|
|
|
else "THPVariableClass"
|
|
|
|
|
)
|
2020-11-08 09:03:59 +00:00
|
|
|
|
|
|
|
|
return f"""\
|
|
|
|
|
if(_r.has_torch_function()) {{
|
|
|
|
|
return handle_torch_function(_r, {self_}, args, kwargs, {namespace}, "{module or "torch.Tensor"}");
|
|
|
|
|
}}
|
|
|
|
|
"""
|
2020-01-30 08:26:16 +00:00
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
|
2020-11-08 09:03:59 +00:00
|
|
|
# handler for output/no-output overload pair
|
2022-04-20 12:51:02 +00:00
|
|
|
PY_VARIABLE_OUT = CodeTemplate(
|
|
|
|
|
"""\
|
2020-11-08 09:03:59 +00:00
|
|
|
if (_r.isNone(${out_idx})) {
|
|
|
|
|
${call_dispatch}
|
|
|
|
|
} else {
|
|
|
|
|
${call_dispatch_out}
|
|
|
|
|
}
|
2022-04-20 12:51:02 +00:00
|
|
|
"""
|
|
|
|
|
)
|
|
|
|
|
|
2020-01-30 08:26:16 +00:00
|
|
|
|
2020-11-08 09:03:59 +00:00
|
|
|
def emit_dispatch_case(
|
|
|
|
|
overload: PythonSignatureGroup,
|
|
|
|
|
namedtuple_typenames: Dict[str, str],
|
|
|
|
|
) -> str:
|
|
|
|
|
"""
|
|
|
|
|
Emit dispatch code for a single parsed signature. This corresponds to either
|
|
|
|
|
a single native function, or a pair that differ only in output params. In the
|
|
|
|
|
latter case, a single python signature is used for both and dispatching
|
|
|
|
|
switches on the presence/absence of passed output args.
|
|
|
|
|
"""
|
|
|
|
|
if overload.outplace is not None:
|
|
|
|
|
# dispatch output and no-output variants, branch on _r.isNone(<out_idx>)
|
|
|
|
|
return PY_VARIABLE_OUT.substitute(
|
|
|
|
|
out_idx=overload.signature.output_idx(),
|
|
|
|
|
call_dispatch=emit_single_dispatch(
|
2022-04-20 12:51:02 +00:00
|
|
|
overload.signature, overload.base, namedtuple_typenames
|
|
|
|
|
),
|
2020-11-08 09:03:59 +00:00
|
|
|
call_dispatch_out=emit_single_dispatch(
|
2022-04-20 12:51:02 +00:00
|
|
|
overload.signature, overload.outplace, namedtuple_typenames
|
|
|
|
|
),
|
2020-11-08 09:03:59 +00:00
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
# no-output version only
|
|
|
|
|
return emit_single_dispatch(
|
2022-04-20 12:51:02 +00:00
|
|
|
overload.signature, overload.base, namedtuple_typenames
|
|
|
|
|
)
|
|
|
|
|
|
2020-11-08 09:03:59 +00:00
|
|
|
|
|
|
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
|
|
|
|
|
#
|
|
|
|
|
# Forward Declarations Codegen
|
|
|
|
|
#
|
|
|
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
|
2020-01-30 08:26:16 +00:00
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
|
2020-11-08 09:03:59 +00:00
|
|
|
def forward_decls(
|
2020-11-18 20:17:37 +00:00
|
|
|
name: BaseOperatorName,
|
2020-11-08 09:03:59 +00:00
|
|
|
overloads: Sequence[PythonSignatureNativeFunctionPair],
|
|
|
|
|
*,
|
2022-04-20 12:51:02 +00:00
|
|
|
method: bool,
|
2020-11-08 09:03:59 +00:00
|
|
|
) -> Tuple[str, ...]:
|
|
|
|
|
if method:
|
|
|
|
|
return ()
|
2020-01-30 08:26:16 +00:00
|
|
|
|
|
|
|
|
pycname = get_pycname(name)
|
2020-11-08 09:03:59 +00:00
|
|
|
if is_noarg(overloads):
|
2022-04-20 12:51:02 +00:00
|
|
|
return (
|
|
|
|
|
f"""\
|
2020-11-08 09:03:59 +00:00
|
|
|
static PyObject * {pycname}(PyObject* self_, PyObject* args);
|
2022-04-20 12:51:02 +00:00
|
|
|
""",
|
|
|
|
|
)
|
2020-11-08 09:03:59 +00:00
|
|
|
else:
|
2022-04-20 12:51:02 +00:00
|
|
|
return (
|
|
|
|
|
f"""\
|
2020-11-08 09:03:59 +00:00
|
|
|
static PyObject * {pycname}(PyObject* self_, PyObject* args, PyObject* kwargs);
|
2022-04-20 12:51:02 +00:00
|
|
|
""",
|
|
|
|
|
)
|
|
|
|
|
|
2020-01-30 08:26:16 +00:00
|
|
|
|
2020-11-08 09:03:59 +00:00
|
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
|
2020-01-30 08:26:16 +00:00
|
|
|
#
|
2020-11-08 09:03:59 +00:00
|
|
|
# Method Def (Binding Table Entry) Codegen
|
2020-01-30 08:26:16 +00:00
|
|
|
#
|
2020-11-08 09:03:59 +00:00
|
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
|
2020-01-30 08:26:16 +00:00
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
|
2020-11-08 09:03:59 +00:00
|
|
|
def method_def(
|
2020-11-18 20:17:37 +00:00
|
|
|
name: BaseOperatorName,
|
2020-11-14 10:22:37 +00:00
|
|
|
module: Optional[str],
|
2020-11-08 09:03:59 +00:00
|
|
|
overloads: Sequence[PythonSignatureNativeFunctionPair],
|
|
|
|
|
*,
|
2022-04-20 12:51:02 +00:00
|
|
|
method: bool,
|
2020-11-08 09:03:59 +00:00
|
|
|
) -> str:
|
2020-01-30 08:26:16 +00:00
|
|
|
"""
|
|
|
|
|
Generate method def entry.
|
|
|
|
|
"""
|
|
|
|
|
pycname = get_pycname(name)
|
|
|
|
|
|
2020-11-08 09:03:59 +00:00
|
|
|
if is_noarg(overloads):
|
2022-04-20 12:51:02 +00:00
|
|
|
pyfunc_cast = ""
|
|
|
|
|
flags = "METH_NOARGS" if method else "METH_VARARGS | METH_KEYWORDS"
|
2020-01-30 08:26:16 +00:00
|
|
|
else:
|
2022-04-20 12:51:02 +00:00
|
|
|
pyfunc_cast = "castPyCFunctionWithKeywords"
|
|
|
|
|
flags = "METH_VARARGS | METH_KEYWORDS"
|
2018-01-17 23:27:42 +00:00
|
|
|
|
2020-05-09 18:56:16 +00:00
|
|
|
if module == "torch":
|
2022-04-20 12:51:02 +00:00
|
|
|
flags += " | METH_STATIC"
|
2020-05-09 18:56:16 +00:00
|
|
|
|
2020-11-18 20:17:37 +00:00
|
|
|
if name.dunder_method:
|
2020-11-08 09:03:59 +00:00
|
|
|
# PyMethodDef entry for binary op, throws not implemented error
|
|
|
|
|
return f"""\
|
|
|
|
|
{{"{name}", {pyfunc_cast}(TypeError_to_NotImplemented_<{pycname}>), {flags}, NULL}},"""
|
2020-01-30 08:26:16 +00:00
|
|
|
else:
|
2020-11-08 09:03:59 +00:00
|
|
|
# PyMethodDef entry
|
|
|
|
|
return f"""\
|
|
|
|
|
{{"{name}", {pyfunc_cast}({pycname}), {flags}, NULL}},"""
|
2020-01-30 08:26:16 +00:00
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
|
2020-11-08 09:03:59 +00:00
|
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
|
2020-01-30 08:26:16 +00:00
|
|
|
#
|
2020-11-08 09:03:59 +00:00
|
|
|
# Overload Sorting and Grouping
|
2020-01-30 08:26:16 +00:00
|
|
|
#
|
2020-11-08 09:03:59 +00:00
|
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
|
2020-01-30 08:26:16 +00:00
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
|
2020-11-08 09:03:59 +00:00
|
|
|
def group_overloads(
|
pyi codegen update - remove Declarations.yaml (#48754)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/48754
The goal of this PR is to kill Declarations.yaml in the pyi codegen, in favor of native_functions + the existing python object model.
**High-level design**
Since the python signatures used by the `python_arg_parser` are “supposed” to resemble the corresponding pyi type hint signatures, I re-used the existing python object model that Jiakai defined in `tools/codegen/api/python.py`. This means that the pyi codegen now reads `native_functions.yaml`, parses it into a bunch of `PythonSignatureGroup` objects, and emits corresponding method + function variants of type-hint signatures for each one, respectively into `__init__.pyi` and `_VariableFunctions.pyi`.
What makes this uglier is that pyi and the python arg parser have a number of differences in how they’re emitted. I expressed that through a `pyi` flag on the `PythonSignature` dataclass, that tells it whether or not to print itself as a pyi vs. arg_parser signature.
One thing worth noting is how pyi generates signatures differently for native / deprecated op signatures.
For native ops:
- The pyi codegen fuses functional and out variants of each op into a single signature with an optional `out` argument. Ops without an `out` variant just get an ordinary functional signature.
- Some ops that fit certain criteria also get a second “varargs” signature - basically ops with a single positional argument of type List[int].
For deprecated signatures:
- Functional and out variants are not fused - they each get their own signature entry
- There are no varargs signatures
This is currently implemented through the `signature_str()` and `signature_str_vararg()` methods on the `PythonSignature`/`PythonSignatureDeprecated` classes. `signature_str()` knows how to print itself with/without out arguments, differently for native/deprecated ops. `signature_str_vararg()` optionally returns a vararg variant of the signature if one exists.
**Calling out the gap between python_arg_parser vs. pyi**
The two formats are notably different, so I don’t think we can expect to unify them completely. That said, I encountered a number of differences in the pyi codegen that looked wrong- I tried to call them out in the PR, to be removed later. Just as an example, looking at the `svd` signature in the python_arg_parser vs. the pyi type hint:
python_arg_parser
```
Static PythonArgParser parser({
“svd(Tensor input, bool some=True, bool compute_uv=True, *, TensorList[3] out=None”,
}, /*traceable=*/true);
```
Pyi
```
def svd(input: Tensor, some: _bool=True, compute_uv: _bool=True, *, out: Optional[Tensor]=None) -> namedtuple_U_S_V: …
```
The two have obvious syntactic differences that we probably don’t plan on changing: the python_arg_parser doesn’t include `def` or return types, and it includes the type hint before the variable name. But the type of `out` in pyi is probably wrong, since `svd` has multiple output params. I tried to clearly call out any instances of the pyi codegen diverging in a way that looks buggy, so we can clean it up in a later PR (see the comments for details).
Another particularly ugly “bug” that I kept in to maintain byte-for-byte compatibility is the fact that the pyi codegen groups operator overloads together. It turns out that the only reason it does this (as far as I can tell) is because is tacks on an out argument to signatures that don’t have one, if ANY overloads of that op have an out variant.
E.g. consider the pyi type hints generated for `nanmedian` in `_VF.pyi`:
```
overload
def nanmedian(input: Tensor, *, out: Optional[Tensor]=None) -> Tensor: ...
overload
def nanmedian(input: Tensor, dim: _int, keepdim: _bool=False, *, out: Optional[Tensor]=None) -> namedtuple_values_indices: ...
overload
def nanmedian(input: Tensor, dim: Union[str, ellipsis, None], keepdim: _bool=False, *, out: Optional[Tensor]=None) -> namedtuple_values_indices: ...
```
And the corresponding native_functions.yaml entries:
```
- func: nanmedian(Tensor self) -> Tensor
- func: nanmedian.dim(Tensor self, int dim, bool keepdim=False) -> (Tensor values, Tensor indices)
- func: nanmedian.dim_values(Tensor self, int dim, bool keepdim=False, *, Tensor(a!) values, Tensor(b!) indices) -> (Tensor(a!) values, Tensor(b!) indices)
- func: nanmedian.names_dim(Tensor self, Dimname dim, bool keepdim=False) -> (Tensor values, Tensor indices)
- func: nanmedian.names_dim_values(Tensor self, Dimname dim, bool keepdim=False, *, Tensor(a!) values, Tensor(b!) indices) -> (Tensor(a!) values, Tensor(b!)
```
Signature 2 corresponds to entries 2 and 3 in native_functions, and Signature 3 corresponds to entries 4 and 5. But signature 1 has an optional out argument, even though entry 1 in native_functions.yaml has no out variant.
I’d like to delete that logic in a later PR- that will also have the added benefit no longer requiring to group overloads together in the pyi codegen. We can just operate independently on each PythonSignatureGroup.
**More detailed accounting of the changes**
Per file:
gen_python_functions.py
- `load_signatures()` can now skip deprecated signatures. Needed because pyi only includes deprecated functions, and skips their method variants (maybe we should add them in…?)
- Moved `namedtuple_fieldnames` into python.cpp
- `group_overloads()` can now opt to not sort the overloads (needed for byte-for-byte compact, pyi doesn’t sort for some reason)
Python.py:
- Gave `PythonSignature`and `PythonSignatureDeprecated` a `pyi` flag that tells it whether or not to print itself in pyi vs. python_arg_parser format
- Added a `PythonReturns` dataclass , which is now a member of PythonSignature. It is only used by pyi. I found this useful because python returns need to know how to deal with named tuple returns properly. I also moved `namedtuple_fieldnames` into this file from gen_python_functions
gen_pyi.py
- Merged `get_py_torch_functions` and `get_py_variable_methods` into a single function, since they’re very similar
- Lifted out all of the pyi type hint type-mapping mess and dropped it into python.py. This required updating the mapping to deal with NativeFunction objects instead of the outputs of Declarations.yaml (this was most of the logic in `type_to_python`, `arg_to_type_hint`, and `generate_type_hints`). `generate_type_hints` is now a small orchestration function that gathers the different signatures for each PythonSignatureGroup.
- NamedTuples are now generated by calling `PythonReturn.named_tuple()` (in `generate_named_tuples()`), rather than appending to a global list
A lot of hardcoded pyi signatures still live in `gen_pyi.py`. I didn’t look to closely into whether or not any of that can be removed as part of this PR.
Test Plan: Imported from OSS
Reviewed By: ljk53
Differential Revision: D25343802
Pulled By: bdhirsh
fbshipit-source-id: f73e99e1afef934ff41e4aca3dabf34273459a52
2020-12-07 18:37:38 +00:00
|
|
|
overloads: Sequence[PythonSignatureNativeFunctionPair],
|
2020-11-08 09:03:59 +00:00
|
|
|
) -> Sequence[PythonSignatureGroup]:
|
|
|
|
|
bases: Dict[str, PythonSignatureNativeFunctionPair] = {}
|
|
|
|
|
outplaces: Dict[str, PythonSignatureNativeFunctionPair] = {}
|
2018-01-17 23:27:42 +00:00
|
|
|
|
|
|
|
|
# first group by signature ignoring out arguments
|
2020-11-08 09:03:59 +00:00
|
|
|
for overload in overloads:
|
|
|
|
|
sig = overload.signature.signature_str(skip_outputs=True)
|
|
|
|
|
if overload.function.func.is_out_fn():
|
|
|
|
|
if sig in outplaces:
|
|
|
|
|
raise RuntimeError(
|
2022-04-20 12:51:02 +00:00
|
|
|
f"Found duplicated function definition:\n- {overload.function.func}.\n"
|
|
|
|
|
f"Existing definition:\n- {outplaces[sig].function.func}."
|
2020-11-08 09:03:59 +00:00
|
|
|
)
|
|
|
|
|
outplaces[sig] = overload
|
2018-01-17 23:27:42 +00:00
|
|
|
else:
|
2020-11-08 09:03:59 +00:00
|
|
|
if sig in bases:
|
|
|
|
|
raise RuntimeError(
|
2022-04-20 12:51:02 +00:00
|
|
|
f"Found duplicated function definition:\n- {overload.function.func}.\n"
|
|
|
|
|
f"Existing definition:\n- {bases[sig].function.func}."
|
2020-11-08 09:03:59 +00:00
|
|
|
)
|
|
|
|
|
bases[sig] = overload
|
|
|
|
|
|
|
|
|
|
for sig, out in outplaces.items():
|
|
|
|
|
if sig not in bases:
|
|
|
|
|
candidates: List[str] = []
|
|
|
|
|
for overload in overloads:
|
2022-04-20 12:51:02 +00:00
|
|
|
if (
|
|
|
|
|
str(overload.function.func.name.name)
|
|
|
|
|
== str(out.function.func.name.name)
|
|
|
|
|
and not overload.function.func.is_out_fn()
|
|
|
|
|
and not overload.signature.deprecated
|
|
|
|
|
):
|
|
|
|
|
candidates.append(
|
|
|
|
|
overload.signature.signature_str(skip_outputs=True)
|
|
|
|
|
)
|
2020-11-08 09:03:59 +00:00
|
|
|
out_sig = out.signature.signature_str()
|
2020-02-04 01:45:03 +00:00
|
|
|
raise RuntimeError(
|
2022-04-20 12:51:02 +00:00
|
|
|
f"While identifying overloads, we found an out schema {out_sig} without a corresponding non-out variant. "
|
|
|
|
|
f"We expected the non-out variant to have schema: \n- {sig}\nPlease check that you spelled the schema "
|
|
|
|
|
"correctly in native_functions.yaml. We discovered the following candidate(s): \n"
|
|
|
|
|
+ "\n".join(f"- {candidate}" for candidate in candidates)
|
|
|
|
|
)
|
2020-11-08 09:03:59 +00:00
|
|
|
|
|
|
|
|
grouped: List[PythonSignatureGroup] = []
|
|
|
|
|
for sig, base in bases.items():
|
|
|
|
|
outplace = outplaces.get(sig)
|
2022-04-20 12:51:02 +00:00
|
|
|
grouped.append(
|
|
|
|
|
PythonSignatureGroup(
|
|
|
|
|
# prefer the signature with optional out=... arguments because it's the
|
|
|
|
|
# superset that can be used to parse input for both base and outplace.
|
|
|
|
|
signature=outplace.signature
|
|
|
|
|
if outplace is not None
|
|
|
|
|
else base.signature,
|
|
|
|
|
base=base.function,
|
|
|
|
|
outplace=outplace.function if outplace is not None else None,
|
|
|
|
|
)
|
|
|
|
|
)
|
2020-11-08 09:03:59 +00:00
|
|
|
|
2020-12-11 21:24:55 +00:00
|
|
|
return sort_overloads(grouped)
|
2018-04-19 01:51:35 +00:00
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
|
2018-04-19 01:51:35 +00:00
|
|
|
# This function declares a partial order on declarations, and sorts them according
|
|
|
|
|
# to its linear extension. This is necessary, because there's some ambiguity in the
|
|
|
|
|
# choice of overload, and we want a different order.
|
Port THS to ATen. (#8409)
* Port THS to ATen.
The basic structure of the patch:
- All kernels in aten/src/THS got rewritten as native
functions in aten/src/ATen/native/sparse
I took the liberty to rename some of the kernels,
opting for a longer, more transparent names than
things like 'spaddcmul'.
- Instead of holding fields for sparse tensor in the TH
C struct THSTensor, they are now held in a C++ class
SparseTensorImpl (this explains why I had to do this
all in one go; I can't have *two* reps for sparse
tensors!)
Along the way, we change a key internal representation
invariant: an "empty" sparse tensor has dimI == 1 and
dimV == 0 (this is different from dimI == 0 and dimV == 0
we had before); this ensures that we maintain the invariant
that dim == dimI + dimV. "Scalar" sparse tensors are
made illegal, because there really is no way to properly
express them in COO format.
- Because we haven't ported THCS or any of the traditional
dense TH implementations, there is a new set of adapter
functions in native/LegacyBridge.cpp exclusively devoted
to deciding whether or not to go to the new native implementation
or back to the legacy TH binding (prefixed with th_).
The intent is that when everything gets ported, we can
delete this file.
- I've kept the stubs for all the THS functions, but they now all
error if you try to actually call them. Eventually, we should
replace these with calls to ATen so that everything keeps
working.
- I gobbled up SparseMM (SparseMM.cpp is no more). It was tasty.
There are some miscellaneous improvements which were needed for other
changes in this patch:
- There is now AT_FORALL_SCALAR_TYPES_EXCEPT_HALF, which does what
it says on the tin.
- axpy templated function moved to TH/BlasUtils.h, there's a new macro
which lets you easily forward to all of the TH functions. We also expose
THBlas_copy. I'm not terribly pleased with these functions but
they seem to serve a purpose they need.
- New method on Tensor to get TensorImpl*, unsafeGetTensorImpl
- accessor() is now this-const, since const-correctness on Tensor is a lie
- New toSparse()/toDense() methods on Type; now you can call these
directly without having to manually apply at::toSparse/toDense
on the Backend and then running toBackend yourself.
Changes to the kernels:
- Previously, the whole body of all kernels was compiled for
every supported scalar type. In our new implementation,
the scalar dispatch has been pushed into the smallest extent
which (1) is not in a type loop and (2) requires statically
knowing the scalar type. These sites all use
AT_DISPATCH_ALL_TYPES. I tried to use lambdas as much as
possible, but sometimes it was not possible when a OpenMP
pragma was used.
- Anywhere we tested if the nDimension of a tensor was zero,
we replaced with a test that numel is zero. Because, as we
known, nDimension of zero-size tensors in TH is zero, and
that's wrong wrong wrong (and not done this way in ATen).
Some subtleties:
- Places where previously fastget1d was used, I now use a
TensorAccessor. However, you have to be careful about grabbing
the accessor, because sometimes you will be accessor'ing
indices/values and they are empty, which means they will
be *1D* ("oh, aren't indices always 2D?" Nope. Nyet.)
So, essentially, it is only safe to grab an accessor *after*
you have checked that nnz != 0. All of these shenanigans
will go away when we properly support zero-size dimensions.
A few places, we test for this case just by wrapping the loop
in a conditional on nnz. Some other places this is not so easy,
so we instead short-circuit the function with a special case for
when nnz == 0 (usually, these implementations are degenerate).
- There is a very subtle but important difference between
_sparse_get_impl(self)->indices() and self._indices();
the latter may return a view! This is because nnz is
not guaranteed to match the dimensions of indices/values;
you can "truncate" a sparse tensor by setting the nnz.
Actually, I think this is not a good idea and we should
enforce a stronger invariant, but for this patch I slavishly
adhere to the old ways, and as such I have to be very
careful if I want to resize something, I had better use
the former and not the latter.
- I had to reimplement broadcasting by hand (thus the s_
and non-s_ functions in the sparse native files). There
is a very important distinction between foo_out and foo_,
so it is important that the LegacyBridge function always
call to the lower layer, and not try to avoid boilerplate
by calling to another LegacyBridge function first.
I did NOT put broadcasting in LegacyBridge (even though,
ultimately, that's where it must live), because the th_
functions which are invoked from LegacyBridge handle
broadcasting themselves, and I don't want to broadcast
twice.
- Sparse function MUST explicitly specify the Type they
dispatch from, otherwise Variable wrapping/unwrapping will
not work correctly. If you use _get_sparse_impl, that is
sufficient to levy this requirement.
- The "has native" tests in LegacyBridge.cpp are not 100%,
because some of the functions are mixed dense-sparse functions,
and so you can't just say, "Oh, if it's sparse and CPU, call
the native sparse implementation." This is handled on a
case by case basis. There is some especially complex
logic for add(), which has dense-dense, sparse-sparse
and dense-sparse implementations.
- I added some uses of SparseTensorRef in native_functions.yaml,
but you will notice that these are all on native_* functions,
and not the actual, top-level functions. So the SparseTensorRef
is purely documentary (helping you not call the wrong overload)
but there is no magic; we do the wrapping ourselves the hard
way. (This is in constrast to the TH binding code which is magical.)
Except for _sparse_mask; _sparse_mask is magical.
- There is a raw_copy_sparse_ method, which is really my way of
getting around the fact that copy_ has never been implemented
for sparse tensors (even before this patch), but there IS a
super secret, internal way of doing these copies that the THS
code used, and which I needed to get my hands on when I did this
port. We should refactor so that either (a) copy_ does support
sparse-sparse copy natively, or (b) we do this other ways.
- Irritatingly, I must explicitly resize_as_ before copy_ into
a tensor. This was not the case with THTensor_(copy) but I don't
have any direct binding that doesn't have this requirement.
- For some reason, the sparse tensor constructor accepts a scalar
tensor for the values tensor. This is kind of weird because
you always need an nnz-dimension. However, the old code supported
this and just expanded it into a 1D size 0 tensor; so we need some
explicit code to do this.
There are maybe a bit more AT_ASSERTs in some of the kernels
than is wise. I added them all when I was debugging and was
loathe to remove them.
Some last mile fixes after this commit went into PR
- Move expand outside of dispatch so autograd works (it used to be inside and then we lost all of the recorded broadcasts).
- Hack to duplicate the derivatives for our now two definitions TH and native. Mercifully the derivatives are short.
- Apparently, TH has a special case to make foo_ functions method only, and if you don't do this the Python arg parsing is wrong. We carefully work around this in the native bindings
- Apply DCE to a test_jit case, fixes wobbling due to DCE trick in tracing
- Update test_function's output
- Some last mile fixes for dispatch confusion in sparse_coo_tensor functions.
- New simplified regression test based on failures I saw in ONNX
- Increase tolerance on super resolution test
- More robust dynamic_type normalization, fixes ONNX bug.
The dynamic_type situation is very delicate; probably need
to stop having both Scalar and real.
- Make new_with_tensor_sparse more CUDA safe
- Note about CUDA-safety in SparseTensorImpl
- Rename dimI/dimV to sparseDims/denseDims.
- Make localScalar on SparseTensorImpl work.
- Make numel uniformly supported on all types, not just dense
types
- Add tests for is_nonzero() method (which exercises localScalar)
- Disable constant JIT autogenerated tests, which are fragile and broken
by this change, but being fixed in a parallel track.
Signed-off-by: Edward Z. Yang <ezyang@fb.com>
2018-06-15 21:52:21 +00:00
|
|
|
#
|
|
|
|
|
# See Note[Order of overloads matters]
|
2020-01-30 08:26:16 +00:00
|
|
|
#
|
2020-11-08 09:03:59 +00:00
|
|
|
# A few examples of ambiguous python signature pairs.
|
2020-01-30 08:26:16 +00:00
|
|
|
#
|
2020-11-08 09:03:59 +00:00
|
|
|
# All parameters have the same type, except one taking Tensor the other taking
|
|
|
|
|
# Scalar. A numeric PyObject can be casted into Tensor, and a zero-dim Tensor
|
|
|
|
|
# object can be accepted as Scalar type parameter (see python_arg_parser.cpp).
|
|
|
|
|
# Therefore, same input arguments might be accepted by either python signature.
|
|
|
|
|
# We want to always parse the one taking Tensor first.
|
2020-01-30 08:26:16 +00:00
|
|
|
#
|
2020-11-08 09:03:59 +00:00
|
|
|
# bitwise_and(Tensor input, Tensor other, *, Tensor out=None)
|
|
|
|
|
# bitwise_and(Tensor input, Scalar other, *, Tensor out=None)
|
2020-01-30 08:26:16 +00:00
|
|
|
#
|
2020-11-08 09:03:59 +00:00
|
|
|
# If they have different number of parameters then they are not ambiguous - but
|
|
|
|
|
# the difference on output param can be ignored as it's optional.
|
2020-01-30 08:26:16 +00:00
|
|
|
#
|
2020-11-08 09:03:59 +00:00
|
|
|
# multiply(Tensor input, Tensor other, *, Tensor out=None)
|
|
|
|
|
# multiply(Tensor input, Scalar other)
|
|
|
|
|
#
|
|
|
|
|
# Both positional args and keyword-only args are considered together.
|
|
|
|
|
#
|
|
|
|
|
# subtract(Tensor other, *, Scalar alpha=1)
|
|
|
|
|
# subtract(Scalar other, Scalar alpha=1)
|
|
|
|
|
#
|
|
|
|
|
# A few ambiguous cases which it does NOT handle yet.
|
|
|
|
|
#
|
|
|
|
|
# If there is any difference in other parameters besides the Tensor/Scalar
|
|
|
|
|
# difference, then they are not considered ambiguous by this method anymore.
|
|
|
|
|
# However, the difference could be too trivial to disambiguate.
|
|
|
|
|
#
|
|
|
|
|
# foo(Tensor input, Scalar other, Scalar bar)
|
|
|
|
|
# foo(Tensor input, Tensor other, double bar)
|
|
|
|
|
#
|
|
|
|
|
# If they are taking different number of parameters then they are not considered
|
|
|
|
|
# ambiguous anymore, even if the difference is only on optional kwargs.
|
|
|
|
|
#
|
|
|
|
|
# foo(Scalar other, Scalar alpha=1)
|
|
|
|
|
# foo(Tensor other, *, Scalar alpha=1, Scalar beta=1)
|
2020-01-30 08:26:16 +00:00
|
|
|
#
|
|
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
|
2020-11-08 09:03:59 +00:00
|
|
|
def sort_overloads(
|
2022-04-20 12:51:02 +00:00
|
|
|
grouped_overloads: Sequence[PythonSignatureGroup],
|
2020-11-08 09:03:59 +00:00
|
|
|
) -> Sequence[PythonSignatureGroup]:
|
|
|
|
|
def is_arg_smaller(t1: Type, t2: Type) -> bool:
|
2022-04-20 12:51:02 +00:00
|
|
|
return (
|
|
|
|
|
str(t1) == "Scalar"
|
|
|
|
|
and str(t2) == "Tensor"
|
|
|
|
|
or "Dimname" in str(t1)
|
|
|
|
|
and "Dimname" not in str(t2)
|
|
|
|
|
or
|
|
|
|
|
# In the discussion https://github.com/pytorch/pytorch/issues/54555 it has been
|
|
|
|
|
# discussed why it is important to prioritize int/int? over int[]
|
|
|
|
|
str(t1) == "int[]"
|
|
|
|
|
and (str(t2) == "int" or str(t2) == "int?")
|
|
|
|
|
or
|
|
|
|
|
# TensorList currently throws an error during argument parsing, that's why it needs to be
|
|
|
|
|
# last in signature ordering. See discussion: https://github.com/pytorch/pytorch/issues/58087
|
|
|
|
|
str(t1) == "Tensor[]"
|
|
|
|
|
and str(t2).find("[]") != -1
|
|
|
|
|
)
|
2020-01-30 08:26:16 +00:00
|
|
|
|
2020-11-08 09:03:59 +00:00
|
|
|
def is_smaller(s1: PythonSignature, s2: PythonSignature) -> bool:
|
|
|
|
|
"""Returns True if s1 < s2 in the partial order."""
|
|
|
|
|
args1, args2 = s1.arguments(skip_outputs=True), s2.arguments(skip_outputs=True)
|
|
|
|
|
if len(args1) != len(args2):
|
|
|
|
|
return False
|
|
|
|
|
# TODO: should use some canonical form instead of 'str(arg.type)' - see comments
|
|
|
|
|
# above. The old codegen used the deprecated 'dynamic_type(arg.type)', which
|
|
|
|
|
# ignores the optional annotation, i.e. 'Scalar' and 'Scalar?'.
|
|
|
|
|
equal = all(arg1.type == arg2.type for arg1, arg2 in zip(args1, args2))
|
2022-04-20 12:51:02 +00:00
|
|
|
smaller_or_equal = all(
|
|
|
|
|
str(arg1.type) == str(arg2.type) or is_arg_smaller(arg1.type, arg2.type)
|
|
|
|
|
for arg1, arg2 in zip(args1, args2)
|
|
|
|
|
)
|
2020-11-08 09:03:59 +00:00
|
|
|
return smaller_or_equal and not equal
|
|
|
|
|
|
|
|
|
|
# First sort by signature
|
2022-04-20 12:51:02 +00:00
|
|
|
grouped_overloads = sorted(
|
|
|
|
|
grouped_overloads, key=lambda x: x.signature.signature_str()
|
|
|
|
|
)
|
2020-08-06 07:18:51 +00:00
|
|
|
|
2020-11-08 09:03:59 +00:00
|
|
|
# Construct the relation graph
|
|
|
|
|
larger_than: Dict[int, Set[int]] = defaultdict(set)
|
|
|
|
|
for i1, overload1 in enumerate(grouped_overloads):
|
|
|
|
|
for i2, overload2 in enumerate(grouped_overloads):
|
|
|
|
|
if is_smaller(overload1.signature, overload2.signature):
|
|
|
|
|
larger_than[i1].add(i2)
|
[pytorch] rewrite of the python binding codegen with the v2 API (#46244)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/46244
- What does the generated binding code do?
The Python binding codegen produces code that takes the input list of
PyObjects, finds the matching ATen C++ function using PythonArgParser,
converts the PyObjects into C++ types and calls the ATen C++ function:
```
+--------+ parsing +------------------------+ binding +-----------------------+
| PyObjs | ---------> | PythonArgParser Output | ---------> | Cpp Function Dispatch |
+--------+ +------------------------+ +-----------------------+
```
- Are Python arguments 1-1 mapped to C++ arguments?
Python arguments might be reordered, packed, unpacked when binding to
C++ arguments, as illustrated below:
```
// Binding - Reorder & Packing
// aten::empty.names(int[] size, *, Dimname[]? names, ScalarType? dtype=None, Layout? layout=None,
Device? device=None, bool? pin_memory=None, MemoryFormat? memory_format=None) -> Tensor
Python Args Cpp Args
-----------------------------------------------------------
0: size size
1: names names
2: memory_format -------+
3: dtype -----+-|--> options
4: layout / |
5: device / +--> memory_format
6: pin_memory /
7: requires_grad -+
// Binding - Unpacking
// aten::max.names_dim(Tensor self, Dimname dim, bool keepdim=False) -> (Tensor values, Tensor indices)
Python Args Cpp Args
-----------------------------------------------------------
+----> max
/-----> max_values
0: input / self
1: dim / dim
2: keepdim / keepdim
3: out -----+
```
- Why do we want to rewrite the python binding codegen?
The old codegen takes Declarations.yaml as input. It doesn't distinguish
between Python arguments and C++ arguments - they are all mixed together
as a bag of non-typed dict objects. Different methods process these arg
objects and add new attributes for various different purposes. It's not so
obvious to figure out the semantics of these attributes. The complicated
binding logic happens implicitly and scatteredly.
```
+--------------------+
| Native Functions |
+--------------------+
|
|
v
+--------------------+
| Cpp Signatures |
+--------------------+
|
|
v
+--------------------+
| Declarations.yaml |
+--------------------+
| +-------------------------------------+
| +-------> | PythonArgParser Schema |
| | +-------------------------------------+
| | .
| | .
v | .
+--------------------+ +-------------------------------------+
| NonTyped Args Objs | --> | PythonArgParser -> Cpp Args Binding |
+--------------------+ +-------------------------------------+
| .
| .
| .
| +-------------------------------------+
+-------> | Cpp Function Dispatch |
+-------------------------------------+
```
This PR leverages the new immutable data models introduced in the new
aten codegen. It introduces dedicated data models for python schema.
This way, we can not only avoid subtle Declaration.yaml conversions but
also decouple the generation of python schema, python to c++ binding and
c++ function call.
The ultimate state will be like the following diagram:
```
+-------------------+ +-------------------------------------+
+-------> | Python Signatures | --> | PythonArgParser Schema |
| +-------------------+ +-------------------------------------+
| | .
| | .
| | .
+------------------+ | +-------------------------------------+
| Native Functions | +-------> | PythonArgParser -> Cpp Args Binding |
+------------------+ | +-------------------------------------+
| | .
| | .
| | .
| +-------------------+ +-------------------------------------+
+-------> | Cpp Signatures | --> | Cpp Function Dispatch |
+-------------------+ +-------------------------------------+
```
This PR has migrated the core binding logic from
tools/autograd/gen_python_functions.py to tools/codegen/api/python.py.
It produces the byte-for-byte same results (tested with #46243).
Will migrate the rest of gen_python_functions.py in subsequent PRs.
Test Plan: Imported from OSS
Reviewed By: bhosmer
Differential Revision: D24388874
Pulled By: ljk53
fbshipit-source-id: f88b6df4e917cf90d868a2bbae2d5ffb680d1841
2020-10-20 00:34:45 +00:00
|
|
|
|
2020-11-08 09:03:59 +00:00
|
|
|
if not larger_than:
|
|
|
|
|
return list(grouped_overloads)
|
2020-08-07 17:16:56 +00:00
|
|
|
|
2020-11-08 09:03:59 +00:00
|
|
|
# Use a topological sort to sort overloads according to the partial order.
|
|
|
|
|
N = len(grouped_overloads)
|
|
|
|
|
sorted_ids: List[int] = list(filter(lambda x: x not in larger_than, range(N)))
|
2020-08-06 07:18:51 +00:00
|
|
|
|
2020-11-08 09:03:59 +00:00
|
|
|
for idx in range(N):
|
|
|
|
|
# The size of sorted_ids will grow to N eventually.
|
|
|
|
|
i = sorted_ids[idx]
|
|
|
|
|
for j in sorted(larger_than.keys()):
|
|
|
|
|
larger = larger_than[j]
|
|
|
|
|
larger.discard(i)
|
|
|
|
|
if not larger:
|
|
|
|
|
del larger_than[j]
|
|
|
|
|
sorted_ids.append(j)
|
[pytorch] rewrite of the python binding codegen with the v2 API (#46244)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/46244
- What does the generated binding code do?
The Python binding codegen produces code that takes the input list of
PyObjects, finds the matching ATen C++ function using PythonArgParser,
converts the PyObjects into C++ types and calls the ATen C++ function:
```
+--------+ parsing +------------------------+ binding +-----------------------+
| PyObjs | ---------> | PythonArgParser Output | ---------> | Cpp Function Dispatch |
+--------+ +------------------------+ +-----------------------+
```
- Are Python arguments 1-1 mapped to C++ arguments?
Python arguments might be reordered, packed, unpacked when binding to
C++ arguments, as illustrated below:
```
// Binding - Reorder & Packing
// aten::empty.names(int[] size, *, Dimname[]? names, ScalarType? dtype=None, Layout? layout=None,
Device? device=None, bool? pin_memory=None, MemoryFormat? memory_format=None) -> Tensor
Python Args Cpp Args
-----------------------------------------------------------
0: size size
1: names names
2: memory_format -------+
3: dtype -----+-|--> options
4: layout / |
5: device / +--> memory_format
6: pin_memory /
7: requires_grad -+
// Binding - Unpacking
// aten::max.names_dim(Tensor self, Dimname dim, bool keepdim=False) -> (Tensor values, Tensor indices)
Python Args Cpp Args
-----------------------------------------------------------
+----> max
/-----> max_values
0: input / self
1: dim / dim
2: keepdim / keepdim
3: out -----+
```
- Why do we want to rewrite the python binding codegen?
The old codegen takes Declarations.yaml as input. It doesn't distinguish
between Python arguments and C++ arguments - they are all mixed together
as a bag of non-typed dict objects. Different methods process these arg
objects and add new attributes for various different purposes. It's not so
obvious to figure out the semantics of these attributes. The complicated
binding logic happens implicitly and scatteredly.
```
+--------------------+
| Native Functions |
+--------------------+
|
|
v
+--------------------+
| Cpp Signatures |
+--------------------+
|
|
v
+--------------------+
| Declarations.yaml |
+--------------------+
| +-------------------------------------+
| +-------> | PythonArgParser Schema |
| | +-------------------------------------+
| | .
| | .
v | .
+--------------------+ +-------------------------------------+
| NonTyped Args Objs | --> | PythonArgParser -> Cpp Args Binding |
+--------------------+ +-------------------------------------+
| .
| .
| .
| +-------------------------------------+
+-------> | Cpp Function Dispatch |
+-------------------------------------+
```
This PR leverages the new immutable data models introduced in the new
aten codegen. It introduces dedicated data models for python schema.
This way, we can not only avoid subtle Declaration.yaml conversions but
also decouple the generation of python schema, python to c++ binding and
c++ function call.
The ultimate state will be like the following diagram:
```
+-------------------+ +-------------------------------------+
+-------> | Python Signatures | --> | PythonArgParser Schema |
| +-------------------+ +-------------------------------------+
| | .
| | .
| | .
+------------------+ | +-------------------------------------+
| Native Functions | +-------> | PythonArgParser -> Cpp Args Binding |
+------------------+ | +-------------------------------------+
| | .
| | .
| | .
| +-------------------+ +-------------------------------------+
+-------> | Cpp Signatures | --> | Cpp Function Dispatch |
+-------------------+ +-------------------------------------+
```
This PR has migrated the core binding logic from
tools/autograd/gen_python_functions.py to tools/codegen/api/python.py.
It produces the byte-for-byte same results (tested with #46243).
Will migrate the rest of gen_python_functions.py in subsequent PRs.
Test Plan: Imported from OSS
Reviewed By: bhosmer
Differential Revision: D24388874
Pulled By: ljk53
fbshipit-source-id: f88b6df4e917cf90d868a2bbae2d5ffb680d1841
2020-10-20 00:34:45 +00:00
|
|
|
|
2020-11-08 09:03:59 +00:00
|
|
|
return list(map(lambda x: grouped_overloads[x], sorted_ids))
|
[pytorch] rewrite of the python binding codegen with the v2 API (#46244)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/46244
- What does the generated binding code do?
The Python binding codegen produces code that takes the input list of
PyObjects, finds the matching ATen C++ function using PythonArgParser,
converts the PyObjects into C++ types and calls the ATen C++ function:
```
+--------+ parsing +------------------------+ binding +-----------------------+
| PyObjs | ---------> | PythonArgParser Output | ---------> | Cpp Function Dispatch |
+--------+ +------------------------+ +-----------------------+
```
- Are Python arguments 1-1 mapped to C++ arguments?
Python arguments might be reordered, packed, unpacked when binding to
C++ arguments, as illustrated below:
```
// Binding - Reorder & Packing
// aten::empty.names(int[] size, *, Dimname[]? names, ScalarType? dtype=None, Layout? layout=None,
Device? device=None, bool? pin_memory=None, MemoryFormat? memory_format=None) -> Tensor
Python Args Cpp Args
-----------------------------------------------------------
0: size size
1: names names
2: memory_format -------+
3: dtype -----+-|--> options
4: layout / |
5: device / +--> memory_format
6: pin_memory /
7: requires_grad -+
// Binding - Unpacking
// aten::max.names_dim(Tensor self, Dimname dim, bool keepdim=False) -> (Tensor values, Tensor indices)
Python Args Cpp Args
-----------------------------------------------------------
+----> max
/-----> max_values
0: input / self
1: dim / dim
2: keepdim / keepdim
3: out -----+
```
- Why do we want to rewrite the python binding codegen?
The old codegen takes Declarations.yaml as input. It doesn't distinguish
between Python arguments and C++ arguments - they are all mixed together
as a bag of non-typed dict objects. Different methods process these arg
objects and add new attributes for various different purposes. It's not so
obvious to figure out the semantics of these attributes. The complicated
binding logic happens implicitly and scatteredly.
```
+--------------------+
| Native Functions |
+--------------------+
|
|
v
+--------------------+
| Cpp Signatures |
+--------------------+
|
|
v
+--------------------+
| Declarations.yaml |
+--------------------+
| +-------------------------------------+
| +-------> | PythonArgParser Schema |
| | +-------------------------------------+
| | .
| | .
v | .
+--------------------+ +-------------------------------------+
| NonTyped Args Objs | --> | PythonArgParser -> Cpp Args Binding |
+--------------------+ +-------------------------------------+
| .
| .
| .
| +-------------------------------------+
+-------> | Cpp Function Dispatch |
+-------------------------------------+
```
This PR leverages the new immutable data models introduced in the new
aten codegen. It introduces dedicated data models for python schema.
This way, we can not only avoid subtle Declaration.yaml conversions but
also decouple the generation of python schema, python to c++ binding and
c++ function call.
The ultimate state will be like the following diagram:
```
+-------------------+ +-------------------------------------+
+-------> | Python Signatures | --> | PythonArgParser Schema |
| +-------------------+ +-------------------------------------+
| | .
| | .
| | .
+------------------+ | +-------------------------------------+
| Native Functions | +-------> | PythonArgParser -> Cpp Args Binding |
+------------------+ | +-------------------------------------+
| | .
| | .
| | .
| +-------------------+ +-------------------------------------+
+-------> | Cpp Signatures | --> | Cpp Function Dispatch |
+-------------------+ +-------------------------------------+
```
This PR has migrated the core binding logic from
tools/autograd/gen_python_functions.py to tools/codegen/api/python.py.
It produces the byte-for-byte same results (tested with #46243).
Will migrate the rest of gen_python_functions.py in subsequent PRs.
Test Plan: Imported from OSS
Reviewed By: bhosmer
Differential Revision: D24388874
Pulled By: ljk53
fbshipit-source-id: f88b6df4e917cf90d868a2bbae2d5ffb680d1841
2020-10-20 00:34:45 +00:00
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
|
[pytorch] rewrite of the python binding codegen with the v2 API (#46244)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/46244
- What does the generated binding code do?
The Python binding codegen produces code that takes the input list of
PyObjects, finds the matching ATen C++ function using PythonArgParser,
converts the PyObjects into C++ types and calls the ATen C++ function:
```
+--------+ parsing +------------------------+ binding +-----------------------+
| PyObjs | ---------> | PythonArgParser Output | ---------> | Cpp Function Dispatch |
+--------+ +------------------------+ +-----------------------+
```
- Are Python arguments 1-1 mapped to C++ arguments?
Python arguments might be reordered, packed, unpacked when binding to
C++ arguments, as illustrated below:
```
// Binding - Reorder & Packing
// aten::empty.names(int[] size, *, Dimname[]? names, ScalarType? dtype=None, Layout? layout=None,
Device? device=None, bool? pin_memory=None, MemoryFormat? memory_format=None) -> Tensor
Python Args Cpp Args
-----------------------------------------------------------
0: size size
1: names names
2: memory_format -------+
3: dtype -----+-|--> options
4: layout / |
5: device / +--> memory_format
6: pin_memory /
7: requires_grad -+
// Binding - Unpacking
// aten::max.names_dim(Tensor self, Dimname dim, bool keepdim=False) -> (Tensor values, Tensor indices)
Python Args Cpp Args
-----------------------------------------------------------
+----> max
/-----> max_values
0: input / self
1: dim / dim
2: keepdim / keepdim
3: out -----+
```
- Why do we want to rewrite the python binding codegen?
The old codegen takes Declarations.yaml as input. It doesn't distinguish
between Python arguments and C++ arguments - they are all mixed together
as a bag of non-typed dict objects. Different methods process these arg
objects and add new attributes for various different purposes. It's not so
obvious to figure out the semantics of these attributes. The complicated
binding logic happens implicitly and scatteredly.
```
+--------------------+
| Native Functions |
+--------------------+
|
|
v
+--------------------+
| Cpp Signatures |
+--------------------+
|
|
v
+--------------------+
| Declarations.yaml |
+--------------------+
| +-------------------------------------+
| +-------> | PythonArgParser Schema |
| | +-------------------------------------+
| | .
| | .
v | .
+--------------------+ +-------------------------------------+
| NonTyped Args Objs | --> | PythonArgParser -> Cpp Args Binding |
+--------------------+ +-------------------------------------+
| .
| .
| .
| +-------------------------------------+
+-------> | Cpp Function Dispatch |
+-------------------------------------+
```
This PR leverages the new immutable data models introduced in the new
aten codegen. It introduces dedicated data models for python schema.
This way, we can not only avoid subtle Declaration.yaml conversions but
also decouple the generation of python schema, python to c++ binding and
c++ function call.
The ultimate state will be like the following diagram:
```
+-------------------+ +-------------------------------------+
+-------> | Python Signatures | --> | PythonArgParser Schema |
| +-------------------+ +-------------------------------------+
| | .
| | .
| | .
+------------------+ | +-------------------------------------+
| Native Functions | +-------> | PythonArgParser -> Cpp Args Binding |
+------------------+ | +-------------------------------------+
| | .
| | .
| | .
| +-------------------+ +-------------------------------------+
+-------> | Cpp Signatures | --> | Cpp Function Dispatch |
+-------------------+ +-------------------------------------+
```
This PR has migrated the core binding logic from
tools/autograd/gen_python_functions.py to tools/codegen/api/python.py.
It produces the byte-for-byte same results (tested with #46243).
Will migrate the rest of gen_python_functions.py in subsequent PRs.
Test Plan: Imported from OSS
Reviewed By: bhosmer
Differential Revision: D24388874
Pulled By: ljk53
fbshipit-source-id: f88b6df4e917cf90d868a2bbae2d5ffb680d1841
2020-10-20 00:34:45 +00:00
|
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
|
|
|
|
|
#
|
|
|
|
|
# Codegen API Integration
|
|
|
|
|
#
|
|
|
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
|
|
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
|
2020-11-08 09:03:59 +00:00
|
|
|
def emit_single_dispatch(
|
|
|
|
|
ps: PythonSignature, f: NativeFunction, namedtuple_typenames: Dict[str, str]
|
|
|
|
|
) -> str:
|
[pytorch] rewrite of the python binding codegen with the v2 API (#46244)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/46244
- What does the generated binding code do?
The Python binding codegen produces code that takes the input list of
PyObjects, finds the matching ATen C++ function using PythonArgParser,
converts the PyObjects into C++ types and calls the ATen C++ function:
```
+--------+ parsing +------------------------+ binding +-----------------------+
| PyObjs | ---------> | PythonArgParser Output | ---------> | Cpp Function Dispatch |
+--------+ +------------------------+ +-----------------------+
```
- Are Python arguments 1-1 mapped to C++ arguments?
Python arguments might be reordered, packed, unpacked when binding to
C++ arguments, as illustrated below:
```
// Binding - Reorder & Packing
// aten::empty.names(int[] size, *, Dimname[]? names, ScalarType? dtype=None, Layout? layout=None,
Device? device=None, bool? pin_memory=None, MemoryFormat? memory_format=None) -> Tensor
Python Args Cpp Args
-----------------------------------------------------------
0: size size
1: names names
2: memory_format -------+
3: dtype -----+-|--> options
4: layout / |
5: device / +--> memory_format
6: pin_memory /
7: requires_grad -+
// Binding - Unpacking
// aten::max.names_dim(Tensor self, Dimname dim, bool keepdim=False) -> (Tensor values, Tensor indices)
Python Args Cpp Args
-----------------------------------------------------------
+----> max
/-----> max_values
0: input / self
1: dim / dim
2: keepdim / keepdim
3: out -----+
```
- Why do we want to rewrite the python binding codegen?
The old codegen takes Declarations.yaml as input. It doesn't distinguish
between Python arguments and C++ arguments - they are all mixed together
as a bag of non-typed dict objects. Different methods process these arg
objects and add new attributes for various different purposes. It's not so
obvious to figure out the semantics of these attributes. The complicated
binding logic happens implicitly and scatteredly.
```
+--------------------+
| Native Functions |
+--------------------+
|
|
v
+--------------------+
| Cpp Signatures |
+--------------------+
|
|
v
+--------------------+
| Declarations.yaml |
+--------------------+
| +-------------------------------------+
| +-------> | PythonArgParser Schema |
| | +-------------------------------------+
| | .
| | .
v | .
+--------------------+ +-------------------------------------+
| NonTyped Args Objs | --> | PythonArgParser -> Cpp Args Binding |
+--------------------+ +-------------------------------------+
| .
| .
| .
| +-------------------------------------+
+-------> | Cpp Function Dispatch |
+-------------------------------------+
```
This PR leverages the new immutable data models introduced in the new
aten codegen. It introduces dedicated data models for python schema.
This way, we can not only avoid subtle Declaration.yaml conversions but
also decouple the generation of python schema, python to c++ binding and
c++ function call.
The ultimate state will be like the following diagram:
```
+-------------------+ +-------------------------------------+
+-------> | Python Signatures | --> | PythonArgParser Schema |
| +-------------------+ +-------------------------------------+
| | .
| | .
| | .
+------------------+ | +-------------------------------------+
| Native Functions | +-------> | PythonArgParser -> Cpp Args Binding |
+------------------+ | +-------------------------------------+
| | .
| | .
| | .
| +-------------------+ +-------------------------------------+
+-------> | Cpp Signatures | --> | Cpp Function Dispatch |
+-------------------+ +-------------------------------------+
```
This PR has migrated the core binding logic from
tools/autograd/gen_python_functions.py to tools/codegen/api/python.py.
It produces the byte-for-byte same results (tested with #46243).
Will migrate the rest of gen_python_functions.py in subsequent PRs.
Test Plan: Imported from OSS
Reviewed By: bhosmer
Differential Revision: D24388874
Pulled By: ljk53
fbshipit-source-id: f88b6df4e917cf90d868a2bbae2d5ffb680d1841
2020-10-20 00:34:45 +00:00
|
|
|
"""
|
2020-11-08 09:03:59 +00:00
|
|
|
Emit dispatch code for a single native function.
|
[pytorch] rewrite of the python binding codegen with the v2 API (#46244)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/46244
- What does the generated binding code do?
The Python binding codegen produces code that takes the input list of
PyObjects, finds the matching ATen C++ function using PythonArgParser,
converts the PyObjects into C++ types and calls the ATen C++ function:
```
+--------+ parsing +------------------------+ binding +-----------------------+
| PyObjs | ---------> | PythonArgParser Output | ---------> | Cpp Function Dispatch |
+--------+ +------------------------+ +-----------------------+
```
- Are Python arguments 1-1 mapped to C++ arguments?
Python arguments might be reordered, packed, unpacked when binding to
C++ arguments, as illustrated below:
```
// Binding - Reorder & Packing
// aten::empty.names(int[] size, *, Dimname[]? names, ScalarType? dtype=None, Layout? layout=None,
Device? device=None, bool? pin_memory=None, MemoryFormat? memory_format=None) -> Tensor
Python Args Cpp Args
-----------------------------------------------------------
0: size size
1: names names
2: memory_format -------+
3: dtype -----+-|--> options
4: layout / |
5: device / +--> memory_format
6: pin_memory /
7: requires_grad -+
// Binding - Unpacking
// aten::max.names_dim(Tensor self, Dimname dim, bool keepdim=False) -> (Tensor values, Tensor indices)
Python Args Cpp Args
-----------------------------------------------------------
+----> max
/-----> max_values
0: input / self
1: dim / dim
2: keepdim / keepdim
3: out -----+
```
- Why do we want to rewrite the python binding codegen?
The old codegen takes Declarations.yaml as input. It doesn't distinguish
between Python arguments and C++ arguments - they are all mixed together
as a bag of non-typed dict objects. Different methods process these arg
objects and add new attributes for various different purposes. It's not so
obvious to figure out the semantics of these attributes. The complicated
binding logic happens implicitly and scatteredly.
```
+--------------------+
| Native Functions |
+--------------------+
|
|
v
+--------------------+
| Cpp Signatures |
+--------------------+
|
|
v
+--------------------+
| Declarations.yaml |
+--------------------+
| +-------------------------------------+
| +-------> | PythonArgParser Schema |
| | +-------------------------------------+
| | .
| | .
v | .
+--------------------+ +-------------------------------------+
| NonTyped Args Objs | --> | PythonArgParser -> Cpp Args Binding |
+--------------------+ +-------------------------------------+
| .
| .
| .
| +-------------------------------------+
+-------> | Cpp Function Dispatch |
+-------------------------------------+
```
This PR leverages the new immutable data models introduced in the new
aten codegen. It introduces dedicated data models for python schema.
This way, we can not only avoid subtle Declaration.yaml conversions but
also decouple the generation of python schema, python to c++ binding and
c++ function call.
The ultimate state will be like the following diagram:
```
+-------------------+ +-------------------------------------+
+-------> | Python Signatures | --> | PythonArgParser Schema |
| +-------------------+ +-------------------------------------+
| | .
| | .
| | .
+------------------+ | +-------------------------------------+
| Native Functions | +-------> | PythonArgParser -> Cpp Args Binding |
+------------------+ | +-------------------------------------+
| | .
| | .
| | .
| +-------------------+ +-------------------------------------+
+-------> | Cpp Signatures | --> | Cpp Function Dispatch |
+-------------------+ +-------------------------------------+
```
This PR has migrated the core binding logic from
tools/autograd/gen_python_functions.py to tools/codegen/api/python.py.
It produces the byte-for-byte same results (tested with #46243).
Will migrate the rest of gen_python_functions.py in subsequent PRs.
Test Plan: Imported from OSS
Reviewed By: bhosmer
Differential Revision: D24388874
Pulled By: ljk53
fbshipit-source-id: f88b6df4e917cf90d868a2bbae2d5ffb680d1841
2020-10-20 00:34:45 +00:00
|
|
|
"""
|
2022-04-20 12:51:02 +00:00
|
|
|
|
[pytorch] rewrite of the python binding codegen with the v2 API (#46244)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/46244
- What does the generated binding code do?
The Python binding codegen produces code that takes the input list of
PyObjects, finds the matching ATen C++ function using PythonArgParser,
converts the PyObjects into C++ types and calls the ATen C++ function:
```
+--------+ parsing +------------------------+ binding +-----------------------+
| PyObjs | ---------> | PythonArgParser Output | ---------> | Cpp Function Dispatch |
+--------+ +------------------------+ +-----------------------+
```
- Are Python arguments 1-1 mapped to C++ arguments?
Python arguments might be reordered, packed, unpacked when binding to
C++ arguments, as illustrated below:
```
// Binding - Reorder & Packing
// aten::empty.names(int[] size, *, Dimname[]? names, ScalarType? dtype=None, Layout? layout=None,
Device? device=None, bool? pin_memory=None, MemoryFormat? memory_format=None) -> Tensor
Python Args Cpp Args
-----------------------------------------------------------
0: size size
1: names names
2: memory_format -------+
3: dtype -----+-|--> options
4: layout / |
5: device / +--> memory_format
6: pin_memory /
7: requires_grad -+
// Binding - Unpacking
// aten::max.names_dim(Tensor self, Dimname dim, bool keepdim=False) -> (Tensor values, Tensor indices)
Python Args Cpp Args
-----------------------------------------------------------
+----> max
/-----> max_values
0: input / self
1: dim / dim
2: keepdim / keepdim
3: out -----+
```
- Why do we want to rewrite the python binding codegen?
The old codegen takes Declarations.yaml as input. It doesn't distinguish
between Python arguments and C++ arguments - they are all mixed together
as a bag of non-typed dict objects. Different methods process these arg
objects and add new attributes for various different purposes. It's not so
obvious to figure out the semantics of these attributes. The complicated
binding logic happens implicitly and scatteredly.
```
+--------------------+
| Native Functions |
+--------------------+
|
|
v
+--------------------+
| Cpp Signatures |
+--------------------+
|
|
v
+--------------------+
| Declarations.yaml |
+--------------------+
| +-------------------------------------+
| +-------> | PythonArgParser Schema |
| | +-------------------------------------+
| | .
| | .
v | .
+--------------------+ +-------------------------------------+
| NonTyped Args Objs | --> | PythonArgParser -> Cpp Args Binding |
+--------------------+ +-------------------------------------+
| .
| .
| .
| +-------------------------------------+
+-------> | Cpp Function Dispatch |
+-------------------------------------+
```
This PR leverages the new immutable data models introduced in the new
aten codegen. It introduces dedicated data models for python schema.
This way, we can not only avoid subtle Declaration.yaml conversions but
also decouple the generation of python schema, python to c++ binding and
c++ function call.
The ultimate state will be like the following diagram:
```
+-------------------+ +-------------------------------------+
+-------> | Python Signatures | --> | PythonArgParser Schema |
| +-------------------+ +-------------------------------------+
| | .
| | .
| | .
+------------------+ | +-------------------------------------+
| Native Functions | +-------> | PythonArgParser -> Cpp Args Binding |
+------------------+ | +-------------------------------------+
| | .
| | .
| | .
| +-------------------+ +-------------------------------------+
+-------> | Cpp Signatures | --> | Cpp Function Dispatch |
+-------------------+ +-------------------------------------+
```
This PR has migrated the core binding logic from
tools/autograd/gen_python_functions.py to tools/codegen/api/python.py.
It produces the byte-for-byte same results (tested with #46243).
Will migrate the rest of gen_python_functions.py in subsequent PRs.
Test Plan: Imported from OSS
Reviewed By: bhosmer
Differential Revision: D24388874
Pulled By: ljk53
fbshipit-source-id: f88b6df4e917cf90d868a2bbae2d5ffb680d1841
2020-10-20 00:34:45 +00:00
|
|
|
@with_native_function
|
|
|
|
|
def go(f: NativeFunction) -> str:
|
|
|
|
|
# header comments
|
2022-04-20 12:51:02 +00:00
|
|
|
deprecated = "[deprecated] " if ps.deprecated else ""
|
|
|
|
|
schema_comment = f"// {deprecated}aten::{f.func}"
|
[pytorch] rewrite of the python binding codegen with the v2 API (#46244)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/46244
- What does the generated binding code do?
The Python binding codegen produces code that takes the input list of
PyObjects, finds the matching ATen C++ function using PythonArgParser,
converts the PyObjects into C++ types and calls the ATen C++ function:
```
+--------+ parsing +------------------------+ binding +-----------------------+
| PyObjs | ---------> | PythonArgParser Output | ---------> | Cpp Function Dispatch |
+--------+ +------------------------+ +-----------------------+
```
- Are Python arguments 1-1 mapped to C++ arguments?
Python arguments might be reordered, packed, unpacked when binding to
C++ arguments, as illustrated below:
```
// Binding - Reorder & Packing
// aten::empty.names(int[] size, *, Dimname[]? names, ScalarType? dtype=None, Layout? layout=None,
Device? device=None, bool? pin_memory=None, MemoryFormat? memory_format=None) -> Tensor
Python Args Cpp Args
-----------------------------------------------------------
0: size size
1: names names
2: memory_format -------+
3: dtype -----+-|--> options
4: layout / |
5: device / +--> memory_format
6: pin_memory /
7: requires_grad -+
// Binding - Unpacking
// aten::max.names_dim(Tensor self, Dimname dim, bool keepdim=False) -> (Tensor values, Tensor indices)
Python Args Cpp Args
-----------------------------------------------------------
+----> max
/-----> max_values
0: input / self
1: dim / dim
2: keepdim / keepdim
3: out -----+
```
- Why do we want to rewrite the python binding codegen?
The old codegen takes Declarations.yaml as input. It doesn't distinguish
between Python arguments and C++ arguments - they are all mixed together
as a bag of non-typed dict objects. Different methods process these arg
objects and add new attributes for various different purposes. It's not so
obvious to figure out the semantics of these attributes. The complicated
binding logic happens implicitly and scatteredly.
```
+--------------------+
| Native Functions |
+--------------------+
|
|
v
+--------------------+
| Cpp Signatures |
+--------------------+
|
|
v
+--------------------+
| Declarations.yaml |
+--------------------+
| +-------------------------------------+
| +-------> | PythonArgParser Schema |
| | +-------------------------------------+
| | .
| | .
v | .
+--------------------+ +-------------------------------------+
| NonTyped Args Objs | --> | PythonArgParser -> Cpp Args Binding |
+--------------------+ +-------------------------------------+
| .
| .
| .
| +-------------------------------------+
+-------> | Cpp Function Dispatch |
+-------------------------------------+
```
This PR leverages the new immutable data models introduced in the new
aten codegen. It introduces dedicated data models for python schema.
This way, we can not only avoid subtle Declaration.yaml conversions but
also decouple the generation of python schema, python to c++ binding and
c++ function call.
The ultimate state will be like the following diagram:
```
+-------------------+ +-------------------------------------+
+-------> | Python Signatures | --> | PythonArgParser Schema |
| +-------------------+ +-------------------------------------+
| | .
| | .
| | .
+------------------+ | +-------------------------------------+
| Native Functions | +-------> | PythonArgParser -> Cpp Args Binding |
+------------------+ | +-------------------------------------+
| | .
| | .
| | .
| +-------------------+ +-------------------------------------+
+-------> | Cpp Signatures | --> | Cpp Function Dispatch |
+-------------------+ +-------------------------------------+
```
This PR has migrated the core binding logic from
tools/autograd/gen_python_functions.py to tools/codegen/api/python.py.
It produces the byte-for-byte same results (tested with #46243).
Will migrate the rest of gen_python_functions.py in subsequent PRs.
Test Plan: Imported from OSS
Reviewed By: bhosmer
Differential Revision: D24388874
Pulled By: ljk53
fbshipit-source-id: f88b6df4e917cf90d868a2bbae2d5ffb680d1841
2020-10-20 00:34:45 +00:00
|
|
|
|
|
|
|
|
# dispatch lambda signature
|
2020-11-08 09:03:59 +00:00
|
|
|
name = cpp.name(f.func)
|
2022-04-20 12:51:02 +00:00
|
|
|
lambda_formals = ", ".join(
|
|
|
|
|
map(lambda a: f"{a.type_str} {a.name}", dispatch_lambda_args(ps, f))
|
|
|
|
|
)
|
[pytorch] rewrite of the python binding codegen with the v2 API (#46244)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/46244
- What does the generated binding code do?
The Python binding codegen produces code that takes the input list of
PyObjects, finds the matching ATen C++ function using PythonArgParser,
converts the PyObjects into C++ types and calls the ATen C++ function:
```
+--------+ parsing +------------------------+ binding +-----------------------+
| PyObjs | ---------> | PythonArgParser Output | ---------> | Cpp Function Dispatch |
+--------+ +------------------------+ +-----------------------+
```
- Are Python arguments 1-1 mapped to C++ arguments?
Python arguments might be reordered, packed, unpacked when binding to
C++ arguments, as illustrated below:
```
// Binding - Reorder & Packing
// aten::empty.names(int[] size, *, Dimname[]? names, ScalarType? dtype=None, Layout? layout=None,
Device? device=None, bool? pin_memory=None, MemoryFormat? memory_format=None) -> Tensor
Python Args Cpp Args
-----------------------------------------------------------
0: size size
1: names names
2: memory_format -------+
3: dtype -----+-|--> options
4: layout / |
5: device / +--> memory_format
6: pin_memory /
7: requires_grad -+
// Binding - Unpacking
// aten::max.names_dim(Tensor self, Dimname dim, bool keepdim=False) -> (Tensor values, Tensor indices)
Python Args Cpp Args
-----------------------------------------------------------
+----> max
/-----> max_values
0: input / self
1: dim / dim
2: keepdim / keepdim
3: out -----+
```
- Why do we want to rewrite the python binding codegen?
The old codegen takes Declarations.yaml as input. It doesn't distinguish
between Python arguments and C++ arguments - they are all mixed together
as a bag of non-typed dict objects. Different methods process these arg
objects and add new attributes for various different purposes. It's not so
obvious to figure out the semantics of these attributes. The complicated
binding logic happens implicitly and scatteredly.
```
+--------------------+
| Native Functions |
+--------------------+
|
|
v
+--------------------+
| Cpp Signatures |
+--------------------+
|
|
v
+--------------------+
| Declarations.yaml |
+--------------------+
| +-------------------------------------+
| +-------> | PythonArgParser Schema |
| | +-------------------------------------+
| | .
| | .
v | .
+--------------------+ +-------------------------------------+
| NonTyped Args Objs | --> | PythonArgParser -> Cpp Args Binding |
+--------------------+ +-------------------------------------+
| .
| .
| .
| +-------------------------------------+
+-------> | Cpp Function Dispatch |
+-------------------------------------+
```
This PR leverages the new immutable data models introduced in the new
aten codegen. It introduces dedicated data models for python schema.
This way, we can not only avoid subtle Declaration.yaml conversions but
also decouple the generation of python schema, python to c++ binding and
c++ function call.
The ultimate state will be like the following diagram:
```
+-------------------+ +-------------------------------------+
+-------> | Python Signatures | --> | PythonArgParser Schema |
| +-------------------+ +-------------------------------------+
| | .
| | .
| | .
+------------------+ | +-------------------------------------+
| Native Functions | +-------> | PythonArgParser -> Cpp Args Binding |
+------------------+ | +-------------------------------------+
| | .
| | .
| | .
| +-------------------+ +-------------------------------------+
+-------> | Cpp Signatures | --> | Cpp Function Dispatch |
+-------------------+ +-------------------------------------+
```
This PR has migrated the core binding logic from
tools/autograd/gen_python_functions.py to tools/codegen/api/python.py.
It produces the byte-for-byte same results (tested with #46243).
Will migrate the rest of gen_python_functions.py in subsequent PRs.
Test Plan: Imported from OSS
Reviewed By: bhosmer
Differential Revision: D24388874
Pulled By: ljk53
fbshipit-source-id: f88b6df4e917cf90d868a2bbae2d5ffb680d1841
2020-10-20 00:34:45 +00:00
|
|
|
lambda_return = dispatch_lambda_return_str(f)
|
|
|
|
|
|
|
|
|
|
# dispatch lambda body
|
|
|
|
|
dispatch_callee = cpp_dispatch_target(f)
|
2022-04-20 12:51:02 +00:00
|
|
|
dispatch_args = ", ".join(cpp_dispatch_exprs(f, python_signature=ps))
|
[pytorch] rewrite of the python binding codegen with the v2 API (#46244)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/46244
- What does the generated binding code do?
The Python binding codegen produces code that takes the input list of
PyObjects, finds the matching ATen C++ function using PythonArgParser,
converts the PyObjects into C++ types and calls the ATen C++ function:
```
+--------+ parsing +------------------------+ binding +-----------------------+
| PyObjs | ---------> | PythonArgParser Output | ---------> | Cpp Function Dispatch |
+--------+ +------------------------+ +-----------------------+
```
- Are Python arguments 1-1 mapped to C++ arguments?
Python arguments might be reordered, packed, unpacked when binding to
C++ arguments, as illustrated below:
```
// Binding - Reorder & Packing
// aten::empty.names(int[] size, *, Dimname[]? names, ScalarType? dtype=None, Layout? layout=None,
Device? device=None, bool? pin_memory=None, MemoryFormat? memory_format=None) -> Tensor
Python Args Cpp Args
-----------------------------------------------------------
0: size size
1: names names
2: memory_format -------+
3: dtype -----+-|--> options
4: layout / |
5: device / +--> memory_format
6: pin_memory /
7: requires_grad -+
// Binding - Unpacking
// aten::max.names_dim(Tensor self, Dimname dim, bool keepdim=False) -> (Tensor values, Tensor indices)
Python Args Cpp Args
-----------------------------------------------------------
+----> max
/-----> max_values
0: input / self
1: dim / dim
2: keepdim / keepdim
3: out -----+
```
- Why do we want to rewrite the python binding codegen?
The old codegen takes Declarations.yaml as input. It doesn't distinguish
between Python arguments and C++ arguments - they are all mixed together
as a bag of non-typed dict objects. Different methods process these arg
objects and add new attributes for various different purposes. It's not so
obvious to figure out the semantics of these attributes. The complicated
binding logic happens implicitly and scatteredly.
```
+--------------------+
| Native Functions |
+--------------------+
|
|
v
+--------------------+
| Cpp Signatures |
+--------------------+
|
|
v
+--------------------+
| Declarations.yaml |
+--------------------+
| +-------------------------------------+
| +-------> | PythonArgParser Schema |
| | +-------------------------------------+
| | .
| | .
v | .
+--------------------+ +-------------------------------------+
| NonTyped Args Objs | --> | PythonArgParser -> Cpp Args Binding |
+--------------------+ +-------------------------------------+
| .
| .
| .
| +-------------------------------------+
+-------> | Cpp Function Dispatch |
+-------------------------------------+
```
This PR leverages the new immutable data models introduced in the new
aten codegen. It introduces dedicated data models for python schema.
This way, we can not only avoid subtle Declaration.yaml conversions but
also decouple the generation of python schema, python to c++ binding and
c++ function call.
The ultimate state will be like the following diagram:
```
+-------------------+ +-------------------------------------+
+-------> | Python Signatures | --> | PythonArgParser Schema |
| +-------------------+ +-------------------------------------+
| | .
| | .
| | .
+------------------+ | +-------------------------------------+
| Native Functions | +-------> | PythonArgParser -> Cpp Args Binding |
+------------------+ | +-------------------------------------+
| | .
| | .
| | .
| +-------------------+ +-------------------------------------+
+-------> | Cpp Signatures | --> | Cpp Function Dispatch |
+-------------------+ +-------------------------------------+
```
This PR has migrated the core binding logic from
tools/autograd/gen_python_functions.py to tools/codegen/api/python.py.
It produces the byte-for-byte same results (tested with #46243).
Will migrate the rest of gen_python_functions.py in subsequent PRs.
Test Plan: Imported from OSS
Reviewed By: bhosmer
Differential Revision: D24388874
Pulled By: ljk53
fbshipit-source-id: f88b6df4e917cf90d868a2bbae2d5ffb680d1841
2020-10-20 00:34:45 +00:00
|
|
|
|
|
|
|
|
# from arg parser outputs to dispatch lambda arguments
|
2020-11-08 09:03:59 +00:00
|
|
|
parser_outputs = arg_parser_output_exprs(ps, f)
|
|
|
|
|
lambda_arg_exprs = dispatch_lambda_exprs(ps, f)
|
2022-04-20 12:51:02 +00:00
|
|
|
inits = "\n".join(lambda_arg_exprs.inits)
|
|
|
|
|
lambda_args = ", ".join(lambda_arg_exprs.exprs)
|
[pytorch] rewrite of the python binding codegen with the v2 API (#46244)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/46244
- What does the generated binding code do?
The Python binding codegen produces code that takes the input list of
PyObjects, finds the matching ATen C++ function using PythonArgParser,
converts the PyObjects into C++ types and calls the ATen C++ function:
```
+--------+ parsing +------------------------+ binding +-----------------------+
| PyObjs | ---------> | PythonArgParser Output | ---------> | Cpp Function Dispatch |
+--------+ +------------------------+ +-----------------------+
```
- Are Python arguments 1-1 mapped to C++ arguments?
Python arguments might be reordered, packed, unpacked when binding to
C++ arguments, as illustrated below:
```
// Binding - Reorder & Packing
// aten::empty.names(int[] size, *, Dimname[]? names, ScalarType? dtype=None, Layout? layout=None,
Device? device=None, bool? pin_memory=None, MemoryFormat? memory_format=None) -> Tensor
Python Args Cpp Args
-----------------------------------------------------------
0: size size
1: names names
2: memory_format -------+
3: dtype -----+-|--> options
4: layout / |
5: device / +--> memory_format
6: pin_memory /
7: requires_grad -+
// Binding - Unpacking
// aten::max.names_dim(Tensor self, Dimname dim, bool keepdim=False) -> (Tensor values, Tensor indices)
Python Args Cpp Args
-----------------------------------------------------------
+----> max
/-----> max_values
0: input / self
1: dim / dim
2: keepdim / keepdim
3: out -----+
```
- Why do we want to rewrite the python binding codegen?
The old codegen takes Declarations.yaml as input. It doesn't distinguish
between Python arguments and C++ arguments - they are all mixed together
as a bag of non-typed dict objects. Different methods process these arg
objects and add new attributes for various different purposes. It's not so
obvious to figure out the semantics of these attributes. The complicated
binding logic happens implicitly and scatteredly.
```
+--------------------+
| Native Functions |
+--------------------+
|
|
v
+--------------------+
| Cpp Signatures |
+--------------------+
|
|
v
+--------------------+
| Declarations.yaml |
+--------------------+
| +-------------------------------------+
| +-------> | PythonArgParser Schema |
| | +-------------------------------------+
| | .
| | .
v | .
+--------------------+ +-------------------------------------+
| NonTyped Args Objs | --> | PythonArgParser -> Cpp Args Binding |
+--------------------+ +-------------------------------------+
| .
| .
| .
| +-------------------------------------+
+-------> | Cpp Function Dispatch |
+-------------------------------------+
```
This PR leverages the new immutable data models introduced in the new
aten codegen. It introduces dedicated data models for python schema.
This way, we can not only avoid subtle Declaration.yaml conversions but
also decouple the generation of python schema, python to c++ binding and
c++ function call.
The ultimate state will be like the following diagram:
```
+-------------------+ +-------------------------------------+
+-------> | Python Signatures | --> | PythonArgParser Schema |
| +-------------------+ +-------------------------------------+
| | .
| | .
| | .
+------------------+ | +-------------------------------------+
| Native Functions | +-------> | PythonArgParser -> Cpp Args Binding |
+------------------+ | +-------------------------------------+
| | .
| | .
| | .
| +-------------------+ +-------------------------------------+
+-------> | Cpp Signatures | --> | Cpp Function Dispatch |
+-------------------+ +-------------------------------------+
```
This PR has migrated the core binding logic from
tools/autograd/gen_python_functions.py to tools/codegen/api/python.py.
It produces the byte-for-byte same results (tested with #46243).
Will migrate the rest of gen_python_functions.py in subsequent PRs.
Test Plan: Imported from OSS
Reviewed By: bhosmer
Differential Revision: D24388874
Pulled By: ljk53
fbshipit-source-id: f88b6df4e917cf90d868a2bbae2d5ffb680d1841
2020-10-20 00:34:45 +00:00
|
|
|
|
|
|
|
|
# scatter fields
|
2020-10-28 16:31:02 +00:00
|
|
|
# TODO: Checking `ps.method and ('requires_grad' in parser_outputs)` is a hacky
|
|
|
|
|
# solution for enabling the 'requires_grad' argument for tensor methods
|
|
|
|
|
# new_full, new_empty, and new_zeros. A much better but more difficult to
|
|
|
|
|
# implement solution involves refactoring according to Ed's description here:
|
|
|
|
|
# https://github.com/pytorch/pytorch/issues/36455#issuecomment-614767589
|
2022-04-20 12:51:02 +00:00
|
|
|
need_set_requires_grad = ps.tensor_options_args and (
|
|
|
|
|
not has_tensor_options(f)
|
|
|
|
|
or (ps.method and ("requires_grad" in parser_outputs))
|
|
|
|
|
)
|
|
|
|
|
set_requires_grad = (
|
|
|
|
|
f'.set_requires_grad({parser_outputs["requires_grad"].expr})'
|
|
|
|
|
if need_set_requires_grad
|
|
|
|
|
else ""
|
|
|
|
|
)
|
[pytorch] rewrite of the python binding codegen with the v2 API (#46244)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/46244
- What does the generated binding code do?
The Python binding codegen produces code that takes the input list of
PyObjects, finds the matching ATen C++ function using PythonArgParser,
converts the PyObjects into C++ types and calls the ATen C++ function:
```
+--------+ parsing +------------------------+ binding +-----------------------+
| PyObjs | ---------> | PythonArgParser Output | ---------> | Cpp Function Dispatch |
+--------+ +------------------------+ +-----------------------+
```
- Are Python arguments 1-1 mapped to C++ arguments?
Python arguments might be reordered, packed, unpacked when binding to
C++ arguments, as illustrated below:
```
// Binding - Reorder & Packing
// aten::empty.names(int[] size, *, Dimname[]? names, ScalarType? dtype=None, Layout? layout=None,
Device? device=None, bool? pin_memory=None, MemoryFormat? memory_format=None) -> Tensor
Python Args Cpp Args
-----------------------------------------------------------
0: size size
1: names names
2: memory_format -------+
3: dtype -----+-|--> options
4: layout / |
5: device / +--> memory_format
6: pin_memory /
7: requires_grad -+
// Binding - Unpacking
// aten::max.names_dim(Tensor self, Dimname dim, bool keepdim=False) -> (Tensor values, Tensor indices)
Python Args Cpp Args
-----------------------------------------------------------
+----> max
/-----> max_values
0: input / self
1: dim / dim
2: keepdim / keepdim
3: out -----+
```
- Why do we want to rewrite the python binding codegen?
The old codegen takes Declarations.yaml as input. It doesn't distinguish
between Python arguments and C++ arguments - they are all mixed together
as a bag of non-typed dict objects. Different methods process these arg
objects and add new attributes for various different purposes. It's not so
obvious to figure out the semantics of these attributes. The complicated
binding logic happens implicitly and scatteredly.
```
+--------------------+
| Native Functions |
+--------------------+
|
|
v
+--------------------+
| Cpp Signatures |
+--------------------+
|
|
v
+--------------------+
| Declarations.yaml |
+--------------------+
| +-------------------------------------+
| +-------> | PythonArgParser Schema |
| | +-------------------------------------+
| | .
| | .
v | .
+--------------------+ +-------------------------------------+
| NonTyped Args Objs | --> | PythonArgParser -> Cpp Args Binding |
+--------------------+ +-------------------------------------+
| .
| .
| .
| +-------------------------------------+
+-------> | Cpp Function Dispatch |
+-------------------------------------+
```
This PR leverages the new immutable data models introduced in the new
aten codegen. It introduces dedicated data models for python schema.
This way, we can not only avoid subtle Declaration.yaml conversions but
also decouple the generation of python schema, python to c++ binding and
c++ function call.
The ultimate state will be like the following diagram:
```
+-------------------+ +-------------------------------------+
+-------> | Python Signatures | --> | PythonArgParser Schema |
| +-------------------+ +-------------------------------------+
| | .
| | .
| | .
+------------------+ | +-------------------------------------+
| Native Functions | +-------> | PythonArgParser -> Cpp Args Binding |
+------------------+ | +-------------------------------------+
| | .
| | .
| | .
| +-------------------+ +-------------------------------------+
+-------> | Cpp Signatures | --> | Cpp Function Dispatch |
+-------------------+ +-------------------------------------+
```
This PR has migrated the core binding logic from
tools/autograd/gen_python_functions.py to tools/codegen/api/python.py.
It produces the byte-for-byte same results (tested with #46243).
Will migrate the rest of gen_python_functions.py in subsequent PRs.
Test Plan: Imported from OSS
Reviewed By: bhosmer
Differential Revision: D24388874
Pulled By: ljk53
fbshipit-source-id: f88b6df4e917cf90d868a2bbae2d5ffb680d1841
2020-10-20 00:34:45 +00:00
|
|
|
|
2022-04-20 12:51:02 +00:00
|
|
|
if lambda_return == "void":
|
[pytorch] rewrite of the python binding codegen with the v2 API (#46244)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/46244
- What does the generated binding code do?
The Python binding codegen produces code that takes the input list of
PyObjects, finds the matching ATen C++ function using PythonArgParser,
converts the PyObjects into C++ types and calls the ATen C++ function:
```
+--------+ parsing +------------------------+ binding +-----------------------+
| PyObjs | ---------> | PythonArgParser Output | ---------> | Cpp Function Dispatch |
+--------+ +------------------------+ +-----------------------+
```
- Are Python arguments 1-1 mapped to C++ arguments?
Python arguments might be reordered, packed, unpacked when binding to
C++ arguments, as illustrated below:
```
// Binding - Reorder & Packing
// aten::empty.names(int[] size, *, Dimname[]? names, ScalarType? dtype=None, Layout? layout=None,
Device? device=None, bool? pin_memory=None, MemoryFormat? memory_format=None) -> Tensor
Python Args Cpp Args
-----------------------------------------------------------
0: size size
1: names names
2: memory_format -------+
3: dtype -----+-|--> options
4: layout / |
5: device / +--> memory_format
6: pin_memory /
7: requires_grad -+
// Binding - Unpacking
// aten::max.names_dim(Tensor self, Dimname dim, bool keepdim=False) -> (Tensor values, Tensor indices)
Python Args Cpp Args
-----------------------------------------------------------
+----> max
/-----> max_values
0: input / self
1: dim / dim
2: keepdim / keepdim
3: out -----+
```
- Why do we want to rewrite the python binding codegen?
The old codegen takes Declarations.yaml as input. It doesn't distinguish
between Python arguments and C++ arguments - they are all mixed together
as a bag of non-typed dict objects. Different methods process these arg
objects and add new attributes for various different purposes. It's not so
obvious to figure out the semantics of these attributes. The complicated
binding logic happens implicitly and scatteredly.
```
+--------------------+
| Native Functions |
+--------------------+
|
|
v
+--------------------+
| Cpp Signatures |
+--------------------+
|
|
v
+--------------------+
| Declarations.yaml |
+--------------------+
| +-------------------------------------+
| +-------> | PythonArgParser Schema |
| | +-------------------------------------+
| | .
| | .
v | .
+--------------------+ +-------------------------------------+
| NonTyped Args Objs | --> | PythonArgParser -> Cpp Args Binding |
+--------------------+ +-------------------------------------+
| .
| .
| .
| +-------------------------------------+
+-------> | Cpp Function Dispatch |
+-------------------------------------+
```
This PR leverages the new immutable data models introduced in the new
aten codegen. It introduces dedicated data models for python schema.
This way, we can not only avoid subtle Declaration.yaml conversions but
also decouple the generation of python schema, python to c++ binding and
c++ function call.
The ultimate state will be like the following diagram:
```
+-------------------+ +-------------------------------------+
+-------> | Python Signatures | --> | PythonArgParser Schema |
| +-------------------+ +-------------------------------------+
| | .
| | .
| | .
+------------------+ | +-------------------------------------+
| Native Functions | +-------> | PythonArgParser -> Cpp Args Binding |
+------------------+ | +-------------------------------------+
| | .
| | .
| | .
| +-------------------+ +-------------------------------------+
+-------> | Cpp Signatures | --> | Cpp Function Dispatch |
+-------------------+ +-------------------------------------+
```
This PR has migrated the core binding logic from
tools/autograd/gen_python_functions.py to tools/codegen/api/python.py.
It produces the byte-for-byte same results (tested with #46243).
Will migrate the rest of gen_python_functions.py in subsequent PRs.
Test Plan: Imported from OSS
Reviewed By: bhosmer
Differential Revision: D24388874
Pulled By: ljk53
fbshipit-source-id: f88b6df4e917cf90d868a2bbae2d5ffb680d1841
2020-10-20 00:34:45 +00:00
|
|
|
return f"""\
|
|
|
|
|
{schema_comment}
|
|
|
|
|
{inits}
|
|
|
|
|
auto dispatch_{name} = []({lambda_formals}) -> {lambda_return} {{
|
2020-11-08 09:03:59 +00:00
|
|
|
pybind11::gil_scoped_release no_gil;
|
[pytorch] rewrite of the python binding codegen with the v2 API (#46244)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/46244
- What does the generated binding code do?
The Python binding codegen produces code that takes the input list of
PyObjects, finds the matching ATen C++ function using PythonArgParser,
converts the PyObjects into C++ types and calls the ATen C++ function:
```
+--------+ parsing +------------------------+ binding +-----------------------+
| PyObjs | ---------> | PythonArgParser Output | ---------> | Cpp Function Dispatch |
+--------+ +------------------------+ +-----------------------+
```
- Are Python arguments 1-1 mapped to C++ arguments?
Python arguments might be reordered, packed, unpacked when binding to
C++ arguments, as illustrated below:
```
// Binding - Reorder & Packing
// aten::empty.names(int[] size, *, Dimname[]? names, ScalarType? dtype=None, Layout? layout=None,
Device? device=None, bool? pin_memory=None, MemoryFormat? memory_format=None) -> Tensor
Python Args Cpp Args
-----------------------------------------------------------
0: size size
1: names names
2: memory_format -------+
3: dtype -----+-|--> options
4: layout / |
5: device / +--> memory_format
6: pin_memory /
7: requires_grad -+
// Binding - Unpacking
// aten::max.names_dim(Tensor self, Dimname dim, bool keepdim=False) -> (Tensor values, Tensor indices)
Python Args Cpp Args
-----------------------------------------------------------
+----> max
/-----> max_values
0: input / self
1: dim / dim
2: keepdim / keepdim
3: out -----+
```
- Why do we want to rewrite the python binding codegen?
The old codegen takes Declarations.yaml as input. It doesn't distinguish
between Python arguments and C++ arguments - they are all mixed together
as a bag of non-typed dict objects. Different methods process these arg
objects and add new attributes for various different purposes. It's not so
obvious to figure out the semantics of these attributes. The complicated
binding logic happens implicitly and scatteredly.
```
+--------------------+
| Native Functions |
+--------------------+
|
|
v
+--------------------+
| Cpp Signatures |
+--------------------+
|
|
v
+--------------------+
| Declarations.yaml |
+--------------------+
| +-------------------------------------+
| +-------> | PythonArgParser Schema |
| | +-------------------------------------+
| | .
| | .
v | .
+--------------------+ +-------------------------------------+
| NonTyped Args Objs | --> | PythonArgParser -> Cpp Args Binding |
+--------------------+ +-------------------------------------+
| .
| .
| .
| +-------------------------------------+
+-------> | Cpp Function Dispatch |
+-------------------------------------+
```
This PR leverages the new immutable data models introduced in the new
aten codegen. It introduces dedicated data models for python schema.
This way, we can not only avoid subtle Declaration.yaml conversions but
also decouple the generation of python schema, python to c++ binding and
c++ function call.
The ultimate state will be like the following diagram:
```
+-------------------+ +-------------------------------------+
+-------> | Python Signatures | --> | PythonArgParser Schema |
| +-------------------+ +-------------------------------------+
| | .
| | .
| | .
+------------------+ | +-------------------------------------+
| Native Functions | +-------> | PythonArgParser -> Cpp Args Binding |
+------------------+ | +-------------------------------------+
| | .
| | .
| | .
| +-------------------+ +-------------------------------------+
+-------> | Cpp Signatures | --> | Cpp Function Dispatch |
+-------------------+ +-------------------------------------+
```
This PR has migrated the core binding logic from
tools/autograd/gen_python_functions.py to tools/codegen/api/python.py.
It produces the byte-for-byte same results (tested with #46243).
Will migrate the rest of gen_python_functions.py in subsequent PRs.
Test Plan: Imported from OSS
Reviewed By: bhosmer
Differential Revision: D24388874
Pulled By: ljk53
fbshipit-source-id: f88b6df4e917cf90d868a2bbae2d5ffb680d1841
2020-10-20 00:34:45 +00:00
|
|
|
{dispatch_callee}({dispatch_args});
|
|
|
|
|
}};
|
|
|
|
|
dispatch_{name}({lambda_args}){set_requires_grad};
|
|
|
|
|
Py_RETURN_NONE;
|
|
|
|
|
"""
|
|
|
|
|
else:
|
2020-11-08 09:03:59 +00:00
|
|
|
typename = namedtuple_typenames.get(gen_namedtuple_typename_key(f))
|
2022-04-20 12:51:02 +00:00
|
|
|
namedtuple_typeref = f"{typename}, " if typename is not None else ""
|
[pytorch] rewrite of the python binding codegen with the v2 API (#46244)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/46244
- What does the generated binding code do?
The Python binding codegen produces code that takes the input list of
PyObjects, finds the matching ATen C++ function using PythonArgParser,
converts the PyObjects into C++ types and calls the ATen C++ function:
```
+--------+ parsing +------------------------+ binding +-----------------------+
| PyObjs | ---------> | PythonArgParser Output | ---------> | Cpp Function Dispatch |
+--------+ +------------------------+ +-----------------------+
```
- Are Python arguments 1-1 mapped to C++ arguments?
Python arguments might be reordered, packed, unpacked when binding to
C++ arguments, as illustrated below:
```
// Binding - Reorder & Packing
// aten::empty.names(int[] size, *, Dimname[]? names, ScalarType? dtype=None, Layout? layout=None,
Device? device=None, bool? pin_memory=None, MemoryFormat? memory_format=None) -> Tensor
Python Args Cpp Args
-----------------------------------------------------------
0: size size
1: names names
2: memory_format -------+
3: dtype -----+-|--> options
4: layout / |
5: device / +--> memory_format
6: pin_memory /
7: requires_grad -+
// Binding - Unpacking
// aten::max.names_dim(Tensor self, Dimname dim, bool keepdim=False) -> (Tensor values, Tensor indices)
Python Args Cpp Args
-----------------------------------------------------------
+----> max
/-----> max_values
0: input / self
1: dim / dim
2: keepdim / keepdim
3: out -----+
```
- Why do we want to rewrite the python binding codegen?
The old codegen takes Declarations.yaml as input. It doesn't distinguish
between Python arguments and C++ arguments - they are all mixed together
as a bag of non-typed dict objects. Different methods process these arg
objects and add new attributes for various different purposes. It's not so
obvious to figure out the semantics of these attributes. The complicated
binding logic happens implicitly and scatteredly.
```
+--------------------+
| Native Functions |
+--------------------+
|
|
v
+--------------------+
| Cpp Signatures |
+--------------------+
|
|
v
+--------------------+
| Declarations.yaml |
+--------------------+
| +-------------------------------------+
| +-------> | PythonArgParser Schema |
| | +-------------------------------------+
| | .
| | .
v | .
+--------------------+ +-------------------------------------+
| NonTyped Args Objs | --> | PythonArgParser -> Cpp Args Binding |
+--------------------+ +-------------------------------------+
| .
| .
| .
| +-------------------------------------+
+-------> | Cpp Function Dispatch |
+-------------------------------------+
```
This PR leverages the new immutable data models introduced in the new
aten codegen. It introduces dedicated data models for python schema.
This way, we can not only avoid subtle Declaration.yaml conversions but
also decouple the generation of python schema, python to c++ binding and
c++ function call.
The ultimate state will be like the following diagram:
```
+-------------------+ +-------------------------------------+
+-------> | Python Signatures | --> | PythonArgParser Schema |
| +-------------------+ +-------------------------------------+
| | .
| | .
| | .
+------------------+ | +-------------------------------------+
| Native Functions | +-------> | PythonArgParser -> Cpp Args Binding |
+------------------+ | +-------------------------------------+
| | .
| | .
| | .
| +-------------------+ +-------------------------------------+
+-------> | Cpp Signatures | --> | Cpp Function Dispatch |
+-------------------+ +-------------------------------------+
```
This PR has migrated the core binding logic from
tools/autograd/gen_python_functions.py to tools/codegen/api/python.py.
It produces the byte-for-byte same results (tested with #46243).
Will migrate the rest of gen_python_functions.py in subsequent PRs.
Test Plan: Imported from OSS
Reviewed By: bhosmer
Differential Revision: D24388874
Pulled By: ljk53
fbshipit-source-id: f88b6df4e917cf90d868a2bbae2d5ffb680d1841
2020-10-20 00:34:45 +00:00
|
|
|
return f"""\
|
|
|
|
|
{schema_comment}
|
|
|
|
|
{inits}
|
|
|
|
|
auto dispatch_{name} = []({lambda_formals}) -> {lambda_return} {{
|
2020-11-08 09:03:59 +00:00
|
|
|
pybind11::gil_scoped_release no_gil;
|
[pytorch] rewrite of the python binding codegen with the v2 API (#46244)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/46244
- What does the generated binding code do?
The Python binding codegen produces code that takes the input list of
PyObjects, finds the matching ATen C++ function using PythonArgParser,
converts the PyObjects into C++ types and calls the ATen C++ function:
```
+--------+ parsing +------------------------+ binding +-----------------------+
| PyObjs | ---------> | PythonArgParser Output | ---------> | Cpp Function Dispatch |
+--------+ +------------------------+ +-----------------------+
```
- Are Python arguments 1-1 mapped to C++ arguments?
Python arguments might be reordered, packed, unpacked when binding to
C++ arguments, as illustrated below:
```
// Binding - Reorder & Packing
// aten::empty.names(int[] size, *, Dimname[]? names, ScalarType? dtype=None, Layout? layout=None,
Device? device=None, bool? pin_memory=None, MemoryFormat? memory_format=None) -> Tensor
Python Args Cpp Args
-----------------------------------------------------------
0: size size
1: names names
2: memory_format -------+
3: dtype -----+-|--> options
4: layout / |
5: device / +--> memory_format
6: pin_memory /
7: requires_grad -+
// Binding - Unpacking
// aten::max.names_dim(Tensor self, Dimname dim, bool keepdim=False) -> (Tensor values, Tensor indices)
Python Args Cpp Args
-----------------------------------------------------------
+----> max
/-----> max_values
0: input / self
1: dim / dim
2: keepdim / keepdim
3: out -----+
```
- Why do we want to rewrite the python binding codegen?
The old codegen takes Declarations.yaml as input. It doesn't distinguish
between Python arguments and C++ arguments - they are all mixed together
as a bag of non-typed dict objects. Different methods process these arg
objects and add new attributes for various different purposes. It's not so
obvious to figure out the semantics of these attributes. The complicated
binding logic happens implicitly and scatteredly.
```
+--------------------+
| Native Functions |
+--------------------+
|
|
v
+--------------------+
| Cpp Signatures |
+--------------------+
|
|
v
+--------------------+
| Declarations.yaml |
+--------------------+
| +-------------------------------------+
| +-------> | PythonArgParser Schema |
| | +-------------------------------------+
| | .
| | .
v | .
+--------------------+ +-------------------------------------+
| NonTyped Args Objs | --> | PythonArgParser -> Cpp Args Binding |
+--------------------+ +-------------------------------------+
| .
| .
| .
| +-------------------------------------+
+-------> | Cpp Function Dispatch |
+-------------------------------------+
```
This PR leverages the new immutable data models introduced in the new
aten codegen. It introduces dedicated data models for python schema.
This way, we can not only avoid subtle Declaration.yaml conversions but
also decouple the generation of python schema, python to c++ binding and
c++ function call.
The ultimate state will be like the following diagram:
```
+-------------------+ +-------------------------------------+
+-------> | Python Signatures | --> | PythonArgParser Schema |
| +-------------------+ +-------------------------------------+
| | .
| | .
| | .
+------------------+ | +-------------------------------------+
| Native Functions | +-------> | PythonArgParser -> Cpp Args Binding |
+------------------+ | +-------------------------------------+
| | .
| | .
| | .
| +-------------------+ +-------------------------------------+
+-------> | Cpp Signatures | --> | Cpp Function Dispatch |
+-------------------+ +-------------------------------------+
```
This PR has migrated the core binding logic from
tools/autograd/gen_python_functions.py to tools/codegen/api/python.py.
It produces the byte-for-byte same results (tested with #46243).
Will migrate the rest of gen_python_functions.py in subsequent PRs.
Test Plan: Imported from OSS
Reviewed By: bhosmer
Differential Revision: D24388874
Pulled By: ljk53
fbshipit-source-id: f88b6df4e917cf90d868a2bbae2d5ffb680d1841
2020-10-20 00:34:45 +00:00
|
|
|
return {dispatch_callee}({dispatch_args});
|
|
|
|
|
}};
|
|
|
|
|
return wrap({namedtuple_typeref}dispatch_{name}({lambda_args}){set_requires_grad});
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
return go(f)
|