Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 83 additions & 8 deletions onnxscript/function_libs/torch_lib/ops/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@
_INT64_MAX = 9223372036854775807
_INT64_MIN = -9223372036854775808
_MATH_PI = math.pi
_INT64_ARANGE_NON_INTEGRAL_USES_FLOAT_LENGTH = (
torch.arange(3.1, dtype=torch.int64).numel() == 4
)
Comment on lines +59 to +61


@torch_op("aten::_local_scalar_dense", trace_only=True)
Expand Down Expand Up @@ -521,6 +524,56 @@ def _range_supported(dtype: int) -> bool:
}


def _is_integral_dtype(dtype: int) -> bool:
return dtype in {
INT8.dtype,
INT16.dtype,
INT32.dtype,
INT64.dtype,
}


def _is_integral_scalar(arg: TRealUnlessFloat16OrInt8) -> bool:
if isinstance(arg, int):
return True
if isinstance(arg, float):
return False
return arg.dtype in {
INT8.dtype,
INT16.dtype,
INT32.dtype,
INT64.dtype,
}


def _arange_integral_dtype_with_non_integral_args(
start: TRealUnlessFloat16OrInt8,
end: TRealUnlessFloat16OrInt8,
step: TRealUnlessFloat16OrInt8,
dtype: int,
) -> TensorType:
"""Implements torch.arange for integral dtypes when not all inputs are integral."""
start_float = op.Cast(start, to=FLOAT.dtype)
end_float = op.Cast(end, to=FLOAT.dtype)
step_float = op.Cast(step, to=FLOAT.dtype)

length = op.Cast(
op.Ceil(op.Div(op.Sub(end_float, start_float), step_float)), to=INT64.dtype
)
index = op.Range(op.Constant(value_int=0), length, op.Constant(value_int=1))

if _range_supported(dtype):
index = op.Cast(index, to=dtype)
start = op.Cast(start, to=dtype)
step = op.Cast(step, to=dtype)
return op.Add(start, op.Mul(step, index))

start = op.Cast(start, to=INT64.dtype)
step = op.Cast(step, to=INT64.dtype)
result = op.Add(start, op.Mul(step, index))
return op.Cast(result, to=dtype)


def _integral_to_be_adjusted(dtype: int) -> bool:
"""Returns true if the dtype is special integral handled by torch."""
return dtype in {
Expand All @@ -544,6 +597,12 @@ def aten_arange(
zero = op.CastLike(0.0, end)
one = op.CastLike(1.0, end)
result = op.Range(zero, end, one)
elif (
_is_integral_dtype(dtype)
and not _is_integral_scalar(end)
and (dtype != INT64.dtype or _INT64_ARANGE_NON_INTEGRAL_USES_FLOAT_LENGTH)
):
result = _arange_integral_dtype_with_non_integral_args(0, end, 1, dtype)
elif _range_supported(dtype):
end = op.Cast(end, to=dtype)
zero = op.Cast(0, to=dtype)
Expand Down Expand Up @@ -576,6 +635,12 @@ def aten_arange_start(
if dtype == -1 or dtype is None:
one = op.CastLike(1.0, end)
result = op.Range(start, end, one)
elif (
_is_integral_dtype(dtype)
and not (_is_integral_scalar(start) and _is_integral_scalar(end))
and (dtype != INT64.dtype or _INT64_ARANGE_NON_INTEGRAL_USES_FLOAT_LENGTH)
):
result = _arange_integral_dtype_with_non_integral_args(start, end, 1, dtype)
elif _range_supported(dtype):
end = op.Cast(end, to=dtype)
start = op.Cast(start, to=dtype)
Expand Down Expand Up @@ -659,17 +724,26 @@ def aten_arange_start_step(
end = op.Cast(end, to=FLOAT.dtype)
step = op.Cast(step, to=FLOAT.dtype)
result = op.Range(start, end, step)
elif _integral_to_be_adjusted(dtype):
# PyTorch arange op handles these integral types differently from INT64,
# so we have to adjust these arguments accordingly.
# https://github.com/pytorch/pytorch/blob/121cfb60c0817816fcbe2190303b7f6d05c77cf3/torch/_refs/__init__.py#L4794
start, end, step = _adjust_args_for_arange_int_dtype(start, end, step)
result = op.Cast(op.Range(start, end, step), to=dtype)
elif (
_is_integral_dtype(dtype)
and not (
_is_integral_scalar(start)
and _is_integral_scalar(end)
and _is_integral_scalar(step)
)
and (dtype != INT64.dtype or _INT64_ARANGE_NON_INTEGRAL_USES_FLOAT_LENGTH)
):
result = _arange_integral_dtype_with_non_integral_args(start, end, step, dtype)
elif dtype == INT64.dtype:
end = op.Cast(end, to=dtype)
start = op.Cast(start, to=dtype)
step = op.Cast(step, to=dtype)
result = op.Range(start, end, step)
elif _integral_to_be_adjusted(dtype):
# PyTorch arange op handles these integral types differently from INT64
# when all arguments are integral.
start, end, step = _adjust_args_for_arange_int_dtype(start, end, step)
result = op.Cast(op.Range(start, end, step), to=dtype)
else:
# Cast input to float if dtype is not supported by Range,
# because the input dtype may be e.g. bfloat16,
Expand Down Expand Up @@ -5804,8 +5878,9 @@ def aten_logit(self: TFloat, eps: Optional[float] = None) -> TFloat:
one_minus_eps = ir.tensor(1 - eps, dtype=self.dtype)
eps = ir.tensor(eps, dtype=self.dtype)

temporary_self = op.Where(self <= one_minus_eps, self, one_minus_eps)
z = op.Where(temporary_self < eps, eps, temporary_self)
# Match torch.clamp behavior for eps > 0.5 by applying max then min.
z = op.Where(self < eps, eps, self)
z = op.Where(z <= one_minus_eps, z, one_minus_eps)

return op.Log(op.Div(z, op.Sub(one, z)))

Expand Down
Loading