prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Tensor.__eq__() with two bool tensors raises error on Torch backend
  This was introduced from #1493
  
  To reproduce:
  ```
  In [24]: (Tensor([1], dtype=dtypes.bool, device="TORCH") == Tensor([1], dtype=dtypes.bool, device="TORCH")).realize()
  RuntimeError: Subtraction, the `-` operator, with a bool tensor is not supported. If you are trying to invert a mask, use the `~` or `logical_not()` operator instead.
  ```
  RuntimeError is from pytorch
  
  
  
  </issue>
  <code>
  [start of tinygrad/runtime/ops_torch.py]
  1 import torch
  2 from typing import Dict, Callable, Optional
  3 from tinygrad.ops import UnaryOps, BinaryOps, MovementOps, TernaryOps, Op, Interpreted
  4 from tinygrad.helpers import getenv, dtypes, prod, DType
  5 from tinygrad.runtime.ops_cpu import base_fxn_for_op, einsum_mulacc
  6 from tinygrad.runtime.lib import RawBuffer
  7 
  8 device = torch.device("cuda:0" if torch.cuda.is_available() else ("mps" if getenv("MPS", 0) else "cpu"))
  9 type_map = {torch.float64: dtypes.float64, torch.float16: dtypes.float16, torch.float32: dtypes.float32, torch.int8: dtypes.int8, torch.int32: dtypes.int32, torch.int64: dtypes.int64, torch.uint8: dtypes.uint8, torch.bool: dtypes.bool}
  10 inverse_type_map = {v:k for k,v in type_map.items()}
  11 
  12 def as_strided(x, arg):
  13   if any(i < 0 for i in arg[1]):
  14     return torch.as_strided(x.contiguous(), arg[0], tuple(abs(i) for i in arg[1]),
  15       arg[2] + sum((s-1)*a if a < 0 else 0 for (s,a) in zip(arg[0], arg[1]))).flip([i for i,a in enumerate(arg[1]) if a < 0])
  16   return torch.as_strided(x.contiguous(), arg[0], arg[1], arg[2])
  17 
  18 torch_fxn_for_op: Dict[Op, Callable] = {**base_fxn_for_op, **{
  19   UnaryOps.NOOP: lambda x: x.contiguous(), UnaryOps.SQRT: lambda x: x.sqrt(), UnaryOps.EXP2: lambda x: x.exp2(), UnaryOps.LOG2: lambda x: x.log2(), UnaryOps.SIN: torch.sin,
  20   UnaryOps.CAST: lambda x,y: (x.view if y[1] else x.type)(next(k for k,v in type_map.items() if v==y[0])),
  21   BinaryOps.MAX: torch.maximum, BinaryOps.CMPLT: lambda x,y: (x<y).type(torch.promote_types(x.dtype, y.dtype)),
  22   MovementOps.PAD: lambda x, padding: torch.nn.functional.pad(x, [item for sublist in padding[::-1] for item in sublist]),
  23   TernaryOps.MULACC: einsum_mulacc(lambda s,a,b: torch.einsum(s, a.float(), b.float()).type(torch.promote_types(a.dtype, b.dtype)), lambda x: x.stride(), lambda x,s: x.expand(s)),
  24   TernaryOps.WHERE: lambda x, y, z: torch.where(x != 0, y, z),
  25   MovementOps.STRIDE: lambda x, arg: x[tuple(slice(None, None, abs(i)) for i in arg)].flip([i for i,a in enumerate(arg) if a < 0]),
  26   MovementOps.EXPAND: lambda x, arg: x.expand(arg), MovementOps.PERMUTE: lambda x, arg: x.permute(arg),
  27   MovementOps.AS_STRIDED: as_strided
  28 }}
  29 
  30 class RawTorchBuffer(RawBuffer):
  31   def __init__(self, size:int, dtype:DType, buf:Optional[torch.Tensor]=None): super().__init__(size, dtype, buf if buf is not None else torch.empty([size], dtype=inverse_type_map[dtype]))
  32   @classmethod
  33   def fromCPU(cls, x):
  34     buf = torch.from_numpy(x if all(s>=0 for s in x.strides) else x.copy()).requires_grad_(False).to(device)
  35     return cls(prod(x.shape), type_map[buf.dtype], buf)
  36   def toCPU(self): return self._buf.cpu().numpy()
  37 TorchBuffer = Interpreted(RawTorchBuffer, torch_fxn_for_op, from_underlying=lambda x: RawTorchBuffer(prod(x.shape), type_map[x.dtype], x))
  38
  [end of tinygrad/runtime/ops_torch.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/tinygrad/runtime/ops_torch.py b/tinygrad/runtime/ops_torch.py
  --- a/tinygrad/runtime/ops_torch.py
  +++ b/tinygrad/runtime/ops_torch.py
  @@ -18,7 +18,7 @@
   torch_fxn_for_op: Dict[Op, Callable] = {**base_fxn_for_op, **{
     UnaryOps.NOOP: lambda x: x.contiguous(), UnaryOps.SQRT: lambda x: x.sqrt(), UnaryOps.EXP2: lambda x: x.exp2(), UnaryOps.LOG2: lambda x: x.log2(), UnaryOps.SIN: torch.sin,
     UnaryOps.CAST: lambda x,y: (x.view if y[1] else x.type)(next(k for k,v in type_map.items() if v==y[0])),
  -  BinaryOps.MAX: torch.maximum, BinaryOps.CMPLT: lambda x,y: (x<y).type(torch.promote_types(x.dtype, y.dtype)),
  +  BinaryOps.MAX: torch.maximum, BinaryOps.CMPLT: lambda x,y: (x<y).type(torch.promote_types(x.dtype, y.dtype)), BinaryOps.SUB: lambda x,y: torch.logical_xor(x, y) if y.dtype is torch.bool else torch.sub(x, y),
     MovementOps.PAD: lambda x, padding: torch.nn.functional.pad(x, [item for sublist in padding[::-1] for item in sublist]),
     TernaryOps.MULACC: einsum_mulacc(lambda s,a,b: torch.einsum(s, a.float(), b.float()).type(torch.promote_types(a.dtype, b.dtype)), lambda x: x.stride(), lambda x,s: x.expand(s)),
     TernaryOps.WHERE: lambda x, y, z: torch.where(x != 0, y, z),
  
verification_info: {"golden_diff": "diff --git a/tinygrad/runtime/ops_torch.py b/tinygrad/runtime/ops_torch.py\n--- a/tinygrad/runtime/ops_torch.py\n+++ b/tinygrad/runtime/ops_torch.py\n@@ -18,7 +18,7 @@\n torch_fxn_for_op: Dict[Op, Callable] = {**base_fxn_for_op, **{\n   UnaryOps.NOOP: lambda x: x.contiguous(), UnaryOps.SQRT: lambda x: x.sqrt(), UnaryOps.EXP2: lambda x: x.exp2(), UnaryOps.LOG2: lambda x: x.log2(), UnaryOps.SIN: torch.sin,\n   UnaryOps.CAST: lambda x,y: (x.view if y[1] else x.type)(next(k for k,v in type_map.items() if v==y[0])),\n-  BinaryOps.MAX: torch.maximum, BinaryOps.CMPLT: lambda x,y: (x<y).type(torch.promote_types(x.dtype, y.dtype)),\n+  BinaryOps.MAX: torch.maximum, BinaryOps.CMPLT: lambda x,y: (x<y).type(torch.promote_types(x.dtype, y.dtype)), BinaryOps.SUB: lambda x,y: torch.logical_xor(x, y) if y.dtype is torch.bool else torch.sub(x, y),\n   MovementOps.PAD: lambda x, padding: torch.nn.functional.pad(x, [item for sublist in padding[::-1] for item in sublist]),\n   TernaryOps.MULACC: einsum_mulacc(lambda s,a,b: torch.einsum(s, a.float(), b.float()).type(torch.promote_types(a.dtype, b.dtype)), lambda x: x.stride(), lambda x,s: x.expand(s)),\n   TernaryOps.WHERE: lambda x, y, z: torch.where(x != 0, y, z),\n", "issue": "Tensor.__eq__() with two bool tensors raises error on Torch backend\nThis was introduced from #1493\r\n\r\nTo reproduce:\r\n```\r\nIn [24]: (Tensor([1], dtype=dtypes.bool, device=\"TORCH\") == Tensor([1], dtype=dtypes.bool, device=\"TORCH\")).realize()\r\nRuntimeError: Subtraction, the `-` operator, with a bool tensor is not supported. If you are trying to invert a mask, use the `~` or `logical_not()` operator instead.\r\n```\r\nRuntimeError is from pytorch\r\n\r\n\n", "before_files": [{"content": "import torch\nfrom typing import Dict, Callable, Optional\nfrom tinygrad.ops import UnaryOps, BinaryOps, MovementOps, TernaryOps, Op, Interpreted\nfrom tinygrad.helpers import getenv, dtypes, prod, DType\nfrom tinygrad.runtime.ops_cpu import base_fxn_for_op, einsum_mulacc\nfrom tinygrad.runtime.lib import RawBuffer\n\ndevice = torch.device(\"cuda:0\" if torch.cuda.is_available() else (\"mps\" if getenv(\"MPS\", 0) else \"cpu\"))\ntype_map = {torch.float64: dtypes.float64, torch.float16: dtypes.float16, torch.float32: dtypes.float32, torch.int8: dtypes.int8, torch.int32: dtypes.int32, torch.int64: dtypes.int64, torch.uint8: dtypes.uint8, torch.bool: dtypes.bool}\ninverse_type_map = {v:k for k,v in type_map.items()}\n\ndef as_strided(x, arg):\n  if any(i < 0 for i in arg[1]):\n    return torch.as_strided(x.contiguous(), arg[0], tuple(abs(i) for i in arg[1]),\n      arg[2] + sum((s-1)*a if a < 0 else 0 for (s,a) in zip(arg[0], arg[1]))).flip([i for i,a in enumerate(arg[1]) if a < 0])\n  return torch.as_strided(x.contiguous(), arg[0], arg[1], arg[2])\n\ntorch_fxn_for_op: Dict[Op, Callable] = {**base_fxn_for_op, **{\n  UnaryOps.NOOP: lambda x: x.contiguous(), UnaryOps.SQRT: lambda x: x.sqrt(), UnaryOps.EXP2: lambda x: x.exp2(), UnaryOps.LOG2: lambda x: x.log2(), UnaryOps.SIN: torch.sin,\n  UnaryOps.CAST: lambda x,y: (x.view if y[1] else x.type)(next(k for k,v in type_map.items() if v==y[0])),\n  BinaryOps.MAX: torch.maximum, BinaryOps.CMPLT: lambda x,y: (x<y).type(torch.promote_types(x.dtype, y.dtype)),\n  MovementOps.PAD: lambda x, padding: torch.nn.functional.pad(x, [item for sublist in padding[::-1] for item in sublist]),\n  TernaryOps.MULACC: einsum_mulacc(lambda s,a,b: torch.einsum(s, a.float(), b.float()).type(torch.promote_types(a.dtype, b.dtype)), lambda x: x.stride(), lambda x,s: x.expand(s)),\n  TernaryOps.WHERE: lambda x, y, z: torch.where(x != 0, y, z),\n  MovementOps.STRIDE: lambda x, arg: x[tuple(slice(None, None, abs(i)) for i in arg)].flip([i for i,a in enumerate(arg) if a < 0]),\n  MovementOps.EXPAND: lambda x, arg: x.expand(arg), MovementOps.PERMUTE: lambda x, arg: x.permute(arg),\n  MovementOps.AS_STRIDED: as_strided\n}}\n\nclass RawTorchBuffer(RawBuffer):\n  def __init__(self, size:int, dtype:DType, buf:Optional[torch.Tensor]=None): super().__init__(size, dtype, buf if buf is not None else torch.empty([size], dtype=inverse_type_map[dtype]))\n  @classmethod\n  def fromCPU(cls, x):\n    buf = torch.from_numpy(x if all(s>=0 for s in x.strides) else x.copy()).requires_grad_(False).to(device)\n    return cls(prod(x.shape), type_map[buf.dtype], buf)\n  def toCPU(self): return self._buf.cpu().numpy()\nTorchBuffer = Interpreted(RawTorchBuffer, torch_fxn_for_op, from_underlying=lambda x: RawTorchBuffer(prod(x.shape), type_map[x.dtype], x))\n", "path": "tinygrad/runtime/ops_torch.py"}]}