Added 8 integer clamping functions

Mon, 04 May 2015 02:46:09 +0300

author
Teemu Piippo <crimsondusk64@gmail.com>
date
Mon, 04 May 2015 02:46:09 +0300
changeset 135
ad27ab7e6fb6
parent 134
7316dc5f61ef
child 136
3812bfce21e0
child 138
d0184734320e

Added 8 integer clamping functions
Fixed hex and binary representation of zero and negative numbers
Fixed modulo operator not working due to missing call to realf()

calc.py file | annotate | diff | comparison | revisions
--- a/calc.py	Mon May 04 02:19:21 2015 +0300
+++ b/calc.py	Mon May 04 02:46:09 2015 +0300
@@ -120,7 +120,7 @@
 	'pow':		{ 'symbol': '**', 'operands': 2, 'priority': 10, 'function': lambda x, y: x ** y },
 	'mul':		{ 'symbol': '*',  'operands': 2, 'priority': 50, 'function': lambda x, y: x * y },
 	'div':		{ 'symbol': '/',  'operands': 2, 'priority': 50, 'function': lambda x, y: x / y },
-	'mod':		{ 'symbol': '%',  'operands': 2, 'priority': 50, 'function': lambda x, y: math.fmod (x, y) },
+	'mod':		{ 'symbol': '%',  'operands': 2, 'priority': 50, 'function': realf (math.fmod) },
 	'add':		{ 'symbol': '+',  'operands': 2, 'priority': 100, 'function': lambda x, y: x + y },
 	'sub':		{ 'symbol': '-',  'operands': 2, 'priority': 100, 'function': lambda x, y: x - y },
 	'eq':		{ 'symbol': '==', 'operands': 2, 'priority': 500, 'function': lambda x, y: x == y },
@@ -150,6 +150,14 @@
 def sgn (x):
 	return cmp (x, 0)
 
+def integerclamp (x, bits, signed):
+	x = x % (2 ** bits)
+
+	if signed and x >= (2 ** (bits - 1)):
+		x = -(2 ** bits) + x
+
+	return x
+
 Constants = {
 	'pi': cmath.pi,
 	'e': cmath.e,
@@ -195,6 +203,14 @@
 	'conjugate':{ 'function': lambda x: x.conjugate() },
 	'rand':		{ 'function': random.random },
 	'sgn':		{ 'function': realf (sgn) },
+	'byte':		{ 'function': intf (lambda x: integerclamp (x, bits=8, signed=False)) },
+	'sbyte':	{ 'function': intf (lambda x: integerclamp (x, bits=8, signed=True)) },
+	'word':		{ 'function': intf (lambda x: integerclamp (x, bits=16, signed=False)) },
+	'sword':	{ 'function': intf (lambda x: integerclamp (x, bits=16, signed=True)) },
+	'dword':	{ 'function': intf (lambda x: integerclamp (x, bits=32, signed=False)) },
+	'sdword':	{ 'function': intf (lambda x: integerclamp (x, bits=32, signed=True)) },
+	'qword':	{ 'function': intf (lambda x: integerclamp (x, bits=64, signed=False)) },
+	'sqword':	{ 'function': intf (lambda x: integerclamp (x, bits=64, signed=True)) },
 }
 
 Tokens = ['(', ')']
@@ -244,6 +260,9 @@
 Attributes['dec'] = Attributes['decimal']
 AttributeNames = sorted ([key for key in Attributes], key=lambda x:len(x), reverse=True)
 
+def is_int (x):
+	return math.fabs (x - math.floor(x)) < epsilon
+
 class Calculator (object):
 	def __init__ (self):
 		self.preferred_base = None
@@ -520,7 +539,7 @@
 				printFunc (self.tabs + 'Evaluating function call: %s' % (sym))
 				expr[i] = Functions[sym.funcname]['function'] (*sym.args)
 				printFunc (self.tabs + '-> %s' % expr[i])
-				
+
 			i += 1
 
 		printFunc (self.tabs + 'Evaluate: %s' % expr)
@@ -559,7 +578,7 @@
 	def repr_number (self, x):
 		"""Returns a string representation for a real number"""
 		base = self.preferred_base if self.preferred_base else 10
-		if math.fabs (x - math.floor(x)) < epsilon and base != 10:
+		if is_int (x) and base != 10:
 			digits='0123456789abcdef'
 			assert base <= len (digits), '''base %d is too large''' % base
 
@@ -568,6 +587,12 @@
 			x = int (x)
 			runaway = 0
 
+			if not x:
+				return '0x0'
+
+			if x < 0:
+				return '-' + self.repr_number (abs (x))
+
 			while x > 0:
 				runaway += 1
 				if runaway > 1000:

mercurial