unitwise 0.6.1 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3f269726294777e995dada36f1169f639de28b5f
4
- data.tar.gz: e9bc9e48ee65a4d08539d5ee85c7cb2d14d65573
3
+ metadata.gz: d9050a8b1974209dc285b85f896030daed2e6319
4
+ data.tar.gz: 239e8d8949dfadf97acd2b5d431d7c9722d93b9e
5
5
  SHA512:
6
- metadata.gz: e5f8cd371aac1c89b4eeab25f3f5d92fa45029244073deb0515dd9ef4c5347d8b91a96838b71319ec040147fed46a0f4b91656296839c408230f9f823bf14860
7
- data.tar.gz: 17cdcce509f3db09c4cb607f8d51c64d0ea5a6ae51653f0a8c56de61756f75d280f677ac6a06c3086058a6f83d8c121a570ef234c6d23be3788038b67a74496e
6
+ metadata.gz: 3ebf1ae8eaa28fbff80dadf844629f74e36593c094ee1b8a82aee615e1989b1d995a5512e573405422814c8bb581b5e44bad928372f91dccf40eff3584b6d854
7
+ data.tar.gz: b8290d0f28ab189333ed4b16efdf5d5ea42f9d0d0b3d65d4822cda9e33ee234ee1da2ed544487b4be9814a4d4cd07aba2480d1ab714262e1c75dfee5812d99b7
data/Gemfile CHANGED
@@ -1,5 +1,2 @@
1
1
  source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in unitwise.gemspec
4
- gem 'pry'
5
2
  gemspec
data/lib/unitwise/atom.rb CHANGED
@@ -4,8 +4,7 @@ module Unitwise
4
4
  # 'meter', 'hour', 'pound force'.
5
5
  class Atom < Base
6
6
  liner :classification, :property, :metric, :special, :arbitrary, :dim
7
-
8
- include Unitwise::Compatible
7
+ include Compatible
9
8
 
10
9
  class << self
11
10
  # Array of hashes representing atom properties.
@@ -71,6 +70,7 @@ module Unitwise
71
70
  def depth
72
71
  base? ? 0 : scale.depth + 1
73
72
  end
73
+ memoize :depth
74
74
 
75
75
  # Determine if this is the last atom in the scale chain
76
76
  # @return [true, false]
@@ -116,5 +116,6 @@ module Unitwise
116
116
  def root_terms
117
117
  base? ? [Term.new(:atom_code => primary_code)] : scale.root_terms
118
118
  end
119
+ memoize :root_terms
119
120
  end
120
121
  end
data/lib/unitwise/base.rb CHANGED
@@ -1,9 +1,9 @@
1
- require 'yaml'
2
1
  module Unitwise
3
2
  # The base class that Atom and Prefix are extended from. This class provides
4
3
  # shared functionality for said classes.
5
4
  class Base
6
5
  liner :names, :primary_code, :secondary_code, :symbol, :scale
6
+ include Memoizable
7
7
 
8
8
  # The list of tracked items.
9
9
  # @return [Array] An array of memoized instances.
@@ -30,14 +30,6 @@ module Unitwise
30
30
  end
31
31
  end
32
32
 
33
- # Setup a new instance. Takes a hash of attributes, or an array of
34
- # attribute values.
35
- # @api public
36
- def initialize(*args)
37
- super(*args)
38
- freeze
39
- end
40
-
41
33
  # Setter for the names attribute. Will always set as an array.
42
34
  # @api semipublic
43
35
  def names=(names)
@@ -52,6 +44,7 @@ module Unitwise
52
44
  n.downcase.strip.gsub(/\s/, '_').gsub(/\W/, '')
53
45
  end
54
46
  end
47
+ memoize :slugs
55
48
 
56
49
  # String representation for the instance.
57
50
  # @return [String]
@@ -6,6 +6,13 @@ module Unitwise
6
6
  # @api private
7
7
  def self.included(base)
8
8
  base.send :include, Comparable
9
+ base.send :include, Memoizable unless base < Memoizable
10
+ base.send :memoize, :composition, :composition_string
11
+ end
12
+
13
+ def initialize(*args)
14
+ super(*args)
15
+ freeze
9
16
  end
10
17
 
11
18
  # A representation of a unit based on the atoms it's derived from.
@@ -1,5 +1,3 @@
1
- require 'parslet'
2
-
3
1
  require 'unitwise/expression/matcher'
4
2
  require 'unitwise/expression/parser'
5
3
  require 'unitwise/expression/transformer'
