Module: Math

Defined in:
lib/rubysl/mathn/mathn.rb

Overview

When mathn is required, the Math module changes as follows:

Standard Math module behaviour:

Math.sqrt(4/9)     # => 0.0
Math.sqrt(4.0/9.0) # => 0.666666666666667
Math.sqrt(- 4/9)   # => Errno::EDOM: Numerical argument out of domain - sqrt

After require ‘mathn’, this is changed to:

require 'mathn'
Math.sqrt(4/9)      # => 2/3
Math.sqrt(4.0/9.0)  # => 0.666666666666667
Math.sqrt(- 4/9)    # => Complex(0, 2/3)

Class Method Summary collapse

Class Method Details

.rsqrt(a) ⇒ Object

Compute square root of a non negative number. This method is internally used by Math.sqrt.



252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
# File 'lib/rubysl/mathn/mathn.rb', line 252

def rsqrt(a)
  if a.kind_of?(Float)
    sqrt!(a)
  elsif a.kind_of?(Rational)
    rsqrt(a.numerator)/rsqrt(a.denominator)
  else
    src = a
    max = 2 ** 32
    byte_a = [src & 0xffffffff]
    # ruby's bug
    while (src >= max) and (src >>= 32)
      byte_a.unshift src & 0xffffffff
    end

    answer = 0
    main = 0
    side = 0
    for elm in byte_a
      main = (main << 32) + elm
      side <<= 16
      if answer != 0
        if main * 4  < side * side
          applo = main.div(side)
        else
          applo = ((sqrt!(side * side + 4 * main) - side)/2.0).to_i + 1
        end
      else
        applo = sqrt!(main).to_i + 1
      end

      while (x = (side + applo) * applo) > main
        applo -= 1
      end
      main -= x
      answer = (answer << 16) + applo
      side += applo * 2
    end
    if main == 0
      answer
    else
      sqrt!(a)
    end
  end
end

.sqrt(a) ⇒ Object

Computes the square root of a. It makes use of Complex and Rational to have no rounding errors if possible.

Math.sqrt(4/9)      # => 2/3
Math.sqrt(- 4/9)    # => Complex(0, 2/3)
Math.sqrt(4.0/9.0)  # => 0.666666666666667


223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
# File 'lib/rubysl/mathn/mathn.rb', line 223

def sqrt(a)
  if a.kind_of?(Complex)
    abs = sqrt(a.real*a.real + a.imag*a.imag)
#      if not abs.kind_of?(Rational)
#        return a**Rational(1,2)
#      end
    x = sqrt((a.real + abs)/Rational(2))
    y = sqrt((-a.real + abs)/Rational(2))
#      if !(x.kind_of?(Rational) and y.kind_of?(Rational))
#        return a**Rational(1,2)
#      end
    if a.imag >= 0
      Complex(x, y)
    else
      Complex(x, -y)
    end
  elsif a.respond_to?(:nan?) and a.nan?
    a
  elsif a >= 0
    rsqrt(a)
  else
    Complex(0,rsqrt(-a))
  end
end