Page 1 of 5

Equivalent to Gamemaker's sign() function?

Posted: Fri Feb 09, 2018 12:53 pm
by hasen
There is a function in gamemaker studio that is quite useful but it doesn't seem to be the same as Math.sin evidently. It works like this:

"This function returns whether a number is positive, negative or neither and returns 1, -1, 0 respectively. For example - sign(458) will return 1, sign(-5) will return -1 and sign(0) will return 0."

Is there any way to do this with Lua?

Re: Equivalent to Gamemaker's sign() function?

Posted: Fri Feb 09, 2018 1:03 pm
by grump

Code: Select all

function sign(n)
	return n < 0 and -1 or n > 0 and 1 or 0
end

Re: Equivalent to Gamemaker's sign() function?

Posted: Fri Feb 09, 2018 1:25 pm
by hasen
Ok thanks. Just wondered if there was a set Math function in lua for that.

Re: Equivalent to Gamemaker's sign() function?

Posted: Fri Feb 09, 2018 7:15 pm
by zorg
There isn't; quite a few small math functions are missing from lua's math library.

Re: Equivalent to Gamemaker's sign() function?

Posted: Fri Feb 09, 2018 9:59 pm
by raidho36
Worth noting that all languages that have it, implement sign funciton that way - there is no hardware CPU operation to which such function would map, so it has to be done in software anyway.

If your target CPU supports hardware min and max functions, and assuming that LuaJIT can leverage them, you can use the following branchless function:

Code: Select all

function sign ( val ) return math.max ( math.min ( val * math.huge, 1 ), -1 ) end
I don't know if it's any good performance-wise, though you cache the math library data to upvalues and that'll improve something. In interpreted mode it probably wouldn't improve anything - the whole reason interpretation is slow is because there's a failed prediction of an execution branch at every single step of the way.

Re: Equivalent to Gamemaker's sign() function?

Posted: Fri Feb 09, 2018 11:08 pm
by pgimeno
Since we're nitpicking I'll play too ;)

I prefer this slight variant of grump's code:

Code: Select all

function sign(n)
	return n < 0 and -1 or n > 0 and 1 or n
end
It returns -1 for a negative number, 1 for a positive number, 0 for positive zero, -0 for negative zero, Not a Number for a NaN input and indeterminate for an indet input. I certainly prefer it to propagate NaNs/indets.

Re: Equivalent to Gamemaker's sign() function?

Posted: Sat Feb 10, 2018 1:30 pm
by ivan
I like grump's version best but I have to throw this one in:

Code: Select all

function sign(n)
  return n == 0 and 0 or n/math.abs(n)
end
Could be simplified if you are certain that n is non-zero:

Code: Select all

assert(n ~= 0)
sign = n/math.abs(n)

Re: Equivalent to Gamemaker's sign() function?

Posted: Sat Feb 10, 2018 2:09 pm
by coffeecat
Both * and / are quite costly for floating numbers, if LuaJIT can't help to optimize. A simple branching like grump's version could be more efficient.

The most efficient way to do this is probably by bitwise operations on the binary representation of floating number, if there's no CPU instruction for this. I don't know how this can be done in Lua though.

Re: Equivalent to Gamemaker's sign() function?

Posted: Sat Feb 10, 2018 3:06 pm
by Rubbermaid
coffeecat wrote: Sat Feb 10, 2018 2:09 pm Both * and / are quite costly for floating numbers, if LuaJIT can't help to optimize. A simple branching like grump's version could be more efficient.

The most efficient way to do this is probably by bitwise operations on the binary representation of floating number, if there's no CPU instruction for this. I don't know how this can be done in Lua though.
I have no idea if this is how bitwise operations work in Lua, but given that all of the numbers are 64-bit doubles I imagine it would look something like:

Code: Select all

sign(n) = ((n & 0x8000000000000000 ~= 0) and -1) or 1

Re: Equivalent to Gamemaker's sign() function?

Posted: Sat Feb 10, 2018 3:26 pm
by zorg
Rubbermaid wrote: Sat Feb 10, 2018 3:06 pm I have no idea if this is how bitwise operations work in Lua, but given that all of the numbers are 64-bit doubles I imagine it would look something like:

Code: Select all

sign(n) = ((n & 0x8000000000000000 ~= 0) and -1) or 1
There are no bitwise operations in lua (at least not in the version löve uses by default)... not using symbols that is, and luaJIT's bitop module functions return signed 32bit numbers; maybe something like the following may work, although ultimately i haven't tested it, and it doesn't have a separate retval for 0.

Code: Select all

function sign(n) return bit.rshift(bit.band(n, bit.tobit(0x80000000)), 31) == 1 and -1 or 1 end
Then again, it is a bit silly to want to do such """""""""""optimalization""""""""""" on such a function. :|