@@ -4,19 +4,13 @@ module Unitwise
4
4
  # magnitude and direction. This class should be considered mostly privateish.
5
5
  class Scale
6
6
  liner :value, :unit
7
-
8
7
  include Unitwise::Compatible
9
8
 
10
- def initialize(*args)
11
- super(*args)
12
- freeze
13
- end
14
-
15
- # The unit associated with this scale.
16
- # @return [Unitwise::Unit]
9
+ # Set the unit vector.
10
+ # @param value [String, Unitwise::Unit]
17
11
  # @api public
18
- def unit
19
- @unit.is_a?(Unit) ? @unit : Unit.new(@unit)
12
+ def unit=(value)
13
+ @unit = value.is_a?(Unit) ? value : Unit.new(value)
20
14
  end
21
15
 
22
16
  # List the atoms associated with this scale's unit.
@@ -40,13 +34,6 @@ module Unitwise
40
34
  unit.special?
41
35
  end
42
36
 
43
- # Return a converted value for this scale, based on it's function for
44
- # scales with special units.
45
- # @param x [Numeric] Value to convert to or from
46
- # @param forward [true, false] whether to convert to this unit or from it.
47
- # @return [Numeric]
48
- # @api public
49
-
50
37
  # Get a scalar value for this scale.
51
38
  # @param magnitude [Numeric] An optional magnitude on this scale.
52
39
  # @return [Numeric] A scalar value on a linear scale
@@ -59,7 +46,7 @@ module Unitwise
59
46
  end
60
47
  end
61
48
 
62
- # Get a magnitude based on a linear scale value. Only used by scales with
49
+ # Get a magnitude based on a linear scale value. Only used by scales with
63
50
  # special atoms in it's hierarchy.
64
51
  # @param scalar [Numeric] A linear scalar value
65
52
  # @return [Numeric] The equivalent magnitude on this scale
@@ -78,6 +65,7 @@ module Unitwise
78
65
  def root_terms
79
66
  unit.root_terms
80
67
  end
68
+ memoize :root_terms
81
69
 
82
70
  # How far away is this instances unit from the deepest leve atom.
83
71
  # @return [Integer]
@@ -85,6 +73,7 @@ module Unitwise
85
73
  def depth
86
74
  unit.depth + 1
87
75
  end
76
+ memoize :depth
88
77
 
89
78
  # Convert to a simple string representing the scale.
90
79
  # @api public
@@ -95,5 +84,18 @@ module Unitwise
95
84
  def inspect
96
85
  "#<#{self.class} value=#{value} unit=#{unit}>"
97
86
  end
87
+
88
+ # Redefine hash for apropriate hash/key lookup
89
+ # @api semipublic
90
+ def hash
91
+ [value, unit.to_s, self.class].hash
92
+ end
93
+ memoize :hash
94
+
95
+ # Redefine hash equality to match the hashes
96
+ # @api semipublic
97
+ def eql?(other)
98
+ hash == other.hash
99
+ end
98
100
  end
99
101
  end
data/lib/unitwise/term.rb CHANGED
@@ -1,17 +1,9 @@
1
- require 'signed_multiset'
2
1
  module Unitwise
3
2
  # A Term is the combination of an atom, prefix, factor and annotation.
4
3
  # Not all properties have to be present. Examples: 'g', 'mm', 'mi2', '4[pi]',
5
4
  # 'kJ{Electric Potential}'
6
5
  class Term < Liner.new(:atom, :prefix, :factor, :exponent, :annotation)
7
- include Unitwise::Compatible
8
-
9
- # Setup a new term. Send a hash of properties, or ordered property values.
10
- # @api public
11
- def initialize(*args)
12
- super(*args)
13
- freeze
14
- end
6
+ include Compatible
15
7
 
16
8
  # Set the atom.
17
9
  # @param value [String, Atom] Either a string representing an Atom, or an
@@ -40,6 +32,7 @@ module Unitwise
40
32
  def depth
41
33
  atom ? atom.depth + 1 : 0
42
34
  end
35
+ memoize :depth
43
36
 
44
37
  # Determine if this is the last term in the scale chain
45
38
  # @return [true, false]
@@ -90,6 +83,7 @@ module Unitwise
90
83
  end
91
84
  end
92
85
  end
86
+ memoize :root_terms
93
87
 
94
88
  # Term multiplication. Multiply by a Unit, another Term, or a Numeric.
95
89
  # params other [Unit, Term, Numeric]
@@ -134,6 +128,7 @@ module Unitwise
134
128
  [(factor if factor != 1), prefix.to_s,
135
129
  atom.to_s, (exponent if exponent != 1)].compact.join('')
