Class: When::Coordinates::Residue

Inherits:
BasicTypes::Object show all
Defined in:
lib/when_exe/coordinates.rb,
lib/when_exe/inspect.rb

Overview

剰余類

Direct Known Subclasses

Branch, Kyusei, Stem, StemBranch, Wuku

Defined Under Namespace

Classes: BestRationalApproximations, Enumerator

Constant Summary collapse

LabelProperty =
'label'

Instance Attribute Summary collapse

Attributes inherited from BasicTypes::Object

#label

Attributes included from Parts::Resource

#_pool, #child, #keys, #locale, #namespace

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Parts::Resource

#^, _decode, _encode, _extract_prefix, _instance, _parse, _path_with_prefix, _replace_tags, _setup_, #each, #hierarchy, #include?, #included?, #iri, #leaf?, #m17n, #map, #next, #parent, #prev, #registered?

Methods included from Parts::Resource::Pool

#[]=, #_pool, #_setup_, #pool_keys

Methods included from Parts::Resource::Synchronize

#synchronize

Constructor Details

#initialize(remainder, divisor, carry = 0, label = nil, format = nil, units = {}) ⇒ Residue

オブジェクトの生成

Options Hash (units):

  • 'day' (Numeric)

    通日に対して使用する場合のオフセット

  • 'year' (Numeric)

    通年に対して使用する場合のオフセット

Raises:

  • (RangeError)

416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
# File 'lib/when_exe/coordinates.rb', line 416

def initialize(*args)
  # units の取得
  options =_get_options(args).dup
  units   = {}
  list    = []
  options.each_pair do |key, value|
    if (PRECISION[key.upcase])
      list << key
      units[key.downcase] = _to_num(value)
    end
  end
  list.each do |key|
    options.delete(key)
  end
  options['units'] ||= {}
  options['units'].update(units)
  _set_variables(options)
  @units ||= {}

  # その他の変数
  remainder, divisor, carry, label, format = args
  @label     = label || @label
  @label     = m17n(@label, nil, nil, options) if (@label)
  @format    = format || @format
  @format    = m17n(@format, nil, nil, options) if (@format)
  _sequence
  @remainder = _to_num(remainder || @remainder)
  @divisor   = _to_num(divisor   || @divisor  )
  @carry     = _to_num(carry     || @carry    )
  raise RangeError, "Divisor shoud be Positive Numeric" if (@divisor <= 0)
  carry, @remainder = @remainder.divmod(@divisor)
  @carry += carry
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object (private)

その他のメソッド

When::Coordinate::Residue で定義されていないメソッドは
指定の桁での剰余算とみなす

459
460
461
462
463
464
465
466
467
468
# File 'lib/when_exe/coordinates.rb', line 459

def method_missing(name, *args, &block)
  return _method_missing(name, *args, &block) if When::Parts::MethodCash::Escape.key?(name) ||
                                                !@units.key?(name.to_s.downcase)
  instance_eval %Q{
    def #{name}(*args, &block)
      self[args[0] % self.to("#{name.to_s.downcase}")]
    end
  } unless When::Parts::MethodCash.escape(name)
  self[args[0] % self.to(name.to_s.downcase)]
end

Instance Attribute Details

#carryInteger

繰り上がり


195
196
197
# File 'lib/when_exe/coordinates.rb', line 195

def carry
  @carry
end

#divisorInteger (readonly)


189
190
191
# File 'lib/when_exe/coordinates.rb', line 189

def divisor
  @divisor
end

#remainderNumeric

剰余


182
183
184
# File 'lib/when_exe/coordinates.rb', line 182

def remainder
  @remainder
end

#unitsHash (readonly)

単位


208
209
210
# File 'lib/when_exe/coordinates.rb', line 208

def units
  @units
end

Class Method Details

._china(a, b) ⇒ Array<Numeric>

中国剰余


147
148
149
150
151
152
153
154
155
156
157
# File 'lib/when_exe/coordinates.rb', line 147

