Commit 4deec279 authored by thatPepe's avatar thatPepe Committed by MaYuhang
Browse files

Merge pull request #631 from InfiniTensor/issue/630

issue/630 - slightly improved unimplemented messages
parents f3a25b70 2a343a3a
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
import torch
import infinicore
from framework.base import BaseOperatorTest, TensorSpec, TestCase
from framework.runner import GenericTestRunner
# Test cases format: (shape, a_strides_or_None, b_strides_or_None, p_or_None)
# dist computes p-norm distance between two tensors
_TEST_CASES_DATA = [
((8, 8), None, None, None),
((8, 8), (16, 1), (16, 1), 1.0),
((2, 3, 4), None, None, 2.0),
((1, 8), None, (0, 1), None),
((16, 64), (128, 1), (128, 1), 3.0),
((4, 5, 6), (60, 12, 2), (60, 12, 2), 0.5),
]
_TOLERANCE_MAP = {
infinicore.float16: {"atol": 1e-3, "rtol": 1e-2},
infinicore.float32: {"atol": 1e-5, "rtol": 1e-4},
}
_TENSOR_DTYPES = [infinicore.float16, infinicore.float32]
def parse_test_cases():
test_cases = []
for data in _TEST_CASES_DATA:
shape, a_strides, b_strides, p = data
for dtype in _TENSOR_DTYPES:
tol = _TOLERANCE_MAP.get(dtype, {"atol": 1e-5, "rtol": 1e-3})
a_spec = TensorSpec.from_tensor(shape, a_strides, dtype)
b_spec = TensorSpec.from_tensor(shape, b_strides, dtype)
kwargs = {}
if p is not None:
kwargs["p"] = p
test_cases.append(
TestCase(
inputs=[a_spec, b_spec],
kwargs=kwargs,
output_spec=None,
comparison_target=None,
tolerance=tol,
description="Dist - OUT_OF_PLACE",
)
)
return test_cases
class OpTest(BaseOperatorTest):
"""Dist operator test with simplified implementation"""
def __init__(self):
super().__init__("Dist")
def get_test_cases(self):
return parse_test_cases()
def torch_operator(self, *args, **kwargs):
return torch.dist(*args, **kwargs)
# def infinicore_operator(self, *args, **kwargs):
# """InfiniCore implementation (operator not yet available)."""
# return infinicore.dist(*args, **kwargs)
def main():
"""Main entry point"""
runner = GenericTestRunner(OpTest)
runner.run_and_exit()
if __name__ == "__main__":
main()
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
import torch
import infinicore
from framework.base import BaseOperatorTest, TensorSpec, TestCase
from framework.runner import GenericTestRunner
# Test cases format: (vec1_shape, vec2_shape, vec1_strides_or_None, vec2_strides_or_None)
# infinicore.dot(a, b) — 1-D vectors; returns scalar
_TEST_CASES_DATA = [
((3,), (3,), None, None),
((8,), (8,), None, None),
((1,), (1,), None, None),
((16,), (16,), None, None),
((5,), (5,), None, None),
((32,), (32,), None, None),
((8,), (8,), (2,), (2,)),
]
_TOLERANCE_MAP = {
infinicore.float16: {"atol": 1e-3, "rtol": 1e-2},
infinicore.float32: {"atol": 1e-5, "rtol": 1e-4},
infinicore.bfloat16: {"atol": 1e-2, "rtol": 5e-2},
}
_TENSOR_DTYPES = [infinicore.float16, infinicore.bfloat16, infinicore.float32]
def parse_test_cases():
test_cases = []
for s1, s2, st1, st2 in _TEST_CASES_DATA:
for dtype in _TENSOR_DTYPES:
tol = _TOLERANCE_MAP.get(dtype, {"atol": 1e-5, "rtol": 1e-4})
a = TensorSpec.from_tensor(s1, st1, dtype)
b = TensorSpec.from_tensor(s2, st2, dtype)
test_cases.append(
TestCase(
inputs=[a, b],
kwargs={},
output_spec=None,
comparison_target=None,
tolerance=tol,
description="dot - OUT_OF_PLACE",
)
)
return test_cases
class OpTest(BaseOperatorTest):
"""dot operator test with simplified implementation"""
def __init__(self):
super().__init__("dot")
def get_test_cases(self):
return parse_test_cases()
def torch_operator(self, *args, **kwargs):
return torch.dot(*args, **kwargs)
# def infinicore_operator(self, *args, **kwargs):
# """InfiniCore implementation (operator not yet available)."""
# return infinicore.dot(*args, **kwargs)
def main():
"""Main entry point"""
runner = GenericTestRunner(OpTest)
runner.run_and_exit()
if __name__ == "__main__":
main()
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
import torch
import infinicore
from framework.base import BaseOperatorTest, TensorSpec, TestCase
from framework.runner import GenericTestRunner
from framework.utils import is_broadcast
# Test cases format: (shape, p, training, in_strides_or_None)
# infinicore.nn.functional.dropout1d(input, p=0.5, training=True)
_TEST_CASES_DATA = [
((8, 16), 0.1, True, None),
((8, 16), 0.2, False, (128, 1)),
((2, 3, 4), 0.5, True, None),
((16, 64), 0.3, True, None),
((4, 5, 6), 0.5, False, None),
((3, 4, 5), 0.4, True, (60, 20, 4)),
]
_TOLERANCE_MAP = {
infinicore.float16: {"atol": 1e-2, "rtol": 1e-2},
infinicore.float32: {"atol": 1e-5, "rtol": 1e-4},
infinicore.bfloat16: {"atol": 1e-2, "rtol": 5e-2},
}
_TENSOR_DTYPES = [infinicore.float16, infinicore.bfloat16, infinicore.float32]
def parse_test_cases():
test_cases = []
for data in _TEST_CASES_DATA:
shape, p, training = data[0], data[1], data[2]
in_strides = data[3] if len(data) > 3 else None
supports_inplace = not is_broadcast(in_strides)
for dtype in _TENSOR_DTYPES:
tol = _TOLERANCE_MAP.get(dtype, {"atol": 1e-2, "rtol": 1e-2})
input_spec = TensorSpec.from_tensor(shape, in_strides, dtype)
kwargs = {"p": p, "training": training}
# Out-of-place
test_cases.append(
TestCase(
inputs=[input_spec],
kwargs=kwargs,
output_spec=None,
comparison_target=None,
tolerance=tol,
description=f"dropout1d - OUT_OF_PLACE",
)
)
return test_cases
class OpTest(BaseOperatorTest):
"""Dropout1d operator test with simplified implementation"""
def __init__(self):
super().__init__("Dropout1d")
def get_test_cases(self):
return parse_test_cases()
def torch_operator(self, *args, **kwargs):
return torch.nn.functional.dropout1d(*args, **kwargs)
# def infinicore_operator(self, *args, **kwargs):
# """InfiniCore implementation (operator not yet available)."""
# return infinicore.nn.functional.dropout1d(*args, **kwargs)
def main():
"""Main entry point"""
runner = GenericTestRunner(OpTest)
runner.run_and_exit()
if __name__ == "__main__":
main()
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
import torch
import infinicore
from framework.base import BaseOperatorTest, TensorSpec, TestCase
from framework.runner import GenericTestRunner
from framework.utils import is_broadcast
# Test cases format: (shape, p, training, in_strides_or_None)
# infinicore.nn.functional.dropout2d(input, p=0.5, training=True)
_TEST_CASES_DATA = [
((8, 16, 8, 8), 0.1, True, None),
((8, 16, 8, 8), 0.2, False, (1024, 64, 8, 1)),
((2, 3, 4, 8), 0.5, True, None),
((16, 64, 4, 4), 0.3, True, None),
((4, 5, 6, 8), 0.5, False, None),
((3, 4, 5, 5), 0.4, True, (60, 20, 4, 1)),
]
_TOLERANCE_MAP = {
infinicore.float16: {"atol": 1e-2, "rtol": 1e-2},
infinicore.float32: {"atol": 1e-5, "rtol": 1e-4},
infinicore.bfloat16: {"atol": 1e-2, "rtol": 5e-2},
}
_TENSOR_DTYPES = [infinicore.float16, infinicore.bfloat16, infinicore.float32]
def parse_test_cases():
test_cases = []
for data in _TEST_CASES_DATA:
shape, p, training = data[0], data[1], data[2]
in_strides = data[3] if len(data) > 3 else None
supports_inplace = not is_broadcast(in_strides)
for dtype in _TENSOR_DTYPES:
tol = _TOLERANCE_MAP.get(dtype, {"atol": 1e-2, "rtol": 1e-2})
input_spec = TensorSpec.from_tensor(shape, in_strides, dtype)
kwargs = {"p": p, "training": training}
test_cases.append(
TestCase(
inputs=[input_spec],
kwargs=kwargs,
output_spec=None,
comparison_target=None,
tolerance=tol,
description=f"dropout2d - OUT_OF_PLACE",
)
)
return test_cases
class OpTest(BaseOperatorTest):
"""Dropout2d operator test with simplified implementation"""
def __init__(self):
super().__init__("Dropout2d")
def get_test_cases(self):
return parse_test_cases()
def torch_operator(self, *args, **kwargs):
return torch.nn.functional.dropout2d(*args, **kwargs)
# def infinicore_operator(self, *args, **kwargs):
# """InfiniCore implementation (operator not yet available)."""
# return infinicore.nn.functional.dropout2d(*args, **kwargs)
def main():
"""Main entry point"""
runner = GenericTestRunner(OpTest)
runner.run_and_exit()
if __name__ == "__main__":
main()
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
import torch
import infinicore
from framework.base import BaseOperatorTest, TensorSpec, TestCase
from framework.runner import GenericTestRunner
from framework.utils import is_broadcast
# Test cases format: (shape, p, training, in_strides_or_None)
# infinicore.nn.functional.dropout3d(input, p=0.5, training=True)
_TEST_CASES_DATA = [
((8, 16, 8, 8), 0.1, True, None),
((8, 16, 8, 8), 0.2, False, (8192, 1024, 128, 16)),
((2, 3, 4, 4), 0.5, True, None),
((16, 64, 4, 4), 0.3, True, None),
((4, 5, 6, 3), 0.5, False, None),
((3, 4, 5, 2), 0.4, True, (240, 60, 12, 2)),
]
_TOLERANCE_MAP = {
infinicore.float16: {"atol": 1e-2, "rtol": 1e-2},
infinicore.float32: {"atol": 1e-5, "rtol": 1e-4},
infinicore.bfloat16: {"atol": 1e-2, "rtol": 5e-2},
}
_TENSOR_DTYPES = [infinicore.float16, infinicore.bfloat16, infinicore.float32]
def parse_test_cases():
test_cases = []
for data in _TEST_CASES_DATA:
shape, p, training = data[0], data[1], data[2]
in_strides = data[3] if len(data) > 3 else None
supports_inplace = not is_broadcast(in_strides)
for dtype in _TENSOR_DTYPES:
tol = _TOLERANCE_MAP.get(dtype, {"atol": 1e-2, "rtol": 1e-2})
input_spec = TensorSpec.from_tensor(shape, in_strides, dtype)
kwargs = {"p": p, "training": training}
test_cases.append(
TestCase(
inputs=[input_spec],
kwargs=kwargs,
output_spec=None,
comparison_target=None,
tolerance=tol,
description=f"dropout3d - OUT_OF_PLACE",
)
)
return test_cases
class OpTest(BaseOperatorTest):
"""Dropout3d operator test with simplified implementation"""
def __init__(self):
super().__init__("Dropout3d")
def get_test_cases(self):
return parse_test_cases()
def torch_operator(self, *args, **kwargs):
return torch.nn.functional.dropout3d(*args, **kwargs)
# def infinicore_operator(self, *args, **kwargs):
# """InfiniCore implementation (operator not yet available)."""
# return infinicore.nn.functional.dropout3d(*args, **kwargs)
def main():
"""Main entry point"""
runner = GenericTestRunner(OpTest)
runner.run_and_exit()
if __name__ == "__main__":
main()
......@@ -56,7 +56,6 @@ def parse_test_cases():
"""
Parse ELU test case data according to format:
(shape, input_strides, alpha)
ELU only supports out-of-place and in-place modes via PyTorch's inplace parameter
"""
test_cases = []
......@@ -133,9 +132,10 @@ class OpTest(BaseOperatorTest):
"""PyTorch ELU implementation"""
return torch.nn.functional.elu(*args, **kwargs)
# def infinicore_operator(self, x, alpha=1.0, out=None, **kwargs):
# def infinicore_operator(self, *args, **kwargs):
# """InfiniCore ELU implementation"""
# return None
# return infinicore.nn.functional.elu(*args, **kwargs)
# # return None
def main():
......
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
import torch
import infinicore
from framework.base import BaseOperatorTest, TensorSpec, TestCase
from framework.datatypes import to_torch_dtype
from framework.runner import GenericTestRunner
# Test cases format: (shape, dtype)
# Note: infinicore.empty returns uninitialized memory. Tests will compare shape and dtype via output_spec
_TEST_CASES_DATA = [
((3, 4), infinicore.float32),
((6, 2), infinicore.float16),
((5, 5), infinicore.float32),
((1, 7), infinicore.bfloat16),
((8, 3), infinicore.float32),
((2, 2, 2), infinicore.float16),
]
_TOLERANCE_MAP = {infinicore.float32: {"atol": 0, "rtol": 0}}
def parse_test_cases():
test_cases = []
for shape, dtype in _TEST_CASES_DATA:
out_spec = TensorSpec.from_tensor(shape, None, dtype)
test_cases.append(
TestCase(
inputs=[],
kwargs={"size": shape, "dtype": dtype},
output_spec=out_spec,
comparison_target="out",
tolerance=_TOLERANCE_MAP.get(dtype, {"atol": 0, "rtol": 0}),
description=f"empty - OUT_OF_PLACE",
)
)
return test_cases
class OpTest(BaseOperatorTest):
"""Empty operator test with simplified implementation"""
def __init__(self):
super().__init__("Empty")
def get_test_cases(self):
return parse_test_cases()
def torch_operator(self, *args, **kwargs):
if "size" not in kwargs:
raise TypeError("full test did not provide 'size' parameter")
size = kwargs.pop("size")
if "dtype" not in kwargs:
raise TypeError("full test did not provide 'dtype' parameter")
dtype_torch = to_torch_dtype(kwargs.pop("dtype"))
if dtype_torch is None:
raise TypeError("full test provided unsupported 'dtype' parameter")
# 支持测试框架通过 kwargs 注入 out 参数
out = kwargs.pop("out", None)
if out is not None:
return torch.empty(tuple(size), dtype=dtype_torch, out=out)
else:
return torch.empty(tuple(size), dtype=dtype_torch)
# return infinicore.empty(*args, **kwargs)
# def infinicore_operator(self, *args, **kwargs):
# """InfiniCore implementation (operator not yet available)."""
# return infinicore.empty(*args, **kwargs)
def main():
"""Main entry point"""
runner = GenericTestRunner(OpTest)
runner.run_and_exit()
if __name__ == "__main__":
main()
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
import torch
import infinicore
from framework.base import BaseOperatorTest, TensorSpec, TestCase
from framework.datatypes import to_torch_dtype
from framework.runner import GenericTestRunner
# Test cases format: (base_shape, base_strides_or_None, dtype_or_None)
# Note: empty_like returns uninitialized memory; we validate shape/dtype via output_spec
_TEST_CASES_DATA = [
((3, 4), None, None),
((6, 2), (12, 1), infinicore.float16),
((5, 5), None, infinicore.float32),
((1, 7), None, infinicore.bfloat16),
((8, 3), (24, 1), None),
((2, 2, 2), None, infinicore.float32),
]
_TOLERANCE_MAP = {
infinicore.float32: {"atol": 1e-6, "rtol": 1e-5},
infinicore.float16: {"atol": 1e-3, "rtol": 1e-3},
infinicore.bfloat16: {"atol": 1e-2, "rtol": 1e-2},
}
_TENSOR_DTYPES = [infinicore.float32, infinicore.float16, infinicore.bfloat16]
def parse_test_cases():
test_cases = []
for base_shape, base_strides, dtype in _TEST_CASES_DATA:
for input_dtype in _TENSOR_DTYPES:
base_spec = TensorSpec.from_tensor(base_shape, base_strides, input_dtype)
kwargs = {"dtype": dtype} if dtype is not None else {}
test_cases.append(
TestCase(
inputs=[base_spec],
kwargs=kwargs,
output_spec=None,
comparison_target=None,
tolerance=_TOLERANCE_MAP.get(
input_dtype, {"atol": 1e-5, "rtol": 1e-4}
),
description="empty_like - OUT_OF_PLACE",
)
)
return test_cases
class OpTest(BaseOperatorTest):
"""EmptyLike operator test with simplified implementation"""
def __init__(self):
super().__init__("EmptyLike")
def get_test_cases(self):
return parse_test_cases()
def torch_operator(self, *args, **kwargs):
if "dtype" not in kwargs:
dtype_torch = None
else:
dtype_torch = to_torch_dtype(kwargs.pop("dtype"))
return torch.empty_like(*args, dtype=dtype_torch)
# def infinicore_operator(self, *args, **kwargs):
# """InfiniCore implementation (operator not yet available)."""
# return infinicore.empty_like(*args, **kwargs)
def main():
"""Main entry point"""
runner = GenericTestRunner(OpTest)
runner.run_and_exit()
if __name__ == "__main__":
main()
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
import torch
import infinicore
from framework.base import BaseOperatorTest, TensorSpec, TestCase
from framework.runner import GenericTestRunner
from framework.datatypes import to_torch_dtype
# Test cases format: (shape, stride, dtype)
# empty_strided creates a tensor with given stride; use small shapes to exercise strides.
_TEST_CASES_DATA = [
((3, 4), (16, 1), infinicore.float32),
((4, 3), (12, 4), infinicore.float16),
((2, 5), (20, 1), infinicore.float32),
((1, 6), (48, 8), infinicore.bfloat16),
((2, 2, 2), (8, 4, 2), infinicore.float32),
((5,), (1,), infinicore.float32),
]
_TOLERANCE_MAP = {
infinicore.float32: {"atol": 0, "rtol": 0},
infinicore.float16: {"atol": 1e-3, "rtol": 1e-3},
infinicore.bfloat16: {"atol": 1e-2, "rtol": 1e-2},
}
def parse_test_cases():
test_cases = []
for shape, stride, dtype in _TEST_CASES_DATA:
kwargs = {"size": shape, "stride": stride, "dtype": dtype}
test_cases.append(
TestCase(
inputs=[],
kwargs=kwargs,
output_spec=None,
comparison_target=None,
tolerance=_TOLERANCE_MAP.get(dtype, {"atol": 0, "rtol": 0}),
description=f"empty_strided - OUT_OF_PLACE",
)
)
return test_cases
class OpTest(BaseOperatorTest):
"""EmptyStrided operator test with simplified implementation"""
def __init__(self):
super().__init__("EmptyStrided")
def get_test_cases(self):
return parse_test_cases()
def torch_operator(self, *args, **kwargs):
if "size" not in kwargs:
raise TypeError("empty_strided test did not provide 'size' parameter")
size = kwargs.pop("size")
if "stride" not in kwargs:
raise TypeError("empty_strided test did not provide 'stride' parameter")
stride = kwargs.pop("stride")
if "dtype" not in kwargs:
raise TypeError("empty_strided test did not provide 'dtype' parameter")
dtype_torch = to_torch_dtype(kwargs.pop("dtype"))
if dtype_torch is None:
raise TypeError("empty_strided test provided unsupported 'dtype' parameter")
return torch.empty_strided(tuple(size), stride=stride, dtype=dtype_torch)
# def infinicore_operator(self, *args, **kwargs):
# """InfiniCore implementation (operator not yet available)."""
# return infinicore.empty_strided(*args, **kwargs)
def main():
"""Main entry point"""
runner = GenericTestRunner(OpTest)
runner.run_and_exit()
if __name__ == "__main__":
main()
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
import torch
import infinicore
from framework.base import BaseOperatorTest, TensorSpec, TestCase
from framework.runner import GenericTestRunner
from framework.utils import is_broadcast
# Test cases format: (shape, a_strides_or_None, b_strides_or_None, out_strides_or_None)
# equal compares element-wise and returns boolean tensor
_TEST_CASES_DATA = [
((8, 8), None, None, None),
((8, 8), (16, 1), (16, 1), None),
((8, 8), None, (0, 1), None),
((1, 8), None, None, (8, 1)),
((2, 3, 4), None, None, None),
((16, 128), (256, 1), (256, 1), None),
]
_TOLERANCE_MAP = {
infinicore.float16: {"atol": 0, "rtol": 1e-2},
infinicore.float32: {"atol": 0, "rtol": 1e-3},
infinicore.int32: {"atol": 0, "rtol": 0},
}
_TENSOR_DTYPES = [infinicore.float16, infinicore.float32, infinicore.int32]
def parse_test_cases():
test_cases = []
for data in _TEST_CASES_DATA:
shape, a_strides, b_strides, out_strides = data[0], data[1], data[2], data[3]
a_supports_inplace = not is_broadcast(a_strides)
b_supports_inplace = not is_broadcast(b_strides)
out_supports_inplace = not is_broadcast(out_strides)
for dtype in _TENSOR_DTYPES:
tol = _TOLERANCE_MAP.get(dtype, {"atol": 0, "rtol": 1e-3})
a_spec = TensorSpec.from_tensor(shape, a_strides, dtype)
b_spec = TensorSpec.from_tensor(shape, b_strides, dtype)
out_spec = TensorSpec.from_tensor(shape, out_strides, infinicore.bool)
# Out-of-place
test_cases.append(
TestCase(
inputs=[a_spec, b_spec],
kwargs={},
output_spec=None,
comparison_target=None,
tolerance=tol,
description="Equal - OUT_OF_PLACE",
)
)
# explicit out
if out_supports_inplace:
test_cases.append(
TestCase(
inputs=[a_spec, b_spec],
kwargs=None,
output_spec=out_spec,
comparison_target="out",
tolerance=tol,
description="Equal - INPLACE(out)",
)
)
# in-place a
if a_supports_inplace:
test_cases.append(
TestCase(
inputs=[a_spec, b_spec],
kwargs={"out": 0},
output_spec=None,
comparison_target=0,
tolerance=tol,
description="Equal - INPLACE(a)",
)
)
# in-place b
if b_supports_inplace:
test_cases.append(
TestCase(
inputs=[a_spec, b_spec],
kwargs={"out": 1},
output_spec=None,
comparison_target=1,
tolerance=tol,
description="Equal - INPLACE(b)",
)
)
return test_cases
class OpTest(BaseOperatorTest):
"""Equal operator test with simplified implementation"""
def __init__(self):
super().__init__("Equal")
def get_test_cases(self):
return parse_test_cases()
def torch_operator(self, *args, **kwargs):
return torch.eq(*args, **kwargs)
# def infinicore_operator(self, *args, **kwargs):
# """InfiniCore implementation (operator not yet available)."""
# return infinicore.eq(*args, **kwargs)
def main():
"""Main entry point"""
runner = GenericTestRunner(OpTest)
runner.run_and_exit()
if __name__ == "__main__":
main()
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
import torch
import infinicore
from framework.base import BaseOperatorTest, TensorSpec, TestCase
from framework.runner import GenericTestRunner
from framework.utils import is_broadcast
# =======================================================================
# Test cases format: (shape, input_strides_or_None)
# =======================================================================
_TEST_CASES_DATA = [
((13, 4), None),
((13, 4), (10, 1)),
((8, 16), None),
((8, 16), (40, 1)),
((2, 3, 4), None),
((16, 5632), None),
]
_TOLERANCE_MAP = {
infinicore.float16: {"atol": 1e-3, "rtol": 1e-2},
infinicore.float32: {"atol": 1e-5, "rtol": 1e-4},
infinicore.bfloat16: {"atol": 1e-2, "rtol": 5e-2},
}
_TENSOR_DTYPES = [infinicore.float16, infinicore.bfloat16, infinicore.float32]
def parse_test_cases():
test_cases = []
for data in _TEST_CASES_DATA:
shape = data[0]
in_strides = data[1] if len(data) > 1 else None
supports_inplace = not is_broadcast(in_strides)
for dtype in _TENSOR_DTYPES:
tol = _TOLERANCE_MAP.get(dtype, {"atol": 1e-5, "rtol": 1e-4})
input_spec = TensorSpec.from_tensor(shape, in_strides, dtype)
out_spec = TensorSpec.from_tensor(shape, None, dtype)
test_cases.append(
TestCase(
inputs=[input_spec],
kwargs={},
output_spec=None,
comparison_target=None,
tolerance=tol,
description="erf - OUT_OF_PLACE",
)
)
test_cases.append(
TestCase(
inputs=[input_spec],
kwargs=None,
output_spec=out_spec,
comparison_target="out",
tolerance=tol,
description="erf - INPLACE(out)",
)
)
if supports_inplace:
test_cases.append(
TestCase(
inputs=[input_spec],
kwargs={"out": 0},
output_spec=None,
comparison_target=0,
tolerance=tol,
description="erf - INPLACE(input)",
)
)
return test_cases
class OpTest(BaseOperatorTest):
"""Erf operator test with simplified implementation"""
def __init__(self):
super().__init__("Erf")
def get_test_cases(self):
return parse_test_cases()
def torch_operator(self, *args, **kwargs):
return torch.erf(*args, **kwargs)
# def infinicore_operator(self, *args, **kwargs):
# """InfiniCore implementation (operator not yet available)."""
# return infinicore.erf(*args, **kwargs)
def main():
"""Main entry point"""
runner = GenericTestRunner(OpTest)
runner.run_and_exit()
if __name__ == "__main__":
main()
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
import torch
import infinicore
from framework.base import BaseOperatorTest, TensorSpec, TestCase
from framework.runner import GenericTestRunner
from framework.utils import is_broadcast
# =======================================================================
# Test cases format: (shape, input_strides_or_None)
# =======================================================================
_TEST_CASES_DATA = [
((13, 4), None),
((13, 4), (10, 1)),
((8, 16), None),
((8, 16), (40, 1)),
((2, 3, 4), None),
((16, 5632), None),
]
_TOLERANCE_MAP = {
infinicore.float16: {"atol": 1e-3, "rtol": 1e-2},
infinicore.float32: {"atol": 1e-5, "rtol": 1e-4},
infinicore.bfloat16: {"atol": 1e-2, "rtol": 5e-2},
}
_TENSOR_DTYPES = [infinicore.float16, infinicore.bfloat16, infinicore.float32]
def parse_test_cases():
test_cases = []
for data in _TEST_CASES_DATA:
shape = data[0]
in_strides = data[1] if len(data) > 1 else None
supports_inplace = not is_broadcast(in_strides)
for dtype in _TENSOR_DTYPES:
tol = _TOLERANCE_MAP.get(dtype, {"atol": 1e-5, "rtol": 1e-4})
input_spec = TensorSpec.from_tensor(shape, in_strides, dtype)
out_spec = TensorSpec.from_tensor(shape, None, dtype)
test_cases.append(
TestCase(
inputs=[input_spec],
kwargs={},
output_spec=None,
comparison_target=None,
tolerance=tol,
description="erfc - OUT_OF_PLACE",
)
)
test_cases.append(
TestCase(
inputs=[input_spec],
kwargs=None,
output_spec=out_spec,
comparison_target="out",
tolerance=tol,
description="erfc - INPLACE(out)",
)
)
if supports_inplace:
test_cases.append(
TestCase(
inputs=[input_spec],
kwargs={"out": 0},
output_spec=None,
comparison_target=0,
tolerance=tol,
description="erfc - INPLACE(input)",
)
)
return test_cases
class OpTest(BaseOperatorTest):
"""Erfc operator test with simplified implementation"""
def __init__(self):
super().__init__("Erfc")
def get_test_cases(self):
return parse_test_cases()
def torch_operator(self, *args, **kwargs):
return torch.erfc(*args, **kwargs)
# def infinicore_operator(self, *args, **kwargs):
# """InfiniCore implementation (operator not yet available)."""
# return infinicore.erfc(*args, **kwargs)
def main():
"""Main entry point"""
runner = GenericTestRunner(OpTest)
runner.run_and_exit()
if __name__ == "__main__":
main()
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
import torch
import infinicore
from framework.base import BaseOperatorTest, TensorSpec, TestCase
from framework.runner import GenericTestRunner
from framework.utils import is_broadcast
# =======================================================================
# Test cases format: (shape, input_strides_or_None)
# Note: erfinv domain is (-1, 1); test generation will use values within that range.
# =======================================================================
_TEST_CASES_DATA = [
((13, 4), None),
((13, 4), (10, 1)),
((8, 16), None),
((8, 16), (40, 1)),
((2, 3, 4), None),
((16, 5632), None),
]
_TOLERANCE_MAP = {
infinicore.float16: {"atol": 1e-2, "rtol": 1e-2},
infinicore.float32: {"atol": 1e-5, "rtol": 1e-4},
infinicore.bfloat16: {"atol": 1e-2, "rtol": 5e-2},
}
_TENSOR_DTYPES = [infinicore.float16, infinicore.bfloat16, infinicore.float32]
def parse_test_cases():
test_cases = []
for data in _TEST_CASES_DATA:
shape = data[0]
in_strides = data[1] if len(data) > 1 else None
supports_inplace = not is_broadcast(in_strides)
for dtype in _TENSOR_DTYPES:
tol = _TOLERANCE_MAP.get(dtype, {"atol": 1e-5, "rtol": 1e-4})
input_spec = TensorSpec.from_tensor(shape, in_strides, dtype)
out_spec = TensorSpec.from_tensor(shape, None, dtype)
test_cases.append(
TestCase(
inputs=[input_spec],
kwargs={},
output_spec=None,
comparison_target=None,
tolerance=tol,
description="erfinv - OUT_OF_PLACE",
)
)
test_cases.append(
TestCase(
inputs=[input_spec],
kwargs=None,
output_spec=out_spec,
comparison_target="out",
tolerance=tol,
description="erfinv - INPLACE(out)",
)
)
if supports_inplace:
test_cases.append(
TestCase(
inputs=[input_spec],
kwargs={"out": 0},
output_spec=None,
comparison_target=0,
tolerance=tol,
description="erfinv - INPLACE(input)",
)
)
return test_cases
class OpTest(BaseOperatorTest):
"""Erfinv operator test with simplified implementation"""
def __init__(self):
super().__init__("Erfinv")
def get_test_cases(self):
return parse_test_cases()
def torch_operator(self, *args, **kwargs):
return torch.erfinv(*args, **kwargs)
# def infinicore_operator(self, *args, **kwargs):
# """InfiniCore implementation (operator not yet available)."""
# return infinicore.erfinv(*args, **kwargs)
def main():
"""Main entry point"""
runner = GenericTestRunner(OpTest)
runner.run_and_exit()
if __name__ == "__main__":
main()
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
import torch
import infinicore
from framework.base import BaseOperatorTest, TensorSpec, TestCase
from framework.runner import GenericTestRunner
from framework.utils import is_broadcast
# Test cases format: (in_shape, in_strides_or_None)
# infinicore.exp2(input)
_TEST_CASES_DATA = [
((2, 3), None),
((1, 4, 8), (32, 8, 1)),
((3, 2, 5, 7), None),
((2, 1, 16), None),
((1, 8, 9, 11), (792, 99, 11, 1)),
((2, 6, 10), None),
]
_TOLERANCE_MAP = {
infinicore.float16: {"atol": 1e-3, "rtol": 1e-2},
infinicore.float32: {"atol": 1e-5, "rtol": 1e-4},
}
_TENSOR_DTYPES = [infinicore.float16, infinicore.float32]
def parse_test_cases():
cases = []
for shape, strides in _TEST_CASES_DATA:
for dtype in _TENSOR_DTYPES:
tol = _TOLERANCE_MAP[dtype]
in_spec = TensorSpec.from_tensor(shape, strides, dtype)
cases.append(
TestCase(
inputs=[in_spec],
kwargs={},
output_spec=None,
comparison_target=None,
tolerance=tol,
description="exp2 - OUT_OF_PLACE",
)
)
out_spec = TensorSpec.from_tensor(shape, None, dtype)
cases.append(
TestCase(
inputs=[in_spec],
kwargs={},
output_spec=out_spec,
comparison_target="out",
tolerance=tol,
description="exp2 - INPLACE(out)",
)
)
if not is_broadcast(in_spec.strides):
cases.append(
TestCase(
inputs=[in_spec],
kwargs={"out": 0},
output_spec=None,
comparison_target=0,
tolerance=tol,
description="exp2 - INPLACE(a)",
)
)
return cases
class OpTest(BaseOperatorTest):
"""Exp2 operator test with simplified implementation"""
def __init__(self):
super().__init__("Exp2")
def get_test_cases(self):
return parse_test_cases()
def torch_operator(self, *args, **kwargs):
return torch.exp2(*args, **kwargs)
# def infinicore_operator(self, *args, **kwargs):
# """InfiniCore implementation (operator not yet available)."""
# return infinicore.exp2(*args, **kwargs)
def main():
"""Main entry point"""
runner = GenericTestRunner(OpTest)
runner.run_and_exit()
if __name__ == "__main__":
main()
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
import torch
import infinicore
from framework.base import BaseOperatorTest, TensorSpec, TestCase
from framework.runner import GenericTestRunner
from framework.utils import is_broadcast
# Test cases format: (in_shape, in_strides_or_None)
# infinicore.expm1(input)
_TEST_CASES_DATA = [
((2, 3), None),
((1, 4, 8), (32, 8, 1)),
((3, 2, 5, 7), None),
((2, 1, 16), None),
((1, 8, 9, 11), (792, 99, 11, 1)),
((2, 6, 10), None),
]
_TOLERANCE_MAP = {
infinicore.float16: {"atol": 1e-3, "rtol": 1e-2},
infinicore.float32: {"atol": 1e-5, "rtol": 1e-4},
}
_TENSOR_DTYPES = [infinicore.float16, infinicore.float32]
def parse_test_cases():
cases = []
for shape, strides in _TEST_CASES_DATA:
for dtype in _TENSOR_DTYPES:
tol = _TOLERANCE_MAP[dtype]
in_spec = TensorSpec.from_tensor(shape, strides, dtype)
cases.append(
TestCase(
inputs=[in_spec],
kwargs={},
output_spec=None,
comparison_target=None,
tolerance=tol,
description="expm1 - OUT_OF_PLACE",
)
)
out_spec = TensorSpec.from_tensor(shape, None, dtype)
cases.append(
TestCase(
inputs=[in_spec],
kwargs={},
output_spec=out_spec,
comparison_target="out",
tolerance=tol,
description="expm1 - INPLACE(out)",
)
)
if not is_broadcast(in_spec.strides):
cases.append(
TestCase(
inputs=[in_spec],
kwargs={"out": 0},
output_spec=None,
comparison_target=0,
tolerance=tol,
description="expm1 - INPLACE(a)",
)
)
return cases
class OpTest(BaseOperatorTest):
"""Expm1 operator test with simplified implementation"""
def __init__(self):
super().__init__("Expm1")
def get_test_cases(self):
return parse_test_cases()
def torch_operator(self, *args, **kwargs):
return torch.expm1(*args, **kwargs)
# def infinicore_operator(self, *args, **kwargs):
# """InfiniCore implementation (operator not yet available)."""
# return infinicore.expm1(*args, **kwargs)
def main():
"""Main entry point"""
runner = GenericTestRunner(OpTest)
runner.run_and_exit()
if __name__ == "__main__":
main()
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
import torch
import infinicore
from framework.base import BaseOperatorTest, TensorSpec, TestCase
from framework.runner import GenericTestRunner
from framework.utils import is_broadcast
# Test cases format: (shape, p, training, in_strides_or_None)
# infinicore.nn.functional.feature_alpha_dropout(input, p=0.5, training=True)
_TEST_CASES_DATA = [
((8, 16), 0.1, True, None),
((8, 16), 0.2, False, (128, 1)),
((2, 3, 4), 0.5, True, None),
((16, 64), 0.3, True, None),
((4, 5, 6), 0.5, False, None),
((3, 4, 5), 0.4, True, (60, 20, 4)),
]
_TOLERANCE_MAP = {
infinicore.float16: {"atol": 1e-2, "rtol": 1e-2},
infinicore.float32: {"atol": 1e-5, "rtol": 1e-4},
infinicore.bfloat16: {"atol": 1e-2, "rtol": 5e-2},
}
_TENSOR_DTYPES = [infinicore.float16, infinicore.bfloat16, infinicore.float32]
def parse_test_cases():
test_cases = []
for data in _TEST_CASES_DATA:
shape, p, training = data[0], data[1], data[2]
in_strides = data[3] if len(data) > 3 else None
supports_inplace = not is_broadcast(in_strides)
for dtype in _TENSOR_DTYPES:
tol = _TOLERANCE_MAP.get(dtype, {"atol": 1e-2, "rtol": 1e-2})
input_spec = TensorSpec.from_tensor(shape, in_strides, dtype)
kwargs = {"p": p, "training": training}
# Out-of-place
test_cases.append(
TestCase(
inputs=[input_spec],
kwargs=kwargs,
output_spec=None,
comparison_target=None,
tolerance=tol,
description=f"feature_alpha_dropout - OUT_OF_PLACE",
)
)
return test_cases
class OpTest(BaseOperatorTest):
"""FeatureAlphaDropout operator test with simplified implementation"""
def __init__(self):
super().__init__("FeatureAlphaDropout")
def get_test_cases(self):
return parse_test_cases()
def torch_operator(self, *args, **kwargs):
return torch.nn.functional.feature_alpha_dropout(*args, **kwargs)
# def infinicore_operator(self, *args, **kwargs):
# """InfiniCore implementation (operator not yet available)."""
# return infinicore.nn.functional.feature_alpha_dropout(*args, **kwargs)
def main():
"""Main entry point"""
runner = GenericTestRunner(OpTest)
runner.run_and_exit()
if __name__ == "__main__":
main()
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
import torch
import infinicore
from framework.base import BaseOperatorTest, TensorSpec, TestCase
from framework.runner import GenericTestRunner
from framework.utils import is_broadcast
# Test cases format: (shape, dims_tuple, input_strides_or_None)
# infinicore.flip(input, dims)
_TEST_CASES_DATA = [
((13, 4), (0,), None),
((8, 16), (1,), (128, 1)),
((2, 3, 4), (2,), None),
((4, 5, 6), (0, 2), None),
((16, 64), (0, 1), None),
((2, 2, 3, 4), (1, 3), None),
]
_TOLERANCE_MAP = {
infinicore.float16: {"atol": 0, "rtol": 1e-2},
infinicore.float32: {"atol": 0, "rtol": 1e-4},
infinicore.bfloat16: {"atol": 0, "rtol": 5e-2},
}
_TENSOR_DTYPES = [infinicore.float16, infinicore.bfloat16, infinicore.float32]
def parse_test_cases():
test_cases = []
for data in _TEST_CASES_DATA:
shape, dims = data[0], data[1]
in_strides = data[2] if len(data) > 2 else None
supports_inplace = not is_broadcast(in_strides)
for dtype in _TENSOR_DTYPES:
tol = _TOLERANCE_MAP.get(dtype, {"atol": 0, "rtol": 1e-4})
in_spec = TensorSpec.from_tensor(shape, in_strides, dtype)
kwargs = {"dims": dims}
test_cases.append(
TestCase(
inputs=[in_spec],
kwargs=kwargs,
output_spec=None,
comparison_target=None,
tolerance=tol,
description=f"flip - OUT_OF_PLACE",
)
)
# infinicore.flip has no explicit out or inplace flag; skip in-place/out variants.
return test_cases
class OpTest(BaseOperatorTest):
"""Flip operator test with simplified implementation"""
def __init__(self):
super().__init__("Flip")
def get_test_cases(self):
return parse_test_cases()
def torch_operator(self, *args, **kwargs):
# dims = kwargs.pop("dims", None)
# if dims is not None:
# return infinicore.flip(*args, dims)
return torch.flip(*args, **kwargs)
# def infinicore_operator(self, *args, **kwargs):
# """InfiniCore implementation (operator not yet available)."""
# dims = kwargs.pop("dims", None)
# if dims is not None:
# return infinicore.flip(*args, dims)
# return infinicore.flip(*args, **kwargs)
def main():
"""Main entry point"""
runner = GenericTestRunner(OpTest)
runner.run_and_exit()
if __name__ == "__main__":
main()
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
import torch
import infinicore
from framework.base import BaseOperatorTest, TensorSpec, TestCase
from framework.runner import GenericTestRunner
from framework.utils import is_broadcast
# Test cases format: (shape, input_strides_or_None)
# infinicore.fliplr(input) flips the left/right (dim=-1 for 2D-like tensors)
_TEST_CASES_DATA = [
((13, 4), None),
((8, 16), (128, 1)),
((2, 3, 4), None),
((4, 5), None),
((16, 64), None),
((3, 4, 5), (60, 20, 4)),
]
_TOLERANCE_MAP = {
infinicore.float16: {"atol": 0, "rtol": 1e-2},
infinicore.float32: {"atol": 0, "rtol": 1e-4},
infinicore.bfloat16: {"atol": 0, "rtol": 5e-2},
}
_TENSOR_DTYPES = [infinicore.float16, infinicore.bfloat16, infinicore.float32]
def parse_test_cases():
test_cases = []
for data in _TEST_CASES_DATA:
shape = data[0]
in_strides = data[1] if len(data) > 1 else None
supports_inplace = not is_broadcast(in_strides)
for dtype in _TENSOR_DTYPES:
tol = _TOLERANCE_MAP.get(dtype, {"atol": 0, "rtol": 1e-4})
in_spec = TensorSpec.from_tensor(shape, in_strides, dtype)
test_cases.append(
TestCase(
inputs=[in_spec],
kwargs={},
output_spec=None,
comparison_target=None,
tolerance=tol,
description="fliplr - OUT_OF_PLACE",
)
)
return test_cases
class OpTest(BaseOperatorTest):
"""FlipLR operator test with simplified implementation"""
def __init__(self):
super().__init__("FlipLR")
def get_test_cases(self):
return parse_test_cases()
def torch_operator(self, *args, **kwargs):
return torch.fliplr(*args, **kwargs)
# def infinicore_operator(self, *args, **kwargs):
# """InfiniCore implementation (operator not yet available)."""
# return infinicore.fliplr(*args, **kwargs)
def main():
"""Main entry point"""
runner = GenericTestRunner(OpTest)
runner.run_and_exit()
if __name__ == "__main__":
main()
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
import torch
import infinicore
from framework.base import BaseOperatorTest, TensorSpec, TestCase
from framework.runner import GenericTestRunner
from framework.utils import is_broadcast
# Test cases format: (shape, input_strides_or_None)
# infinicore.flipud(input) flips up/down (dim=-2 for 2D-like tensors)
_TEST_CASES_DATA = [
((13, 4), None),
((8, 16), (128, 1)),
((2, 3, 4), None),
((4, 5), None),
((16, 64), None),
((3, 4, 5), (60, 20, 4)),
]
_TOLERANCE_MAP = {
infinicore.float16: {"atol": 0, "rtol": 1e-2},
infinicore.float32: {"atol": 0, "rtol": 1e-4},
infinicore.bfloat16: {"atol": 0, "rtol": 5e-2},
}
_TENSOR_DTYPES = [infinicore.float16, infinicore.bfloat16, infinicore.float32]
def parse_test_cases():
test_cases = []
for data in _TEST_CASES_DATA:
shape = data[0]
in_strides = data[1] if len(data) > 1 else None
supports_inplace = not is_broadcast(in_strides)
for dtype in _TENSOR_DTYPES:
tol = _TOLERANCE_MAP.get(dtype, {"atol": 0, "rtol": 1e-4})
in_spec = TensorSpec.from_tensor(shape, in_strides, dtype)
test_cases.append(
TestCase(
inputs=[in_spec],
kwargs={},
output_spec=None,
comparison_target=None,
tolerance=tol,
description="flipud - OUT_OF_PLACE",
)
)
return test_cases
class OpTest(BaseOperatorTest):
"""FlipUD operator test with simplified implementation"""
def __init__(self):
super().__init__("FlipUD")
def get_test_cases(self):
return parse_test_cases()
def torch_operator(self, *args, **kwargs):
return torch.flipud(*args, **kwargs)
# def infinicore_operator(self, *args, **kwargs):
# """InfiniCore implementation (operator not yet available)."""
# return infinicore.flipud(*args, **kwargs)
def main():
"""Main entry point"""
runner = GenericTestRunner(OpTest)
runner.run_and_exit()
if __name__ == "__main__":
main()
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
import torch
import infinicore
from framework.base import BaseOperatorTest, TensorSpec, TestCase
from framework.runner import GenericTestRunner
from framework.utils import is_broadcast
# Test cases format: (in_shape, in_strides_or_None, exponent_scalar_or_None, exponent_tensor_shape_or_None)
# infinicore.float_power(input, exponent)
_TEST_CASES_DATA = [
((2, 3, 4), None, 2.0, None),
((1, 4, 8), (32, 8, 1), None, (1, 4, 8)),
((3, 2, 5, 7), None, 3.0, None),
((2, 1, 16), None, None, (2, 1, 16)),
((1, 8, 9, 11), (792, 99, 11, 1), 1.5, None),
((2, 6, 10), None, None, (2, 6, 10)),
]
_TOLERANCE_MAP = {
infinicore.float16: {"atol": 1e-3, "rtol": 1e-2},
infinicore.float32: {"atol": 1e-5, "rtol": 1e-4},
}
_TENSOR_DTYPES = [infinicore.float16, infinicore.float32]
def parse_test_cases():
cases = []
dtype_map = {
infinicore.float16: infinicore.float64,
infinicore.float32: infinicore.float64,
infinicore.complex64: infinicore.complex128,
}
for shape, strides, exp_scalar, exp_tensor_shape in _TEST_CASES_DATA:
for dtype in _TENSOR_DTYPES:
tol = _TOLERANCE_MAP[dtype]
input_spec = TensorSpec.from_tensor(shape, strides, dtype)
out_dtype = dtype_map.get(dtype, dtype)
# exponent as scalar
if exp_scalar is not None:
kwargs = {}
cases.append(
TestCase(
inputs=[input_spec, exp_scalar],
kwargs=kwargs,
output_spec=None,
comparison_target=None,
tolerance=tol,
description="float_power_scalar_exp - OUT_OF_PLACE",
)
)
out_spec = TensorSpec.from_tensor(shape, None, out_dtype)
cases.append(
TestCase(
inputs=[input_spec, exp_scalar],
kwargs={},
output_spec=out_spec,
comparison_target="out",
tolerance=tol,
description="float_power_scalar_exp - INPLACE(out)",
)
)
# exponent as tensor
if exp_tensor_shape is not None:
exp_spec = TensorSpec.from_tensor(exp_tensor_shape, None, dtype)
cases.append(
TestCase(
inputs=[input_spec, exp_spec],
kwargs={},
output_spec=None,
comparison_target=None,
tolerance=tol,
description="float_power_tensor_exp - OUT_OF_PLACE",
)
)
out_spec = TensorSpec.from_tensor(shape, None, out_dtype)
cases.append(
TestCase(
inputs=[input_spec, exp_spec],
kwargs={},
output_spec=out_spec,
comparison_target="out",
tolerance=tol,
description="float_power_tensor_exp_explicit_out",
)
)
return cases
class OpTest(BaseOperatorTest):
"""FloatPower operator test with simplified implementation"""
def __init__(self):
super().__init__("FloatPower")
def get_test_cases(self):
return parse_test_cases()
def torch_operator(self, *args, **kwargs):
return torch.float_power(*args, **kwargs)
# def infinicore_operator(self, *args, **kwargs):
# """InfiniCore implementation (operator not yet available)."""
# return infinicore.float_power(*args, **kwargs)
def main():
"""Main entry point"""
runner = GenericTestRunner(OpTest)
runner.run_and_exit()
if __name__ == "__main__":
main()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment