Class: Number

Inherits:
Numeric show all
Defined in:
opal/opal/corelib/number.rb

Instance Method Summary collapse

Methods inherited from Numeric

#__coerced__, #clone, #conj, #div, #dup, #i, #imag, #polar, #real, #real?, #rect, #to_c

Methods included from Comparable

#between?, normalize

Instance Method Details

#%(other) ⇒ Object Also known as: modulo



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'opal/opal/corelib/number.rb', line 80

def %(other)
  %x{
    if (other.$$is_number) {
      if (other == -Infinity) {
        return other;
      }
      else if (other == 0) {
        #{raise ZeroDivisionError, "divided by 0"};
      }
      else if (other < 0 || self < 0) {
        return (self % other + other) % other;
      }
      else {
        return self % other;
      }
    }
    else {
      return #{__coerced__ :%, other};
    }
  }
end

#&(other) ⇒ Object



102
103
104
105
106
107
108
109
110
111
# File 'opal/opal/corelib/number.rb', line 102

def &(other)
  %x{
    if (other.$$is_number) {
      return self & other;
    }
    else {
      return #{__coerced__ :&, other};
    }
  }
end

#*(other) ⇒ Object



56
57
58
59
60
61
62
63
64
65
# File 'opal/opal/corelib/number.rb', line 56

def *(other)
  %x{
    if (other.$$is_number) {
      return self * other;
    }
    else {
      return #{__coerced__ :*, other};
    }
  }
end

#**(other) ⇒ Object



237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
# File 'opal/opal/corelib/number.rb', line 237

def **(other)
  if Integer === other
    if !(Integer === self) || other > 0
      `Math.pow(self, other)`
    else
      Rational.new(self, 1) ** other
    end
  elsif self < 0 && (Float === other || Rational === other)
    Complex.new(self, 0) ** other.to_f
  elsif `other.$$is_number != null`
    `Math.pow(self, other)`
  else
    __coerced__ :**, other
  end
end

#+(other) ⇒ Object



34
35
36
37
38
39
40
41
42
43
# File 'opal/opal/corelib/number.rb', line 34

def +(other)
  %x{
    if (other.$$is_number) {
      return self + other;
    }
    else {
      return #{__coerced__ :+, other};
    }
  }
end

#+@Object



225
226
227
# File 'opal/opal/corelib/number.rb', line 225

def +@
  `+self`
end

#-(other) ⇒ Object



45
46
47
48
49
50
51
52
53
54
# File 'opal/opal/corelib/number.rb', line 45

def -(other)
  %x{
    if (other.$$is_number) {
      return self - other;
    }
    else {
      return #{__coerced__ :-, other};
    }
  }
end

#-@Object



229
230
231
# File 'opal/opal/corelib/number.rb', line 229

def -@
  `-self`
end

#/(other) ⇒ Object Also known as: fdiv



67
68
69
70
71
72
73
74
75
76
# File 'opal/opal/corelib/number.rb', line 67

def /(other)
  %x{
    if (other.$$is_number) {
      return self / other;
    }
    else {
      return #{__coerced__ :/, other};
    }
  }
end

#<(other) ⇒ Object



135
136
137
138
139
140
141
142
143
144
# File 'opal/opal/corelib/number.rb', line 135

def <(other)
  %x{
    if (other.$$is_number) {
      return self < other;
    }
    else {
      return #{__coerced__ :<, other};
    }
  }
end

#<<(count) ⇒ Object



196
197
198
199
200
# File 'opal/opal/corelib/number.rb', line 196

def <<(count)
  count = Opal.coerce_to! count, Integer, :to_int

  `#{count} > 0 ? self << #{count} : self >> -#{count}`
end

#<=(other) ⇒ Object



146
147
148
149
150
151
152
153
154
155
# File 'opal/opal/corelib/number.rb', line 146

def <=(other)
  %x{
    if (other.$$is_number) {
      return self <= other;
    }
    else {
      return #{__coerced__ :<=, other};
    }
  }
end

#<=>(other) ⇒ Object



179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'opal/opal/corelib/number.rb', line 179

def <=>(other)
  %x{
    if (other.$$is_number) {
      if (isNaN(self) || isNaN(other)) {
        return nil;
      }

      return self > other ? 1 : (self < other ? -1 : 0);
    }
    else {
      return #{__coerced__ :<=>, other};
    }
  }
rescue ArgumentError
  nil
end

#==(other) ⇒ Object Also known as: eql?



253
254
255
256
257
258
259
260
261
262
263
264
265
# File 'opal/opal/corelib/number.rb', line 253

def ==(other)
  %x{
    if (other.$$is_number) {
      return self == Number(other);
    }
    else if (#{other.respond_to? :==}) {
      return #{other == self};
    }
    else {
      return false;
    }
  }
end

#>(other) ⇒ Object



157
158
159
160
161
162
163
164
165
166
# File 'opal/opal/corelib/number.rb', line 157

def >(other)
  %x{
    if (other.$$is_number) {
      return self > other;
    }
    else {
      return #{__coerced__ :>, other};
    }
  }
end

#>=(other) ⇒ Object



168
169
170
171
172
173
174
175
176
177
# File 'opal/opal/corelib/number.rb', line 168

def >=(other)
  %x{
    if (other.$$is_number) {
      return self >= other;
    }
    else {
      return #{__coerced__ :>=, other};
    }
  }
end

#>>(count) ⇒ Object



202
203
204
205
206
# File 'opal/opal/corelib/number.rb', line 202

def >>(count)
  count = Opal.coerce_to! count, Integer, :to_int

  `#{count} > 0 ? self >> #{count} : self << -#{count}`
end

#[](bit) ⇒ Object



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'opal/opal/corelib/number.rb', line 208

