From 053d89ca2bde48126e058700799baa7ca370ca8d Mon Sep 17 00:00:00 2001 From: akr Date: Thu, 18 Mar 2010 20:35:18 +0000 Subject: * string.c (rb_str_sum): don't call method for each byte. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@26975 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- string.c | 58 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 25 deletions(-) (limited to 'string.c') diff --git a/string.c b/string.c index 435a06d76b..29d083a230 100644 --- a/string.c +++ b/string.c @@ -6537,7 +6537,7 @@ rb_str_ord(VALUE s) * Returns a basic n-bit checksum of the characters in str, * where n is the optional Fixnum parameter, defaulting * to 16. The result is simply the sum of the binary value of each character in - * str modulo 2n - 1. This is not a particularly good + * str modulo 2**n - 1. This is not a particularly good * checksum. */ @@ -6548,6 +6548,8 @@ rb_str_sum(int argc, VALUE *argv, VALUE str) int bits; char *ptr, *p, *pend; long len; + VALUE sum = INT2FIX(0); + unsigned long sum0 = 0; if (argc == 0) { bits = 16; @@ -6559,36 +6561,42 @@ rb_str_sum(int argc, VALUE *argv, VALUE str) ptr = p = RSTRING_PTR(str); len = RSTRING_LEN(str); pend = p + len; - if (bits >= (int)sizeof(long)*CHAR_BIT) { - VALUE sum = INT2FIX(0); - while (p < pend) { - str_mod_check(str, ptr, len); - sum = rb_funcall(sum, '+', 1, INT2FIX((unsigned char)*p)); - p++; - } - if (bits != 0) { - VALUE mod; + while (p < pend) { + if (FIXNUM_MAX - 255 < sum0) { + sum = rb_funcall(sum, '+', 1, LONG2FIX(sum0)); + str_mod_check(str, ptr, len); + sum0 = 0; + } + sum0 += (unsigned char)*p; + p++; + } - mod = rb_funcall(INT2FIX(1), rb_intern("<<"), 1, INT2FIX(bits)); - mod = rb_funcall(mod, '-', 1, INT2FIX(1)); - sum = rb_funcall(sum, '&', 1, mod); - } - return sum; + if (bits == 0) { + if (sum0) { + sum = rb_funcall(sum, '+', 1, LONG2FIX(sum0)); + } } else { - unsigned long sum = 0; + if (sum == INT2FIX(0)) { + if (bits < (int)sizeof(long)*CHAR_BIT) { + sum0 &= (((unsigned long)1)<