~ubuntu-branches/ubuntu/intrepid/ruby1.9/intrepid-updates

« back to all changes in this revision

Viewing changes to numeric.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2007-09-04 16:01:17 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20070904160117-i15zckg2nhxe9fyw
Tags: 1.9.0+20070830-2ubuntu1
* Sync from Debian; remaining changes:
  - Add -g to CFLAGS.
* Fixes build failure on ia64.
* Fixes build failure with gcc-4.2 on lpia.
* Robustify check for target_os, fixing build failure on lpia.
* Set Ubuntu maintainer address.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
  numeric.c -
4
4
 
5
5
  $Author: matz $
6
 
  $Date: 2007-06-05 14:31:05 +0900 (火, 05  6月 2007) $
 
6
  $Date: 2007-08-25 12:29:39 +0900 (土, 25  8月 2007) $
7
7
  created at: Fri Aug 13 18:33:09 JST 1993
8
8
 
9
 
  Copyright (C) 1993-2003 Yukihiro Matsumoto
 
9
  Copyright (C) 1993-2007 Yukihiro Matsumoto
10
10
 
11
11
**********************************************************************/
12
12
 
13
 
#include "ruby.h"
 
13
#include "ruby/ruby.h"
14
14
#include <ctype.h>
15
15
#include <math.h>
16
16
#include <stdio.h>
714
714
    }
715
715
    flodivmod(RFLOAT(x)->value, fy, &div, &mod);
716
716
    if (FIXABLE(div)) {
717
 
        val = div;
718
 
        a = LONG2FIX(val);
 
717
        val = div;
 
718
        a = LONG2FIX(val);
719
719
    }
720
720
    else {
721
 
        a = rb_dbl2big(div);
 
721
        a = rb_dbl2big(div);
722
722
    }
723
723
    b = rb_float_new(mod);
724
724
    return rb_assoc_new(a, b);
737
737
{
738
738
    switch (TYPE(y)) {
739
739
      case T_FIXNUM:
740
 
        return rb_float_new(pow(RFLOAT(x)->value, (double)FIX2LONG(y)));
 
740
        return rb_float_new(pow(RFLOAT(x)->value, (double)FIX2LONG(y)));
741
741
      case T_BIGNUM:
742
742
        return rb_float_new(pow(RFLOAT(x)->value, rb_big2dbl(y)));
743
743
      case T_FLOAT:
744
 
        return rb_float_new(pow(RFLOAT(x)->value, RFLOAT(y)->value));
 
744
        return rb_float_new(pow(RFLOAT(x)->value, RFLOAT(y)->value));
745
745
      default:
746
 
        return rb_num_coerce_bin(x, y);
 
746
        return rb_num_coerce_bin(x, y);
747
747
    }
748
748
}
749
749
 
1577
1577
    unsigned long num;
1578
1578
 
1579
1579
    if (!FIXNUM_P(val)) {
1580
 
        return rb_num2uint(val);
 
1580
        return rb_num2uint(val);
1581
1581
    }
1582
1582
    num = FIX2ULONG(val);
