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)


440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
# File 'lib/when_exe/coordinates.rb', line 440

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


483
484
485
486
487
488
489
490
491
492
# File 'lib/when_exe/coordinates.rb', line 483

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)


219
220
221
# File 'lib/when_exe/coordinates.rb', line 219

def carry
  @carry
end

#divisorInteger (readonly)

Returns:

  • (Integer)

    (>0)



213
214
215
# File 'lib/when_exe/coordinates.rb', line 213

def divisor
  @divisor
end

#remainderNumeric

剰余

Returns:



206
207
208
# File 'lib/when_exe/coordinates.rb', line 206

def remainder
  @remainder
end

#unitsHash (readonly)

単位

Returns:

  • (Hash)

    { String=>Numeric }

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

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


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

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 ]



171
172
173
174
175
176
177
178
179
180
181
# File 'lib/when_exe/coordinates.rb', line 171

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

曜日(剰余類)

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').child
  case day
  when Numeric ; return week[day]
  when String  ; day = When::EncodingConversion.to_internal_encoding(day)
  else         ; return nil
  end

  match = day[/\A...|^.{1,2}\z/]
  if match
    week.size.times do |i|
      return week[i] if week[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

.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。



152
153
154
155
156
157
158
159
160
161
162
# File 'lib/when_exe/coordinates.rb', line 152

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


388
389
390
391
392
393
394
395
396
397
398
399
400
401
# File 'lib/when_exe/coordinates.rb', line 388

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

剰余類の共通集合



349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
# File 'lib/when_exe/coordinates.rb', line 349

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


307
308
309
310
# File 'lib/when_exe/coordinates.rb', line 307

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:



318
319
320
321
# File 'lib/when_exe/coordinates.rb', line 318

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:



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

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

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

carryの加算

Parameters:

Returns:



329
330
331
# File 'lib/when_exe/coordinates.rb', line 329

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)


262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
# File 'lib/when_exe/coordinates.rb', line 262

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:



194
195
196
197
198
# File 'lib/when_exe/inspect.rb', line 194

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:



419
420
421
422
423
424
# File 'lib/when_exe/coordinates.rb', line 419

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:



177
178
179
180
181
182
183
184
185
186
# File 'lib/when_exe/inspect.rb', line 177

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



297
298
299
# File 'lib/when_exe/coordinates.rb', line 297

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:



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

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

#eventString

オブジェクトの単位

Returns:

  • (String)

    現在使用中の単位を返す



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

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:



240
241
242
243
# File 'lib/when_exe/coordinates.rb', line 240

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

#to_m17nWhen::BasicTypes::M17n

多言語対応文字列化



155
156
157
158
159
# File 'lib/when_exe/inspect.rb', line 155

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:



165
166
167
168
169
# File 'lib/when_exe/inspect.rb', line 165

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