Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve performance some Float methods #4018

Merged
merged 1 commit into from Jan 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .document
Expand Up @@ -14,7 +14,7 @@ array.rb
ast.rb
dir.rb
gc.rb
integer.rb
numeric.rb
io.rb
kernel.rb
pack.rb
Expand Down
14 changes: 14 additions & 0 deletions benchmark/float_methods.yml
@@ -0,0 +1,14 @@
prelude: |
flo = 4.2
benchmark:
to_f: |
flo.to_f
abs: |
flo.abs
magnitude: |
flo.magnitude
-@: |
-flo
zero?: |
flo.zero?
loop_count: 20000000
8 changes: 4 additions & 4 deletions common.mk
Expand Up @@ -1020,7 +1020,7 @@ BUILTIN_RB_SRCS = \
$(srcdir)/ast.rb \
$(srcdir)/dir.rb \
$(srcdir)/gc.rb \
$(srcdir)/integer.rb \
$(srcdir)/numeric.rb \
$(srcdir)/io.rb \
$(srcdir)/pack.rb \
$(srcdir)/trace_point.rb \
Expand Down Expand Up @@ -8224,7 +8224,6 @@ miniinit.$(OBJEXT): {$(VPATH)}encoding.h
miniinit.$(OBJEXT): {$(VPATH)}gc.rb
miniinit.$(OBJEXT): {$(VPATH)}gem_prelude.rb
miniinit.$(OBJEXT): {$(VPATH)}id.h
miniinit.$(OBJEXT): {$(VPATH)}integer.rb
miniinit.$(OBJEXT): {$(VPATH)}intern.h
miniinit.$(OBJEXT): {$(VPATH)}internal.h
miniinit.$(OBJEXT): {$(VPATH)}internal/anyargs.h
Expand Down Expand Up @@ -8376,6 +8375,7 @@ miniinit.$(OBJEXT): {$(VPATH)}miniinit.c
miniinit.$(OBJEXT): {$(VPATH)}miniprelude.c
miniinit.$(OBJEXT): {$(VPATH)}missing.h
miniinit.$(OBJEXT): {$(VPATH)}node.h
miniinit.$(OBJEXT): {$(VPATH)}numeric.rb
miniinit.$(OBJEXT): {$(VPATH)}onigmo.h
miniinit.$(OBJEXT): {$(VPATH)}oniguruma.h
miniinit.$(OBJEXT): {$(VPATH)}pack.rb
Expand Down Expand Up @@ -9062,8 +9062,6 @@ numeric.$(OBJEXT): {$(VPATH)}defines.h
numeric.$(OBJEXT): {$(VPATH)}encoding.h
numeric.$(OBJEXT): {$(VPATH)}id.h
numeric.$(OBJEXT): {$(VPATH)}id_table.h
numeric.$(OBJEXT): {$(VPATH)}integer.rb
numeric.$(OBJEXT): {$(VPATH)}integer.rbinc
numeric.$(OBJEXT): {$(VPATH)}intern.h
numeric.$(OBJEXT): {$(VPATH)}internal.h
numeric.$(OBJEXT): {$(VPATH)}internal/anyargs.h
Expand Down Expand Up @@ -9208,6 +9206,8 @@ numeric.$(OBJEXT): {$(VPATH)}internal/warning_push.h
numeric.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
numeric.$(OBJEXT): {$(VPATH)}missing.h
numeric.$(OBJEXT): {$(VPATH)}numeric.c
numeric.$(OBJEXT): {$(VPATH)}numeric.rb
numeric.$(OBJEXT): {$(VPATH)}numeric.rbinc
numeric.$(OBJEXT): {$(VPATH)}onigmo.h
numeric.$(OBJEXT): {$(VPATH)}oniguruma.h
numeric.$(OBJEXT): {$(VPATH)}ruby_assert.h
Expand Down
2 changes: 1 addition & 1 deletion inits.c
Expand Up @@ -87,7 +87,7 @@ rb_call_builtin_inits(void)
#define BUILTIN(n) CALL(builtin_##n)
BUILTIN(gc);
BUILTIN(ractor);
BUILTIN(integer);
BUILTIN(numeric);
BUILTIN(io);
BUILTIN(dir);
BUILTIN(ast);
Expand Down
54 changes: 1 addition & 53 deletions numeric.c
Expand Up @@ -1030,13 +1030,6 @@ flo_coerce(VALUE x, VALUE y)
return rb_assoc_new(rb_Float(y), x);
}

/*
* call-seq:
* -float -> float
*
* Returns +float+, negated.
*/

VALUE
rb_float_uminus(VALUE flt)
{
Expand Down Expand Up @@ -1701,53 +1694,13 @@ rb_float_eql(VALUE x, VALUE y)

#define flo_eql rb_float_eql

/*
* call-seq:
* float.to_f -> self
*
* Since +float+ is already a Float, returns +self+.
*/

static VALUE
flo_to_f(VALUE num)
{
return num;
}

/*
* call-seq:
* float.abs -> float
* float.magnitude -> float
*
* Returns the absolute value of +float+.
*
* (-34.56).abs #=> 34.56
* -34.56.abs #=> 34.56
* 34.56.abs #=> 34.56
*
* Float#magnitude is an alias for Float#abs.
*/

VALUE
rb_float_abs(VALUE flt)
{
double val = fabs(RFLOAT_VALUE(flt));
return DBL2NUM(val);
}

/*
* call-seq:
* float.zero? -> true or false
*
* Returns +true+ if +float+ is 0.0.
*/

static VALUE
flo_zero_p(VALUE num)
{
return flo_iszero(num) ? Qtrue : Qfalse;
}

/*
* call-seq:
* float.nan? -> true or false
Expand Down Expand Up @@ -5677,7 +5630,6 @@ Init_Numeric(void)
rb_define_method(rb_cFloat, "to_s", flo_to_s, 0);
rb_define_alias(rb_cFloat, "inspect", "to_s");
rb_define_method(rb_cFloat, "coerce", flo_coerce, 1);
rb_define_method(rb_cFloat, "-@", rb_float_uminus, 0);
rb_define_method(rb_cFloat, "+", rb_float_plus, 1);
rb_define_method(rb_cFloat, "-", rb_float_minus, 1);
rb_define_method(rb_cFloat, "*", rb_float_mul, 1);
Expand All @@ -5697,10 +5649,6 @@ Init_Numeric(void)
rb_define_method(rb_cFloat, "<=", flo_le, 1);
rb_define_method(rb_cFloat, "eql?", flo_eql, 1);
rb_define_method(rb_cFloat, "hash", flo_hash, 0);
rb_define_method(rb_cFloat, "to_f", flo_to_f, 0);
rb_define_method(rb_cFloat, "abs", rb_float_abs, 0);
rb_define_method(rb_cFloat, "magnitude", rb_float_abs, 0);
rb_define_method(rb_cFloat, "zero?", flo_zero_p, 0);

rb_define_method(rb_cFloat, "to_i", flo_to_i, 0);
rb_define_method(rb_cFloat, "to_int", flo_to_i, 0);
Expand Down Expand Up @@ -5732,4 +5680,4 @@ rb_float_new(double d)
return rb_float_new_inline(d);
}

#include "integer.rbinc"
#include "numeric.rbinc"
57 changes: 57 additions & 0 deletions integer.rb → numeric.rb
Expand Up @@ -148,3 +148,60 @@ def zero?
Primitive.cexpr! 'rb_int_zero_p(self)'
end
end

class Float
#
# call-seq:
# float.to_f -> self
#
# Since +float+ is already a Float, returns +self+.
#
def to_f
return self
end

#
# call-seq:
# float.abs -> float
# float.magnitude -> float
#
# Returns the absolute value of +float+.
#
# (-34.56).abs #=> 34.56
# -34.56.abs #=> 34.56
# 34.56.abs #=> 34.56
#
# Float#magnitude is an alias for Float#abs.
#
def abs
Primitive.attr! 'inline'
Primitive.cexpr! 'rb_float_abs(self)'
end

def magnitude
Primitive.attr! 'inline'
Primitive.cexpr! 'rb_float_abs(self)'
end

#
# call-seq:
# -float -> float
#
# Returns +float+, negated.
#
def -@
Primitive.attr! 'inline'
Primitive.cexpr! 'rb_float_uminus(self)'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To understand better, does using Primitive.attr! 'inline' require using Primitive.cexpr!?
Or could it also be done like:

  def -@
    Primitive.attr! 'inline'
    Primitive.rb_float_uminus
  end

?
(which seems nicer to me because it's not mixing C code inside Ruby code)

Copy link
Member

@k0kubun k0kubun Jan 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be. To use that, we need to have ec as a first argument even if it's not needed, which is again ko1's design. (I don't like this particular part because I don't want to take unused arguments. Using cexpr is currently the only way to avoid the redundant C argument.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think an unused ec argument is fine, and would be cleaner.
cc @ko1

Another advantage of using a named Primitive and not cexpr! is the Ruby code could be reused on other Ruby implementations. For Float#-@ it doesn't matter much, but as more methods are declared like this it will become valuable.

Actually, I just noticed a difference, on TruffleRuby, Primitive.foo pass no arguments (Primitive.rb_float_uminus(self) would be needed), but on CRuby, it seems self is always passed "implicitly".

end

#
# call-seq:
# float.zero? -> true or false
#
# Returns +true+ if +float+ is 0.0.
#
def zero?
Primitive.attr! 'inline'
Primitive.cexpr! 'flo_iszero(self) ? Qtrue : Qfalse'
end
end