def _china(a, b)
  b, a = a, b if (a[1] <= b[1])
  g, p, q = _gcd(a[1], b[1])
  return [((b[0]*a[1]*q-a[0]*b[1]*p)*(a[1]*q-b[1]*p)) % (a[1]*b[1]), a[1]*b[1]] if (g == 1)
  r = a[0] % g
  s = b[0] % g
  return nil unless (r == s)
  m = _china([(a[0]-r).div(g), a[1].div(g)], [(b[0]-s).div(g), b[1].div(g)])
  return nil unless (m)
  return [m[0]*g+r, m[1]*g]
end

.day_of_week(day) ⇒ When::Coordinates::Residue Also known as: to_residue

曜日(剰余類)


87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/when_exe/coordinates.rb', line 87

def day_of_week(day)
  return day if day.kind_of?(self)

  day ||= 0
  week  = When.Resource('_co:CommonResidue::Week').child
  case day
  when Numeric ; return week[day]
  when String  ;
  else         ; return nil
  end

  match = day[/^...|^.{1,2}$/]
  if match
    week.size.times do |i|
      return week[i] if week[i].label.=~(/^#{match}/i)
    end
  end

  ObjectSpace.each_object(self) do |object|
    return object if object.registered? && object.label.=~(/^#{day}$/)
  end

  return nil
end

.mod(nn, &dd) ⇒ Array<Numeric>

汎用の mod


128
129
130
131
132
133
134
135
136
137
138
# File 'lib/when_exe/coordinates.rb', line 128

def mod(nn, &dd)
  u = dd.call(0)
  y = ((nn-u)*256).divmod(dd.call(256)-u)[0] - 1
  w1, w2 = dd.call(y), dd.call(y+1)
  until  w1 <= nn && nn < w2
    if w2 <= nn then  y, w1, w2 = y+1, w2, dd.call(y+2)
    else              y, w1, w2 = y-1, dd.call(y-1), w1
    end
  end
  return y, nn-w1, w2-w1
end

Instance Method Details

#%(other) ⇒ 'other' と同じクラス

剰余


364
365
366
367
368
369
370
371
372
373
374
375
376
377
# File 'lib/when_exe/coordinates.rb', line 364

def %(other)
  case other
  when Pair
    return Pair.new(self % other.trunk, other.branch)
  when Numeric
    keys = @units.keys
    d    = (keys.size == 1) ? @units[keys[0]] : (@units['day']||0)
    return (other-d) % @divisor
  else
    position = When::TM::Position.any_other(other)
    raise TypeError, "Can't convert #{other.class} to When::TM::TemporalPosition" unless position
    return self[position % self]
  end
end

#&(other) ⇒ When::Coordinates::Residue

剰余類の共通集合


325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
# File 'lib/when_exe/coordinates.rb', line 325

def &(other)
  case other
  when Residue
    if self.units == other.units
      m = self.class._china([@remainder, @divisor], [other.remainder, other.divisor])
      u = units.dup
    else
      keys = units.keys & other.units.keys
      keys = ['day'] if keys == []
      return nil unless (keys.size==1)
      self_base  = self.units[keys[0]]  || 0
      other_base = other.units[keys[0]] || 0
      m = self.class._china([@remainder, @divisor],
                            [(other.remainder+other_base-self_base) % other.divisor, other.divisor])
      u = {keys[0]=>self_base}
    end
    return nil unless (m)
    return self.class.new(m[0], m[1], @carry, u)
  when Pair
    return Pair.new(self & other.trunk, other.branch)
  when Numeric
    keys = @units.keys
    d    = (keys.size == 1) ? @units[keys[0]] : (@units['day']||0)
    c, m = (other-d).divmod(@divisor)
    c += 1 if (m > @remainder)
    return (c + @carry) * @divisor + @remainder + d
  else
    position = When::TM::Position.any_other(other)
    raise TypeError, "Can't convert #{other.class} to When::TM::TemporalPosition" unless position
    return position & self
  end
end

#+(other) ⇒ When::Coordinates::Residue

remainderの加算

other   : Numeric

283
284
285
286
# File 'lib/when_exe/coordinates.rb', line 283

def +(other)
  carry, remainder = (@remainder + other).divmod(@divisor)
  return self.class.new(remainder, @divisor, @carry+carry, @units)
end

#-(other) ⇒ When::Coordinates::Residue

remainderの減算


294
295
296
297
# File 'lib/when_exe/coordinates.rb', line 294

def -(other)
  carry, remainder = (@remainder - other).divmod(@divisor)
  return self.class.new(remainder, @divisor, @carry+carry, @units)
end

#<<(other) ⇒ When::Coordinates::Residue

carryの減算


315
316
317
# File 'lib/when_exe/coordinates.rb', line 315

def <<(other)
  return self.class.new(@remainder, @divisor, @carry-other, @units)
end

#>>(other) ⇒ When::Coordinates::Residue

carryの加算


305
306
307
# File 'lib/when_exe/coordinates.rb', line 305

def >>(other)
  return self.class.new(@remainder, @divisor, @carry+other, @units)
end

#[](remainder) ⇒ When::Coordinates::Residue

remainder の指定

Raises:

  • (ArgumentError)

238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'lib/when_exe/coordinates.rb', line 238

def [](remainder)
  return super if !remainder.kind_of?(Numeric) || (child && child.length == @divisor)
  return self  if remainder == 0 && !child
  remainder *= 1
  return self.class.new(@remainder+remainder, @divisor, @carry, @label, @format, @units) unless (child && child.length > 0)
  carry, remainder = (@remainder+remainder).divmod(@divisor)
  base = child.reverse.each do |residue|
    break residue if residue.remainder <= remainder
  end
  raise ArgumentError, "remainder out of range: #{remainder}" unless base.kind_of?(self.class)
  base = base.dup
  base.remainder = remainder
  base.carry    += carry
  return base
end

#initializeWhen::Coordinates::Residue::BestRationalApproximations, When::Coordinates::Residue::Enumerator #initialize(range, count_limit = nil) ⇒ When::Coordinates::Residue::BestRationalApproximations, When::Coordinates::Residue::Enumerator #initialize(first, direction, count_limit) ⇒ When::Coordinates::Residue::BestRationalApproximations, When::Coordinates::Residue::Enumerator Also known as: to_enum, enum_for

Enumerator の生成


395
396
397
398
399
400
# File 'lib/when_exe/coordinates.rb', line 395

def _enumerator(*args)
  length  = args.length
  length -= 1 if args[-1].kind_of?(Hash)
  args.unshift(self)
  (length==0) ? BestRationalApproximations.new(self, *args) : Enumerator.new(*args)
end

#_to_hash_value(options = {}) ⇒ Object

to_h のための要素生成


128
129
130
# File 'lib/when_exe/inspect.rb', line 128

def _to_hash_value(options={})
  options[:residue] ? self : to_m17n
end

#differenceInteger

派生オブジェクトと元オブジェクトの remainder の差 (派生オブジェクトとは、元オブジェクトに[]演算を施して @remainder を変えたオブジェクト)


273
274
275
# File 'lib/when_exe/coordinates.rb', line 273

def difference
  @difference ||= (registered? || iri !~ /:/) ? @remainder : @remainder - When.Resource(iri).remainder
end

#duration(event = self.event) ⇒ When::TM::PeriodDuration

典型的なイベントの発生間隔


260
261
262
# File 'lib/when_exe/coordinates.rb', line 260

def duration(event=self.event)
  When::TM::PeriodDuration.new(@divisor, When::Coordinates::PRECISION[event.upcase])
end

#eventString

オブジェクトの単位


226
227
228
229
# File 'lib/when_exe/coordinates.rb', line 226

def event
  keys = @units.keys
  return (keys.size == 1) ? keys[0] : 'day'
end

#to(arg) ⇒ When::Coordinates::Residue Also known as: /

units の指定


216
217
218
219
# File 'lib/when_exe/coordinates.rb', line 216

def to(arg)
  return nil unless @units[arg]
  self.class.new(@remainder, @divisor, @carry, {arg=>@units[arg]})
end

#to_m17nWhen::BasicTypes::M17n

多言語対応文字列化


109
110
111
112
113
# File 'lib/when_exe/inspect.rb', line 109

def to_m17n
  return m17n(@remainder.to_s)     unless label
  return label + "(#{difference})" unless @format
  label[0...0] + (@format % [label, difference, difference+1])
end

#to_sString

文字列化


119
120
121
122
123
# File 'lib/when_exe/inspect.rb', line 119

def to_s
  return @remainder.to_s                unless label
  return label.to_s + "(#{difference})" unless @format
  (@format % [label, difference, difference+1]).to_s
end