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 Namespace

Namespace::DC, Namespace::DCQ, Namespace::DCT, Namespace::FOAF, Namespace::OWL, Namespace::RDF, Namespace::RDFC, Namespace::RDFS, Namespace::RSS, Namespace::XSD

Instance Attribute Summary collapse

Attributes inherited from BasicTypes::Object

#label

Attributes included from Parts::Resource

#child, #keys, #locale, #namespace

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Parts::Resource

#^, _instance, _setup_, _setup_info, base_uri, #each, #hierarchy, #include?, #included?, #iri, #leaf?, #m17n, #map, #parent, #registered?, root_dir

Methods included from Parts::Resource::Pool

#[]=, #_setup_

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)


472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
# File 'lib/when_exe/coordinates.rb', line 472

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
  @shifted   = @carry != 0
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

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

その他のメソッド

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


516
517
518
519
520
521
522
523
524
525
# File 'lib/when_exe/coordinates.rb', line 516

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)


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

def carry
  @carry
end

#divisorInteger (readonly)

Returns:

  • (Integer)

    (>0)



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

def divisor
  @divisor
end

#remainderNumeric

剰余

Returns:



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

def remainder
  @remainder
end

#shiftedBoolean

周期分の補正の有無

Returns:

  • (Boolean)


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

def shifted
  @shifted
end

#unitsHash (readonly)

単位

Returns:

  • (Hash)

    { String=>Numeric }

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

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


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

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 ]



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

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



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

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:



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

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 =~ /\A([-+\d]+)(.+)/ ? [$2, $1] : 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 << '1' unless shift =~ /\d/
  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。



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

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


420
421
422
423
424
425
426
427
428
429
430
431
432
433
# File 'lib/when_exe/coordinates.rb', line 420

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

剰余類の共通集合



381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
# File 'lib/when_exe/coordinates.rb', line 381

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


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

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:



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

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:



369
370
371
372
373
# File 'lib/when_exe/coordinates.rb', line 369

def <<(other)
  result = self.class.new(@remainder, @divisor, @carry-other, @units)
  result.shifted = true
  result
end

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

carryの加算

Parameters:

Returns:



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

def >>(other)
  result = self.class.new(@remainder, @divisor, @carry+other, @units)
  result.shifted = true
  result
end

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

remainder の指定

Parameters:

  • remainder (Numeric)

    指定値を@remainderとする

  • remainder (String)

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

Returns:

Raises:

  • (ArgumentError)


290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
# File 'lib/when_exe/coordinates.rb', line 290

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:



451
452
453
454
455
456
# File 'lib/when_exe/coordinates.rb', line 451

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

#differenceInteger

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

Returns:

  • (Integer)

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

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



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

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:



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

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

#eventString

オブジェクトの単位

Returns:

  • (String)

    現在使用中の単位を返す



278
279
280
281
# File 'lib/when_exe/coordinates.rb', line 278

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:



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

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