1583
1583
    if (FIX2LONG(val) > 0) {
1720
1720
int_odd_p(VALUE num)
1721
1721
{
1722
1722
    if (rb_funcall(num, '%', 1, INT2FIX(2)) != INT2FIX(0)) {
1723
 
      return Qtrue;
 
1723
        return Qtrue;
1724
1724
    }
1725
1725
    return Qfalse;
1726
1726
}
1736
1736
int_even_p(VALUE num)
1737
1737
{
1738
1738
    if (rb_funcall(num, '%', 1, INT2FIX(2)) == INT2FIX(0)) {
1739
 
      return Qtrue;
 
1739
        return Qtrue;
1740
1740
    }
1741
1741
    return Qfalse;
1742
1742
}
2046
2046
 * result.
2047
2047
 */
2048
2048
 
 
2049
#define SQRT_LONG_MAX ((SIGNED_VALUE)1<<((SIZEOF_VALUE*CHAR_BIT-1)/2))
 
2050
/*tests if N*N would overflow*/
 
2051
#define FIT_SQRT_LONG(n) (((n)<SQRT_LONG_MAX)&&((n)>=-SQRT_LONG_MAX))
 
2052
 
2049
2053
static VALUE
2050
2054
fix_mul(VALUE x, VALUE y)
2051
2055
{
2052
2056
    if (FIXNUM_P(y)) {
2053
2057
#ifdef __HP_cc
2054
2058
/* avoids an optimization bug of HP aC++/ANSI C B3910B A.06.05 [Jul 25 2005] */
2055
 
        volatile
 
2059
        volatile
2056
2060
#endif
2057
2061
        SIGNED_VALUE a, b;
2058
2062
#if SIZEOF_VALUE * 2 <= SIZEOF_LONG_LONG
2070
2074
        if (FIXABLE(d)) return LONG2FIX(d);
2071
2075
        return rb_ll2inum(d);
2072
2076
#else
2073
 
#       define SQRT_LONG_MAX ((SIGNED_VALUE)1<<((SIZEOF_VALUE*CHAR_BIT-1)/2))
2074
 
        /*tests if N*N would overflow*/
2075
 
#       define FIT_SQRT_LONG(n) (((n)<SQRT_LONG_MAX)&&((n)>=-SQRT_LONG_MAX))
2076
2077
        if (FIT_SQRT_LONG(a) && FIT_SQRT_LONG(b))
2077
2078
            return LONG2FIX(a*b);
2078
2079
        c = a * b;
2281
2282
    long z = 1;
2282
2283
 
2283
2284
    if (neg) x = -x;
2284
 
    if (y & 1) z = x;
 
2285
    if (y & 1)
 
2286
        z = x;
 
2287
    else
 
2288
        neg = 0;
2285
2289
    y &= ~1;
2286
2290
    do {
2287
2291
        while (y % 2 == 0) {
2288
 
            long x2 = x * x;
2289
 
            if (x2 < x || !POSFIXABLE(x2)) {
 
2292
            if (!FIT_SQRT_LONG(x)) {
2290
2293
                VALUE v;
2291
2294
              bignum:
2292
 
                v = rb_big_pow(rb_int2big(neg ? -x : x), LONG2NUM(y));
2293
 
                if (z != 1) v = rb_big_mul(rb_int2big(z), v);
 
2295
                v = rb_big_pow(rb_int2big(x), LONG2NUM(y));
 
2296
                if (z != 1) v = rb_big_mul(rb_int2big(neg ? -z : z), v);
2294
2297
                return v;
2295
2298
            }
2296
 
            x = x2;
 
2299
            x = x * x;
2297
2300
            y >>= 1;
2298
2301
        }
2299
2302
        {
2323
2326
static VALUE
2324
2327
fix_pow(VALUE x, VALUE y)
2325
2328
{
 
2329
    long a = FIX2LONG(x);
 
2330
 
2326
2331
    if (FIXNUM_P(y)) {
2327
 
        long a, b;
 
2332
        long b = FIX2LONG(y);
2328
2333
 
2329
 
        b = FIX2LONG(y);
2330
2334
        if (b == 0) return INT2FIX(1);
2331
2335
        if (b == 1) return x;
2332
 
        a = FIX2LONG(x);
 
2336
        if (a == 0) return INT2FIX(0);
 
2337
        if (a == 1) return INT2FIX(1);
 
2338
        if (a == -1) {
 
2339
            if (b % 2 == 0)
 
2340
                return INT2FIX(1);
 
2341
            else 
 
2342
                return INT2FIX(-1);
 
2343
        }
2333
2344
        if (b > 0) {
2334
2345
            return int_pow(a, b);
2335
2346
        }
2337
2348
    }
2338
2349
    switch (TYPE(y)) {
2339
2350
      case T_BIGNUM:
 
2351
        if (a == 0) return INT2FIX(0);
 
2352
        if (a == 1) return INT2FIX(1);
 
2353
        if (a == -1) {
 
2354
            if (int_even_p(y)) return INT2FIX(1);
 
2355
            else return INT2FIX(-1);
 
2356
        }
2340
2357
        x = rb_int2big(FIX2LONG(x));
2341
2358
        return rb_big_pow(x, y);
2342
2359
      case T_FLOAT:
2343
 
        return rb_float_new(pow((double)FIX2LONG(x), RFLOAT(y)->value));
 
2360
        if (a == 0) return rb_float_new(0.0);
 
2361
        if (a == 1) return rb_float_new(1.0);
 
2362
        return rb_float_new(pow((double)a, RFLOAT(y)->value));
2344
2363
      default:
2345
2364
        return rb_num_coerce_bin(x, y);
2346
2365
    }
2572
2591
    return LONG2NUM(val);
2573
2592
}
2574
2593
 
2575
 
static VALUE fix_rshift(VALUE, VALUE);
 
2594
static VALUE fix_lshift(long, unsigned long);
 
2595
static VALUE fix_rshift(long, unsigned long);
2576
2596
 
2577
2597
/*
2578
2598
 * call-seq:
2582
2602
 */
2583
2603
 
2584
2604
static VALUE
2585
 
fix_lshift(VALUE x, VALUE y)
 
2605
rb_fix_lshift(VALUE x, VALUE y)
2586
2606
{
2587
2607
    long val, width;
2588
2608
 
2589
2609
    val = NUM2LONG(x);
2590
 
    width = NUM2LONG(y);
 
2610
    if (!FIXNUM_P(y))
 
2611
        return rb_big_lshift(rb_int2big(val), y);
 
2612
    width = FIX2LONG(y);
2591
2613
    if (width < 0)
2592
 
        return fix_rshift(x, LONG2FIX(-width));
 
2614
        return fix_rshift(val, (unsigned long)-width);
 
2615
    return fix_lshift(val, width);
 
2616
}
 
2617
 
 
2618
static VALUE
 
2619
fix_lshift(long val, unsigned long width)
 
2620
{
2593
2621
    if (width > (sizeof(VALUE)*CHAR_BIT-1)
2594
2622
        || ((unsigned long)val)>>(sizeof(VALUE)*CHAR_BIT-1-width) > 0) {
2595
 
        return rb_big_lshift(rb_int2big(val), y);
 
2623
        return rb_big_lshift(rb_int2big(val), ULONG2NUM(width));
2596
2624
    }
2597
2625
    val = val << width;
2598
2626
    return LONG2NUM(val);
2606
2634
 */
2607
2635
 
2608
2636
static VALUE
2609
 
fix_rshift(VALUE x, VALUE y)
 
2637
rb_fix_rshift(VALUE x, VALUE y)
2610
2638
{
2611
2639
    long i, val;
2612
2640
 
2613
 
    i = NUM2LONG(y);
 
2641
    val = FIX2LONG(x);
 
2642
    if (!FIXNUM_P(y))
 
2643
        return rb_big_rshift(rb_int2big(val), y);
 
2644
    i = FIX2LONG(y);
 
2645
    if (i == 0) return x;
2614
2646
    if (i < 0)
2615
 
        return fix_lshift(x, LONG2FIX(-i));
2616
 
    if (i == 0) return x;
2617
 
    val = FIX2LONG(x);
 
2647
        return fix_lshift(val, (unsigned long)-i);
 
2648
    return fix_rshift(val, i);
 
2649
}
 
2650
 
 
2651
static VALUE
 
2652
fix_rshift(long val, unsigned long i)
 
2653
{
2618
2654
    if (i >= sizeof(long)*CHAR_BIT-1) {
2619
2655
        if (val < 0) return INT2FIX(-1);
2620
2656
        return INT2FIX(0);
2863
2899
 *     0 1 2 3 4
2864
2900
 */
2865
2901
 
2866
 
VALUE yarv_invoke_Integer_times_special_block(VALUE);
2867
 
 
2868
2902
static VALUE
2869
2903
int_dotimes(VALUE num)
2870
2904
{
2871
 
  VALUE val;
2872
 
 
2873
 
  RETURN_ENUMERATOR(num, 0, 0);
2874
 
  if((val = yarv_invoke_Integer_times_special_block(num)) != Qundef){
2875
 
    return val;
2876
 
  }
2877
 
 
2878
 
  if (FIXNUM_P(num)) {
2879
 
    long i, end;
2880
 
 
2881
 
    end = FIX2LONG(num);
2882
 
    for (i=0; i<end; i++) {
2883
 
      rb_yield(LONG2FIX(i));
2884
 
    }
2885
 
  }
2886
 
  else {
2887
 
    VALUE i = INT2FIX(0);
2888
 
 
2889
 
    for (;;) {
2890
 
      if (!RTEST(rb_funcall(i, '<', 1, num))) break;
2891
 
      rb_yield(i);
2892
 
      i = rb_funcall(i, '+', 1, INT2FIX(1));
2893
 
    }
2894
 
  }
2895
 
  return num;
 
2905
    RETURN_ENUMERATOR(num, 0, 0);
 
2906
 
 
2907
    if (FIXNUM_P(num)) {
 
2908
        long i, end;
 
2909
 
 
2910
        end = FIX2LONG(num);
 
2911
        for (i=0; i<end; i++) {
 
2912
            rb_yield(LONG2FIX(i));
 
2913
        }
 
2914
    }
 
2915
    else {
 
2916
        VALUE i = INT2FIX(0);
 
2917
 
 
2918
        for (;;) {
 
2919
            if (!RTEST(rb_funcall(i, '<', 1, num))) break;
 
2920
            rb_yield(i);
 
2921
            i = rb_funcall(i, '+', 1, INT2FIX(1));
 
2922
        }
 
2923
    }
 
2924
    return num;
2896
2925
}
2897
2926
 
2898
2927
static VALUE
2902
2931
    int ndigits;
2903
2932
 
2904
2933
    if (argc == 0) return num;
2905
 
    if (FIXNUM_P(num)) return num_round(argc, argv, num);
2906
 
 
2907
2934
    rb_scan_args(argc, argv, "1", &n);
2908
2935
    ndigits = NUM2INT(n);
2909
2936
    if (ndigits > 0) {
2910
2937
        return rb_Float(num);
2911
2938
    }
 
2939
    if (ndigits == 0) {
 
2940
        return num;
 
2941
    }
2912
2942
    ndigits = -ndigits;
 
2943
    if (ndigits < 0) {
 
2944
        rb_raise(rb_eArgError, "ndigits out of range");
 
2945
    }
2913
2946
    f = int_pow(10, ndigits);
 
2947
    if (FIXNUM_P(num) && FIXNUM_P(f)) {
 
2948
        SIGNED_VALUE x = FIX2LONG(num), y = FIX2LONG(f);
 
2949
        int neg = x < 0;
 
2950
        if (neg) x = -x;
 
2951
        x = (x + y / 2) / y * y;
 
2952
        if (neg) x = -x;
 
2953
        return LONG2NUM(x);
 
2954
    }
2914
2955
    h = rb_funcall(f, '/', 1, INT2FIX(2));
2915
2956
    r = rb_funcall(num, '%', 1, f);
2916
2957
    n = rb_funcall(num, '-', 1, r);
3079
3120
    rb_define_method(rb_cFixnum, "^", fix_xor, 1);
3080
3121
    rb_define_method(rb_cFixnum, "[]", fix_aref, 1);
3081
3122
 
3082
 
    rb_define_method(rb_cFixnum, "<<", fix_lshift, 1);
3083
 
    rb_define_method(rb_cFixnum, ">>", fix_rshift, 1);
 
3123
    rb_define_method(rb_cFixnum, "<<", rb_fix_lshift, 1);
 
3124
    rb_define_method(rb_cFixnum, ">>", rb_fix_rshift, 1);
3084
3125
 
3085
3126
    rb_define_method(rb_cFixnum, "to_f", fix_to_f, 0);
3086
3127
    rb_define_method(rb_cFixnum, "size", fix_size, 0);