* 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
@ -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>
|
Wed Mar 31 16:05:13 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* test/rake/test_{package_task,rules,task_manager}.rb: use
|
* 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 */
|
/* strftime --- produce formatted time */
|
||||||
|
|
||||||
size_t
|
static size_t
|
||||||
rb_strftime(char *s, size_t maxsize, const char *format, const struct vtm *vtm, VALUE timev, int gmt)
|
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 *endp = s + maxsize;
|
||||||
char *start = s;
|
char *start = s;
|
||||||
@ -306,7 +306,7 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct vtm *vtm,
|
|||||||
} while (0)
|
} while (0)
|
||||||
#define STRFTIME(fmt) \
|
#define STRFTIME(fmt) \
|
||||||
do { \
|
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 (!i) return 0; \
|
||||||
if (precision > i) {\
|
if (precision > i) {\
|
||||||
memmove(s + precision - i, s, 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;
|
break;
|
||||||
|
|
||||||
case 's':
|
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));
|
VALUE sec = div(timev, INT2FIX(1));
|
||||||
FMTV('0', 1, "d", sec);
|
FMTV('0', 1, "d", sec);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
|
|
||||||
case 'S': /* second, 00 - 60 */
|
case 'S': /* second, 00 - 60 */
|
||||||
i = range(0, vtm->sec, 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;
|
w = 9;
|
||||||
subsec:
|
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));
|
VALUE subsec = mod(timev, INT2FIX(1));
|
||||||
int ww;
|
int ww;
|
||||||
long n;
|
long n;
|
||||||
|
|
||||||
if (precision <= 0) {
|
|
||||||
precision = w;
|
|
||||||
}
|
|
||||||
NEEDS(precision);
|
|
||||||
|
|
||||||
ww = precision;
|
ww = precision;
|
||||||
while (9 <= ww) {
|
while (9 <= ww) {
|
||||||
subsec = mul(subsec, INT2FIX(1000000000));
|
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;
|
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? */
|
/* isleap --- is a year a leap year? */
|
||||||
|
|
||||||
#ifndef __STDC__
|
#ifndef __STDC__
|
||||||
|
@ -172,6 +172,15 @@ class TestTime < Test::Unit::TestCase
|
|||||||
|
|
||||||
t = Time.at(2**40 + "1/3".to_r, 9999999999999).utc
|
t = Time.at(2**40 + "1/3".to_r, 9999999999999).utc
|
||||||
assert_equal(36812, t.year)
|
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
|
end
|
||||||
|
|
||||||
def test_at2
|
def test_at2
|
||||||
@ -579,6 +588,26 @@ class TestTime < Test::Unit::TestCase
|
|||||||
assert_equal("JANUARY", T2000.strftime("%#B"))
|
assert_equal("JANUARY", T2000.strftime("%#B"))
|
||||||
assert_equal("JAN", T2000.strftime("%#h"))
|
assert_equal("JAN", T2000.strftime("%#h"))
|
||||||
assert_equal("FRIDAY", Time.local(2008,1,4).strftime("%#A"))
|
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
|
end
|
||||||
|
|
||||||
def test_delegate
|
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 NMOD(x,y) ((y)-(-((x)+1)%(y))-1)
|
||||||
#define DIV(n,d) ((n)<0 ? NDIV((n),(d)) : (n)/(d))
|
#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
|
static int
|
||||||
eq(VALUE x, VALUE y)
|
eq(VALUE x, VALUE y)
|
||||||
{
|
{
|
||||||
@ -285,6 +157,192 @@ divmodv(VALUE n, VALUE d, VALUE *q, VALUE *r)
|
|||||||
*r = rb_ary_entry(ary, 1);
|
*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
|
static inline int
|
||||||
weq(wideval_t wx, wideval_t wy)
|
weq(wideval_t wx, wideval_t wy)
|
||||||
{
|
{
|
||||||
@ -351,7 +409,7 @@ wsub(wideval_t wx, wideval_t wy)
|
|||||||
static wideval_t
|
static wideval_t
|
||||||
wmul(wideval_t wx, wideval_t wy)
|
wmul(wideval_t wx, wideval_t wy)
|
||||||
{
|
{
|
||||||
VALUE x;
|
VALUE x, z;
|
||||||
#if WIDEVALUE_IS_WIDER
|
#if WIDEVALUE_IS_WIDER
|
||||||
if (FIXWV_P(wx) && FIXWV_P(wy)) {
|
if (FIXWV_P(wx) && FIXWV_P(wy)) {
|
||||||
wideint_t a, b, c;
|
wideint_t a, b, c;
|
||||||
@ -366,7 +424,11 @@ wmul(wideval_t wx, wideval_t wy)
|
|||||||
#endif
|
#endif
|
||||||
x = w2v(wx);
|
x = w2v(wx);
|
||||||
if (TYPE(x) == T_BIGNUM) return v2w(rb_big_mul(x, w2v(wy)));
|
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
|
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));
|
*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
|
static VALUE
|
||||||
num_exact(VALUE v)
|
num_exact(VALUE v)
|
||||||
{
|
{
|
||||||
@ -1086,7 +1175,7 @@ init_leap_second_info()
|
|||||||
|
|
||||||
timew = timegmw_noleapsecond(&vtm);
|
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;
|
wideval_t timew2;
|
||||||
|
|
||||||
if (timew_out_of_timet_range(timew))
|
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);
|
split_second(timew, &timew2, &subsecx);
|
||||||
ts.tv_sec = WV2TIMET(timew2);
|
ts.tv_sec = WV2TIMET(timew2);
|
||||||
ts.tv_nsec = NUM2LONG(mulquo(subsecx, INT2FIX(1000000000), INT2FIX(TIME_SCALE)));
|
ts.tv_nsec = NUM2LONG(mulquo(subsecx, INT2FIX(1000000000), INT2FIX(TIME_SCALE)));
|
||||||
return ts;
|
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
|
* Document-method: now
|
||||||
*
|
*
|
||||||
@ -2862,7 +2969,7 @@ time_to_i(VALUE time)
|
|||||||
struct time_object *tobj;
|
struct time_object *tobj;
|
||||||
|
|
||||||
GetTimeval(time, 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)
|
time_usec(VALUE time)
|
||||||
{
|
{
|
||||||
struct time_object *tobj;
|
struct time_object *tobj;
|
||||||
|
wideval_t w, q, r;
|
||||||
|
|
||||||
GetTimeval(time, tobj);
|
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;
|
struct time_object *tobj;
|
||||||
|
|
||||||
GetTimeval(time, 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,
|
const struct vtm *vtm, VALUE timev,
|
||||||
int gmt);
|
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
|
#define SMALLBUF 100
|
||||||
static size_t
|
static size_t
|
||||||
rb_strftime_alloc(char **buf, const char *format,
|
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;
|
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';
|
(*buf)[0] = '\0';
|
||||||
flen = strlen(format);
|
flen = strlen(format);
|
||||||
@ -3996,12 +4115,18 @@ rb_strftime_alloc(char **buf, const char *format,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
errno = 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;
|
if (len != 0 || (**buf == '\0' && errno != ERANGE)) return len;
|
||||||
for (size=1024; ; size*=2) {
|
for (size=1024; ; size*=2) {
|
||||||
*buf = xmalloc(size);
|
*buf = xmalloc(size);
|
||||||
(*buf)[0] = '\0';
|
(*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
|
* buflen can be zero EITHER because there's not enough
|
||||||
* room in the string, or because the control command
|
* room in the string, or because the control command
|
||||||
@ -4025,7 +4150,7 @@ strftimev(const char *fmt, VALUE time)
|
|||||||
|
|
||||||
GetTimeval(time, tobj);
|
GetTimeval(time, tobj);
|
||||||
MAKE_TM(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);
|
str = rb_str_new(buf, len);
|
||||||
if (buf != buffer) xfree(buf);
|
if (buf != buffer) xfree(buf);
|
||||||
return str;
|
return str;
|
||||||
@ -4123,7 +4248,7 @@ time_strftime(VALUE time, VALUE format)
|
|||||||
|
|
||||||
str = rb_str_new(0, 0);
|
str = rb_str_new(0, 0);
|
||||||
while (p < pe) {
|
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);
|
rb_str_cat(str, buf, len);
|
||||||
p += strlen(p);
|
p += strlen(p);
|
||||||
if (buf != buffer) {
|
if (buf != buffer) {
|
||||||
@ -4137,7 +4262,7 @@ time_strftime(VALUE time, VALUE format)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
len = rb_strftime_alloc(&buf, RSTRING_PTR(format),
|
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);
|
str = rb_str_new(buf, len);
|
||||||
if (buf != buffer) xfree(buf);
|
if (buf != buffer) xfree(buf);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user