www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - signbit question

reply Miguel L <mlabayru gmail.com> writes:
Why does std.math.signbit only work for floating point types?
Is there an analogue function for integer types? what is the best 
way to compare the sign of a float with the sign of an integer?
Thanks in advance
Mar 15 2018
next sibling parent Seb <seb wilzba.ch> writes:
On Thursday, 15 March 2018 at 15:28:16 UTC, Miguel L wrote:
 Why does std.math.signbit only work for floating point types?
 Is there an analogue function for integer types?
I guess because for integers you don't need to distinguish between +0.0 and -0.0, so no one bother until now to add it to std.math. That being said there are a few options for integer types: --- import std.math, std.stdio; void main() { foreach (a; -1 .. 2) { "a:".writeln(a); signbit(cast(double) a).writefln!"signbit: %2d"; (cast(uint) a >> a.sizeof * 8 - 1).writefln!"bitshift: %2d"; (a < 0).writefln!"< 0:\t %2d"; writeln; } } --- https://run.dlang.io/is/pts6dj The first option is a bit slower for integers and the second and third option generate equivalent assembly [1], so I would recommend `a < 0` for integer types. [1] https://godbolt.org/g/4ohTJx
 what is the best way to compare the sign of a float with the 
 sign of an integer?
Ideas: 1) Make a PR to signbit to add integer support 2) Create your own signsbit a la: --- auto signbit(A)(A a) { static import std.math; import std.traits : isIntegral; static if (isIntegral!A) return a < 0; else return std.math.signbit(a); } ---
Mar 15 2018
prev sibling next sibling parent Adam D. Ruppe <destructionator gmail.com> writes:
On Thursday, 15 March 2018 at 15:28:16 UTC, Miguel L wrote:
 Why does std.math.signbit only work for floating point types?
Integers are stored in an entirely different way, twos-complement instead of having a sign bit. You probably shouldn't be using the sign bit function at all, it is for digging deeper into the float binary format. Instead, I'd just say if(f > 0 && i > 0) if(f < 0 && i < 0) if(f == 0 && i == 0) etc. in math stuff to see if they have the same sign. floats have weird things like +0 and -0 which doesn't exist at all in ints...
Mar 15 2018
prev sibling parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Thursday, 15 March 2018 at 15:28:16 UTC, Miguel L wrote:
 Why does std.math.signbit only work for floating point types?
 Is there an analogue function for integer types? what is the 
 best way to compare the sign of a float with the sign of an 
 integer?
 Thanks in advance
integers don't have a sign-bit. since they are not necessarily singed. However if an integer is signed and using 1-complement you can either do sign = var < 0 or sign = (var & (1 << (sizeof(var)*8 - 1)); though I cannot tell which one is faster you have to experiment.
Mar 15 2018
next sibling parent reply Miguel L <mlabayru gmail.com> writes:
On Thursday, 15 March 2018 at 16:31:56 UTC, Stefan Koch wrote:
 On Thursday, 15 March 2018 at 15:28:16 UTC, Miguel L wrote:
 Why does std.math.signbit only work for floating point types?
 Is there an analogue function for integer types? what is the 
 best way to compare the sign of a float with the sign of an 
 integer?
 Thanks in advance
integers don't have a sign-bit. since they are not necessarily singed. However if an integer is signed and using 1-complement you can either do sign = var < 0 or sign = (var & (1 << (sizeof(var)*8 - 1)); though I cannot tell which one is faster you have to experiment.
Thanks. Just one more question: Is this code correct? I don't care about +0 or -0 as the calculations on f guarantee it cannot be 0 at all. int a; float f; .... if((a<0)==signbit(f)) {....} else {...}
Mar 15 2018
next sibling parent reply rumbu <rumbu rumbu.ro> writes:
On Thursday, 15 March 2018 at 17:18:08 UTC, Miguel L wrote:
 On Thursday, 15 March 2018 at 16:31:56 UTC, Stefan Koch wrote:
 On Thursday, 15 March 2018 at 15:28:16 UTC, Miguel L wrote:
 Why does std.math.signbit only work for floating point types?
 Is there an analogue function for integer types? what is the 
 best way to compare the sign of a float with the sign of an 
 integer?
 Thanks in advance
integers don't have a sign-bit. since they are not necessarily singed. However if an integer is signed and using 1-complement you can either do sign = var < 0 or sign = (var & (1 << (sizeof(var)*8 - 1)); though I cannot tell which one is faster you have to experiment.
Thanks. Just one more question: Is this code correct? I don't care about +0 or -0 as the calculations on f guarantee it cannot be 0 at all. int a; float f; .... if((a<0)==signbit(f)) {....} else {...}
If you are comparing with an integer, please avoid signbit. It will return 1 also for -0.0, -inf and -nan. Don't bother also with signbit for integer types. The compiler usually outsmarts the programmer in finding the best way to compare an integer with 0. You can simply write: if (a < 0 && f < 0) {...} This will cover the [-inf..0) but not the NaN case. You can test it in a separate branch if (isNaN(f)) {...}
Mar 15 2018
parent reply Miguel L <mlabayru gmail.com> writes:
On Thursday, 15 March 2018 at 17:31:38 UTC, rumbu wrote:
 On Thursday, 15 March 2018 at 17:18:08 UTC, Miguel L wrote:
 On Thursday, 15 March 2018 at 16:31:56 UTC, Stefan Koch wrote:
 On Thursday, 15 March 2018 at 15:28:16 UTC, Miguel L wrote:
 [...]
