prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Perp-Neg implementation is wrong, parallel component not ignored
  https://github.com/comfyanonymous/ComfyUI/blob/18c151b3e3f6838fab4028e7a8ba526e30e610d3/comfy_extras/nodes_perpneg.py#L38-L40
  
  The Perp-Neg node does not match the [paper](https://arxiv.org/pdf/2304.04968.pdf) (pytorch code in Appendix A.1).
  When positive and negative prompt are the same, the result should be the same as an empty negative prompt because the prompts are completely parallel (i.e. there is no perpendicular component).
  
  Positive: "forest"
  Negative: ""
  ![ComfyUI_00194_](https://github.com/comfyanonymous/ComfyUI/assets/114889020/6c86c0d5-ec8b-478d-aa29-e41794bd3184)
  
  Positive: "forest"
  Negative: "forest"
  ![ComfyUI_00195_](https://github.com/comfyanonymous/ComfyUI/assets/114889020/fa4f2938-bc7a-48cb-8750-f76e6426dd4e)
  
  I'll submit a PR in a bit.
  
  </issue>
  <code>
  [start of comfy_extras/nodes_perpneg.py]
  1 import torch
  2 import comfy.model_management
  3 import comfy.sample
  4 import comfy.samplers
  5 import comfy.utils
  6 
  7 
  8 class PerpNeg:
  9     @classmethod
  10     def INPUT_TYPES(s):
  11         return {"required": {"model": ("MODEL", ),
  12                              "empty_conditioning": ("CONDITIONING", ),
  13                              "neg_scale": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 100.0}),
  14                             }}
  15     RETURN_TYPES = ("MODEL",)
  16     FUNCTION = "patch"
  17 
  18     CATEGORY = "_for_testing"
  19 
  20     def patch(self, model, empty_conditioning, neg_scale):
  21         m = model.clone()
  22         nocond = comfy.sample.convert_cond(empty_conditioning)
  23 
  24         def cfg_function(args):
  25             model = args["model"]
  26             noise_pred_pos = args["cond_denoised"]
  27             noise_pred_neg = args["uncond_denoised"]
  28             cond_scale = args["cond_scale"]
  29             x = args["input"]
  30             sigma = args["sigma"]
  31             model_options = args["model_options"]
  32             nocond_processed = comfy.samplers.encode_model_conds(model.extra_conds, nocond, x, x.device, "negative")
  33 
  34             (noise_pred_nocond, _) = comfy.samplers.calc_cond_uncond_batch(model, nocond_processed, None, x, sigma, model_options)
  35 
  36             pos = noise_pred_pos - noise_pred_nocond
  37             neg = noise_pred_neg - noise_pred_nocond
  38             perp = ((torch.mul(pos, neg).sum())/(torch.norm(neg)**2)) * neg
  39             perp_neg = perp * neg_scale
  40             cfg_result = noise_pred_nocond + cond_scale*(pos - perp_neg)
  41             cfg_result = x - cfg_result
  42             return cfg_result
  43 
  44         m.set_model_sampler_cfg_function(cfg_function)
  45 
  46         return (m, )
  47 
  48 
  49 NODE_CLASS_MAPPINGS = {
  50     "PerpNeg": PerpNeg,
  51 }
  52 
  53 NODE_DISPLAY_NAME_MAPPINGS = {
  54     "PerpNeg": "Perp-Neg",
  55 }
  56
  [end of comfy_extras/nodes_perpneg.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/comfy_extras/nodes_perpneg.py b/comfy_extras/nodes_perpneg.py
  --- a/comfy_extras/nodes_perpneg.py
  +++ b/comfy_extras/nodes_perpneg.py
  @@ -35,7 +35,7 @@
   
               pos = noise_pred_pos - noise_pred_nocond
               neg = noise_pred_neg - noise_pred_nocond
  -            perp = ((torch.mul(pos, neg).sum())/(torch.norm(neg)**2)) * neg
  +            perp = neg - ((torch.mul(neg, pos).sum())/(torch.norm(pos)**2)) * pos
               perp_neg = perp * neg_scale
               cfg_result = noise_pred_nocond + cond_scale*(pos - perp_neg)
               cfg_result = x - cfg_result
  
verification_info: {"golden_diff": "diff --git a/comfy_extras/nodes_perpneg.py b/comfy_extras/nodes_perpneg.py\n--- a/comfy_extras/nodes_perpneg.py\n+++ b/comfy_extras/nodes_perpneg.py\n@@ -35,7 +35,7 @@\n \n             pos = noise_pred_pos - noise_pred_nocond\n             neg = noise_pred_neg - noise_pred_nocond\n-            perp = ((torch.mul(pos, neg).sum())/(torch.norm(neg)**2)) * neg\n+            perp = neg - ((torch.mul(neg, pos).sum())/(torch.norm(pos)**2)) * pos\n             perp_neg = perp * neg_scale\n             cfg_result = noise_pred_nocond + cond_scale*(pos - perp_neg)\n             cfg_result = x - cfg_result\n", "issue": "Perp-Neg implementation is wrong, parallel component not ignored\nhttps://github.com/comfyanonymous/ComfyUI/blob/18c151b3e3f6838fab4028e7a8ba526e30e610d3/comfy_extras/nodes_perpneg.py#L38-L40\r\n\r\nThe Perp-Neg node does not match the [paper](https://arxiv.org/pdf/2304.04968.pdf) (pytorch code in Appendix A.1).\r\nWhen positive and negative prompt are the same, the result should be the same as an empty negative prompt because the prompts are completely parallel (i.e. there is no perpendicular component).\r\n\r\nPositive: \"forest\"\r\nNegative: \"\"\r\n![ComfyUI_00194_](https://github.com/comfyanonymous/ComfyUI/assets/114889020/6c86c0d5-ec8b-478d-aa29-e41794bd3184)\r\n\r\nPositive: \"forest\"\r\nNegative: \"forest\"\r\n![ComfyUI_00195_](https://github.com/comfyanonymous/ComfyUI/assets/114889020/fa4f2938-bc7a-48cb-8750-f76e6426dd4e)\r\n\r\nI'll submit a PR in a bit.\n", "before_files": [{"content": "import torch\nimport comfy.model_management\nimport comfy.sample\nimport comfy.samplers\nimport comfy.utils\n\n\nclass PerpNeg:\n    @classmethod\n    def INPUT_TYPES(s):\n        return {\"required\": {\"model\": (\"MODEL\", ),\n                             \"empty_conditioning\": (\"CONDITIONING\", ),\n                             \"neg_scale\": (\"FLOAT\", {\"default\": 1.0, \"min\": 0.0, \"max\": 100.0}),\n                            }}\n    RETURN_TYPES = (\"MODEL\",)\n    FUNCTION = \"patch\"\n\n    CATEGORY = \"_for_testing\"\n\n    def patch(self, model, empty_conditioning, neg_scale):\n        m = model.clone()\n        nocond = comfy.sample.convert_cond(empty_conditioning)\n\n        def cfg_function(args):\n            model = args[\"model\"]\n            noise_pred_pos = args[\"cond_denoised\"]\n            noise_pred_neg = args[\"uncond_denoised\"]\n            cond_scale = args[\"cond_scale\"]\n            x = args[\"input\"]\n            sigma = args[\"sigma\"]\n            model_options = args[\"model_options\"]\n            nocond_processed = comfy.samplers.encode_model_conds(model.extra_conds, nocond, x, x.device, \"negative\")\n\n            (noise_pred_nocond, _) = comfy.samplers.calc_cond_uncond_batch(model, nocond_processed, None, x, sigma, model_options)\n\n            pos = noise_pred_pos - noise_pred_nocond\n            neg = noise_pred_neg - noise_pred_nocond\n            perp = ((torch.mul(pos, neg).sum())/(torch.norm(neg)**2)) * neg\n            perp_neg = perp * neg_scale\n            cfg_result = noise_pred_nocond + cond_scale*(pos - perp_neg)\n            cfg_result = x - cfg_result\n            return cfg_result\n\n        m.set_model_sampler_cfg_function(cfg_function)\n\n        return (m, )\n\n\nNODE_CLASS_MAPPINGS = {\n    \"PerpNeg\": PerpNeg,\n}\n\nNODE_DISPLAY_NAME_MAPPINGS = {\n    \"PerpNeg\": \"Perp-Neg\",\n}\n", "path": "comfy_extras/nodes_perpneg.py"}]}