Possible to create min(x,y,z) and max(x,y,z)???

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
IcarusLives
Posts: 175
Joined: 17 Jan 2016 23:55

Possible to create min(x,y,z) and max(x,y,z)???

#1 Post by IcarusLives » 26 Aug 2017 12:15

Hello everyone ^-^

I would like to create some sort of math function that can compare 3 integers and determine the MIN or MAX of the 3.

My only problem is that I'm clueless on how this would work in a mathematical sense, but I'm desperate to learn how to do it!

My current project is working on an RGB to HSL convert algorithm, but I need a MIN(x,y,z) or... MIN(r,g,b) and MAX(r,g,b)

Is it possible to do this with just math? I would really like to not use and IF's if I could.

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Possible to create min(x,y,z) and max(x,y,z)???

#2 Post by aGerman » 26 Aug 2017 13:10

You can do that with bitwise operations.
Source:
Bit Twiddling Hacks

Code: Select all

@echo off &setlocal

set /a "x=-55, y=99, z=11"

set /a "min= y + ((x - y) & ((x - y) >> 31)), min= z + ((min - z) & ((min - z) >> 31))"
set /a "max= x - ((x - y) & ((x - y) >> 31)), max= max - ((max - z) & ((max - z) >> 31))"

echo %min%
echo %max%
pause

This technique is risky with big positive or negative numbers because of possible type overflows. Even though I'm sure you won't get any trouble with RGB values.

Steffen

IcarusLives
Posts: 175
Joined: 17 Jan 2016 23:55

Re: Possible to create min(x,y,z) and max(x,y,z)???

#3 Post by IcarusLives » 26 Aug 2017 16:11

Aha! This is perfect! This is exactly what I needed! And thanks for the link you provided as well!


EDIT:

For my own purposes I changed out the variables.

Code: Select all

set /a "min= g + ((r - g) & ((r - g) >> 31)), min= b + ((min - b) & ((min - b) >> 31))"
set /a "max= r - ((r - g) & ((r - g) >> 31)), max= max - ((max - b) & ((max - b) >> 31))"


I also have one more question!

Is it possible to know the value AND the name of the variable of MIN and MAX?

For example...

Code: Select all

set /a "r=131", "g=34", "b=190"

set /a "max= r - ((r - g) & ((r - g) >> 31)), max= max - ((max - b) & ((max - b) >> 31))"

echo %MAX% = 190

But I would also like to know that it was b - BLUE


How would I go about doing that..?

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Possible to create min(x,y,z) and max(x,y,z)???

#4 Post by aGerman » 26 Aug 2017 16:49

You can't return any string (variable name) using SET /A.

Right now I had a look at my C++ code for this kind of conversion. I don't see any reason why you would need it. You would rather need floating point calculation which isn't supported using Batch.

Steffen

IcarusLives
Posts: 175
Joined: 17 Jan 2016 23:55

Re: Possible to create min(x,y,z) and max(x,y,z)???

#5 Post by IcarusLives » 26 Aug 2017 17:03

I was trying to follow a Javascript code, and I found it used this.

Code: Select all

switch(max){
   case r: h = (g - b) / d + (g < b ? 6 : 0); break;
   case g: h = (b - r) / d + 2; break;
   case b: h = (r - g) / d + 4; break;
}


And I assumed this meant that it new not only the max value, but the name as well, which would be how it's choosing what to do..?

Perhaps I am wrong! I guess I will need to keep looking v.v

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Possible to create min(x,y,z) and max(x,y,z)???

#6 Post by aGerman » 26 Aug 2017 17:14

No it doesn't know the name.
You can use IF-ELSE instead of switch-case in the Java code

Code: Select all

if %max%==%r% (
  ...
) else if %max%==%g% (
  ...
) else ( REM only %b% is left here
  ...
)


Steffen

IcarusLives
Posts: 175
Joined: 17 Jan 2016 23:55

Re: Possible to create min(x,y,z) and max(x,y,z)???

#7 Post by IcarusLives » 26 Aug 2017 17:39

Oooh that works as well! Thank you so much for your help

Aacini
Expert
Posts: 1914
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Possible to create min(x,y,z) and max(x,y,z)???

#8 Post by Aacini » 26 Aug 2017 21:32

You may also use this slightly different approach:

Code: Select all

@echo off
setlocal EnableDelayedExpansion

:loop
set /P "rgb=Enter R,G,B values: "
if errorlevel 1 goto :EOF

for /F "tokens=1-3 delims=, " %%a in ("%rgb%") do set /A r=%%a, g=%%b, b=%%c
echo r=%r%, g=%g%, b=%b%
set "var[%r%]=r" & set "var[%g%]=g" & set "var[%b%]=b"

set /A "a=((r-g)>>31)+1, max=a*r+^!a*g, a=((max-b)>>31)+1, max=a*max+^!a*b"
set /A "a=((g-r)>>31)+1, min=a*r+^!a*g, a=((b-min)>>31)+1, min=a*min+^!a*b"
echo The max is: !var[%max%]!=%max%.  The min is: !var[%min%]!=%min%.

goto loop

Antonio

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Possible to create min(x,y,z) and max(x,y,z)???

#9 Post by aGerman » 28 Aug 2017 09:39

I took a few minutes to "translate" the C++ code I have.

Code: Select all

@echo off &setlocal
set /a "r= 65, g= 105, b= 225"
echo Red: %r%, Green: %g%, Blue: %b%
call :rgb2hsv %r% %g% %b%
echo Hue: %h% deg., Saturation: %s%%%, Value: %v%%%
pause
exit /b

:rgb2hsv
setlocal DisableDelayedExpansion
set /a "r= %~1 * 10000 / 255, g= %~2 * 10000 / 255, b= %~3 * 10000 / 255, h= 0, s= 0"
set /a "min= g + ((r - g) & ((r - g) >> 31)), min= b + ((min - b) & ((min - b) >> 31))"
set /a "v= r - ((r - g) & ((r - g) >> 31)), v= v - ((v - b) & ((v - b) >> 31)), d= v - min"
if %d% gtr 0 (
  set /a "s= ((10000 * d / v) + 50) / 100"
  if %v%==%r% (
    set /a "h= ((6000 * (g - b) / d) + 50) / 100"
  ) else if %v%==%g% (
    set /a "h= ((12000 + 6000 * (b - r) / d) + 50) / 100"
  ) else (
    set /a "h= ((24000 + 6000 * (r - g) / d) + 50) / 100"
  )
)
set /a "v= (v + 50) / 100, h= (h + 360) %% 360"
endlocal &set "h=%h%" &set "s=%s%" &set "v=%v%" &exit /b

Values in the sub routine are calculated with 1/100 of degrees or percent in order to minimize rounding errors (although you can't avoid them).
Calculations using (... + 50) / 100 are there for rounding half up.

Steffen

IcarusLives
Posts: 175
Joined: 17 Jan 2016 23:55

Re: Possible to create min(x,y,z) and max(x,y,z)???

#10 Post by IcarusLives » 29 Aug 2017 08:07

aGerman wrote:I took a few minutes to "translate" the C++ code I have.

Code: Select all

@echo off &setlocal
set /a "r= 65, g= 105, b= 225"
echo Red: %r%, Green: %g%, Blue: %b%
call :rgb2hsv %r% %g% %b%
echo Hue: %h% deg., Saturation: %s%%%, Value: %v%%%
pause
exit /b

:rgb2hsv
setlocal DisableDelayedExpansion
set /a "r= %~1 * 10000 / 255, g= %~2 * 10000 / 255, b= %~3 * 10000 / 255, h= 0, s= 0"
set /a "min= g + ((r - g) & ((r - g) >> 31)), min= b + ((min - b) & ((min - b) >> 31))"
set /a "v= r - ((r - g) & ((r - g) >> 31)), v= v - ((v - b) & ((v - b) >> 31)), d= v - min"
if %d% gtr 0 (
  set /a "s= ((10000 * d / v) + 50) / 100"
  if %v%==%r% (
    set /a "h= ((6000 * (g - b) / d) + 50) / 100"
  ) else if %v%==%g% (
    set /a "h= ((12000 + 6000 * (b - r) / d) + 50) / 100"
  ) else (
    set /a "h= ((24000 + 6000 * (r - g) / d) + 50) / 100"
  )
)
set /a "v= (v + 50) / 100, h= (h + 360) %% 360"
endlocal &set "h=%h%" &set "s=%s%" &set "v=%v%" &exit /b

Values in the sub routine are calculated with 1/100 of degrees or percent in order to minimize rounding errors (although you can't avoid them).
Calculations using (... + 50) / 100 are there for rounding half up.

Steffen


Please excuse me absence the past few days.

Thank you very much for your help. My RGB2HSL was very similar to yours, but I can see the obvious mistakes I was making now.

Post Reply