integers don't have a sign-bit. since they are not necessarily singed. However if an integer is signed and using 1-complement you can either do sign = var < 0 or sign = (var & (1 << (sizeof(var)*8 - 1)); though I cannot tell which one is faster you have to experiment.
Thanks. Just one more question: Is this code correct? I don't care about +0 or -0 as the calculations on f guarantee it cannot be 0 at all. int a; float f; .... if((a<0)==signbit(f)) {....} else {...}
If you are comparing with an integer, please avoid signbit. It will return 1 also for -0.0, -inf and -nan. Don't bother also with signbit for integer types. The compiler usually outsmarts the programmer in finding the best way to compare an integer with 0. You can simply write: if (a < 0 && f < 0) {...} This will cover the [-inf..0) but not the NaN case. You can test it in a separate branch if (isNaN(f)) {...}
There are various in my code there are more than two variables, and i'd like to check when their signs differ.I am trying to avoid this, maybe there is no point in it: if(!((a>=0 && f>=0) || (a<0 && f<0))){ //signs are different .... } Thanks, anyway
Mar 15 2018
parent Dlang User <dlang.user gmx.com> writes:
On 3/15/2018 12:39 PM, Miguel L wrote:
 On Thursday, 15 March 2018 at 17:31:38 UTC, rumbu wrote:
 On Thursday, 15 March 2018 at 17:18:08 UTC, Miguel L wrote:
 On Thursday, 15 March 2018 at 16:31:56 UTC, Stefan Koch wrote:
 On Thursday, 15 March 2018 at 15:28:16 UTC, Miguel L wrote:
 [...]
integers don't have a sign-bit. since they are not necessarily singed. However if an integer is signed and using 1-complement you can either do sign = var < 0 or sign = (var & (1 << (sizeof(var)*8 - 1)); though I cannot tell which one is faster you have to experiment.
Thanks. Just one more question: Is this code correct? I don't care about +0 or -0 as the calculations on f guarantee it cannot be 0 at all. int a; float f; .... if((a<0)==signbit(f)) {....} else {...}
If you are comparing with an integer, please avoid signbit. It will return 1 also for -0.0, -inf and -nan. Don't bother also with signbit for integer types. The compiler usually outsmarts the programmer in finding the best way to compare an integer with 0. You can simply write: if (a < 0 && f < 0) {...} This will cover the [-inf..0) but not the NaN case. You can test it in a separate branch if (isNaN(f)) {...}
There are various in my code there are more than two variables, and i'd like to check when their signs differ.I am trying to avoid this, maybe there is no point in it: if(!((a>=0 && f>=0) || (a<0 && f<0))){ //signs are different .... } Thanks, anyway
You could simplify that to this: if ((a < 0) != (f < 0)) { } Or if you have more than two variables you could do something like this: bool AllSameSign(double[] args ...) { //Only need to check if there are more than one of them if (args.length > 1) { //Compare arg[0] to all the other args. for (int i = 1; i < args.length; i++) { if ((args[0] < 0) != (args[i] < 0)) { return false; } } } return true; } Which you could call like this, with as many variables as you like: AllSameSign(a,f);
Mar 15 2018
prev sibling parent ketmar <ketmar ketmar.no-ip.org> writes:
Miguel L wrote:

 as the calculations on f guarantee it cannot be 0 at all.
than `f` will become zero very soon. something that "cannot happen" is the most probable thing to happen. otherwise, LGTM.
Mar 15 2018
prev sibling parent reply Seb <seb wilzba.ch> writes:
On Thursday, 15 March 2018 at 16:31:56 UTC, Stefan Koch wrote:
 On Thursday, 15 March 2018 at 15:28:16 UTC, Miguel L wrote:
 Why does std.math.signbit only work for floating point types?
 Is there an analogue function for integer types? what is the 
 best way to compare the sign of a float with the sign of an 
 integer?
 Thanks in advance
integers don't have a sign-bit. since they are not necessarily singed. However if an integer is signed and using 1-complement you can either do sign = var < 0 or sign = (var & (1 << (sizeof(var)*8 - 1)); though I cannot tell which one is faster you have to experiment.
They generate the same assembly: https://godbolt.org/g/4ohTJx
Mar 15 2018
parent reply ashit axar <www.ashit.axar gmail.com> writes:
On Thursday, 15 March 2018 at 17:30:48 UTC, Seb wrote:

 They generate the same assembly: https://godbolt.org/g/4ohTJx
import std.stdio; void main() { writeln("hello"); } this generate error for dmd there.
Mar 16 2018
parent reply Radu <void null.pt> writes:
On Friday, 16 March 2018 at 07:00:36 UTC, ashit axar wrote:
 On Thursday, 15 March 2018 at 17:30:48 UTC, Seb wrote:

 They generate the same assembly: https://godbolt.org/g/4ohTJx
import std.stdio; void main() { writeln("hello"); } this generate error for dmd there.
`writeln` is not supported in betterC for dmd. Use `printf` instead.
Mar 16 2018
parent Seb <seb wilzba.ch> writes:
On Friday, 16 March 2018 at 08:35:58 UTC, Radu wrote:
 On Friday, 16 March 2018 at 07:00:36 UTC, ashit axar wrote:
 On Thursday, 15 March 2018 at 17:30:48 UTC, Seb wrote:

 They generate the same assembly: https://godbolt.org/g/4ohTJx
import std.stdio; void main() { writeln("hello"); } this generate error for dmd there.
`writeln` is not supported in betterC for dmd. Use `printf` instead.
Or remove -betterC. I just used it because then no module constructors/destructors are generated and thus the assembly is even shorter.
Mar 16 2018