[MATRIX-SIG] Much ado about nothingness.

Jody Winston jody@sccsi.com
Wed, 9 Jul 1997 14:53:10 -0500


Here's a simple Missing class:

import sys
import types



class Missing:

    """An object that defines math operations on missing values.
    """

    def __init__(self, value=0, missing=-999.25):
	"""This method constructs the object.
	The following exceptions are thrown:

	o  If the value is not number.
	"""

	if not((type(value) != types.IntType) or 
	       (type(value) != types.LongType) or 
	       (type(value) != types.FloatType) or 
	       (type(value) != types.ComplexType)):

	    raise TypeError, "Not number"

	self.value = value
	self.missing = missing

    def absent(self):
	return self.value == self.missing

    def __eitherMissing(self, other):
	if self.absent():
	    return 1
	elif other.absent():
	    return 1

    def __repr__(self):
	"""Called by the print statement and conversions (reverse quotes) to
	compute the string representation of an object."""

	return str(self.value) + \
	       " (" + \
	       "missing = " + str(self.missing) + \
	       ")"

    def __str__(self):
	return str(self.value) + \
	       " (" + \
	       "missing = " + str(self.missing) + \
	       ")"

    def __sum(self, other, sign1, sign2):
	if isMissing(other):
	    if self.__eitherMissing(other):
		result = self.missing
	    else:
		result = sign1 * self.value + sign2 * other.value
	    missing = self.missing
	else:
	    if self.absent():
		result = self.missing
	    else:
		result = sign1 * self.value + sign2 * other
	    missing = self.missing

	return Missing(result, missing)

    def __add__(self, other):
	return self.__sum(other, 1, 1)
    
    __radd__ = __add__

    def __sub__(self, other):
	return self.__sum(other, 1, -1)

    def __rsub__(self, other):
	return self.__sum(other, -1, 1)

    def __cmp__(self, other):
	if isMissing(other):
	    if self.absent() and other.absent():
		return 0

	diff = self.__sum(other, 1, -1)
	return cmp(diff.value, 0)

    def __mul__(self, other):
	if isMissing(other):
	    if self.__eitherMissing(other):
		result = self.missing
	    else:
		result = self.value * other.value
	    missing = self.missing
	else:
	    if self.absent():
		result = self.missing
	    else:
		result = self.value * other
	    missing = self.missing

	return Missing(result, missing)

    __rmul__ = __mul__

    def __div__(self, other):
	if isMissing(other):
	    if self.__eitherMissing(other):
		result = self.missing
	    else:
		result = self.value / other.value
	    missing = self.missing
	else:
	    if self.absent():
		result = self.missing
	    else:
		result = self.value / other
	    missing = self.missing

	return Missing(result, missing)

    def __rdiv__(self, other):
	if isMissing(other):
	    if self.__eitherMissing(other):
		result = self.missing
	    else:
		result = other.value / self.value
	    missing = self.missing
	else:
	    if self.absent():
		result = self.missing
	    else:
		result = other / self.value
	    missing = self.missing

	return Missing(result, missing)

    def __pow__(self, other):
	if isMissing(other):
	    if self.__eitherMissing(other):
		result = self.missing
	    else:
		result = pow(self.value, other.value)
	    missing = self.missing
	else:
	    if self.absent():
		result = self.missing
	    else:
		result = pow(self.value, other)
	    missing = self.missing

	return Missing(result, missing)

    def __rpow__(self, other):
	if isMissing(other):
	    if self.__eitherMissing(other):
		result = self.missing
	    else:
		result = pow(other.value, self.value)
	    missing = self.missing
	else:
	    if self.absent():
		result = self.missing
	    else:
		result = pow(other, self.value)
	    missing = self.missing

	return Missing(result, missing)

    def __abs__(self):
	if self.absent():
	    return Missing(self.value, self.missing)
	
	return Missing(abs(self.value), self.missing)

    def __pos__(self):
	return self

    def __neg__(self):
	if self.absent():
	    return Missing(self.value, self.missing)

	return Missing(-self.value, self.missing)

    def __nonzero__(self):
	return self.value != 0




def isMissing(x):
    return hasattr(x, "value") and hasattr(x, "missing")



def main(argv):
    a = Missing()
    
    if (a + 10) != 10:
	raise ValueError

    b = Missing(20, -100)

    if (a + b) != Missing(20):
	raise ValueError


    
if __name__ == '__main__':     
    main(sys.argv)

    sys.exit(0)
    


_______________
MATRIX-SIG  - SIG on Matrix Math for Python

send messages to: matrix-sig@python.org
administrivia to: matrix-sig-request@python.org
_______________