00001 __copyright__ = """
00002 Copyright 2008 Sean Ross-Ross
00003 """
00004 __license__ = """
00005 This file is part of SLIMpy .
00006
00007 SLIMpy is free software: you can redistribute it and/or modify
00008 it under the terms of the GNU Lesser General Public License as published by
00009 the Free Software Foundation, either version 3 of the License, or
00010 (at your option) any later version.
00011
00012 SLIMpy is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00015 GNU Lesser General Public License for more details.
00016
00017 You should have received a copy of the GNU Lesser General Public License
00018 along with SLIMpy . If not, see <http://www.gnu.org/licenses/>.
00019 """
00020
00021 from slimpy_base.Environment.InstanceManager import InstanceManager
00022 from slimpy_base.Core.Interface.node import Source,Target
00023 from slimpy_base.Core.Command.CommandPack import CommandPack
00024 from slimpy_base.Core.Command.Command import Command as general_command
00025
00026 import traceback
00027 from numpy import inf
00028
00029 class ScalarProxy( object ):
00030
00031 def __init__( self, value ):
00032 self.method_name = value
00033
00034 def __call__(self , src_self,other_obj,trg_scal=None ):
00035
00036 method = getattr(self, self.method_name)
00037
00038 val = method( get_num(src_self), get_num(other_obj) )
00039 if trg_scal is None:
00040 return val
00041 else:
00042 trg_scal.set(val)
00043 return
00044
00045 def __str__(self):
00046 return "Scalar Function: %s" %self.method_name
00047
00048 def add( self, one, other ):
00049 return one + other
00050 def radd( self, one, other ):
00051 return other + one
00052 def sub( self, one, other ):
00053 return one - other
00054 def rsub( self, one, other ):
00055 return other - one
00056 def div( self, one, other ):
00057 if one == 0:
00058 return 0
00059 elif other == 0:
00060 return inf
00061 else:
00062 return one / other
00063 def rdiv( self, one, other ):
00064 if other == 0:
00065 return 0
00066 elif one == 0:
00067 return inf
00068 else:
00069 return other / one
00070
00071 def mul( self, one, other ):
00072 return one * other
00073 def rmul( self, one, other ):
00074 return other * one
00075 def pow( self, one, other ):
00076 return one ** other
00077 def neg( self, one ,other):
00078 return -one
00079 def abs( self, one, other ):
00080 return abs(one)
00081 def real(self, x ,other ):
00082 return hasattr( x,'real') and x.real or x
00083 def imag(self, x ,other ):
00084 return hasattr(x,'imag') and x.imag or x , "imag"
00085 def conjugate(self, x ,other ):
00086 return hasattr(x,'conjugate') and x.conjugate() or x
00087 def and_( self, one, other ):
00088 return one & other
00089 def or_( self, one, other ):
00090 return one | other
00091 def lt(self, one, other):
00092 return one < other
00093 def le(self, one, other):
00094 return one <= other
00095 def gt(self, one, other):
00096 return one > other
00097 def ge(self, one, other):
00098 return one >= other
00099 def eq(self, one, other):
00100 return one == other
00101 def ne(self, one, other):
00102 return one != other
00103
00104
00105
00106 class Scalar( object ):
00107 """
00108 Scalar object represents a number
00109 a scalar object does not contain a number until
00110 built by the AST
00111 """
00112 _count = 0
00113
00114 env = InstanceManager( )
00115
00116 @classmethod
00117 def _inc_count(cls):
00118 cls._count += 1
00119
00120 def __init__(self,val=None):
00121 self._inc_count()
00122 if val is None:
00123 self._is_set = False
00124 self._name = "${SCALAR[%s]}" %self._count
00125 self.__val = self._name
00126 else:
00127 self._is_set = True
00128 self._name = "${SCALAR[%s]}" %self._count
00129 self.__val = val
00130
00131
00132 def set(self,val):
00133 if self._is_set:
00134 print "Warning: Scalar Object is already set"
00135
00136 self.env['table'].scalars_map[self._name] = val
00137 self.__val = val
00138 self._is_set = True
00139
00140 return
00141
00142 def item(self):
00143 if not self._is_set:
00144 if self.env['slimvars']['runtype'] == 'dryrun':
00145 raise Exception( 'can not do evaluation of slimpy.scalar in "dryrun" mode' )
00146 self.env['graphmgr'].flush( self )
00147 return self.__val
00148
00149 def get_data(self, nodename ):
00150 return self.__val
00151
00152 def _get_data(self):
00153 return self.__val
00154
00155 def get_nodenames(self):
00156 return ['localhost']
00157
00158 data = property( _get_data )
00159
00160 nodenames = property(get_nodenames)
00161
00162 def _get_node_names(self):
00163 return [ 'localhost' ]
00164
00165 def node_copy(self,to_node):
00166 pass
00167
00168 def __str__(self):
00169 if self._is_set:
00170 st = "Scalar(%s)" %self.__val
00171 else:
00172 st = self._name
00173
00174 return st
00175
00176 def __repr__(self):
00177 return self.__str__( )
00178
00179 def _num_src(self,num):
00180 if is_scalar_obj(num):
00181 return Source( num )
00182 else:
00183 return Scalar( num )
00184
00185 def gen_new_scal(self,other,func):
00186
00187 scalar = Scalar( )
00188 trg_scal = Target( scalar )
00189 src_self = Source( self )
00190
00191 other_obj = self._num_src( other )
00192
00193
00194
00195 tag = str(func)
00196 command = general_command( tag , None, src_self,other_obj,trg_scal )
00197 command.func = func
00198
00199 if self.env['slimvars']['keep_tb_info']:
00200 stack = traceback.extract_stack( )
00201 st_list = traceback.format_list( stack[:-3] )
00202 command.tb_info = "".join(st_list)
00203
00204 compack = CommandPack([command], None, None)
00205
00206 self.env['graphmgr'].graphAppend( compack )
00207
00208 return scalar
00209
00210 def __scalar_operation__(self,other,func):
00211
00212 if has_num(self) and has_num(other):
00213 return func( get_num(self), get_num(other) )
00214
00215 if is_number(other) or other is None:
00216 return self.gen_new_scal(other, func )
00217 else:
00218 return NotImplemented
00219
00220 def __add__( self, other ):
00221 return self.__scalar_operation__(other, ScalarProxy('add') )
00222
00223 def __radd__( self, other ):
00224 return self.__scalar_operation__(other, ScalarProxy('radd') )
00225
00226 def __sub__( self, other ):
00227 return self.__scalar_operation__(other, ScalarProxy('sub') )
00228
00229 def __rsub__( self, other ):
00230 return self.__scalar_operation__(other, ScalarProxy('rsub') )
00231
00232 def __div__( self, other ):
00233 return self.__scalar_operation__(other, ScalarProxy('div') )
00234
00235 def __rdiv__( self, other ):
00236 return self.__scalar_operation__(other, ScalarProxy('rdiv') )
00237
00238 def __mul__( self, other ):
00239 return self.__scalar_operation__(other, ScalarProxy('mul') )
00240
00241 def __rmul__( self, other ):
00242 return self.__scalar_operation__(other, ScalarProxy('rmul') )
00243
00244 def __pow__( self, other ):
00245 return self.__scalar_operation__(other, ScalarProxy('pow') )
00246
00247 def __neg__( self ):
00248 return self.__scalar_operation__(None, ScalarProxy('neg') )
00249
00250 def __abs__( self ):
00251 return self.__scalar_operation__(None, ScalarProxy('abs') )
00252
00253 def __real__(self):
00254 return self.__scalar_operation__(None, ScalarProxy('real') )
00255
00256 def __imag__(self):
00257 return self.__scalar_operation__(None, ScalarProxy('imag') )
00258
00259 def conjugate(self):
00260 return self.__scalar_operation__(None, ScalarProxy('conjugate') )
00261
00262 real = property( __real__ )
00263 imag = property( __imag__ )
00264
00265 def __and__( self, other ):
00266 return self.__scalar_operation__( other, ScalarProxy('and_') )
00267
00268 def __or__( self, other ):
00269 return self.__scalar_operation__( other, ScalarProxy('or_') )
00270
00271 def __lt__(self, other):
00272 return self.__scalar_operation__( other, ScalarProxy('lt') )
00273
00274 def __le__(self, other):
00275 return self.__scalar_operation__( other, ScalarProxy('le') )
00276
00277 def __gt__(self, other):
00278 return self.__scalar_operation__( other, ScalarProxy('gt') )
00279
00280 def __ge__(self, other):
00281 return self.__scalar_operation__( other, ScalarProxy('ge') )
00282
00283 def __eq__(self, other):
00284 return self.__scalar_operation__( other, ScalarProxy('eq') )
00285
00286 def __ne__(self, other):
00287 return self.__scalar_operation__( other, ScalarProxy('ne') )
00288
00289 def __nonzero__(self):
00290
00291 return bool( self.item( ) )
00292
00293
00294
00295
00296 number = (int, long, float, complex, Scalar)
00297 is_number = lambda num: isinstance(num, number)
00298 is_scalar_obj = lambda scal: isinstance(scal, Scalar)
00299 is_source = lambda scal: isinstance(scal, Source )
00300 has_num = lambda scal: is_scalar_obj(scal) and scal._is_set or not is_scalar_obj(scal)
00301
00302 def get_num( scal ):
00303 if is_source(scal) or is_scalar_obj( scal ) :
00304 return scal.data
00305 else:
00306 return scal
00307
00308
00309