136
130
  end
131
+ memoize :to_s
137
132
 
138
133
  private
139
134
 
data/lib/unitwise/unit.rb CHANGED
@@ -4,7 +4,7 @@ module Unitwise
4
4
  # a magnitude, but it does have a scale.
5
5
  class Unit
6
6
  liner :expression, :terms
7
- include Unitwise::Compatible
7
+ include Compatible
8
8
 
9
9
  # Create a new unit. You can send an expression or a collection of terms
10
10
  # @param input [String, Unit, [Term]] A string expression, a unit, or a
@@ -17,32 +17,34 @@ module Unitwise
17
17
  @expression = input.to_s
18
18
  else
19
19
  @terms = input
20
+ @expression = Expression.compose(input)
20
21
  end
21
- end
22
-
23
- def expression
24
- @expression ||= (Expression.compose(@terms) if @terms)
22
+ freeze
25
23
  end
26
24
 
27
25
  def terms
28
- @terms ||= (Expression.decompose(@expression) if @expression)
26
+ @terms || Expression.decompose(expression)
29
27
  end
30
28
 
31
29
  def atoms
32
30
  terms.map(&:atom)
33
31
  end
32
+ memoize :atoms
34
33
 
35
34
  def special?
36
35
  terms.count == 1 && terms.all?(&:special?)
37
36
  end
37
+ memoize :special?
38
38
 
39
39
  def depth
40
40
  terms.map(&:depth).max + 1
41
41
  end
42
+ memoize :depth
42
43
 
43
44
  def root_terms
44
45
  terms.map(&:root_terms).flatten
45
46
  end
47
+ memoize :root_terms
46
48
 
47
49
  def scalar(magnitude = 1)
48
50
  terms.reduce(1) do |prod, term|
@@ -1,3 +1,3 @@
1
1
  module Unitwise
2
- VERSION = '0.6.1'
2
+ VERSION = '0.6.2'
3
3
  end
data/lib/unitwise.rb CHANGED
@@ -1,4 +1,8 @@
1
1
  require 'liner'
2
+ require 'memoizable'
3
+ require 'parslet'
4
+ require 'signed_multiset'
5
+ require 'yaml'
2
6
 
3
7
  require 'unitwise/version'
4
8
  require 'unitwise/base'
@@ -4,15 +4,15 @@ module ScaleTests
4
4
  base.class_eval do
5
5
  subject { described_class.new(4, "J") }
6
6
 
7
- let(:mph) { Unitwise::Measurement.new(60, '[mi_i]/h') }
8
- let(:kmh) { Unitwise::Measurement.new(100, 'km/h') }
9
- let(:mile) { Unitwise::Measurement.new(3, '[mi_i]') }
10
- let(:hpm) { Unitwise::Measurement.new(6, 'h/[mi_i]') }
11
- let(:cui) { Unitwise::Measurement.new(12, "[in_i]3") }
12
- let(:cel) { Unitwise::Measurement.new(22, 'Cel') }
13
- let(:k) { Unitwise::Measurement.new(373.15, 'K') }
14
- let(:f) { Unitwise::Measurement.new(98.6, '[degF]')}
15
- let(:r) { Unitwise::Measurement.new(491.67, '[degR]') }
7
+ let(:mph) { described_class.new(60, '[mi_i]/h') }
8
+ let(:kmh) { described_class.new(100, 'km/h') }
9
+ let(:mile) { described_class.new(3, '[mi_i]') }
10
+ let(:hpm) { described_class.new(6, 'h/[mi_i]') }
11
+ let(:cui) { described_class.new(12, "[in_i]3") }
12
+ let(:cel) { described_class.new(22, 'Cel') }
13
+ let(:k) { described_class.new(373.15, 'K') }
14
+ let(:f) { described_class.new(98.6, '[degF]')}
15
+ let(:r) { described_class.new(491.67, '[degR]') }
16
16
 
17
17
  describe "#new" do
18
18
  it "must set attributes" do
@@ -79,6 +79,12 @@ module ScaleTests
79
79
  end
80
80
  end
81
81
 
82
+ describe "#frozen?" do
83
+ it "must be frozen" do
84
+ subject.frozen?.must_equal true
85
+ end
86
+ end
87
+
82
88
  end
83
89
  end
84
90
  end
@@ -120,4 +120,10 @@ describe Unitwise::Atom do
120
120
  skip("need to figure out mocking and stubbing with minitest")
121
121
  end
122
122
  end
123
+
124
+ describe "#frozen?" do
125
+ it "should be frozen" do
126
+ second.frozen?.must_equal true
127
+ end
128
+ end
123
129
  end
@@ -117,13 +117,44 @@ describe Unitwise::Measurement do
117
117
  describe "#coerce" do
118
118
  let(:meter) { Unitwise::Measurement.new(1, 'm') }
119
119
  it "must coerce numerics" do
120
- meter.coerce(5).must_equal [ Unitwise::Measurement.new(5, '1'), meter ]
120
+ (5 * meter).must_equal Unitwise::Measurement.new(5, 'm')
121
121
  end
122
122
  it "should raise an error for other crap" do
123
123
  lambda { meter.coerce("foo") }.must_raise TypeError
124
124
  end
125
125
  end
126
126
 
127
+ describe "equality" do
128
+ let(:m) { Unitwise::Measurement.new(1,'m') }
129
+ let(:mm) { Unitwise::Measurement.new(1000,'mm') }
130
+ let(:foot) { Unitwise::Measurement.new(1,'foot') }
131
+ let(:g) { Unitwise::Measurement.new(1,'gram') }
132
+ it "should be ==" do
133
+ assert m == m
134
+ assert m == mm
135
+ refute m == foot
136
+ refute m == g
137
+ end
138
+ it "should be ===" do
139
+ assert m == m
140
+ assert m === mm
141
+ refute m === foot
142
+ refute m == g
143
+ end
144
+ it "should be equal?" do
145
+ assert m.equal?(m)
146
+ refute m.equal?(mm)
147
+ refute m.equal?(foot)
148
+ refute m.equal?(g)
149
+ end
150
+ it "should be eql?" do
151
+ assert m.eql?(m)
152
+ refute m.equal?(mm)
153
+ refute m.equal?(foot)
154
+ refute m.equal?(g)
155
+ end
156
+ end
157
+
127
158
  describe "#method_missing" do
128
159
  let(:meter) { Unitwise::Measurement.new(1, 'm')}
129
160
  it "must convert 'to_mm'" do
@@ -40,5 +40,10 @@ describe Unitwise::Term do
40
40
  end
41
41
  end
42
42
 
43
+ describe "#frozen?" do
44
+ it "should be frozen" do
45
+ subject.frozen?.must_equal true
46
+ end
47
+ end
43
48
  end
44
49
  end
@@ -50,16 +50,22 @@ describe Unitwise::Unit do
50
50
  describe "#*" do
51
51
  it "should multiply units" do
52
52
  mult = kg * ms2
53
- mult.expression.to_s.must_match /kg.*\/s2/
54
- mult.expression.to_s.must_match /m.*\/s2/
53
+ mult.expression.to_s.must_match(/kg.*\/s2/)
54
+ mult.expression.to_s.must_match(/m.*\/s2/)
55
55
  end
56
56
  end
57
57
 
58
58
  describe "#/" do
59
59
  it "should divide units" do
60
60
  div = kg / ms2
61
- div.expression.to_s.must_match /kg.*\/m/
62
- div.expression.to_s.must_match /s2.*\/m/
61
+ div.expression.to_s.must_match(/kg.*\/m/)
62
+ div.expression.to_s.must_match(/s2.*\/m/)
63
+ end
64
+ end
65
+
66
+ describe "#frozen?" do
67
+ it "should be frozen" do
68
+ kg.frozen?.must_equal true
63
69
  end
64
70
  end
65
71
 
data/unitwise.gemspec CHANGED
@@ -8,11 +8,11 @@ Gem::Specification.new do |gem|
8
8
  gem.version = Unitwise::VERSION
9
9
  gem.authors = ['Josh Lewis']
10
10
  gem.email = ['josh.w.lewis@gmail.com']
11
- gem.description = 'Ruby implementation of the Unified Code for Units of ' \
12
- 'Measure (UCUM)'
13
- gem.summary = 'Unitwise is a library for performing mathematical '\
14
- 'operations and conversions on all units defined by '\
15
- 'the Unified Code for Units of Measure(UCUM).'
11
+ gem.description = 'Physical quantity and units of measure conversion ' \
12
+ 'and math library'
13
+ gem.summary = 'Convert between and perform mathematical operations ' \
14
+ 'on physical quantities and units of measure defined ' \
15
+ 'by the Unified Code for Units of Measure.'
16
16
  gem.homepage = 'http://github.com/joshwlewis/unitwise'
17
17
  gem.license = 'MIT'
18
18
 
@@ -20,19 +20,21 @@ Gem::Specification.new do |gem|
20
20
  gem.test_files = gem.files.grep(/^test\//)
21
21
  gem.require_paths = ['lib']
22
22
 
23
- gem.add_dependency 'liner', '~> 0.2.4'
24
- gem.add_dependency 'signed_multiset', '~> 0.2.0'
23
+ gem.add_dependency 'liner', '~> 0.2'
24
+ gem.add_dependency 'signed_multiset', '~> 0.2'
25
+ gem.add_dependency 'memoizable', '~> 0.4'
25
26
 
26
27
  if RUBY_VERSION > '1.8.7'
27
- gem.add_dependency 'parslet', '~> 1.5'
28
- gem.add_development_dependency 'nokogiri', '~> 1.5'
29
- gem.add_development_dependency 'coveralls', '~> 0.6'
28
+ gem.add_dependency 'parslet', '~> 1.5'
29
+ gem.add_development_dependency 'nokogiri', '~> 1.5'
30
+ gem.add_development_dependency 'coveralls', '~> 0.6'
30
31
  else
31
- gem.add_dependency 'parslet', '~> 1.5.0'
32
- gem.add_development_dependency 'nokogiri', '~> 1.5.10'
32
+ gem.add_dependency 'parslet', '~> 1.5.0'
33
+ gem.add_development_dependency 'nokogiri', '~> 1.5.10'
33
34
  end
34
35
 
35
- gem.add_development_dependency 'minitest', '>= 5.0'
36
- gem.add_development_dependency 'rake', '>= 10.0'
37
- gem.add_development_dependency 'nori', '~> 2.3'
36
+ gem.add_development_dependency 'pry', '~> 0.9'
37
+ gem.add_development_dependency 'minitest', '~> 5.0'
38
+ gem.add_development_dependency 'rake', '~> 10.0'
39
+ gem.add_development_dependency 'nori', '~> 2.3'
38
40
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unitwise
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Lewis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-19 00:00:00.000000000 Z
11
+ date: 2014-06-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: liner
@@ -16,28 +16,42 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.2.4
19
+ version: '0.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.2.4
26
+ version: '0.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: signed_multiset
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.2.0
33
+ version: '0.2'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.2.0
40
+ version: '0.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: memoizable
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.4'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.4'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: parslet
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -80,32 +94,46 @@ dependencies:
80
94
  - - "~>"
81
95
  - !ruby/object:Gem::Version
82
96
  version: '0.6'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.9'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.9'
83
111
  - !ruby/object:Gem::Dependency
84
112
  name: minitest
85
113
  requirement: !ruby/object:Gem::Requirement
86
114
  requirements:
87
- - - ">="
115
+ - - "~>"
88
116
  - !ruby/object:Gem::Version
89
117
  version: '5.0'
90
118
  type: :development
91
119
  prerelease: false
92
120
  version_requirements: !ruby/object:Gem::Requirement
93
121
  requirements:
94
- - - ">="
122
+ - - "~>"
95
123
  - !ruby/object:Gem::Version
96
124
  version: '5.0'
97
125
  - !ruby/object:Gem::Dependency
98
126
  name: rake
99
127
  requirement: !ruby/object:Gem::Requirement
100
128
  requirements:
101
- - - ">="
129
+ - - "~>"
102
130
  - !ruby/object:Gem::Version
103
131
  version: '10.0'
104
132
  type: :development
105
133
  prerelease: false
106
134
  version_requirements: !ruby/object:Gem::Requirement
107
135
  requirements:
108
- - - ">="
136
+ - - "~>"
109
137
  - !ruby/object:Gem::Version
110
138
  version: '10.0'
111
139
  - !ruby/object:Gem::Dependency
@@ -122,7 +150,7 @@ dependencies:
122
150
  - - "~>"
123
151
  - !ruby/object:Gem::Version
124
152
  version: '2.3'
125
- description: Ruby implementation of the Unified Code for Units of Measure (UCUM)
153
+ description: Physical quantity and units of measure conversion and math library
126
154
  email:
127
155
  - josh.w.lewis@gmail.com
128
156
  executables: []
@@ -209,8 +237,8 @@ rubyforge_project:
209
237
  rubygems_version: 2.2.0
210
238
  signing_key:
211
239
  specification_version: 4
212
- summary: Unitwise is a library for performing mathematical operations and conversions
213
- on all units defined by the Unified Code for Units of Measure(UCUM).
240
+ summary: Convert between and perform mathematical operations on physical quantities
241
+ and units of measure defined by the Unified Code for Units of Measure.
214
242
  test_files:
215
243
  - test/support/scale_tests.rb
216
244
  - test/test_helper.rb