def [](bit)
  bit = Opal.coerce_to! bit, Integer, :to_int

  %x{
    if (#{bit} < #{Integer::MIN} || #{bit} > #{Integer::MAX}) {
      return 0;
    }

    if (self < 0) {
      return (((~self) + 1) >> #{bit}) % 2;
    }
    else {
      return (self >> #{bit}) % 2;
    }
  }
end

#^(other) ⇒ Object



124
125
126
127
128
129
130
131
132
133
# File 'opal/opal/corelib/number.rb', line 124

def ^(other)
  %x{
    if (other.$$is_number) {
      return self ^ other;
    }
    else {
      return #{__coerced__ :^, other};
    }
  }
end

#__id__Object Also known as: object_id



28
29
30
# File 'opal/opal/corelib/number.rb', line 28

def __id__
  `(self * 2) + 1`
end

#absObject Also known as: magnitude



267
268
269
# File 'opal/opal/corelib/number.rb', line 267

def abs
  `Math.abs(self)`
end

#abs2Object



271
272
273
# File 'opal/opal/corelib/number.rb', line 271

def abs2
  `Math.abs(self * self)`
end

#angleObject Also known as: arg, phase



275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
# File 'opal/opal/corelib/number.rb', line 275

def angle
  return self if nan?

  %x{
    if (self == 0) {
      if (1 / self > 0) {
        return 0;
      }
      else {
        return Math.PI;
      }
    }
    else if (self < 0) {
      return Math.PI;
    }
    else {
      return 0;
    }
  }
end

#bit_lengthObject



299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
# File 'opal/opal/corelib/number.rb', line 299

def bit_length
  unless Integer === self
    raise NoMethodError.new("undefined method `bit_length` for #{self}:Float", 'bit_length')
  end

  %x{
    if (self === 0 || self === -1) {
      return 0;
    }

    var result = 0,
        value  = self < 0 ? ~self : self;

    while (value != 0) {
      result   += 1;
      value  >>>= 1;
    }

    return result;
  }
end

#ceilObject



321
322
323
# File 'opal/opal/corelib/number.rb', line 321

def ceil
  `Math.ceil(self)`
end

#chr(encoding = undefined) ⇒ Object



325
326
327
# File 'opal/opal/corelib/number.rb', line 325

def chr(encoding = undefined)
  `String.fromCharCode(self)`
end

#coerce(other) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'opal/opal/corelib/number.rb', line 8

def coerce(other)
  %x{
    if (other === nil) {
      #{raise TypeError, "can't convert #{other.class} into Float"};
    }
    else if (other.$$is_string) {
      return [#{Float(other)}, self];
    }
    else if (#{other.respond_to?(:to_f)}) {
      return [#{Opal.coerce_to!(other, Float, :to_f)}, self];
    }
    else if (other.$$is_number) {
      return [other, self];
    }
    else {
      #{raise TypeError, "can't convert #{other.class} into Float"};
    }
  }
end

#denominatorObject



329
330
331
332
333
334
335
# File 'opal/opal/corelib/number.rb', line 329

def denominator
  if nan? || infinite?
    1
  else
    super
  end
end

#divmod(other) ⇒ Object



641
642
643
644
645
646
647
648
649
# File 'opal/opal/corelib/number.rb', line 641

def divmod(other)
  if nan? || other.nan?
    raise FloatDomainError, "NaN"
  elsif infinite?
    raise FloatDomainError, "Infinity"
  else
    super
  end
end

#downto(stop, &block) ⇒ Object



337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
# File 'opal/opal/corelib/number.rb', line 337

def downto(stop, &block)
  return enum_for(:downto, stop){
    raise ArgumentError, "comparison of #{self.class} with #{stop.class} failed" unless Numeric === stop
    stop > self ? 0 : self - stop + 1
  } unless block_given?

  %x{
    if (!stop.$$is_number) {
      #{raise ArgumentError, "comparison of #{self.class} with #{stop.class} failed"}
    }
    for (var i = self; i >= stop; i--) {
      if (block(i) === $breaker) {
        return $breaker.$v;
      }
    }
  }

  self
end

#equal?(other) ⇒ Boolean

Returns:



359
360
361
# File 'opal/opal/corelib/number.rb', line 359

def equal?(other)
  self == other || `isNaN(self) && isNaN(other)`
end

#even?Boolean

Returns:



363
364
365
# File 'opal/opal/corelib/number.rb', line 363

def even?
  `self % 2 === 0`
end

#finite?Boolean

Returns:



684
685
686
# File 'opal/opal/corelib/number.rb', line 684

def finite?
  `self != Infinity && self != -Infinity && !isNaN(self)`
end

#floorObject



367
368
369
# File 'opal/opal/corelib/number.rb', line 367

def floor
  `Math.floor(self)`
end

#gcd(other) ⇒ Object



371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
# File 'opal/opal/corelib/number.rb', line 371

def gcd(other)
  unless Integer === other
    raise TypeError, 'not an integer'
  end

  %x{
    var min = Math.abs(self),
        max = Math.abs(other);

    while (min > 0) {
      var tmp = min;

      min = max % min;
      max = tmp;
    }

    return max;
  }
end

#gcdlcm(other) ⇒ Object



391
392
393
# File 'opal/opal/corelib/number.rb', line 391

def gcdlcm(other)
  [gcd, lcm]
end

#infinite?Boolean

Returns:



688
689
690
691
692
693
694
695
696
697
698
699
700
# File 'opal/opal/corelib/number.rb', line 688

def infinite?
  %x{
    if (self == Infinity) {
      return +1;
    }
    else if (self == -Infinity) {
      return -1;
    }
    else {
      return nil;
    }
  }
end

#instance_of?(klass) ⇒ Boolean

Returns:



409
410
411
412
413
414
415
# File 'opal/opal/corelib/number.rb', line 409

def instance_of?(klass)
  return true if klass == Fixnum && Integer === self
  return true if klass == Integer && Integer === self
  return true if klass == Float && Float === self

  super
end

#integer?Boolean

Returns:



395
396
397
# File 'opal/opal/corelib/number.rb', line 395

def integer?
  `self % 1 === 0`
end

#is_a?(klass) ⇒ Boolean Also known as: kind_of?

Returns:



399
400
401
402
403
404
405
# File 'opal/opal/corelib/number.rb', line 399

def is_a?(klass)
  return true if klass == Fixnum && Integer === self
  return true if klass == Integer && Integer === self
  return true if klass == Float && Float === self

  super
end

#lcm(other) ⇒ Object



417
418
419
420
421
422
423
424
425
426
427
428
429
430
# File 'opal/opal/corelib/number.rb', line 417

def lcm(other)
  unless Integer === other
    raise TypeError, 'not an integer'
  end

  %x{
    if (self == 0 || other == 0) {
      return 0;
    }
    else {
      return Math.abs(self * other / #{gcd(other)});
    }
  }
end

#nan?Boolean

Returns:



680
681
682
# File 'opal/opal/corelib/number.rb', line 680

def nan?
  `isNaN(self)`
end

#negative?Boolean

Returns:



706
707
708
# File 'opal/opal/corelib/number.rb', line 706

def negative?
  `self == -Infinity || 1 / self < 0`
end

#nextObject Also known as: succ



436
437
438
# File 'opal/opal/corelib/number.rb', line 436

def next
  `self + 1`
end

#nonzero?Boolean

Returns:



440
441
442
# File 'opal/opal/corelib/number.rb', line 440

def nonzero?
  `self == 0 ? nil : self`
end

#numeratorObject



444
445
446
447
448
449
450
# File 'opal/opal/corelib/number.rb', line 444

def numerator
  if nan? || infinite?
    self
  else
    super
  end
end

#odd?Boolean

Returns:



452
453
454
# File 'opal/opal/corelib/number.rb', line 452

def odd?
  `self % 2 !== 0`
end

#ordObject



456
457
458
# File 'opal/opal/corelib/number.rb', line 456

def ord
  self
end

#positive?Boolean

Returns:



702
703
704
# File 'opal/opal/corelib/number.rb', line 702

def positive?
  `self == Infinity || 1 / self > 0`
end

#predObject



460
461
462
# File 'opal/opal/corelib/number.rb', line 460

def pred
  `self - 1`
end

#quo(other) ⇒ Object



464
465
466
467
468
469
470
# File 'opal/opal/corelib/number.rb', line 464

def quo(other)
  if Integer === self
    super
  else
    self / other
  end
end

#rationalize(eps = undefined) ⇒ Object



472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
# File 'opal/opal/corelib/number.rb', line 472

def rationalize(eps = undefined)
  %x{
    if (arguments.length > 1) {
      #{raise ArgumentError, "wrong number of arguments (#{`arguments.length`} for 0..1)"};
    }
  }

  if Integer === self
    Rational.new(self, 1)
  elsif infinite?
    raise FloatDomainError, "Infinity"
  elsif nan?
    raise FloatDomainError, "NaN"
  elsif `eps == null`
    f, n  = Math.frexp self
    f     = Math.ldexp(f, Float::MANT_DIG).to_i
    n    -= Float::MANT_DIG

    Rational.new(2 * f, 1 << (1 - n)).rationalize(Rational.new(1, 1 << (1 - n)))
  else
    to_r.rationalize(eps)
  end
end

#round(ndigits = undefined) ⇒ Object



496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
# File 'opal/opal/corelib/number.rb', line 496

def round(ndigits = undefined)
  if Integer === self
    if `ndigits == null`
      return self
    end

    if Float === ndigits && ndigits.infinite?
      raise RangeError, "Infinity"
    end

    ndigits = Opal.coerce_to!(ndigits, Integer, :to_int)

    if ndigits < Integer::MIN
      raise RangeError, "out of bounds"
    end

    if `ndigits >= 0`
      return self
    end

    ndigits = -ndigits;

    %x{
      if (0.415241 * ndigits - 0.125 > #{size}) {
        return 0;
      }

      var f = Math.pow(10, ndigits),
          x = Math.floor((Math.abs(x) + f / 2) / f) * f;

      return self < 0 ? -x : x;
    }
  else
    if nan? && `ndigits == null`
      raise FloatDomainError, "NaN"
    end

    ndigits = Opal.coerce_to!(`ndigits || 0`, Integer, :to_int)

    if ndigits <= 0
      if nan?
        raise RangeError, "NaN"
      elsif infinite?
        raise FloatDomainError, "Infinity"
      end
    elsif ndigits == 0
      return `Math.round(self)`
    elsif nan? || infinite?
      return self
    end

    _, exp = Math.frexp(self)

    if ndigits >= (Float::DIG + 2) - (exp > 0 ? exp / 4 : exp / 3 - 1)
      return self
    end

    if ndigits < -(exp > 0 ? exp / 3 + 1 : exp / 4)
      return 0
    end

    `Math.round(self * Math.pow(10, ndigits)) / Math.pow(10, ndigits)`
  end
end

#sizeObject

Since bitwise operations are 32 bit, declare it to be so.



676
677
678
# File 'opal/opal/corelib/number.rb', line 676

def size
  4
end

#step(limit, step = 1, &block) ⇒ Object

Raises:



561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
# File 'opal/opal/corelib/number.rb', line 561

def step(limit, step = 1, &block)
  return enum_for :step, limit, step unless block

  raise ArgumentError, 'step cannot be 0' if `step == 0`

  %x{
    var value = self;

    if (limit === Infinity || limit === -Infinity) {
      block(value);
      return self;
    }

    if (step > 0) {
      while (value <= limit) {
        block(value);
        value += step;
      }
    }
    else {
      while (value >= limit) {
        block(value);
        value += step;
      }
    }
  }

  self
end

#times(&block) ⇒ Object



593
594
595
596
597
598
599
600
601
602
603
604
605
# File 'opal/opal/corelib/number.rb', line 593

def times(&block)
  return enum_for :times unless block

  %x{
    for (var i = 0; i < self; i++) {
      if (block(i) === $breaker) {
        return $breaker.$v;
      }
    }
  }

  self
end

#to_fObject



607
608
609
# File 'opal/opal/corelib/number.rb', line 607

def to_f
  self
end

#to_iObject Also known as: to_int, truncate



611
612
613
# File 'opal/opal/corelib/number.rb', line 611

def to_i
  `parseInt(self, 10)`
end

#to_rObject



617
618
619
620
621
622
623
624
625
626
627
# File 'opal/opal/corelib/number.rb', line 617

def to_r
  if Integer === self
    Rational.new(self, 1)
  else
    f, e  = Math.frexp(self)
    f     = Math.ldexp(f, Float::MANT_DIG).to_i
    e    -= Float::MANT_DIG

    (f * (Float::RADIX ** e)).to_r
  end
end

#to_s(base = 10) ⇒ Object Also known as: inspect



629
630
631
632
633
634
635
# File 'opal/opal/corelib/number.rb', line 629

def to_s(base = 10)
  if base < 2 || base > 36
    raise ArgumentError, 'base must be between 2 and 36'
  end

  `self.toString(base)`
end

#upto(stop, &block) ⇒ Object



651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
# File 'opal/opal/corelib/number.rb', line 651

def upto(stop, &block)
  return enum_for(:upto, stop){
    raise ArgumentError, "comparison of #{self.class} with #{stop.class} failed" unless Numeric === stop
    stop < self ? 0 : stop - self + 1
  } unless block_given?

  %x{
    if (!stop.$$is_number) {
      #{raise ArgumentError, "comparison of #{self.class} with #{stop.class} failed"}
    }
    for (var i = self; i <= stop; i++) {
      if (block(i) === $breaker) {
        return $breaker.$v;
      }
    }
  }

  self
end

#zero?Boolean

Returns:



671
672
673
# File 'opal/opal/corelib/number.rb', line 671

def zero?
  `self == 0`
end

#|(other) ⇒ Object



113
114
115
116
117
118
119
120
121
122
# File 'opal/opal/corelib/number.rb', line 113

def |(other)
  %x{
    if (other.$$is_number) {
      return self | other;
    }
    else {
      return #{__coerced__ :|, other};
    }
  }
end

#~Object



233
234
235
# File 'opal/opal/corelib/number.rb', line 233

def ~
  `~self`
end