perf: Remove sqrt in palette match

#4213 · open · 2 comments

View on GitHub ↗

Leuchak

sqrt is not needed when only the minimum distance is required. ```diff diff --git i/rich/palette.py w/rich/palette.py index f2958794..8c6ba963 100644 --- i/rich/palette.py +++ w/rich/palette.py @@ -1,4 +1,3 @@ -from math import sqrt from functools import lru_cache from typing import Sequence, Tuple, TYPE_CHECKING @@ -52,17 +51,16 @@ class Palette: int: Index of closes matching color. """ red1, green1, blue1 = color - _sqrt = sqrt get_color = self._colors.__getitem__ - def get_color_distance(index: int) -> float: + def get_color_distance(index: int) -> int: """Get the distance to a color.""" red2, green2, blue2 = get_color(index) red_mean = (red1 + red2) // 2 red = red1 - red2 green = green1 - green2 blue = blue1 - blue2 - return _sqrt( + return ( (((512 + red_mean) * red * red) >> 8) + 4 * green * green + (((767 - red_mean) * blue * blue) >> 8) ```

Comments

UsmanGhias

Hi there! Regarding issue #4213 (perf: Remove sqrt in palette match): Calculating the square root is computationally expensive and unnecessary when we only need to compare relative color distances to find the minimum value, as square root is a monotonically increasing function for non-negative numbers. ```python import time from rich.palette import Palette palette = Palette([(i, i, i) for i in range(256)]) start = time.perf_counter() for r in range(0, 256, 5): for g in range(0, 256, 5): for b in range(0, 256, 5): palette.match((r, g, b)) print(f"Time taken: {time.perf_counter() - start:.4f}s") ``` ```diff diff --git i/rich/palette.py w/rich/palette.py index f2958794..8c6ba963 100644 --- i/rich/palette.py +++ w/rich/palette.py @@ -1,4 +1,3 @@ -from math import sqrt from functools import lru_cache from typing import Sequence, Tuple, TYPE_CHECKING @@ -52,17 +51,16 @@ class Palette: int: Index of closes matching color. """ red1, green1, blue1 = color - _sqrt = sqrt get_color = self._colors.__getitem__ - def get_color_distance(index: int) -> float: + def get_color_distance(index: int) -> int: """Get the distance to a color.""" red2, green2, blue2 = get_color(index) red_mean = (red1 + red2) // 2 red = red1 - red2 green = green1 - green2 blue = blue1 - blue2 - return _sqrt( + return ( (((512 + red_mean) * red * red) >> 8) + 4 * green * green + (((767 - red_mean) * blue * blue) >> 8) ``` Hope this helps point you in the right direction! Let me know if you run into any issues. Best, Usman

Leuchak

@UsmanGhias ai slop/20 > Hi there! > > Regarding issue [#4213](https://github.com/Textualize/rich/issues/4213) (perf: Remove sqrt in palette match): > > Calculating the square root is computationally expensive and unnecessary when we only need to compare relative color distances to find the minimum value, as square root is a monotonically increasing function for non-negative numbers. > > import time > from rich.palette import Palette > > palette = Palette([(i, i, i) for i in range(256)]) > start = time.perf_counter() > for r in range(0, 256, 5): > for g in range(0, 256, 5): > for b in range(0, 256, 5): > palette.match((r, g, b)) > print(f"Time taken: {time.perf_counter() - start:.4f}s") > diff --git i/rich/palette.py w/rich/palette.py > index f2958794..8c6ba963 100644 > --- i/rich/palette.py > +++ w/rich/palette.py > @@ -1,4 +1,3 @@ > -from math import sqrt > from functools import lru_cache > from typing import Sequence, Tuple, TYPE_CHECKING > > @@ -52,17 +51,16 @@ class Palette: > int: Index of closes matching color. > """ > red1, green1, blue1 = color > - _sqrt = sqrt > get_color = self._colors.__getitem__ > > - def get_color_distance(index: int) -> float: > + def get_color_distance(index: int) -> int: > """Get the distance to a color.""" > red2, green2, blue2 = get_color(index) > red_mean = (red1 + red2) // 2 > red = red1 - red2 > green = green1 - green2 > blue = blue1 - blue2 > - return _sqrt( > + return ( > (((512 + red_mean) * red * red) >> 8) > + 4 * green * green > + (((767 - red_mean) * blue * blue) >> 8) > Hope this helps point you in the right direction! Let me know if you run into any issues. > > Best, Usman