Project

General

Profile

Feature #2561 ยป ruby-1.8.7-rational.patch

kstephens (Kurt Stephens), 01/06/2010 10:58 AM

View differences:

lib/rational.rb
7 7
#
8 8
# Documentation by Kevin Jackson and Gavin Sinclair.
9 9
# 
10
# Performance improvements by Kurt Stephens.
11
#
10 12
# When you <tt>require 'rational'</tt>, all interactions between numbers
11 13
# potentially return a rational result.  For example:
12 14
#
......
104 106
      num = -num
105 107
      den = -den
106 108
    end
107
    if num.kind_of?(Integer) and den.kind_of?(Integer)
108
      @numerator = num
109
      @denominator = den
110
    else
111
      @numerator = num.to_i
112
      @denominator = den.to_i
113
    end
109
    @numerator = num.to_i
110
    @denominator = den.to_i
114 111
  end
115 112

  
116 113
  #
......
122 119
  #   r + 0.5                # -> 1.25
123 120
  #
124 121
  def + (a)
125
    if a.kind_of?(Rational)
126
      num = @numerator * a.denominator
127
      num_a = a.numerator * @denominator
128
      Rational(num + num_a, @denominator * a.denominator)
129
    elsif a.kind_of?(Integer)
130
      self + Rational.new!(a, 1)
131
    elsif a.kind_of?(Float)
122
    case a
123
    when Rational
124
      Rational((@numerator * a.denominator) + (a.numerator * @denominator), @denominator * a.denominator)
125
    when Integer
126
      Rational((@numerator                ) + (a           * @denominator), @denominator)
127
    when Float
132 128
      Float(self) + a
133 129
    else
134 130
      x, y = a.coerce(self)
......
146 142
  #   r - 0.5              # -> 0.25
147 143
  #
148 144
  def - (a)
149
    if a.kind_of?(Rational)
150
      num = @numerator * a.denominator
151
      num_a = a.numerator * @denominator
152
      Rational(num - num_a, @denominator*a.denominator)
153
    elsif a.kind_of?(Integer)
154
      self - Rational.new!(a, 1)
155
    elsif a.kind_of?(Float)
145
    case a
146
    when Rational
147
      Rational((@numerator * a.denominator) - (a.numerator * @denominator), @denominator * a.denominator)
148
    when Integer
149
      Rational((@numerator                ) - (a           * @denominator), @denominator)
150
    when Float
156 151
      Float(self) - a
157 152
    else
158 153
      x, y = a.coerce(self)
......
161 156
  end
162 157

  
163 158
  #
159
  # Unary Minus--Returns the receiver's value, negated.
160
  #
161
  def -@
162
    Rational.new!(- @numerator, @denominator)
163
  end
164

  
165
  #
164 166
  # Returns the product of this value and +a+.
165 167
  #
166 168
  # Examples:
......
171 173
  #   r * Rational(1,2)    # -> Rational(3,8)
172 174
  #
173 175
  def * (a)
174
    if a.kind_of?(Rational)
175
      num = @numerator * a.numerator
176
      den = @denominator * a.denominator
177
      Rational(num, den)
178
    elsif a.kind_of?(Integer)
179
      self * Rational.new!(a, 1)
180
    elsif a.kind_of?(Float)
176
    case a
177
    when Rational
178
      Rational(@numerator * a.numerator, @denominator * a.denominator)
179
    when Integer
180
      Rational(@numerator * a          , @denominator)
181
    when Float
181 182
      Float(self) * a
182 183
    else
183 184
      x, y = a.coerce(self)
......
193 194
  #   r / Rational(1,2)    # -> Rational(3,2)
194 195
  #
195 196
  def / (a)
196
    if a.kind_of?(Rational)
197
      num = @numerator * a.denominator
198
      den = @denominator * a.numerator
199
      Rational(num, den)
200
    elsif a.kind_of?(Integer)
197
    case a
198
    when Rational
199
      Rational(@numerator * a.denominator, @denominator * a.numerator)
200
    when Integer
201 201
      raise ZeroDivisionError, "division by zero" if a == 0
202
      self / Rational.new!(a, 1)
203
    elsif a.kind_of?(Float)
202
      Rational(@numerator                , @denominator * a          )
203
    when Float
204 204
      Float(self) / a
205 205
    else
206 206
      x, y = a.coerce(self)
......
218 218
  #   r ** Rational(1,2)   # -> 0.866025403784439
219 219
  #
220 220
  def ** (other)
221
    if other.kind_of?(Rational)
221
    case other
222
    when Rational, Float
222 223
      Float(self) ** other
223
    elsif other.kind_of?(Integer)
224
    when Integer
224 225
      if other > 0
225
	num = @numerator ** other
226
	den = @denominator ** other
226
	Rational.new!(@numerator ** other, @denominator ** other)
227 227
      elsif other < 0
228
	num = @denominator ** -other
229
	den = @numerator ** -other
230
      elsif other == 0
231
	num = 1
232
	den = 1
228
	Rational.new!(@denominator ** -other, @numerator ** -other)
229
      else
230
	Rational.new!(1, 1) # why not Fixnum 1?
233 231
      end
234
      Rational.new!(num, den)
235
    elsif other.kind_of?(Float)
236
      Float(self) ** other
237 232
    else
238 233
      x, y = other.coerce(self)
239 234
      x ** y
......
256 251
  #
257 252
  def % (other)
258 253
    value = (self / other).floor
259
    return self - other * value
254
    self - other * value
260 255
  end
261 256

  
262 257
  #
......
268 263
  #
269 264
  def divmod(other)
270 265
    value = (self / other).floor
271
    return value, self - other * value
266
    [ value, self - other * value ]
272 267
  end
