Forum: Ruby Minor Change Proposal for Class 'Numeric'

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
A131b672fdbd2a58dce12031ad78b121?d=identicon&s=25 Wolfgang Nádasi-Donner (wonado)
on 2007-01-22 21:50
(Received via mailing list)
Hi!

I didn't find there a discussion about this here, so first a description
of this
(very) minor change proposal.

I miss the "Sign function" in class "Numeric".

It can simply be added by something like...

class Numeric
   def sign
     self<0?-1:self>0?1:0
   end
end

...but it should be much faster if be defined in the original class.

This method will be used in several algorithms, so it should be
available from
my point of view.

Wolfgang Nádasi-Donner
Ea24c17719a975fb38c107a60f4b3802?d=identicon&s=25 Vincent Fourmond (Guest)
on 2007-01-22 21:54
(Received via mailing list)
Wolfgang Nádasi-Donner wrote:
>   def sign
>     self<0?-1:self>0?1:0
>   end
> end
>
> ...but it should be much faster if be defined in the original class.
>
> This method will be used in several algorithms, so it should be
> available from my point of view.

  Seconded.

  Vince
852a62a28f1de229dc861ce903b07a60?d=identicon&s=25 Gavin Kistner (phrogz)
on 2007-01-23 00:16
(Received via mailing list)
Wolfgang Nádasi-Donner wrote:
> class Numeric
>    def sign
>      self<0?-1:self>0?1:0
>    end
> end
>
> ...but it should be much faster if be defined in the original class.

a) Why do you need it to be so fast? Two comparisons seems pretty
lightweight to me!
b) Why do you think it's generally useful? I think such a method would
have helped me only once or twice in all my programming years.

c) You can implement that more compactly (if not more efficiently) as:

irb(main):001:0> class Numeric; def sign; self <=> 0; end; end
=> nil
irb(main):002:0> -1.sign
=> -1
irb(main):003:0> -5.sign
=> -1
irb(main):004:0> 0.sign
=> 0
irb(main):005:0> 3.sign
=> 1
Ea24c17719a975fb38c107a60f4b3802?d=identicon&s=25 Vincent Fourmond (Guest)
on 2007-01-23 00:19
(Received via mailing list)
Phrogz wrote:
> lightweight to me!
You forget function lookup: there is three function lookup for this
code. Hardcoded in C is way faster (with only one function lookup).

  Vince
58479f76374a3ba3c69b9804163f39f4?d=identicon&s=25 Eric Hodel (Guest)
on 2007-01-23 00:45
(Received via mailing list)
On Jan 22, 2007, at 15:18, Vincent Fourmond wrote:
>> a) Why do you need it to be so fast? Two comparisons seems pretty
>> lightweight to me!
>
>   You forget function lookup: there is three function lookup for this
> code. Hardcoded in C is way faster (with only one function lookup).

So you've benchmarked it and found that calling Numeric#sign takes up
a significant part of your runtime?

Note that you can write this in C for about 5 extra lines using
RubyInline.

--
Eric Hodel - drbrain@segment7.net - http://blog.segment7.net

I LIT YOUR GEM ON FIRE!
Ea24c17719a975fb38c107a60f4b3802?d=identicon&s=25 Vincent Fourmond (Guest)
on 2007-01-23 00:53
(Received via mailing list)
Eric Hodel wrote:
>>
>>   You forget function lookup: there is three function lookup for this
>> code. Hardcoded in C is way faster (with only one function lookup).
>
> So you've benchmarked it and found that calling Numeric#sign takes up a
> significant part of your runtime?

  No ;-) I just point out that a C implementation will be faster than a
pure Ruby one. Then, if you rely heavily on it, well, it would count,
wouldn't it ?

  But I mainly raised the point to provoke, I obviously got what I
wanted, didn't I ;-)

> Note that you can write this in C for about 5 extra lines using
RubyInline.

  That definitely is a good idea !

  Cheers,

  Vince
852a62a28f1de229dc861ce903b07a60?d=identicon&s=25 Gavin Kistner (phrogz)
on 2007-01-23 00:56
(Received via mailing list)
Vincent Fourmond wrote:
> > a) Why do you need it to be so fast? Two comparisons seems pretty
> > lightweight to me!
>
>   You forget function lookup: there is three function lookup for this
> code. Hardcoded in C is way faster (with only one function lookup).

I actually hadn't forgotten it, but (mistakenly) thought that < and >
didn't have normal method overhead. So, the spaceship operator is
actually more terse and faster:

class Numeric
  def sign1; self < 1 ? -1 : self > 1 ? 1 : 0; end
  def sign2; self<=>0; end
  def sign3; 0; end
end

require 'benchmark'

N = 1_000_000
Benchmark.bmbm{ |x|
  x.report{
    N.times{ -5.sign1; 5.sign1; 0.sign1 }
  }
  x.report{
    N.times{ -5.sign2; 5.sign2; 0.sign2 }
  }
  x.report{
    N.times{ -5.sign3; 5.sign3; 0.sign3 }
  }
  x.report{
    N.times{ -5.abs; 5.abs; 0.abs }
  }
}

Rehearsal ------------------------------------
   3.391000   0.000000   3.391000 (  3.421000)
   2.296000   0.000000   2.296000 (  2.313000)
   1.610000   0.000000   1.610000 (  1.609000)
   0.969000   0.000000   0.969000 (  0.969000)
--------------------------- total: 8.266000sec

       user     system      total        real
   2.781000   0.000000   2.781000 (  2.797000)
   2.250000   0.000000   2.250000 (  2.249000)
   1.547000   0.000000   1.547000 (  1.547000)
   0.922000   0.000000   0.922000 (  0.922000)

So, if we assume that it would be about as fast as #abs, then you're
talking about saving about 1.3 MICRO seconds per call (on a 3GHz P4). I
would be surprised (and interested) if saving that amount of time made
a difference in someone's application, for this particular method.

To put it in perspective:
Suppose your Ruby program were controlling a game or simulation.
Suppose you were getting 30fps. Suppose you were calling this method
10,000 times PER FRAME. The difference between having this method
rewritten in the core and using the spaceship operator gets you all the
way to...30.9fps.
A131b672fdbd2a58dce12031ad78b121?d=identicon&s=25 Wolfgang Nádasi-Donner (wonado)
on 2007-01-23 01:10
(Received via mailing list)
Phrogz schrieb:
> b) Why do you think it's generally useful? I think such a method would
> have helped me only once or twice in all my programming years.

There is only one reason: It is a standard function used in mathematics
and
nearly everybody knows a function names "sign" or "sgn" from other
programming
languages.

I think that the code for this method is still there in the kernel.

> c) You can implement that more compactly (if not more efficiently) as:
>
> irb(main):001:0> class Numeric; def sign; self <=> 0; end; end

It was only an example to describe what I mean. I have no suggestions
for an
implementation in the Ruby kernel.

I only think, that a mathematical standard function should be available.

Wolfgang Nádasi-Donner
This topic is locked and can not be replied to.