mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* time.c: less bignum allocations.
* strftime.c (rb_strftime_timespec): defined to avoid rational for nano second resolution time. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27128 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
59ad28c261
commit
fbc42054e8
4 changed files with 347 additions and 152 deletions
|
@ -1,3 +1,10 @@
|
|||
Wed Mar 31 21:30:38 2010 Tanaka Akira <akr@fsij.org>
|
||||
|
||||
* time.c: less bignum allocations.
|
||||
|
||||
* strftime.c (rb_strftime_timespec): defined to avoid rational for
|
||||
nano second resolution time.
|
||||
|
||||
Wed Mar 31 16:05:13 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* test/rake/test_{package_task,rules,task_manager}.rb: use
|
||||
|
|
56
strftime.c
56
strftime.c
|
@ -189,8 +189,8 @@ max(int a, int b)
|
|||
|
||||
/* strftime --- produce formatted time */
|
||||
|
||||
size_t
|
||||
rb_strftime(char *s, size_t maxsize, const char *format, const struct vtm *vtm, VALUE timev, int gmt)
|
||||
static size_t
|
||||
rb_strftime_with_timespec(char *s, size_t maxsize, const char *format, const struct vtm *vtm, VALUE timev, struct timespec *ts, int gmt)
|
||||
{
|
||||
char *endp = s + maxsize;
|
||||
char *start = s;
|
||||
|
@ -306,7 +306,7 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct vtm *vtm,
|
|||
} while (0)
|
||||
#define STRFTIME(fmt) \
|
||||
do { \
|
||||
i = rb_strftime(s, endp - s, fmt, vtm, timev, gmt); \
|
||||
i = rb_strftime_with_timespec(s, endp - s, fmt, vtm, timev, ts, gmt); \
|
||||
if (!i) return 0; \
|
||||
if (precision > i) {\
|
||||
memmove(s + precision - i, s, i);\
|
||||
|
@ -459,11 +459,18 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct vtm *vtm,
|
|||
break;
|
||||
|
||||
case 's':
|
||||
{
|
||||
if (ts) {
|
||||
time_t sec = ts->tv_sec;
|
||||
if (~(time_t)0 <= 0)
|
||||
FMT('0', 1, PRI_TIMET_PREFIX"d", sec);
|
||||
else
|
||||
FMT('0', 1, PRI_TIMET_PREFIX"u", sec);
|
||||
}
|
||||
else {
|
||||
VALUE sec = div(timev, INT2FIX(1));
|
||||
FMTV('0', 1, "d", sec);
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
|
||||
case 'S': /* second, 00 - 60 */
|
||||
i = range(0, vtm->sec, 60);
|
||||
|
@ -753,16 +760,31 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct vtm *vtm,
|
|||
*/
|
||||
w = 9;
|
||||
subsec:
|
||||
{
|
||||
if (precision <= 0) {
|
||||
precision = w;
|
||||
}
|
||||
NEEDS(precision);
|
||||
|
||||
if (ts) {
|
||||
long subsec = ts->tv_nsec;
|
||||
if (9 < precision) {
|
||||
snprintf(s, endp - s, "%09ld", subsec);
|
||||
memset(s+9, '0', precision-9);
|
||||
s += precision;
|
||||
}
|
||||
else {
|
||||
int i;
|
||||
for (i = 0; i < 9-precision; i++)
|
||||
subsec /= 10;
|
||||
snprintf(s, endp - s, "%0*ld", precision, subsec);
|
||||
s += precision;
|
||||
}
|
||||
}
|
||||
else {
|
||||
VALUE subsec = mod(timev, INT2FIX(1));
|
||||
int ww;
|
||||
long n;
|
||||
|
||||
if (precision <= 0) {
|
||||
precision = w;
|
||||
}
|
||||
NEEDS(precision);
|
||||
|
||||
ww = precision;
|
||||
while (9 <= ww) {
|
||||
subsec = mul(subsec, INT2FIX(1000000000));
|
||||
|
@ -867,6 +889,18 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct vtm *vtm,
|
|||
return 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
rb_strftime(char *s, size_t maxsize, const char *format, const struct vtm *vtm, VALUE timev, int gmt)
|
||||
{
|
||||
return rb_strftime_with_timespec(s, maxsize, format, vtm, timev, NULL, gmt);
|
||||
}
|
||||
|
||||
size_t
|
||||
rb_strftime_timespec(char *s, size_t maxsize, const char *format, const struct vtm *vtm, struct timespec *ts, int gmt)
|
||||
{
|
||||
return rb_strftime_with_timespec(s, maxsize, format, vtm, Qnil, ts, gmt);
|
||||
}
|
||||
|
||||
/* isleap --- is a year a leap year? */
|
||||
|
||||
#ifndef __STDC__
|
||||
|
|
|
@ -172,6 +172,15 @@ class TestTime < Test::Unit::TestCase
|
|||
|
||||
t = Time.at(2**40 + "1/3".to_r, 9999999999999).utc
|
||||
assert_equal(36812, t.year)
|
||||
|
||||
t = Time.at(-0x3fff_ffff_ffff_ffff)
|
||||
assert_equal(-146138510344, t.year)
|
||||
t = Time.at(-0x4000_0000_0000_0000)
|
||||
assert_equal(-146138510344, t.year)
|
||||
t = Time.at(-0x4000_0000_0000_0001)
|
||||
assert_equal(-146138510344, t.year)
|
||||
t = Time.at(-0x5000_0000_0000_0001)
|
||||
assert_equal(-182673138422, t.year)
|
||||
end
|
||||
|
||||
def test_at2
|
||||
|
@ -579,6 +588,26 @@ class TestTime < Test::Unit::TestCase
|
|||
assert_equal("JANUARY", T2000.strftime("%#B"))
|
||||
assert_equal("JAN", T2000.strftime("%#h"))
|
||||
assert_equal("FRIDAY", Time.local(2008,1,4).strftime("%#A"))
|
||||
|
||||
t = Time.utc(2000,3,14, 6,53,"58.979323846".to_r) # Pi Day
|
||||
assert_equal("03/14/2000 6:53:58.97932384600000000000000000000",
|
||||
t.strftime("%m/%d/%Y %l:%M:%S.%29N"))
|
||||
assert_equal("03/14/2000 6:53:58.9793238460",
|
||||
t.strftime("%m/%d/%Y %l:%M:%S.%10N"))
|
||||
assert_equal("03/14/2000 6:53:58.979323846",
|
||||
t.strftime("%m/%d/%Y %l:%M:%S.%9N"))
|
||||
assert_equal("03/14/2000 6:53:58.97932384",
|
||||
t.strftime("%m/%d/%Y %l:%M:%S.%8N"))
|
||||
|
||||
t = Time.utc(1592,3,14, 6,53,"58.97932384626433832795028841971".to_r) # Pi Day
|
||||
assert_equal("03/14/1592 6:53:58.97932384626433832795028841971",
|
||||
t.strftime("%m/%d/%Y %l:%M:%S.%29N"))
|
||||
assert_equal("03/14/1592 6:53:58.9793238462",
|
||||
t.strftime("%m/%d/%Y %l:%M:%S.%10N"))
|
||||
assert_equal("03/14/1592 6:53:58.979323846",
|
||||
t.strftime("%m/%d/%Y %l:%M:%S.%9N"))
|
||||
assert_equal("03/14/1592 6:53:58.97932384",
|
||||
t.strftime("%m/%d/%Y %l:%M:%S.%8N"))
|
||||
end
|
||||
|
||||
def test_delegate
|
||||
|
|
407
time.c
407
time.c
|
@ -31,134 +31,6 @@ static ID id_eq, id_ne, id_quo, id_div, id_cmp, id_lshift;
|
|||
#define NMOD(x,y) ((y)-(-((x)+1)%(y))-1)
|
||||
#define DIV(n,d) ((n)<0 ? NDIV((n),(d)) : (n)/(d))
|
||||
|
||||
#if SIZEOF_LONG == 8
|
||||
# define INT64toNUM(x) LONG2NUM(x)
|
||||
# define UINT64toNUM(x) ULONG2NUM(x)
|
||||
#elif defined(HAVE_LONG_LONG) && SIZEOF_LONG_LONG == 8
|
||||
# define INT64toNUM(x) LL2NUM(x)
|
||||
# define UINT64toNUM(x) ULL2NUM(x)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_UINT64_T) && SIZEOF_LONG*2 <= SIZEOF_UINT64_T
|
||||
typedef uint64_t uwideint_t;
|
||||
typedef int64_t wideint_t;
|
||||
typedef uint64_t WIDEVALUE;
|
||||
typedef int64_t SIGNED_WIDEVALUE;
|
||||
# define WIDEVALUE_IS_WIDER 1
|
||||
# define FIXWINT_P(tv) ((tv) & 1)
|
||||
# define FIXWVtoINT64(tv) RSHIFT((SIGNED_WIDEVALUE)(tv), 1)
|
||||
# define INT64toFIXWV(wi) ((WIDEVALUE)((SIGNED_WIDEVALUE)(wi) << 1 | FIXNUM_FLAG))
|
||||
# define FIXWV_MAX (((int64_t)1 << 62) - 1)
|
||||
# define FIXWV_MIN (-((int64_t)1 << 62))
|
||||
# define POSFIXWVABLE(wi) ((wi) < FIXWV_MAX+1)
|
||||
# define NEGFIXWVABLE(wi) ((wi) >= FIXWV_MIN)
|
||||
# define FIXWVABLE(wi) (POSFIXWVABLE(wi) && NEGFIXWVABLE(wi))
|
||||
# define WINT2FIXWV(i) WIDEVAL_WRAP(INT64toFIXWV(i))
|
||||
# define FIXWV2WINT(w) FIXWVtoINT64(WIDEVAL_GET(w))
|
||||
#else
|
||||
typedef unsigned long uwideint_t;
|
||||
typedef long wideint_t;
|
||||
typedef VALUE WIDEVALUE;
|
||||
typedef SIGNED_VALUE SIGNED_WIDEVALUE;
|
||||
# define WIDEVALUE_IS_WIDER 0
|
||||
# define FIXWINT_P(v) FIXNUM_P(v)
|
||||
# define FIXWVABLE(i) FIXABLE(i)
|
||||
# define WINT2FIXWV(i) WIDEVAL_WRAP(LONG2FIX(i))
|
||||
# define FIXWV2WINT(w) FIX2LONG(WIDEVAL_GET(w))
|
||||
#endif
|
||||
|
||||
#define FIXWV_P(w) FIXWINT_P(WIDEVAL_GET(w))
|
||||
|
||||
#define STRUCT_WIDEVAL
|
||||
/* #define STRUCT_WIDEVAL */
|
||||
#ifdef STRUCT_WIDEVAL
|
||||
/* for type checking */
|
||||
typedef struct {
|
||||
WIDEVALUE value;
|
||||
} wideval_t;
|
||||
static inline wideval_t WIDEVAL_WRAP(WIDEVALUE v) { wideval_t w = { v }; return w; }
|
||||
# define WIDEVAL_GET(w) ((w).value)
|
||||
#else
|
||||
typedef WIDEVALUE wideval_t;
|
||||
# define WIDEVAL_WRAP(v) (v)
|
||||
# define WIDEVAL_GET(w) (w)
|
||||
#endif
|
||||
|
||||
#if WIDEVALUE_IS_WIDER
|
||||
static inline wideval_t
|
||||
wint2wv(wideint_t wi)
|
||||
{
|
||||
if (FIXWVABLE(wi))
|
||||
return WINT2FIXWV(wi);
|
||||
else
|
||||
return WIDEVAL_WRAP(INT64toNUM(wi));
|
||||
}
|
||||
# define WINT2WV(wi) wint2wv(wi)
|
||||
#else
|
||||
# define WINT2WV(wi) WIDEVAL_WRAP(LONG2NUM(wi))
|
||||
#endif
|
||||
|
||||
static inline VALUE
|
||||
w2v(wideval_t w)
|
||||
{
|
||||
#if WIDEVALUE_IS_WIDER
|
||||
if (FIXWV_P(w))
|
||||
return INT64toNUM(FIXWV2WINT(w));
|
||||
return (VALUE)WIDEVAL_GET(w);
|
||||
#else
|
||||
return WIDEVAL_GET(w);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if WIDEVALUE_IS_WIDER
|
||||
# if SIZEOF_UINT64_T % SIZEOF_BDIGITS != 0
|
||||
# error SIZEOF_UINT64 is not multiple of SIZEOF_BDIGITS
|
||||
# endif
|
||||
static wideval_t
|
||||
xv2w_bignum(VALUE xv)
|
||||
{
|
||||
long len = RBIGNUM_LEN(xv);
|
||||
BDIGIT *ds;
|
||||
wideval_t w;
|
||||
ds = RBIGNUM_DIGITS(xv);
|
||||
w = WIDEVAL_WRAP(xv);
|
||||
if (RBIGNUM_POSITIVE_P(xv)) {
|
||||
if (ds[len-1] < ((BDIGIT)1 << (sizeof(BDIGIT)*CHAR_BIT-2))) {
|
||||
wideint_t i = 0;
|
||||
while (len)
|
||||
i = (i << sizeof(BDIGIT)*CHAR_BIT) | ds[--len];
|
||||
if (FIXWVABLE(i))
|
||||
w = WINT2FIXWV(i);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ds[len-1] < ((BDIGIT)1 << (sizeof(BDIGIT)*CHAR_BIT-2))) {
|
||||
wideint_t i = 0;
|
||||
while (len)
|
||||
i = (i << sizeof(BDIGIT)*CHAR_BIT) | ds[--len];
|
||||
i = -i;
|
||||
w = WINT2FIXWV(i);
|
||||
}
|
||||
}
|
||||
return w;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline wideval_t
|
||||
v2w(VALUE xv)
|
||||
{
|
||||
#if WIDEVALUE_IS_WIDER
|
||||
if (FIXNUM_P(xv)) {
|
||||
return WIDEVAL_WRAP((WIDEVALUE)(SIGNED_WIDEVALUE)(long)xv);
|
||||
}
|
||||
else if (TYPE(xv) == T_BIGNUM &&
|
||||
RBIGNUM_LEN(xv) * sizeof(BDIGIT) <= sizeof(WIDEVALUE)) {
|
||||
return xv2w_bignum(xv);
|
||||
}
|
||||
#endif
|
||||
return WIDEVAL_WRAP(xv);
|
||||
}
|
||||
|
||||
static int
|
||||
eq(VALUE x, VALUE y)
|
||||
{
|
||||
|
@ -285,6 +157,192 @@ divmodv(VALUE n, VALUE d, VALUE *q, VALUE *r)
|
|||
*r = rb_ary_entry(ary, 1);
|
||||
}
|
||||
|
||||
#if SIZEOF_LONG == 8
|
||||
# define INT64toNUM(x) LONG2NUM(x)
|
||||
# define UINT64toNUM(x) ULONG2NUM(x)
|
||||
#elif defined(HAVE_LONG_LONG) && SIZEOF_LONG_LONG == 8
|
||||
# define INT64toNUM(x) LL2NUM(x)
|
||||
# define UINT64toNUM(x) ULL2NUM(x)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_UINT64_T) && SIZEOF_LONG*2 <= SIZEOF_UINT64_T
|
||||
typedef uint64_t uwideint_t;
|
||||
typedef int64_t wideint_t;
|
||||
typedef uint64_t WIDEVALUE;
|
||||
typedef int64_t SIGNED_WIDEVALUE;
|
||||
# define WIDEVALUE_IS_WIDER 1
|
||||
# define FIXWINT_P(tv) ((tv) & 1)
|
||||
# define FIXWVtoINT64(tv) RSHIFT((SIGNED_WIDEVALUE)(tv), 1)
|
||||
# define INT64toFIXWV(wi) ((WIDEVALUE)((SIGNED_WIDEVALUE)(wi) << 1 | FIXNUM_FLAG))
|
||||
# define FIXWV_MAX (((int64_t)1 << 62) - 1)
|
||||
# define FIXWV_MIN (-((int64_t)1 << 62))
|
||||
# define POSFIXWVABLE(wi) ((wi) < FIXWV_MAX+1)
|
||||
# define NEGFIXWVABLE(wi) ((wi) >= FIXWV_MIN)
|
||||
# define FIXWVABLE(wi) (POSFIXWVABLE(wi) && NEGFIXWVABLE(wi))
|
||||
# define WINT2FIXWV(i) WIDEVAL_WRAP(INT64toFIXWV(i))
|
||||
# define FIXWV2WINT(w) FIXWVtoINT64(WIDEVAL_GET(w))
|
||||
#else
|
||||
typedef unsigned long uwideint_t;
|
||||
typedef long wideint_t;
|
||||
typedef VALUE WIDEVALUE;
|
||||
typedef SIGNED_VALUE SIGNED_WIDEVALUE;
|
||||
# define WIDEVALUE_IS_WIDER 0
|
||||
# define FIXWINT_P(v) FIXNUM_P(v)
|
||||
# define FIXWVABLE(i) FIXABLE(i)
|
||||
# define WINT2FIXWV(i) WIDEVAL_WRAP(LONG2FIX(i))
|
||||
# define FIXWV2WINT(w) FIX2LONG(WIDEVAL_GET(w))
|
||||
#endif
|
||||
|
||||
#define FIXWV_P(w) FIXWINT_P(WIDEVAL_GET(w))
|
||||
|
||||
/* #define STRUCT_WIDEVAL */
|
||||
#ifdef STRUCT_WIDEVAL
|
||||
/* for type checking */
|
||||
typedef struct {
|
||||
WIDEVALUE value;
|
||||
} wideval_t;
|
||||
static inline wideval_t WIDEVAL_WRAP(WIDEVALUE v) { wideval_t w = { v }; return w; }
|
||||
# define WIDEVAL_GET(w) ((w).value)
|
||||
#else
|
||||
typedef WIDEVALUE wideval_t;
|
||||
# define WIDEVAL_WRAP(v) (v)
|
||||
# define WIDEVAL_GET(w) (w)
|
||||
#endif
|
||||
|
||||
#if WIDEVALUE_IS_WIDER
|
||||
static inline wideval_t
|
||||
wint2wv(wideint_t wi)
|
||||
{
|
||||
if (FIXWVABLE(wi))
|
||||
return WINT2FIXWV(wi);
|
||||
else
|
||||
return WIDEVAL_WRAP(INT64toNUM(wi));
|
||||
}
|
||||
# define WINT2WV(wi) wint2wv(wi)
|
||||
#else
|
||||
# define WINT2WV(wi) WIDEVAL_WRAP(LONG2NUM(wi))
|
||||
#endif
|
||||
|
||||
static inline VALUE
|
||||
w2v(wideval_t w)
|
||||
{
|
||||
#if WIDEVALUE_IS_WIDER
|
||||
if (FIXWV_P(w))
|
||||
return INT64toNUM(FIXWV2WINT(w));
|
||||
return (VALUE)WIDEVAL_GET(w);
|
||||
#else
|
||||
return WIDEVAL_GET(w);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if WIDEVALUE_IS_WIDER
|
||||
static int
|
||||
bdigit_find_maxbit(BDIGIT d)
|
||||
{
|
||||
int res = 0;
|
||||
if (d & ~(BDIGIT)0xffff) {
|
||||
d >>= 16;
|
||||
res += 16;
|
||||
}
|
||||
if (d & ~(BDIGIT)0xff) {
|
||||
d >>= 8;
|
||||
res += 8;
|
||||
}
|
||||
if (d & ~(BDIGIT)0xf) {
|
||||
d >>= 4;
|
||||
res += 4;
|
||||
}
|
||||
if (d & ~(BDIGIT)0x3) {
|
||||
d >>= 2;
|
||||
res += 2;
|
||||
}
|
||||
if (d & ~(BDIGIT)0x1) {
|
||||
d >>= 1;
|
||||
res += 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
rb_big_abs_find_maxbit(VALUE big)
|
||||
{
|
||||
BDIGIT *ds = RBIGNUM_DIGITS(big);
|
||||
BDIGIT d;
|
||||
long len = RBIGNUM_LEN(big);
|
||||
VALUE res;
|
||||
while (0 < len && ds[len-1] == 0)
|
||||
len--;
|
||||
if (len == 0)
|
||||
return Qnil;
|
||||
res = mul(LONG2NUM(len-1), INT2FIX(SIZEOF_BDIGITS * CHAR_BIT));
|
||||
d = ds[len-1];
|
||||
res = add(res, LONG2FIX(bdigit_find_maxbit(d)));
|
||||
return res;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
rb_big_abs_find_minbit(VALUE big)
|
||||
{
|
||||
BDIGIT *ds = RBIGNUM_DIGITS(big);
|
||||
BDIGIT d;
|
||||
long len = RBIGNUM_LEN(big);
|
||||
long i;
|
||||
VALUE res;
|
||||
for (i = 0; i < len; i++)
|
||||
if (ds[i])
|
||||
break;
|
||||
if (i == len)
|
||||
return Qnil;
|
||||
res = mul(LONG2NUM(i), INT2FIX(SIZEOF_BDIGITS * CHAR_BIT));
|
||||
d = ds[i];
|
||||
res = add(res, LONG2FIX(bdigit_find_maxbit(d)));
|
||||
return res;
|
||||
}
|
||||
|
||||
static wideval_t
|
||||
v2w_bignum(VALUE v)
|
||||
{
|
||||
long len = RBIGNUM_LEN(v);
|
||||
BDIGIT *ds;
|
||||
wideval_t w;
|
||||
VALUE maxbit;
|
||||
ds = RBIGNUM_DIGITS(v);
|
||||
w = WIDEVAL_WRAP(v);
|
||||
maxbit = rb_big_abs_find_maxbit(v);
|
||||
if (NIL_P(maxbit))
|
||||
return WINT2FIXWV(0);
|
||||
if (lt(maxbit, INT2FIX(sizeof(wideint_t) * CHAR_BIT - 2)) ||
|
||||
(eq(maxbit, INT2FIX(sizeof(wideint_t) * CHAR_BIT - 2)) &&
|
||||
RBIGNUM_NEGATIVE_P(v) &&
|
||||
eq(rb_big_abs_find_minbit(v), INT2FIX(sizeof(wideint_t) * CHAR_BIT - 2)))) {
|
||||
wideint_t i;
|
||||
i = 0;
|
||||
while (len)
|
||||
i = (i << sizeof(BDIGIT)*CHAR_BIT) | ds[--len];
|
||||
if (RBIGNUM_NEGATIVE_P(v)) {
|
||||
i = -i;
|
||||
}
|
||||
w = WINT2FIXWV(i);
|
||||
}
|
||||
return w;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline wideval_t
|
||||
v2w(VALUE v)
|
||||
{
|
||||
#if WIDEVALUE_IS_WIDER
|
||||
if (FIXNUM_P(v)) {
|
||||
return WIDEVAL_WRAP((WIDEVALUE)(SIGNED_WIDEVALUE)(long)v);
|
||||
}
|
||||
else if (TYPE(v) == T_BIGNUM &&
|
||||
RBIGNUM_LEN(v) * sizeof(BDIGIT) <= sizeof(WIDEVALUE)) {
|
||||
return v2w_bignum(v);
|
||||
}
|
||||
#endif
|
||||
return WIDEVAL_WRAP(v);
|
||||
}
|
||||
|
||||
static inline int
|
||||
weq(wideval_t wx, wideval_t wy)
|
||||
{
|
||||
|
@ -351,7 +409,7 @@ wsub(wideval_t wx, wideval_t wy)
|
|||
static wideval_t
|
||||
wmul(wideval_t wx, wideval_t wy)
|
||||
{
|
||||
VALUE x;
|
||||
VALUE x, z;
|
||||
#if WIDEVALUE_IS_WIDER
|
||||
if (FIXWV_P(wx) && FIXWV_P(wy)) {
|
||||
wideint_t a, b, c;
|
||||
|
@ -366,7 +424,11 @@ wmul(wideval_t wx, wideval_t wy)
|
|||
#endif
|
||||
x = w2v(wx);
|
||||
if (TYPE(x) == T_BIGNUM) return v2w(rb_big_mul(x, w2v(wy)));
|
||||
return v2w(rb_funcall(x, '*', 1, w2v(wy)));
|
||||
z = rb_funcall(x, '*', 1, w2v(wy));
|
||||
if (TYPE(z) == T_RATIONAL && RRATIONAL(z)->den == INT2FIX(1)) {
|
||||
z = RRATIONAL(z)->num;
|
||||
}
|
||||
return v2w(z);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -488,6 +550,33 @@ wdivmod(wideval_t wn, wideval_t wd, wideval_t *wq, wideval_t *wr)
|
|||
*wr = v2w(rb_ary_entry(ary, 1));
|
||||
}
|
||||
|
||||
static void
|
||||
wmuldivmod(wideval_t wx, wideval_t wy, wideval_t wz, wideval_t *wq, wideval_t *wr)
|
||||
{
|
||||
if (WIDEVAL_GET(wy) == WIDEVAL_GET(wz)) {
|
||||
*wq = wx;
|
||||
*wr = WINT2FIXWV(0);
|
||||
return;
|
||||
}
|
||||
wdivmod(wmul(wx,wy), wz, wq, wr);
|
||||
}
|
||||
|
||||
static wideval_t
|
||||
wdiv(wideval_t wx, wideval_t wy)
|
||||
{
|
||||
wideval_t q, r;
|
||||
wdivmod(wx, wy, &q, &r);
|
||||
return q;
|
||||
}
|
||||
|
||||
static wideval_t
|
||||
wmod(wideval_t wx, wideval_t wy)
|
||||
{
|
||||
wideval_t q, r;
|
||||
wdivmod(wx, wy, &q, &r);
|
||||
return r;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
num_exact(VALUE v)
|
||||
{
|
||||
|
@ -1086,7 +1175,7 @@ init_leap_second_info()
|
|||
|
||||
timew = timegmw_noleapsecond(&vtm);
|
||||
|
||||
number_of_leap_seconds_known = NUM2INT(sub(TIMET2NUM(known_leap_seconds_limit), w2v(rb_time_unmagnify(timew))));
|
||||
number_of_leap_seconds_known = NUM2INT(w2v(wsub(TIMET2WV(known_leap_seconds_limit), rb_time_unmagnify(timew))));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1633,13 +1722,31 @@ timew2timespec(wideval_t timew)
|
|||
wideval_t timew2;
|
||||
|
||||
if (timew_out_of_timet_range(timew))
|
||||
rb_raise(rb_eArgError, "time out of system range");
|
||||
rb_raise(rb_eArgError, "time out of system range");
|
||||
split_second(timew, &timew2, &subsecx);
|
||||
ts.tv_sec = WV2TIMET(timew2);
|
||||
ts.tv_nsec = NUM2LONG(mulquo(subsecx, INT2FIX(1000000000), INT2FIX(TIME_SCALE)));
|
||||
return ts;
|
||||
}
|
||||
|
||||
static struct timespec *
|
||||
timew2timespec_exact(wideval_t timew, struct timespec *ts)
|
||||
{
|
||||
VALUE subsecx;
|
||||
wideval_t timew2;
|
||||
VALUE nsecv;
|
||||
|
||||
if (timew_out_of_timet_range(timew))
|
||||
return NULL;
|
||||
split_second(timew, &timew2, &subsecx);
|
||||
ts->tv_sec = WV2TIMET(timew2);
|
||||
nsecv = mulquo(subsecx, INT2FIX(1000000000), INT2FIX(TIME_SCALE));
|
||||
if (!FIXNUM_P(nsecv))
|
||||
return NULL;
|
||||
ts->tv_nsec = NUM2LONG(nsecv);
|
||||
return ts;
|
||||
}
|
||||
|
||||
/*
|
||||
* Document-method: now
|
||||
*
|
||||
|
@ -2862,7 +2969,7 @@ time_to_i(VALUE time)
|
|||
struct time_object *tobj;
|
||||
|
||||
GetTimeval(time, tobj);
|
||||
return div(w2v(tobj->timew), INT2FIX(TIME_SCALE));
|
||||
return w2v(wdiv(tobj->timew, WINT2FIXWV(TIME_SCALE)));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2934,9 +3041,13 @@ static VALUE
|
|||
time_usec(VALUE time)
|
||||
{
|
||||
struct time_object *tobj;
|
||||
wideval_t w, q, r;
|
||||
|
||||
GetTimeval(time, tobj);
|
||||
return rb_to_int(mulquo(mod(w2v(tobj->timew), INT2FIX(TIME_SCALE)), INT2FIX(1000000), INT2FIX(TIME_SCALE)));
|
||||
|
||||
w = wmod(tobj->timew, WINT2WV(TIME_SCALE));
|
||||
wmuldivmod(w, WINT2FIXWV(1000000), WINT2FIXWV(TIME_SCALE), &q, &r);
|
||||
return rb_to_int(w2v(q));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2962,7 +3073,7 @@ time_nsec(VALUE time)
|
|||
struct time_object *tobj;
|
||||
|
||||
GetTimeval(time, tobj);
|
||||
return rb_to_int(mulquo(mod(w2v(tobj->timew), INT2FIX(TIME_SCALE)), INT2FIX(1000000000), INT2FIX(TIME_SCALE)));
|
||||
return rb_to_int(w2v(wmulquoll(wmod(tobj->timew, WINT2WV(TIME_SCALE)), 1000000000, TIME_SCALE)));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3983,12 +4094,20 @@ rb_strftime(char *s, size_t maxsize, const char *format,
|
|||
const struct vtm *vtm, VALUE timev,
|
||||
int gmt);
|
||||
|
||||
size_t
|
||||
rb_strftime_timespec(char *s, size_t maxsize, const char *format, const struct vtm *vtm, struct timespec *ts, int gmt);
|
||||
|
||||
#define SMALLBUF 100
|
||||
static size_t
|
||||
rb_strftime_alloc(char **buf, const char *format,
|
||||
struct vtm *vtm, VALUE timev, int gmt)
|
||||
struct vtm *vtm, wideval_t timew, int gmt)
|
||||
{
|
||||
size_t size, len, flen;
|
||||
VALUE timev = Qnil;
|
||||
struct timespec ts;
|
||||
|
||||
if (!timew2timespec_exact(timew, &ts))
|
||||
timev = w2v(rb_time_unmagnify(timew));
|
||||
|
||||
(*buf)[0] = '\0';
|
||||
flen = strlen(format);
|
||||
|
@ -3996,12 +4115,18 @@ rb_strftime_alloc(char **buf, const char *format,
|
|||
return 0;
|
||||
}
|
||||
errno = 0;
|
||||
len = rb_strftime(*buf, SMALLBUF, format, vtm, timev, gmt);
|
||||
if (timev == Qnil)
|
||||
len = rb_strftime_timespec(*buf, SMALLBUF, format, vtm, &ts, gmt);
|
||||
else
|
||||
len = rb_strftime(*buf, SMALLBUF, format, vtm, timev, gmt);
|
||||
if (len != 0 || (**buf == '\0' && errno != ERANGE)) return len;
|
||||
for (size=1024; ; size*=2) {
|
||||
*buf = xmalloc(size);
|
||||
(*buf)[0] = '\0';
|
||||
len = rb_strftime(*buf, size, format, vtm, timev, gmt);
|
||||
if (timev == Qnil)
|
||||
len = rb_strftime_timespec(*buf, size, format, vtm, &ts, gmt);
|
||||
else
|
||||
len = rb_strftime(*buf, size, format, vtm, timev, gmt);
|
||||
/*
|
||||
* buflen can be zero EITHER because there's not enough
|
||||
* room in the string, or because the control command
|
||||
|
@ -4025,7 +4150,7 @@ strftimev(const char *fmt, VALUE time)
|
|||
|
||||
GetTimeval(time, tobj);
|
||||
MAKE_TM(time, tobj);
|
||||
len = rb_strftime_alloc(&buf, fmt, &tobj->vtm, w2v(rb_time_unmagnify(tobj->timew)), TIME_UTC_P(tobj));
|
||||
len = rb_strftime_alloc(&buf, fmt, &tobj->vtm, tobj->timew, TIME_UTC_P(tobj));
|
||||
str = rb_str_new(buf, len);
|
||||
if (buf != buffer) xfree(buf);
|
||||
return str;
|
||||
|
@ -4123,7 +4248,7 @@ time_strftime(VALUE time, VALUE format)
|
|||
|
||||
str = rb_str_new(0, 0);
|
||||
while (p < pe) {
|
||||
len = rb_strftime_alloc(&buf, p, &tobj->vtm, w2v(rb_time_unmagnify(tobj->timew)), TIME_UTC_P(tobj));
|
||||
len = rb_strftime_alloc(&buf, p, &tobj->vtm, tobj->timew, TIME_UTC_P(tobj));
|
||||
rb_str_cat(str, buf, len);
|
||||
p += strlen(p);
|
||||
if (buf != buffer) {
|
||||
|
@ -4137,7 +4262,7 @@ time_strftime(VALUE time, VALUE format)
|
|||
}
|
||||
else {
|
||||
len = rb_strftime_alloc(&buf, RSTRING_PTR(format),
|
||||
&tobj->vtm, w2v(rb_time_unmagnify(tobj->timew)), TIME_UTC_P(tobj));
|
||||
&tobj->vtm, tobj->timew, TIME_UTC_P(tobj));
|
||||
}
|
||||
str = rb_str_new(buf, len);
|
||||
if (buf != buffer) xfree(buf);
|
||||
|
|
Loading…
Reference in a new issue