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

オブジェクトの生成

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)


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

繰り上がり

Returns:

  • (Integer)


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

def carry
  @carry
end

#divisorInteger (readonly)

Returns:

  • (Integer)

    (>0)



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

def divisor
  @divisor
end

#remainderNumeric

剰余

Returns:



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

def remainder
  @remainder
end

#unitsHash (readonly)

単位

Returns:

  • (Hash)

    { String=>Numeric }

    Example : { 'day'=>11, 'year'=4 }

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


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

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 ]



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

曜日(剰余類)

Parameters:

  • day (Numeric)

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

  • day (String)

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

Returns:



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

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。



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

剰余

Parameters:

Returns:

  • ('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の減算

Parameters:

Returns:



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の減算

Parameters:

Returns:



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の加算

Parameters:

Returns:



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 の指定

Parameters:

  • remainder (Numeric)

    指定値を@remainderとする

  • remainder (String)

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

Returns:

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 の生成

Overloads:

Returns:



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 を変えたオブジェクト)

Returns:

  • (Integer)

    派生オブジェクトでない場合 : 自身の 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

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

Parameters:

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

Returns:



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

オブジェクトの単位

Returns:

  • (String)

    現在使用中の単位を返す



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 の指定

Parameters:

  • arg (String)

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

Returns:



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

文字列化

Returns:



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