Slowly going through functions cleaning them up. THis includes massive cleanup to...
[gonvert] / src / converters.py
1 """
2 All classes for conversions are defined below:
3  each class should have one method for converting "to_base and another for converting "from_base"
4 the return value is the converted value to or from base
5 """
6
7
8 # used for Computer numbers base definitions.
9 ALPHA_NUMERIC = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
10
11
12 def makeBase(x, base = len(ALPHA_NUMERIC), table=ALPHA_NUMERIC):
13         """
14         Convert from base 10 to any other base.
15         >> makeBase(1, 10)
16         '1'
17         >> makeBase(11, 10)
18         '11'
19         >> makeBase(11, 16)
20         'b'
21         """
22         d, m = divmod(x, base)
23         if not d:
24                 return table[m]
25         return makeBase(d, base, table) + table[m]
26
27
28 # roman numerals
29 roman_group = {
30         1: ('i','v'),
31         10: ('x','l'),
32         100: ('c','d'),
33         1000: ('m','A'),
34         10000: ('B','C'),
35 }
36
37
38 # functions that convert Arabic digits to roman numerals
39 roman_value = {
40         0: lambda i,v,x: '',
41         1: lambda i,v,x: i,
42         2: lambda i,v,x: i+i,
43         3: lambda i,v,x: i+i+i,
44         4: lambda i,v,x: i+v,
45         5: lambda i,v,x: v,
46         6: lambda i,v,x: v+i,
47         7: lambda i,v,x: v+i+i,
48         8: lambda i,v,x: v+i+i+i,
49         9: lambda i,v,x: i+x,
50 }
51
52
53 def toroman(n):
54         """
55         convert a decimal number in [1,4000) to a roman numeral
56         >>> toroman(0)
57         >>> toroman(4001)
58         >>> toroman(1)
59         'i'
60         >>> toroman(4)
61         'iv'
62         >>> toroman(5)
63         'v'
64         >>> toroman(10)
65         'x'
66         >>> toroman(15)
67         'xv'
68         """
69         if n < 0:
70                 raise NotImplementedError("Value out of roman comprehension")
71         elif n == 0:
72                 ''
73         elif n >= 4000:
74                 raise NotImplementedError("Value Out of Range")
75
76         base = 1
77         s = ''
78         while n > 0:
79             i,v = roman_group[base]
80             base = base * 10
81             x,l = roman_group[base]
82             digit = n % 10
83             n = (n-digit)/10
84             s = roman_value[digit](i,v,x) + s
85         return s
86
87
88 def fromroman(s, rbase = 1):
89         """
90         convert a roman numeral (in lowercase) to a decimal integer
91         >>> fromroman('')
92         0
93         >>> fromroman('x')
94         5
95         >>> fromroman('xv')
96         15
97         """
98         if len(s) == 0:
99             return 0
100         elif rbase > 1000:
101             return 0
102
103         i, v = roman_group[rbase]
104         x, l = roman_group[rbase*10]
105         conversions = [
106                 (v+i+i+i, 8),
107                 (i+i+i+i, 5),
108                 (v+i+i, 7),
109                 (i+i+i, 3),
110                 (v+i, 6),
111                 (i+x, 9),
112                 (i+v, 4),
113                 (i+i, 2),
114                 (i, 1),
115                 (v, 5),
116         ]
117         for conversion in conversions:
118                 if s.endswith(conversion[0]):
119                         digit = conversion[1]
120                         s = s[:-len(conversion[0])]
121                         break
122         else:
123                 digit = 0
124                 s = s
125
126         return digit * rbase + fromroman(s, rbase*10)
127
128
129 class simple_multiplier(object):
130
131         def to_base(self,value,multiplier):
132                 return value * (multiplier)
133
134         def from_base(self,value,multiplier):
135                 if multiplier == 0:
136                         return 0.0
137                 else:
138                         return value / (multiplier)
139
140
141 class simple_inverter(object):
142
143         def to_base(self,value,multiplier):
144                 if value == 0:
145                         return 0.0
146                 else:
147                         return (multiplier) / value
148
149         def from_base(self,value,multiplier):
150                 if value == 0:
151                         return 0.0
152                 else:
153                         return (multiplier) / value
154
155
156 class simple_gain_offset(object):
157
158         def to_base(self,value,(gain,offset)):
159                 return (value * (gain)) + offset
160
161         def from_base(self,value,(gain,offset)):
162                 if gain == 0:
163                         return 0.0
164                 else:
165                         return (value - offset) / gain
166
167
168 class simple_offset_gain(object):
169
170         def to_base(self,value,(offset,gain)):
171                 return (value + offset) * gain
172
173         def from_base(self,value,(offset,gain)):
174                 if gain == 0:
175                         return 0.0
176                 else:
177                         return (value / gain) - offset
178
179
180 class slope_offset(object):
181         ''"convert using points on a graph''"
182
183         def to_base(self,value,((low_in,high_in),(low_out,high_out))):
184                 gain = (high_out-low_out)/(high_in-low_in)
185                 offset = low_out - gain*low_in
186                 return gain*value+offset
187
188         def from_base(self,value,((low_out,high_out),(low_in,high_in))):
189                 gain = (high_out-low_out)/(high_in-low_in)
190                 offset = low_out - gain*low_in
191                 return gain*value+offset
192
193
194 class double_slope_offset(object):
195         ''"convert using points on a graph, graph split into two slopes''"
196
197         def to_base(self,value,((low1_in,high1_in),(low1_out,high1_out),(low2_in,high2_in),(low2_out,high2_out))):
198                 if low1_in<=value<=high1_in:
199                         gain = (high1_out-low1_out)/(high1_in-low1_in)
200                         offset = low1_out - gain*low1_in
201                         return gain*value+offset
202                 if low2_in<=value<=high2_in:
203                         gain = (high2_out-low2_out)/(high2_in-low2_in)
204                         offset = low2_out - gain*low2_in
205                         return gain*value+offset
206                 return 0.0
207
208         def from_base(self,value,((low1_in,high1_in),(low1_out,high1_out),(low2_in,high2_in),(low2_out,high2_out))):
209                 if low1_out<=value<=high1_out:
210                         gain = (high1_in-low1_in)/(high1_out-low1_out)
211                         offset = low1_in - gain*low1_out
212                         return gain*value+offset
213                 if low2_out<=value<=high2_out:
214                         gain = (high2_in-low2_in)/(high2_out-low2_out)
215                         offset = low2_in - gain*low2_out
216                         return gain*value+offset
217                 return 0.0
218
219
220 class base_converter(object):
221
222         def to_base(self,value,base):
223                 """
224                 Convert from any base to base 10 (decimal)
225                 """
226                 result = 0L #will contain the long base-10 (decimal) number to be returned
227                 position = len(value) #length of the string that is to be converted
228                 for x in value:
229                         position = position-1
230                         result = long(result + long(long(ALPHA_NUMERIC.find(x))*(long(base)**long(position))))
231                 return result
232
233         def from_base(self,value,base):
234                 """
235                 Convert from decimal to any base
236                 """
237                 return makeBase(value,base)
238
239
240 class roman_numeral(object):
241
242         def to_base(self,value,junk):
243                 """
244                 Convert from roman numeral to base 10 (decimal)
245                 """
246                 if value=="0":
247                         return 0L
248                 else:
249                         return fromroman(value)
250
251         def from_base(self,value,junk):
252                 """
253                 Convert from decimal to roman numeral
254                 """
255                 return toroman(value)
256
257
258
259 class function(object):
260         ''"defined simple function can be as complicated as you like, however, both to/from base must be defined.''"
261
262         #value is assumed to be a string
263         #convert from a defined function to base
264         def to_base(self,value,(to_base,from_base)):
265                 exec "y="+to_base[:to_base.find('x')]+str(value)+to_base[to_base.find('x')+1:]
266                 return y
267
268         def from_base(self,value,(to_base,from_base)):
269                 exec "y="+from_base[:from_base.find('x')]+str(value)+from_base[from_base.find('x')+1:]
270                 return y
271
272
273 #--------- function definitions from classes ------------
274 m = simple_multiplier()
275 inv = simple_inverter()
276 gof = simple_gain_offset()
277 ofg = simple_offset_gain()
278 slo = slope_offset()
279 dso = double_slope_offset()
280 b = base_converter()
281 r = roman_numeral()
282 f = function()