dkastner-alchemist 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/gempackagetask'
4
+
5
+ task :default => [:test]
6
+ task :test => ['test:units']
7
+
8
+ namespace :test do
9
+ Rake::TestTask.new(:units) do |test|
10
+ test.libs << 'test'
11
+ test.ruby_opts << '-rubygems'
12
+ test.pattern = 'test/*.rb'
13
+ test.verbose = true
14
+ end
15
+ end
16
+
17
+ eval("$specification = begin; #{IO.read('alchemist.gemspec')}; end")
18
+ Rake::GemPackageTask.new($specification) do |package|
19
+ package.need_zip = true
20
+ package.need_tar = true
21
+ end
data/lib/alchemist.rb ADDED
@@ -0,0 +1,99 @@
1
+ require 'alchemist/conversion_table'
2
+ require 'alchemist/compound_numeric_conversion'
3
+ require 'alchemist/numeric_conversion'
4
+ require 'alchemist/numeric_ext'
5
+ require 'alchemist/unit_prefixes'
6
+
7
+ module Alchemist
8
+ Conversions = {}
9
+
10
+ @use_si = false
11
+ class << self
12
+ attr_accessor :use_si
13
+ end
14
+
15
+ @@si_units = %w[m meter metre meters metres liter litre litres liters l L farad farads F coulombs C gray grays Gy siemen siemens S mhos mho ohm ohms volt volts V ]
16
+ @@si_units += %w[joule joules J newton newtons N lux lx henry henrys H b B bits bytes bit byte lumen lumens lm candela candelas cd]
17
+ @@si_units += %w[tesla teslas T gauss Gs G gram gramme grams grammes g watt watts W pascal pascals Pa]
18
+ @@si_units += %w[becquerel becquerels Bq curie curies Ci]
19
+
20
+ def self.unit_prefixes
21
+ @@unit_prefixes ||= UnitPrefixes.default
22
+ end
23
+
24
+ def self.conversion_table
25
+ @@conversion_table ||= ConversionTable.default
26
+ end
27
+
28
+ def self.operator_actions
29
+ @@operator_actions ||= {}
30
+ end
31
+
32
+ def self.type(measurement)
33
+ convos = Conversions[base(measurement)]
34
+ convos ? convos.first : nil
35
+ end
36
+
37
+ def self.convertable_units(unit)
38
+ list = conversion_table[type(unit)]
39
+ list ? list.keys - [unit] : nil
40
+ end
41
+
42
+ def self.convertable?(*units)
43
+ raise ArgumentError.new('You need specify at least two units') if units.length < 2
44
+
45
+ units.each do |unit_a|
46
+ type_a = type(unit_a)
47
+ units.each do |unit_b|
48
+ return false if type_a != type(unit_b)
49
+ end
50
+ end
51
+
52
+ true
53
+ end
54
+
55
+ conversion_table.each do |type, conversions|
56
+ conversions.each do |name, value|
57
+ Conversions[name] ||= []
58
+ Conversions[name] << type
59
+ end
60
+ end
61
+
62
+ def self.register(type, names, value)
63
+ names = [names] unless names.is_a?(Array)
64
+ value = value.is_a?(NumericConversion) ? value.base(type) : value
65
+ Alchemist.conversion_table[type] ||= {}
66
+ names.each do |name|
67
+ Conversions[name] ||= []
68
+ Conversions[name] << type
69
+ Alchemist.conversion_table[type][name] = value
70
+ end
71
+ end
72
+
73
+ def self.register_operation_conversions type, other_type, operation, converted_type
74
+ operator_actions[operation] ||= []
75
+ operator_actions[operation] << [type, other_type, converted_type]
76
+ end
77
+
78
+ def self.parse_prefix(unit)
79
+ unit_prefixes.each do |prefix, value|
80
+ if unit.to_s =~ /^#{prefix}.+/ && @@si_units.include?(unit.to_s.gsub(/^#{prefix}/,''))
81
+ if !(Conversions[ unit.to_s.gsub(/^#{prefix}/,'').to_sym ] & [ :information_storage ]).empty? && !@use_si && value >= 1000.0 && value.to_i & -value.to_i != value
82
+ value = 2 ** (10 * (Math.log(value) / Math.log(10)) / 3)
83
+ end
84
+ return [value, unit.to_s.gsub(/^#{prefix}/,'').to_sym]
85
+ end
86
+ end
87
+ [1.0, unit]
88
+ end
89
+
90
+ def self.base(unit)
91
+ parse_prefix(unit).last
92
+ end
93
+ end
94
+
95
+ class Numeric
96
+ include Alchemist::NumericExt
97
+ end
98
+
99
+ require 'alchemist/compound'
@@ -0,0 +1,6 @@
1
+ Alchemist.register_operation_conversions(:distance, :distance, :*, :square_meters)
2
+ Alchemist.register_operation_conversions(:area, :distance, :*, :cubic_meters)
3
+ Alchemist.register_operation_conversions(:distance, :area, :*, :cubic_meters)
4
+ Alchemist.register_operation_conversions(:area, :distance, :/, :meters)
5
+ Alchemist.register_operation_conversions(:volume, :distance, :/, :square_meters)
6
+ Alchemist.register_operation_conversions(:volume, :area, :/, :meters)
@@ -0,0 +1,53 @@
1
+ module Alchemist
2
+ class CompoundNumericConversion
3
+ attr_accessor :numerators, :denominators
4
+ def initialize(numerator)
5
+ @coefficient = 1 #* numerator.to_f
6
+ @numerators = [numerator]
7
+ @denominators = []
8
+ end
9
+ def *(value)
10
+ case value
11
+ when Numeric
12
+ @coefficient *= value
13
+ self
14
+ when Alchemist::NumericConversion
15
+ @numerators << value
16
+ return consolidate
17
+ end
18
+ end
19
+
20
+ def consolidate
21
+ @numerators.each_with_index do |numerator, n|
22
+ @denominators.each_with_index do |denominator, d|
23
+ next if numerator.is_a?(Numeric)
24
+ next if denominator.is_a?(Numeric)
25
+ if (Conversions[numerator.unit_name] & Conversions[denominator.unit_name]).length > 0
26
+ value = numerator / denominator
27
+ @numerators.delete_at(n)
28
+ @denominators.delete_at(d)
29
+ @coefficient *= value
30
+ end
31
+ end
32
+ end
33
+ if @denominators.length == 0 && @numerators.length == 1
34
+ @numerators[0] * @coefficient
35
+ elsif @denominators.length == 0 && @numerators.length == 0
36
+ @coefficient
37
+ else
38
+ self
39
+ end
40
+ end
41
+
42
+ def to_s
43
+
44
+ end
45
+
46
+ def method_missing(method, *attrs, &block)
47
+ if Conversions[method]
48
+ @denominators << 1.send(method)
49
+ consolidate
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,296 @@
1
+ module Alchemist
2
+ module ConversionTable
3
+ def self.default
4
+ {
5
+ :absorbed_radiation_dose => {
6
+ :gray => 1.0, :grays => 1.0, :Gy => 1.0,
7
+ :rad => 1.0e-2, :rads => 1.0e-2
8
+ },
9
+ :angles => {
10
+ :radian => 1.0, :radians => 1.0,
11
+ :degree => Math::PI / 180.0, :degrees => Math::PI / 180.0,
12
+ :arcminute => Math::PI / 10800.0, :arcminutes => Math::PI / 10800.0,
13
+ :arcsecond => Math::PI / 648000.0, :arcseconds => Math::PI / 648000.0,
14
+ :mil => 9.817477e-4, :mils => 9.817477e-4,
15
+ :revolution => Math::PI * 2.0, :revolutions => Math::PI * 2.0,
16
+ :circle => Math::PI * 2.0, :circles => Math::PI * 2.0,
17
+ :right_angle => Math::PI / 2.0, :right_angles => Math::PI / 2.0,
18
+ :grad => Math::PI / 200.0, :grade => Math::PI / 200.0, :gradian => Math::PI / 200.0, :gon => Math::PI / 200.0, :grads => Math::PI / 200.0, :grades => Math::PI / 200.0, :gradians => Math::PI / 200.0, :gons => Math::PI / 200.0,
19
+ #unusual measurements
20
+ :furman => 9.58737992858887e-5, :furmans => 9.58737992858887e-5
21
+ },
22
+ :area => {
23
+ :square_meter => 1.0, :square_meters => 1.0, :square_metre => 1.0, :square_metres => 1.0,
24
+ :acre => 4046.85642, :acres => 4046.85642,
25
+ :are => 1.0e+2, :ares => 1.0e+2, :a => 1.0e+2,
26
+ :barn => 1.0e-28, :barns => 1.0e-28, :b => 1.0e-28,
27
+ :circular_mil => 5.067075e-10, :circular_mils => 5.067075e-10,
28
+ :hectare => 1.0e+4, :hectares => 1.0e+4, :ha => 1.0e+4,
29
+ :square_foot => 9.290304e-2, :square_feet => 9.290304e-2,
30
+ :square_inch => 6.4516e-4, :square_inches => 6.4516e-4,
31
+ :square_mile => 2.589988e+6, :square_miles => 2.589988e+6,
32
+ :square_yard => 0.83612736, :square_yards => 0.83612736
33
+ },
34
+ :capacitance => {
35
+ :farad => 1.0, :farads => 1.0, :F => 1.0,
36
+ :abfarad => 1.0e+9, :emu_of_capacitance => 1.0e+9, :abfarads => 1.0e+9, :emus_of_capacitance => 1.0e+9,
37
+ :statfarad => 1.112650e-12, :esu_of_capacitance => 1.112650e-12, :statfarads => 1.112650e-12, :esus_of_capacitance => 1.112650e-12
38
+ },
39
+ :density => {
40
+ :specific_gravity => 1, :sg => 1,
41
+ :brix => [Proc.new{ |d| -261.3 / (d - 261.3) }, Proc.new{ |d| 261.3 - (261.3 / d) }],
42
+ :plato => [Proc.new{ |d| -260.0 / (d - 260.0) }, Proc.new{ |d| 260.0 - (260.0 / d) }],
43
+ :baume => [Proc.new{ |d| -145.0 / (d - 145.0) }, Proc.new{ |d| 145.0 - (145.0 / d) }]
44
+ },
45
+ :distance => {
46
+ :meter => 1.0, :metres => 1.0, :meters => 1.0, :m => 1.0,
47
+ :fermi => 1.0e-15, :fermis => 1.0e-15,
48
+ :micron => 1.0e-6, :microns => 1.0e-6,
49
+ :chain => 20.1168, :chains => 20.1168,
50
+ :inch => 25.4e-3, :inches => 25.4e-3, :in => 25.4e-3,
51
+ :microinch => 2.54e-8, :microinches => 2.54e-8,
52
+ :mil => 2.54e-05, :mils => 2.54e-05,
53
+ :rod => 5.029210, :rods => 5.029210,
54
+ :league => 5556, :leagues => 5556,
55
+ :foot => 0.3048, :feet => 0.3048, :ft => 0.3048,
56
+ :yard => 0.9144, :yards => 0.9144, :yd => 0.9144,
57
+ :mile =>1609.344, :miles =>1609.344, :mi => 1609.344,
58
+ :astronomical_unit => 149.60e+9, :astronomical_units => 149.60e+9, :au => 149.60e+9, :ua => 149.60e+9,
59
+ :light_year => 9.461e+15, :light_years => 9.461e+15, :ly => 9.461e+15,
60
+ :parsec => 30.857e+15, :parsecs => 30.857e+15,
61
+ :nautical_mile => 1852.0, :nautical_miles => 1852.0,
62
+ :admirality_mile => 185.3184, :admirality_miles => 185.3184,
63
+ :fathom => 1.8288, :fathoms => 1.8288,
64
+ :cable_length => 185.2, :cable_lengths => 185.2,
65
+ :angstrom => 100.0e-12, :angstroms => 100.0e-12,
66
+ :pica => 4.233333e-3, :picas => 4.233333e-3,
67
+ :printer_pica => 4.217518e-3, :printer_picas => 4.217518e-3,
68
+ :point => 3.527778e-4, :points => 3.527778e-4,
69
+ :printer_point => 3.514598e-4, :printer_points => 3.514598e-4,
70
+ # unusual mesaurements
71
+ :empire_state_building => 449.0, :empire_state_buildings => 449.0,
72
+ :sears_tower => 519.0, :sears_towers => 519.0,
73
+ :seattle_space_needle => 184.0, :seattle_space_needles => 184.0, :space_needle => 184.0, :space_needles => 184.0,
74
+ :statue_of_liberty => 46.0, :statue_of_liberties => 46.0,
75
+ :washington_monument => 169.294, :washington_monuments => 169.294,
76
+ :eiffel_tower => 324.0, :eiffel_towers => 324.0,
77
+ :nelsons_column => 61.5, :nelsons_columns => 61.5,
78
+ :blackpool_tower => 158.0, :blackpool_towers => 158.0,
79
+ :big_ben => 96.3, :big_bens => 96.3, :clock_tower_of_the_palace_of_westminster => 96.3, :clock_towers_of_the_palace_of_westminster => 96.3,
80
+ :st_pauls_cathedral => 108.0, :st_pauls_cathedrals => 108.0,
81
+ :toronto_cn_tower => 553.0, :toronto_cn_towers => 553.0, :cn_tower => 553.0, :cn_towers => 553.0,
82
+ :circle_of_the_earth => 40075016.686, :equator => 40075016.686, :circles_of_the_earth => 40075016.686, :equators => 40075016.686,
83
+ :siriometer => 1.494838e+17, :siriometers => 1.494838e+17,
84
+ :football_field => 91.0, :football_fields => 91.0,
85
+ :length_of_a_double_decker_bus => 8.4, :height_of_a_double_decker_bus => 4.4,
86
+ :smoot => 1.7018, :smoots => 1.7018
87
+ },
88
+ :dose_equivalent => {
89
+ :sievert => 1.0, :sieverts => 1.0, :Si => 1.0,
90
+ :rem => 1.0e-2, :rems => 1.0e-2
91
+ },
92
+ :electric_charge => {
93
+ :coulomb => 1.0, :coulombs => 1.0, :C => 1.0,
94
+ :abcoulomb => 10.0, :abcoulombs => 10.0,
95
+ :ampere_hour => 3.6e+3, :ampere_hours => 3.6e+3,
96
+ :faraday => 9.648534e+4, :faradays => 9.648534e+4,
97
+ :franklin => 3.335641e-10, :franklins => 3.335641e-10, :Fr => 3.335641e-10,
98
+ :statcoulomb => 3.335641e-10, :statcoulombs => 3.335641e-10
99
+ },
100
+ :electric_conductance => {
101
+ :siemen => 1.0, :siemens => 1.0, :S => 1.0, :mho => 1.0,
102
+ :abmho => 1.0e+9, :absiemen => 1.0e+9, :absiemens => 1.0e+9,
103
+ :statmho => 1.112650e-12, :statsiemen => 1.112650e-12, :statsiemens => 1.112650e-12
104
+ },
105
+ :electrical_impedance => {
106
+ :ohm => 1.0, :ohms => 1.0,
107
+ :abohm => 1.0e-9, :emu_of_resistance => 1.0e-9, :abohms => 1.0e-9, :emus_of_resistance => 1.0e-9,
108
+ :statohm => 8.987552e+11, :esu_of_resistance => 8.987552e+11, :statohms => 8.987552e+11, :esus_of_resistance => 8.987552e+11
109
+ },
110
+ :electromotive_force => {
111
+ :volt => 1.0, :volts => 1.0, :V => 1.0,
112
+ :abvolt => 1.0e-8, :emu_of_electric_potential => 1.0e-8, :abvolts => 1.0e-8, :emus_of_electric_potential => 1.0e-8,
113
+ :statvolt => 2.997925e+2, :esu_of_electric_potential => 2.997925e+2, :statvolts => 2.997925e+2, :esus_of_electric_potential => 2.997925e+2
114
+ },
115
+ :energy => {
116
+ :joule => 1.0, :joules => 1.0, :J => 1.0, :watt_second => 1.0, :watt_seconds => 1.0,
117
+ :watt_hour => 3.6e+3, :watt_hours => 3.6e+3,
118
+ :ton_of_tnt => 4.184e+9, :tons_of_tnt => 4.184e+9,
119
+ :therm => 1.05506e+8, :therms => 1.05506e+8,
120
+ :us_therm => 1.054804e+8, :us_therms => 1.054804e+8,
121
+ :kilowatt_hour => 3.6e+6, :kilowatt_hours => 3.6e+6,
122
+ :kilocalorie => 4184.0, :kilocalories => 4184.0,
123
+ :calorie => 4.184, :calories => 4.184,
124
+ :mean_kilocalorie => 4190, :mean_kilocalories => 4190,
125
+ :mean_calorie => 4.190, :mean_calories => 4.190,
126
+ :it_kilocalorie => 4186.8, :it_kilocalories => 4186.8,
127
+ :it_calorie => 4.1868, :it_calories => 4.1868,
128
+ :foot_poundal => 4.214011e-2, :foot_poundals => 4.214011e-2,
129
+ :foot_pound_force => 1.355818,
130
+ :erg => 1.0e-7, :ergs => 1.0e-7,
131
+ :electronvolt => 1.602176e-19, :electronvolts => 1.602176e-19, :eV => 1.602176e-19,
132
+ :british_thermal_unit => 1.054350e+3, :british_thermal_units => 1.054350e+3,
133
+ :mean_british_thermal_unit => 1.05587e+3, :mean_british_thermal_units => 1.05587e+3,
134
+ :it_british_thermal_unit => 1.055056e+3, :it_british_thermal_units => 1.055056e+3,
135
+ #unusual measurements
136
+ :foe => 1e+44, :foes => 1e+44
137
+ },
138
+ :force => {
139
+ :newton => 1.0, :newtons => 1.0, :N => 1.0,
140
+ :dyne => 1.0e-5, :dynes => 1.0e-5, :dyn => 1.0e-5,
141
+ :kilogram_force => 9.80665, :kgf => 9.80665, :kilopond => 9.80665, :kiloponds => 9.80665, :kp => 9.80665,
142
+ :kip => 4.448222e+3, :kips => 4.448222e+3,
143
+ :ounce_force => 2.780139e-1, :ozf => 2.780139e-1,
144
+ :poundal => 1.382550e-1, :poundals => 1.382550e-1,
145
+ :pound_force => 4.448222, :lbf => 4.448222,
146
+ :ton_force => 8.896443e+3
147
+ },
148
+ :illuminance => {
149
+ :lux => 1.0, :lx => 1.0, :lumens_per_square_metre => 1.0, :lumens_per_square_meter => 1.0, :lumen_per_square_metre => 1.0, :lumen_per_square_meter => 1.0,
150
+ :phot => 1.0e+4, :phots => 1.0e+4, :ph => 1.0e+4,
151
+ :lumens_per_square_foot => 10.76391, :footcandle => 10.76391, :lumen_per_square_foot => 10.76391, :footcandles => 10.76391
152
+ },
153
+ :inductance => {
154
+ :henry => 1.0, :henrys => 1.0, :H => 1.0,
155
+ :abhenrys => 1.0e-9, :emus_of_inductance => 1.0e-9, :abhenry => 1.0e-9, :emu_of_inductance => 1.0e-9,
156
+ :stathenrys => 8.987552e+11, :esus_of_inductance => 8.987552e+11, :stathenry => 8.987552e+11, :esu_of_inductance => 8.987552e+11
157
+ },
158
+ :information_storage => {
159
+ :bit => 1.0, :bits => 1.0, :b => 1.0,
160
+ :byte => 8.0, :bytes => 8.0, :B => 8.0,
161
+ :nibbles => 4.0, :nybbles => 4.0
162
+ },
163
+ :luminous_flux => {
164
+ :lumen => 1.0, :lumens => 1.0, :lm => 1.0
165
+ },
166
+ :luminous_intensity => {
167
+ :candela => 1.0, :candelas => 1.0, :cd => 1.0
168
+ },
169
+ :magnetic_flux => {
170
+ :webers => 1.0, :Wb => 1.0,
171
+ :maxwells => 1.0e-8, :Mx => 1.0e-8,
172
+ :unit_poles => 1.256637e-7
173
+ },
174
+ :magnetic_inductance => {
175
+ :tesla => 1.0, :teslas => 1.0, :T => 1.0,
176
+ :gamma => 1.0e-9, :gammas => 1.0e-9,
177
+ :gauss => 1.0e-4, :Gs => 1.0e-4, :G => 1.0e-4
178
+ },
179
+ :mass => {
180
+ :gram => 1.0, :gramme => 1.0, :grams => 1.0, :grammes => 1.0, :g => 1.0,
181
+ :carat => 2.0e-1, :carats => 2.0e-1,
182
+ :ounce => 2.834952e+1, :ounces => 2.834952e+1, :oz => 2.834952e+1,
183
+ :pennyweight => 1.555174, :pennyweights => 1.555174, :dwt => 1.555174,
184
+ :pound => 453.59237, :pounds => 453.59237, :lb => 453.59237, :lbs => 453.59237,
185
+ :troy_pound => 373.2417, :apothecary_pound => 373.2417, :troy_pounds => 373.2417, :apothecary_pounds => 373.2417,
186
+ :slug => 14593.9029, :slugs => 14593.9029,
187
+ :assay_ton => 29.1667, :assay_tons => 29.1667, :AT => 29.1667,
188
+ :metric_ton => 1000000, :metric_tons => 1000000,
189
+ :ton => 907184.74, :tons => 907184.74, :short_tons => 907184.74,
190
+ #unusual measurements
191
+ :elephant => 5443108.44, :elephants => 5443108.44
192
+ },
193
+ :power => {
194
+ :watt => 1.0, :watts => 1.0, :W => 1.0,
195
+ :british_thermal_unit_per_hour => 2.928751e-1, :british_thermal_units_per_hour => 2.928751e-1,
196
+ :it_british_thermal_unit_per_hour => 2.930711e-1, :it_british_thermal_units_per_hour => 2.930711e-1,
197
+ :british_thermal_unit_per_second => 1.054350e+3, :british_thermal_units_per_second => 1.054350e+3,
198
+ :it_british_thermal_unit_per_second => 1.055056e+3, :it_british_thermal_units_per_second => 1.055056e+3,
199
+ :calorie_per_minute => 6.973333e-2, :calories_per_minute => 6.973333e-2,
200
+ :calorie_per_second => 4.184, :calories_per_second => 4.184,
201
+ :erg_per_second => 1.0e-7, :ergs_per_second => 1.0e-7,
202
+ :foot_pound_force_per_hour => 3.766161e-4,
203
+ :foot_pound_force_per_minute => 2.259697e-2,
204
+ :foot_pound_force_per_second => 1.355818,
205
+ :horsepower => 7.456999e+2,
206
+ :boiler_horsepower => 9.80950e+3,
207
+ :electric_horsepower => 7.46e+2,
208
+ :metric_horsepower => 7.354988e+2,
209
+ :uk_horsepower => 7.4570e+2,
210
+ :water_horsepower => 7.46043e+2,
211
+ :kilocalorie_per_minute => 6.973333*10, :kilocalories_per_minute => 6.973333*10,
212
+ :kilocalorie_per_second => 4.184e+3, :kilocalories_per_second => 4.184e+3,
213
+ :ton_of_refrigeration => 3.516853e+3, :tons_of_refrigeration => 3.516853e+3
214
+ },
215
+ :pressure => {
216
+ :pascal => 1.0, :pascals => 1.0, :Pa => 1.0,
217
+ :atmosphere => 1.01325e+5, :atmospheres => 1.01325e+5,
218
+ :technical_atmosphere => 9.80665e+4, :technical_atmospheres => 9.80665e+4,
219
+ :bar => 1.0e+5, :bars => 1.0e+5,
220
+ :centimeter_of_mercury => 1.333224e+3, :centimeters_of_mercury => 1.333224e+3,
221
+ :centimeter_of_water => 98.0665, :centimeters_of_water => 98.0665, :gram_force_per_square_centimeter => 98.0665,
222
+ :dyne_per_square_centimeter => 1.0e-1, :dynes_per_square_centimeter => 1.0e-1,
223
+ :foot_of_mercury => 4.063666e+4, :feet_of_mercury => 4.063666e+4,
224
+ :foot_of_water => 2.989067e+3, :feet_of_water => 2.989067e+3,
225
+ :inch_of_mercury => 3.386389e+3, :inches_of_mercury => 3.386389e+3,
226
+ :inch_of_water => 2.490889e+2, :inches_of_water => 2.490889e+2,
227
+ :kilogram_force_per_square_centimeter => 9.80665e+4,
228
+ :kilogram_force_per_square_meter => 9.80665,
229
+ :kilogram_force_per_square_millimeter => 9.80665e+6,
230
+ :kip_per_square_inch => 6.894757e+6, :kips_per_square_inch => 6.894757e+6, :ksi => 6.894757e+6,
231
+ :millibar => 1.0e+2, :mbar => 1.0e+2, :millibars => 1.0e+2, :mbars => 1.0e+2,
232
+ :millimeter_of_mercury => 1.333224e+2, :millimeters_of_mercury => 1.333224e+2,
233
+ :millimeter_of_water => 9.80665, :millimeters_of_water => 9.80665,
234
+ :poundal_per_square_foot => 1.488164, :poundals_per_square_foot => 1.488164,
235
+ :pound_force_per_square_foot => 47.88026,
236
+ :pound_force_per_square_inch => 6.894757e+3, :psi => 6.894757e+3,
237
+ :torr => 1.333224e+2, :torrs => 1.333224e+2
238
+ },
239
+ :radioactivity => {
240
+ :becquerel => 1.0, :becquerels => 1.0, :Bq => 1.0,
241
+ :curie => 3.7e+10, :curies => 3.7e+10, :Ci => 3.7e+10
242
+ },
243
+ :temperature => {
244
+ :kelvin => 1.0, :K => 1.0,
245
+
246
+ :celsius => [Proc.new{ |t| t + 273.15 }, Proc.new{ |t| t - 273.15 }], :centrigrade => [Proc.new{ |t| t + 273.15 }, Proc.new{ |t| t - 273.15 }],
247
+ :degree_celsius => [Proc.new{ |t| t + 273.15 }, Proc.new{ |t| t - 273.15 }], :degree_centrigrade => [Proc.new{ |t| t + 273.15 }, Proc.new{ |t| t - 273.15 }],
248
+ :degrees_celsius => [Proc.new{ |t| t + 273.15 }, Proc.new{ |t| t - 273.15 }], :degrees_centrigrade => [Proc.new{ |t| t + 273.15 }, Proc.new{ |t| t - 273.15 }],
249
+ :fahrenheit => [Proc.new{ |t| (t + 459.67) * (5.0/9.0) }, Proc.new{ |t| t * (9.0/5.0) - 459.67 }],
250
+ :degree_fahrenheit => [Proc.new{ |t| (t + 459.67) * (5.0/9.0) }, Proc.new{ |t| t * (9.0/5.0) - 459.67 }],
251
+ :degrees_fahrenheit => [Proc.new{ |t| (t + 459.67) * (5.0/9.0) }, Proc.new{ |t| t * (9.0/5.0) - 459.67 }],
252
+ :rankine => 1.8, :rankines => 1.8
253
+ },
254
+ :time => {
255
+ :second => 1.0, :seconds => 1.0, :s => 1.0,
256
+ :minute => 60.0, :minutes => 60.0, :min => 60.0,
257
+ :sidereal_minute => 5.983617, :sidereal_minutes => 5.983617,
258
+ :hour => 3600.0, :hours => 3600.0, :hr => 3600.0, :h => 3600.0,
259
+ :sidereal_hour => 3.590170e+3, :sidereal_hours => 3.590170e+3,
260
+ :day => 86400.0, :days => 86400.0,
261
+ :sidereal_day => 8.616409e+4, :sidereal_days => 8.616409e+4,
262
+ :shake => 1.0e-8, :shakes => 1.0e-8,
263
+ :year => 3.1536e+7, :years => 3.1536e+7,
264
+ :sidereal_year => 3.155815e+7, :sidereal_years => 3.155815e+7,
265
+ :tropical_year => 3.155693e+7, :tropical_years => 3.155693e+7,
266
+ #unusual measurements
267
+ :jiffy => 0.01, :jiffies => 0.01,
268
+ :microfortnight => 1.2096, :microfortnights => 1.2096,
269
+ :megaannum => 3.1536e+16, :Ma => 3.1536e+16, :megaannums => 3.1536e+16,
270
+ :galactic_year => 7.884e+18, :galactic_years => 7.884e+18, :GY => 7.884e+18
271
+ },
272
+ :volume => {
273
+ :litre => 1.0, :liter => 1.0, :litres => 1.0, :liters => 1.0, :l => 1.0, :L => 1.0,
274
+ :barrel => 1.589873e+2, :barrels => 1.589873e+2,
275
+ :bushel => 3.523907e+1, :bushels => 3.523907e+1,
276
+ :cubic_meter => 1000.0, :cubic_meters => 1000.0,
277
+ :cup => 2.365882e-1, :cups => 2.365882e-1,
278
+ :imperial_fluid_ounce => 0.0284130742, :imperial_fluid_ounces => 0.0284130742,
279
+ :ounce => 0.0295735296, :ounces => 0.0295735296, :fluid_ounce => 0.0295735296, :fluid_ounces => 0.0295735296,
280
+ :imperial_gallon => 4.54609, :imperial_gallons => 4.54609,
281
+ :gallon => 3.785412, :gallons => 3.785412, :gals => 3.785412, :Gals => 3.785412,
282
+ :imperial_gill => 1.420653e-1, :imperial_gills => 1.420653e-1,
283
+ :gill => 1.182941e-1, :gills => 1.182941e-1, :gi => 1.182941e-1,
284
+ :pint => 5.506105e-1, :pints => 5.506105e-1,
285
+ :liquid_pint => 4.731765e-1, :liquid_pints => 4.731765e-1,
286
+ :quart => 1.101221, :quarts => 1.101221,
287
+ :liquid_quart => 9.463529e-1, :liquid_quarts => 9.463529e-1,
288
+ :tablespoon => 0.0147867648, :tablespoons => 0.0147867648,
289
+ :teaspoon => 0.00492892159, :teaspoons => 0.00492892159,
290
+ #unusual measurements
291
+ :sydharb => 5.0e+11, :sydharbs => 5.0e+11
292
+ }
293
+ }
294
+ end
295
+ end
296
+ end
@@ -0,0 +1,103 @@
1
+ module Alchemist
2
+ class NumericConversion
3
+ include Comparable
4
+
5
+ def per
6
+ Alchemist::CompoundNumericConversion.new(self)
7
+ end
8
+
9
+ def p
10
+ per
11
+ end
12
+
13
+ def to(type = nil)
14
+ unless type
15
+ self
16
+ else
17
+ send(type)
18
+ end
19
+ end
20
+ alias_method :as, :to
21
+
22
+ def base(unit_type)
23
+ if(Alchemist.conversion_table[unit_type][@unit_name].is_a?(Array))
24
+ @exponent * Alchemist.conversion_table[unit_type][@unit_name][0].call(@value)
25
+ else
26
+ @exponent * @value * Alchemist.conversion_table[unit_type][@unit_name]
27
+ end
28
+ end
29
+
30
+ def unit_name
31
+ @unit_name
32
+ end
33
+
34
+ def to_s
35
+ @value.to_s
36
+ end
37
+
38
+ def value
39
+ @value
40
+ end
41
+
42
+ def to_f
43
+ @value
44
+ end
45
+
46
+ def ==(other)
47
+ self <=> other
48
+ end
49
+
50
+ def <=>(other)
51
+ other.respond_to?(:to) && (self.to_f * @exponent).to_f <=> other.to(@unit_name).to_f
52
+ end
53
+
54
+ private
55
+ def initialize value, unit_name, exponent = 1.0
56
+ @value = value.to_f
57
+ @unit_name = unit_name
58
+ @exponent = exponent
59
+ end
60
+
61
+ def method_missing unit_name, *args, &block
62
+ exponent, unit_name = Alchemist.parse_prefix(unit_name)
63
+ if Conversions[ unit_name ]
64
+ types = Conversions[ @unit_name] & Conversions[ unit_name]
65
+ if types[0] # assume first type
66
+ if(Alchemist.conversion_table[types[0]][unit_name].is_a?(Array))
67
+ Alchemist.conversion_table[types[0]][unit_name][1].call(base(types[0]))
68
+ else
69
+ NumericConversion.new(base(types[0]) / (exponent * Alchemist.conversion_table[types[0]][unit_name]), unit_name)
70
+ end
71
+ else
72
+ raise Exception, "Incompatible Types"
73
+ end
74
+ else
75
+ if args[0] && args[0].is_a?(NumericConversion) && Alchemist.operator_actions[unit_name]
76
+ t1 = Conversions[ @unit_name ][0]
77
+ t2 = Conversions[ args[0].unit_name ][0]
78
+ Alchemist.operator_actions[unit_name].each do |s1, s2, new_type|
79
+ if t1 == s1 && t2 == s2
80
+ return (@value * args[0].to_f).send(new_type)
81
+ end
82
+ end
83
+ end
84
+ if unit_name == :*
85
+ if args[0].is_a?(Numeric)
86
+ @value *= args[0]
87
+ return self
88
+ else
89
+ raise Exception, "Incompatible Types"
90
+ end
91
+ end
92
+ if unit_name == :/ && args[0].is_a?(NumericConversion)
93
+ raise Exception, "Incompatible Types" unless (Conversions[@unit_name] & Conversions[args[0].unit_name]).length > 0
94
+ end
95
+ args.map!{|a| a.is_a?(NumericConversion) ? a.send(@unit_name).to_f / @exponent : a }
96
+ @value = @value.send( unit_name, *args, &block )
97
+
98
+
99
+ unit_name == :/ ? @value : self
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,13 @@
1
+ module Alchemist
2
+ module NumericExt
3
+ def from(unit_name)
4
+ send(unit_name)
5
+ end
6
+
7
+ def method_missing unit_name, *args, &block
8
+ exponent, unit_name = Alchemist.parse_prefix(unit_name)
9
+ Conversions[ unit_name ] || super( unit_name, *args, &block )
10
+ NumericConversion.new self, unit_name, exponent
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,40 @@
1
+ module Alchemist
2
+ module UnitPrefixes
3
+ def self.default
4
+ {
5
+ :googol => 1e+100,
6
+ :yotta => 1e+24, :Y => 1e+24,
7
+ :zetta => 1e+21, :Z => 1e+21,
8
+ :exa => 1e+18, :E => 1e+18,
9
+ :peta => 1e+15, :P => 1e+15,
10
+ :tera => 1e+12, :T => 1e+12,
11
+ :giga => 1e+9, :G => 1e+9,
12
+ :mega => 1e+6, :M => 1e+6,
13
+ :kilo => 1e+3, :k => 1e+3,
14
+ :hecto => 1e+2, :h => 1e+2,
15
+ :deca => 10, :da => 10,
16
+ :deci => 1e-1, :d => 1e-1,
17
+ :centi => 1e-2, :c => 1e-2,
18
+ :milli => 1e-3, :m => 1e-3,
19
+ :micro => 1e-6, :u => 1e-6,
20
+ :nano => 1e-9, :n => 1e-9,
21
+ :pico => 1e-12, :p => 1e-12,
22
+ :femto => 1e-15, :f => 1e-15,
23
+ :atto => 1e-18, :a => 1e-18,
24
+ :zepto => 1e-21, :z => 1e-21,
25
+ :yocto => 1e-24, :y => 1e-24,
26
+
27
+ # binary prefixes
28
+
29
+ :kibi => 2.0**10.0, :Ki => 2.0**10.0,
30
+ :mebi => 2.0**20.0, :Mi => 2.0**20.0,
31
+ :gibi => 2.0**30.0, :Gi => 2.0**30.0,
32
+ :tebi => 2.0**40.0, :Ti => 2.0**40.0,
33
+ :pebi => 2.0**50.0, :Pi => 2.0**50.0,
34
+ :exbi => 2.0**60.0, :Ei => 2.0**60.0,
35
+ :zebi => 2.0**70.0, :Zi => 2.0**70.0,
36
+ :yobi => 2.0**80.0, :Yi => 2.0**80.0
37
+ }
38
+ end
39
+ end
40
+ end
metadata ADDED
@@ -0,0 +1,53 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dkastner-alchemist
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Derek Kastner
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-30 00:00:00.000000000Z
13
+ dependencies: []
14
+ description: Conversions... like you've never seen them before!!
15
+ email: dkastner@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - Rakefile
21
+ - lib/alchemist/compound.rb
22
+ - lib/alchemist/compound_numeric_conversion.rb
23
+ - lib/alchemist/conversion_table.rb
24
+ - lib/alchemist/numeric_conversion.rb
25
+ - lib/alchemist/numeric_ext.rb
26
+ - lib/alchemist/unit_prefixes.rb
27
+ - lib/alchemist.rb
28
+ homepage: http://github.com/dkastner/alchemist
29
+ licenses: []
30
+ post_install_message:
31
+ rdoc_options: []
32
+ require_paths:
33
+ - lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ none: false
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ required_rubygems_version: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ requirements: []
47
+ rubyforge_project:
48
+ rubygems_version: 1.8.11
49
+ signing_key:
50
+ specification_version: 3
51
+ summary: Conversions... like you've never seen them before!
52
+ test_files: []
53
+ has_rdoc: