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'
HashProperty =
[:label, :remainder, :divisor]

Constants included from Parts::Resource

Parts::Resource::ConstList, Parts::Resource::ConstTypes, Parts::Resource::IRIDecode, Parts::Resource::IRIDecodeTable, Parts::Resource::IRIEncode, Parts::Resource::IRIEncodeTable, 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)


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
489
490
491
# File 'lib/when_exe/coordinates.rb', line 459

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


502
503
504
505
506
507
508
509
510
511
# File 'lib/when_exe/coordinates.rb', line 502

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)


238
239
240
# File 'lib/when_exe/coordinates.rb', line 238

def carry
  @carry
end

#divisorInteger (readonly)

Returns:

  • (Integer)

    (>0)



232
233
234
# File 'lib/when_exe/coordinates.rb', line 232

def divisor
  @divisor
end

#remainderNumeric

剰余

Returns:



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

def remainder
  @remainder
end

#unitsHash (readonly)

単位

Returns:

  • (Hash)

    { String=>Numeric }

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

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


251
252
253
# File 'lib/when_exe/coordinates.rb', line 251

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


407
408
409
410
411
412
413
414
415
416
417
418
419
420
# File 'lib/when_exe/coordinates.rb', line 407

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

剰余類の共通集合



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
397
398
399
# File 'lib/when_exe/coordinates.rb', line 368

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


326
327
328
329
# File 'lib/when_exe/coordinates.rb', line 326

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:



337
338
339
340
# File 'lib/when_exe/coordinates.rb', line 337

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:



358
359
360
# File 'lib/when_exe/coordinates.rb', line 358

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

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

carryの加算

Parameters:

Returns:



348
349
350
# File 'lib/when_exe/coordinates.rb', line 348

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)


281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
# File 'lib/when_exe/coordinates.rb', line 281

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:



231
232
233
234
235
# File 'lib/when_exe/inspect.rb', line 231

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:



438
439
440
441
442
443
# File 'lib/when_exe/coordinates.rb', line 438

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:



214
215
216
217
218
219
220
221
222
223
# File 'lib/when_exe/inspect.rb', line 214

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 の差



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

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:



303
304
305
# File 'lib/when_exe/coordinates.rb', line 303

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

#eventString

オブジェクトの単位

Returns:

  • (String)

    現在使用中の単位を返す



269
270
271
272
# File 'lib/when_exe/coordinates.rb', line 269

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:



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

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

#to_m17nWhen::BasicTypes::M17n

多言語対応文字列化



192
193
194
195
196
# File 'lib/when_exe/inspect.rb', line 192

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:



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

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