From: matz@... (Yukihiro Matsumoto) Date: 2004-04-06T16:42:35+09:00 Subject: [ruby-dev:23341] Re: Time#[+-] when given a negative argument まつもと ゆきひろです In message "[ruby-dev:22675] Re: Time#[+-] when given a negative argument" on 04/01/23, Tanaka Akira writes: |> はい。sign で場合分けしている点と、time_plus() と time_minus() で |> 原理的には同じコードが重複している点を指していました。 |> リファクタリングすべきかなと思いながらも、やっつけ仕事で |> 済ましてしまったので。ちょっと気になっていたのでした。 | |ちょっとやってみまたところ、8行短くなりました。 これでコミットしていただけませんか。 |Index: configure.in |=================================================================== |RCS file: /src/ruby/configure.in,v |retrieving revision 1.221 |diff -p -u -r1.221 configure.in |--- configure.in 21 Jan 2004 16:09:40 -0000 1.221 |+++ configure.in 23 Jan 2004 13:57:02 -0000 |@@ -205,6 +205,7 @@ AC_CHECK_SIZEOF(off_t, 0) | AC_CHECK_SIZEOF(void*, 4) | AC_CHECK_SIZEOF(float, 4) | AC_CHECK_SIZEOF(double, 8) |+AC_CHECK_SIZEOF(time_t, 0) | | AC_CACHE_CHECK(for prototypes, rb_cv_have_prototypes, | [AC_TRY_COMPILE([int foo(int x) { return 0; }], [return foo(10);], |Index: time.c |=================================================================== |RCS file: /src/ruby/time.c,v |retrieving revision 1.95 |diff -p -u -r1.95 time.c |--- time.c 18 Jan 2004 14:16:47 -0000 1.95 |+++ time.c 23 Jan 2004 13:57:02 -0000 |@@ -1168,6 +1168,57 @@ time_to_s(time) | return rb_str_new(buf, len); | } | |+#if SIZEOF_TIME_T == SIZEOF_LONG |+typedef unsigned long unsigned_time_t; |+#elif SIZEOF_TIME_T == SIZEOF_LONG_LONG |+typedef unsigned long long unsigned_time_t; |+#else |+# error cannot find integer type which size is same as time_t. |+#endif |+ |+static VALUE |+time_add(tobj, offset, sign) |+ struct time_object *tobj; |+ VALUE offset; |+ int sign; |+{ |+ double v = NUM2DBL(offset); |+ double f, d; |+ unsigned_time_t sec_off; |+ time_t usec_off, sec, usec; |+ VALUE result; |+ |+ if (v < 0) { |+ v = -v; |+ sign = -sign; |+ } |+ d = modf(v, &f); |+ sec_off = (unsigned_time_t)f; |+ if (f != (double)sec_off) |+ rb_raise(rb_eRangeError, "time %s %f out of Time range", |+ sign < 0 ? "-" : "+", v); |+ usec_off = (time_t)(d*1e6); |+ |+ if (sign < 0) { |+ sec = tobj->tv.tv_sec - sec_off; |+ usec = tobj->tv.tv_usec - usec_off; |+ if (sec > tobj->tv.tv_sec) |+ rb_raise(rb_eRangeError, "time - %f out of Time range", v); |+ } |+ else { |+ sec = tobj->tv.tv_sec + sec_off; |+ usec = tobj->tv.tv_usec + usec_off; |+ if (sec < tobj->tv.tv_sec) |+ rb_raise(rb_eRangeError, "time + %f out of Time range", v); |+ } |+ result = rb_time_new(sec, usec); |+ if (tobj->gmt) { |+ GetTimeval(result, tobj); |+ tobj->gmt = 1; |+ } |+ return result; |+} |+ | /* | * call-seq: | * time + numeric => time |@@ -1184,42 +1235,12 @@ time_plus(time1, time2) | VALUE time1, time2; | { | struct time_object *tobj; |- time_t sec, usec; |- double f, d, v; |- int sign; |- | GetTimeval(time1, tobj); | | if (TYPE(time2) == T_DATA && RDATA(time2)->dfree == time_free) { | rb_raise(rb_eTypeError, "time + time?"); | } |- v = NUM2DBL(time2); |- d = modf(v, &f); |- sign = (f < 0 ? -1 : 1); |- f *= sign; |- sec = (time_t)f; |- if (f != (double)sec) { |- rb_raise(rb_eRangeError, "time + %f out of Time range", v); |- } |-#ifndef NEGATIVE_TIME_T |- if (sign < 0 && f >= tobj->tv.tv_sec) { |- rb_raise(rb_eArgError, "time must be positive"); |- } |-#endif |- usec = tobj->tv.tv_usec + (time_t)(d*1e6); |- sec = (sign > 0 ? tobj->tv.tv_sec + sec : tobj->tv.tv_sec - sec); |-#ifdef NEGATIVE_TIME_T |- if ((tobj->tv.tv_sec >= 0 && sign >= 0 && sec < 0) || |- (tobj->tv.tv_sec <= 0 && sign <= 0 && sec > 0)) { |- rb_raise(rb_eRangeError, "time + %f out of Time range", v); |- } |-#endif |- time2 = rb_time_new(sec, usec); |- if (tobj->gmt) { |- GetTimeval(time2, tobj); |- tobj->gmt = 1; |- } |- return time2; |+ return time_add(tobj, time2, 1); | } | | /* |@@ -1242,13 +1263,11 @@ time_minus(time1, time2) | VALUE time1, time2; | { | struct time_object *tobj; |- time_t sec, usec; |- double f, d, v; |- int sign; | | GetTimeval(time1, tobj); | if (TYPE(time2) == T_DATA && RDATA(time2)->dfree == time_free) { | struct time_object *tobj2; |+ double f; | | GetTimeval(time2, tobj2); | f = (double)tobj->tv.tv_sec - (double)tobj2->tv.tv_sec; |@@ -1257,34 +1276,7 @@ time_minus(time1, time2) | | return rb_float_new(f); | } |- v = NUM2DBL(time2); |- d = modf(v, &f); |- sign = (f < 0 ? -1 : 1); |- f *= sign; |- sec = (time_t)f; |- if (f != (double)sec) { |- rb_raise(rb_eRangeError, "time - %f out of Time range", v); |- } |-#ifndef NEGATIVE_TIME_T |- if (sign > 0 && f >= tobj->tv.tv_sec) { |- rb_raise(rb_eArgError, "time must be positive"); |- } |-#endif |- usec = tobj->tv.tv_usec - (time_t)(d*1e6); |- sec = (sign > 0 ? tobj->tv.tv_sec - sec : tobj->tv.tv_sec + sec); |-#ifdef NEGATIVE_TIME_T |- if ((tobj->tv.tv_sec <= 0 && sign >= 0 && sec > 0) || |- (tobj->tv.tv_sec >= 0 && sign <= 0 && sec < 0)) { |- rb_raise(rb_eRangeError, "time - %f out of Time range", v); |- } |-#endif |- |- time2 = rb_time_new(sec, usec); |- if (tobj->gmt) { |- GetTimeval(time2, tobj); |- tobj->gmt = 1; |- } |- return time2; |+ return time_add(tobj, time2, -1); | } | | /* |-- |[田中 哲][たなか あきら][Tanaka Akira]