273 268

  
274 269
  #
......
282 277
    end
283 278
  end
284 279

  
280
  # Returns true or false.
281
  def zero?
282
    @numerator.zero?
283
  end
284

  
285
  # See Numeric#nonzero?
286
  def nonzero?
287
    @numerator.nonzero? ? self : nil
288
  end
289

  
290

  
285 291
  #
286 292
  # Returns +true+ iff this value is numerically equal to +other+.
287 293
  #
......
292 298
  # Don't use Rational.new!
293 299
  #
294 300
  def == (other)
295
    if other.kind_of?(Rational)
301
    case other
302
    when Rational
296 303
      @numerator == other.numerator and @denominator == other.denominator
297
    elsif other.kind_of?(Integer)
298
      self == Rational.new!(other, 1)
299
    elsif other.kind_of?(Float)
304
    when Integer
305
      @numerator == other && @denominator == 1
306
    when Float
300 307
      Float(self) == other
301 308
    else
302 309
      other == self
......
307 314
  # Standard comparison operator.
308 315
  #
309 316
  def <=> (other)
310
    if other.kind_of?(Rational)
311
      num = @numerator * other.denominator
312
      num_a = other.numerator * @denominator
313
      v = num - num_a
314
      if v > 0
315
	return 1
316
      elsif v < 0
317
	return  -1
318
      else
319
	return 0
320
      end
321
    elsif other.kind_of?(Integer)
322
      return self <=> Rational.new!(other, 1)
323
    elsif other.kind_of?(Float)
324
      return Float(self) <=> other
325
    elsif defined? other.coerce
326
      x, y = other.coerce(self)
327
      return x <=> y
317
    case other
318
    when Rational
319
      ((@numerator * other.denominator) <=> (other.numerator * @denominator))
320
    when Integer
321
      ((@numerator                    ) <=> (other           * @denominator))
322
    when Float
323
      Float(self) <=> other
328 324
    else
329
      return nil
325
      if defined? other.coerce
326
        x, y = other.coerce(self)
327
        x <=> y
328
      end # nil
330 329
    end
331 330
  end
332 331

  
333 332
  def coerce(other)
334
    if other.kind_of?(Float)
335
      return other, self.to_f
336
    elsif other.kind_of?(Integer)
337
      return Rational.new!(other, 1), self
333
    case other
334
    when Float
335
      [ other, self.to_f ]
336
    when Integer
337
      [ Rational.new!(other, 1), self ]
338 338
    else
339 339
      super
340 340
    end
......
363 363

  
364 364
  def truncate()
365 365
    if @numerator < 0
366
      return -((-@numerator).div(@denominator))
366
      -((-@numerator).div(@denominator))
367
    else
368
      @numerator.div(@denominator)
367 369
    end
368
    @numerator.div(@denominator)
369 370
  end
370 371

  
371 372
  alias_method :to_i, :truncate
372 373

  
373 374
  def round()
374 375
    if @numerator < 0
375
      num = -@numerator
376
      num = num * 2 + @denominator
377
      den = @denominator * 2
378
      -(num.div(den))
376
      -((@numerator * -2 + @denominator).div(@denominator * 2))
379 377
    else
380
      num = @numerator * 2 + @denominator
381
      den = @denominator * 2
382
      num.div(den)
378
      ((@numerator * 2 + @denominator).div(@denominator * 2))
383 379
    end
384 380
  end
385 381

  
......
401 397
    if @denominator == 1
402 398
      @numerator.to_s
403 399
    else
404
      @numerator.to_s+"/"+@denominator.to_s
400
      "#{@numerator}/#{@denominator}"
405 401
    end
406 402
  end
407 403

  
......
418 414
  #   Rational(5,8).inspect     # -> "Rational(5, 8)"
419 415
  #
420 416
  def inspect
421
    sprintf("Rational(%s, %s)", @numerator.inspect, @denominator.inspect)
417
    "Rational(#{@numerator.inspect}, #{@denominator.inspect})"
422 418
  end
423 419

  
424 420
  #
numeric.c
3022 3022
    return Qtrue;
3023 3023
}
3024 3024

  
3025
static VALUE
3026
fix_gcd(int argc, VALUE *argv, VALUE self) {
3027
  if ( argc != 1 ) {
3028
    rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, 1);
3029
  }
3030
  /* Handle Fixnum#gcd(Fixnum) here. */
3031
  if ( FIXNUM_P(argv[0]) ) {
3032
    /* fprintf(stderr, "Using Fixnum#gcd(Fixnum)\n"); */
3033
    long a = FIX2LONG(self);
3034
    long b = FIX2LONG(argv[0]);
3035
    long min = a < 0 ? - a : a;
3036
    long max = b < 0 ? - b : b;
3037
    while ( min > 0 ) {
3038
      int tmp = min;
3039
      min = max % min;
3040
      max = tmp;
3041
    }
3042
    return LONG2FIX(max);
3043
  } else {
3044
    /* Delegate to Integer#gcd. */
3045
    return rb_call_super(1, argv);
3046
  }
3047
}
3048

  
3025 3049
void
3026 3050
Init_Numeric()
3027 3051
{
......
3115 3139
    rb_define_method(rb_cFixnum, "divmod", fix_divmod, 1);
3116 3140
    rb_define_method(rb_cFixnum, "quo", fix_quo, 1);
3117 3141
    rb_define_method(rb_cFixnum, "fdiv", fix_quo, 1);
3142
    rb_define_method(rb_cFixnum, "gcd", fix_gcd, -1);
3118 3143
    rb_define_method(rb_cFixnum, "**", fix_pow, 1);
3119 3144

  
3120 3145
    rb_define_method(rb_cFixnum, "abs", fix_abs, 0);