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'

Constants included from Parts::Resource

Parts::Resource::ConstList, Parts::Resource::ConstTypes, Parts::Resource::IRIHeader

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

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

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

オブジェクトの生成

Parameters:

  • remainder (Numeric)

    剰余

  • divisor (Integer)

  • carry (Integer) (defaults to: 0)

    繰り上がり

  • label (String, When::BasicTypes::M17n) (defaults to: nil)

    名前

  • format (String, When::BasicTypes::M17n) (defaults to: nil)

    名前の書式

  • units (Hash) (defaults to: {})

    単位(下記の通り)

Options Hash (units):

  • 'day' (Numeric)

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

  • 'year' (Numeric)

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

Raises:

  • (RangeError)


456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
# File 'lib/when_exe/coordinates.rb', line 456

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 で定義されていないメソッドは
指定の桁での剰余算とみなす


499
500
501
502
503
504
505
506
507
508
# File 'lib/when_exe/coordinates.rb', line 499

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

繰り上がり

Returns:

  • (Integer)


235
236
237
# File 'lib/when_exe/coordinates.rb', line 235

def carry
  @carry
end

#divisorInteger (readonly)

Returns:

  • (Integer)

    (>0)



229
230
231
# File 'lib/when_exe/coordinates.rb', line 229

def divisor
  @divisor
end

#remainderNumeric

剰余

Returns:



222
223
224
# File 'lib/when_exe/coordinates.rb', line 222

def remainder
  @remainder
end

#unitsHash (readonly)

単位

Returns:

  • (Hash)

    { String=>Numeric }

    Example : { ‘day’=>11, ‘year’=4 }

    通日に適用するときは、11 ずらして計算 - 甲子日 = ユリウス日 11 + 60n
    
    通年に適用するときは、 4 ずらして計算 - 甲子年 = 西暦 4 + 60n
    


248
249
250
# File 'lib/when_exe/coordinates.rb', line 248

def units
  @units
end

Class Method Details

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

中国剰余

Parameters:

  • a (Array<Numeric>)
    num, den

    den で割って num 余ることを示す配列

  • b (Array<Numeric>)
    num, den

    den で割って num 余ることを示す配列

Returns:

  • (Array<Numeric>)

    a と b の条件をともに満たす [ num, den ]



187
188
189
190
191
192
193
194
195
196
197
# File 'lib/when_exe/coordinates.rb', line 187

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, dow) ⇒ Object



137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/when_exe/coordinates.rb', line 137

def _day_of_week(day, dow)
  match = day[/\A...|^.{1,2}\z/]
  if match
    dow.size.times do |i|
      return dow[i] if dow[i].label.=~(/\A#{match}/i)
    end
  end

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

  return nil
end

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

曜日(剰余類)

Parameters:

  • day (Numeric)

    月曜を 0 とする七曜(剰余類)を返します

  • day (String)

    最初の3文字から決定した七曜(剰余類)を返します。 一致する七曜(剰余類)がない場合、名前の一致するその他の剰余類を探して返します。

Returns:



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/when_exe/coordinates.rb', line 111

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

  day ||= 0
  week  = When.Resource('_co:Common::Week')
  dow   = week.child
  case day
  when Numeric    ; return dow[day]
  when /\AWeek\z/ ; return week
  when String     ; day = When::EncodingConversion.to_internal_encoding(day)
  else            ; return nil
  end

  day, shift = day.split(':', 2)
  residue = day.split('&').inject(nil) {|res,d|
    r = _day_of_week(d.strip, dow)
    return nil unless r
    res ? res & r : r
  }
  return residue unless shift
  shift  = shift.to_i
  shift -= 1 if shift > 0
  residue >> shift
end

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

汎用の mod

Parameters:

  • nn (Numeric)

    被除数

  • dd (Block)

    手続き

    nn = rem + dd(quot)

    div = dd(quot+1)-dd(quot)

    となるように rem, div, quot を決めたい手続き

Returns:

  • (Array<Numeric>)
    quot, rem, div

    nn を dd で「割った」商(quot), 余り(rem)および除数(div)を返します。 remは非負、quotは Integer。



168
169
170
171
172
173
174
175
176
177
178
# File 'lib/when_exe/coordinates.rb', line 168

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' と同じクラス

剰余

Parameters:

Returns:

  • ('other' と同じクラス)


404
405
406
407
408
409
410
411
412
413
414
415
416
417
# File 'lib/when_exe/coordinates.rb', line 404

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

剰余類の共通集合



365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
# File 'lib/when_exe/coordinates.rb', line 365

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


323
324
325
326
# File 'lib/when_exe/coordinates.rb', line 323

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

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

remainderの減算

Parameters:

Returns:



334
335
336
337
# File 'lib/when_exe/coordinates.rb', line 334

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

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

carryの減算

Parameters:

Returns:



355
356
357
# File 'lib/when_exe/coordinates.rb', line 355

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

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

carryの加算

Parameters:

Returns:



345
346
347
# File 'lib/when_exe/coordinates.rb', line 345

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

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

remainder の指定

Parameters:

  • remainder (Numeric)

    指定値を@remainderとする

  • remainder (String)

    When::Parts::Resource の has-a 関係によりString に対応する子供オブジェクトを取得

Returns:

Raises:

  • (ArgumentError)


278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
# File 'lib/when_exe/coordinates.rb', line 278

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

#_column_for_week_included(base, range, opt, &block) ⇒ Array<Object>

week_included のためのコラムの生成

Returns:



202
203
204
205
206
# File 'lib/when_exe/inspect.rb', line 202

def _column_for_week_included(base, range, opt, &block)
  range.inject([]) {|s,r| s + r.map { |date|
    yield(date, !opt.key?(:Range) || opt[:Range].include?(date.to_i) ? DAY : nil)
  }}
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 の生成

Overloads:

Returns:



435
436
437
438
439
440
# File 'lib/when_exe/coordinates.rb', line 435

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

#_range_for_week_included(date, first, length, block_given = false) ⇒ Array<Range>

week_included のための range の決定

Returns:



185
186
187
188
189
190
191
192
193
194
# File 'lib/when_exe/inspect.rb', line 185

def _range_for_week_included(date, first, length, block_given=false)
  today = date.floor
  begun = today.succ & self >> first-1
  unless date.frame.equal?(begun.frame)
    begun  = (date.frame ^ today).succ & self >> first-1
    middle = today
  end
  ended = begun.succ & self >> length-1
  middle && block_given ? [begun...middle, middle...ended] : [begun...ended]
end

#differenceInteger

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

Returns:

  • (Integer)

    派生オブジェクトでない場合 : 自身の remainder

    派生オブジェクトである場合 : 派生オブジェクトと元オブジェクトの remainder の差



313
314
315
# File 'lib/when_exe/coordinates.rb', line 313

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

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

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

Parameters:

  • event (String) (defaults to: self.event)

Returns:



300
301
302
# File 'lib/when_exe/coordinates.rb', line 300

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

#eventString

オブジェクトの単位

Returns:

  • (String)

    現在使用中の単位を返す



266
267
268
269
# File 'lib/when_exe/coordinates.rb', line 266

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

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

units の指定

Parameters:

  • arg (String)

    あらかじめ units に指定した単位を用いる

Returns:



256
257
258
259
# File 'lib/when_exe/coordinates.rb', line 256

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

#to_m17nWhen::BasicTypes::M17n

多言語対応文字列化



163
164
165
166
167
# File 'lib/when_exe/inspect.rb', line 163

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

文字列化

Returns:



173
174
175
176
177
# File 'lib/when_exe/inspect.rb', line 173

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