PageRenderTime 482ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/sympycore/heads/number.py

https://github.com/escheffel/pymaclab
Python | 315 lines | 259 code | 46 blank | 10 comment | 88 complexity | 605aa42bc55d524e2c4c6237e72a8374 MD5 | raw file
  1. __all__ = ['NUMBER']
  2. import re
  3. from .base import Head, Expr, heads_precedence, AtomicHead, Pair
  4. from ..core import init_module
  5. init_module.import_heads()
  6. init_module.import_numbers()
  7. init_module.import_lowlevel_operations()
  8. _is_number = re.compile(r'\A[-]?\d+\Z').match
  9. _is_neg_number = re.compile(r'\A-\d+([/]\d+)?\Z').match
  10. _is_rational = re.compile(r'\A\d+[/]\d+\Z').match
  11. class NumberHead(AtomicHead):
  12. """
  13. NumberHead is a head for symbols, data can be any Python object.
  14. """
  15. def __repr__(self): return 'NUMBER'
  16. def new(self, cls, data):
  17. if isinstance(data, Infinity):
  18. return data
  19. return cls(NUMBER, data)
  20. def reevaluate(self, cls, data):
  21. return cls(self, data)
  22. def is_data_ok(self, cls, data):
  23. return
  24. def nonzero(self, cls, data):
  25. return data
  26. def to_SPARSE_POLY(self, cls, data, expr):
  27. """
  28. Obsolete method: SPARSE_POLY will be removed in future.
  29. """
  30. return cls(data)
  31. def to_TERM_COEFF_DICT(self, cls, data, expr):
  32. return expr
  33. def to_ADD(self, cls, data, expr):
  34. return expr
  35. def to_EXP_COEFF_DICT(self, cls, data, expr, variables = None):
  36. if variables is None:
  37. variables = ()
  38. if data:
  39. return cls(EXP_COEFF_DICT, Pair(variables, {EXP_COEFF_DICT.make_exponent(0, variables):data}))
  40. return cls(EXP_COEFF_DICT, Pair(variables, {}))
  41. def data_to_str_and_precedence(self, cls, data):
  42. if isinstance(data, complextypes):
  43. r, i = data.real, data.imag
  44. if r!=0 and i!=0:
  45. return str(data), heads_precedence.ADD
  46. if r==0:
  47. if i<0:
  48. return str(data), heads_precedence.NEG
  49. return str(data), heads_precedence.NUMBER
  50. return self.data_to_str_and_precedence(self, cls, r)
  51. elif isinstance(data, rationaltypes):
  52. if data < 0:
  53. return str(data), heads_precedence.NEG
  54. return str(data), heads_precedence.DIV
  55. elif isinstance(data, realtypes):
  56. if data < 0:
  57. return str(data), heads_precedence.NEG
  58. return str(data), heads_precedence.NUMBER
  59. elif isinstance(data, Expr):
  60. h, d = data.pair
  61. return h.data_to_str_and_precedence(type(data), d)
  62. return str(data), 0.0 # force parenthesis
  63. def non_commutative_mul(self, cls, lhs, rhs):
  64. head, data = rhs.pair
  65. if head is NUMBER:
  66. return cls(NUMBER, lhs.data * data)
  67. # Numbers are ring commutants:
  68. return rhs.head.non_commutative_mul(cls, rhs, lhs)
  69. def commutative_mul_number(self, cls, lhs, rhs):
  70. return cls(NUMBER, lhs.data * rhs)
  71. non_commutative_rmul_number = commutative_mul_number
  72. def commutative_div_number(self, cls, lhs, rhs):
  73. r = number_div(cls, lhs.data, rhs)
  74. if rhs==0:
  75. return r * lhs
  76. return cls(NUMBER, number_div(cls, lhs.data, rhs))
  77. def commutative_rdiv_number(self, cls, lhs, rhs):
  78. r = number_div(cls, rhs, lhs.data)
  79. if rhs==0:
  80. return r * lhs
  81. return cls(NUMBER, r)
  82. def commutative_div(self, cls, lhs, rhs):
  83. return rhs.head.commutative_rdiv_number(cls, rhs, lhs.data)
  84. non_commutative_mul_number = commutative_mul_number
  85. def commutative_mul(self, cls, lhs, rhs):
  86. head, data = rhs.pair
  87. if head is NUMBER:
  88. return cls(NUMBER, lhs.data * data)
  89. return rhs.head.commutative_mul(cls, rhs, lhs)
  90. inplace_commutative_mul = commutative_mul
  91. def term_coeff(self, cls, expr):
  92. if isinstance(expr, Expr):
  93. return cls(NUMBER, 1), expr.data
  94. return cls(NUMBER, 1), expr
  95. def neg(self, cls, expr):
  96. return cls(self, -expr.data)
  97. def add(self, cls, lhs, rhs):
  98. ldata = lhs.data
  99. if ldata==0:
  100. return rhs
  101. h, d = rhs.pair
  102. if h is NUMBER:
  103. return cls(NUMBER, ldata + d)
  104. elif h is SYMBOL or h is APPLY or h is CALLABLE:
  105. return cls(TERM_COEFF_DICT, {cls(NUMBER,1): ldata, rhs:1})
  106. elif h is ADD:
  107. terms = []
  108. for term in d:
  109. h1, c = term.pair
  110. if h1 is NUMBER:
  111. c = lhs.data + c
  112. if c:
  113. terms.append(cls(NUMBER, c))
  114. else:
  115. terms.append(term)
  116. if not terms:
  117. return cls(NUMBER, 0)
  118. if len(terms)==1:
  119. return terms[0]
  120. return cls(ADD, terms)
  121. elif h is TERM_COEFF:
  122. term, coeff = d
  123. return cls(TERM_COEFF_DICT, {term:coeff, cls(NUMBER,1):lhs.data})
  124. elif h is POW or h is BASE_EXP_DICT:
  125. return cls(TERM_COEFF_DICT, {cls(NUMBER,1):lhs.data, rhs:1})
  126. elif h is TERM_COEFF_DICT:
  127. data = d.copy()
  128. dict_add_item(cls, data, cls(NUMBER,1), lhs.data)
  129. return term_coeff_dict_new(cls, data)
  130. elif h is MUL:
  131. return cls(ADD, [lhs, rhs])
  132. raise NotImplementedError(`self, lhs.pair, rhs.pair`)
  133. inplace_add = add
  134. def add_number(self, cls, lhs, rhs):
  135. return cls(NUMBER, lhs.data + rhs) if rhs else lhs
  136. def sub_number(self, cls, lhs, rhs):
  137. return cls(NUMBER, lhs.data - rhs) if rhs else lhs
  138. def sub(self, cls, lhs, rhs):
  139. return lhs + (-rhs)
  140. def pow(self, cls, base, exp):
  141. h, d = exp.pair
  142. if h is NUMBER and type(d) in numbertypes_set:
  143. return self.pow_number(cls, base, d)
  144. return pow_new(cls, (base, exp))
  145. def pow_number(self, cls, base, exp):
  146. if exp==1:
  147. return base
  148. if exp==0:
  149. return cls(NUMBER, 1)
  150. bd = base.data
  151. if bd==1:
  152. return base
  153. if bd==0:
  154. if exp>0: return base
  155. # exp is negative
  156. return number_div(cls, 1, 0)
  157. r, l = try_power(bd, exp)
  158. if not l:
  159. return cls(NUMBER, r)
  160. if len(l)==1:
  161. b, e = l[0]
  162. if r==1:
  163. return cls(POW, (cls(NUMBER, b), e))
  164. return cls(TERM_COEFF, (cls(POW, (cls(NUMBER, b), e)), r))
  165. d = {}
  166. for b, e in l:
  167. d[cls(NUMBER, b)] = e
  168. if r == 1:
  169. return cls(BASE_EXP_DICT, d)
  170. return cls(TERM_COEFF, (cls(BASE_EXP_DICT, d), r))
  171. def expand(self, cls, expr):
  172. return expr
  173. def diff(self, cls, data, expr, symbol, order, cache={}):
  174. #if isinstance(data, Expr):
  175. # return cls(NUMBER, data.head.diff(type(data), data.data, data, symbol, order))
  176. return cls(NUMBER, 0)
  177. def apply(self, cls, data, func, args):
  178. if isinstance(data, cls):
  179. return data
  180. return cls(NUMBER, data)
  181. def integrate_indefinite(self, cls, data, expr, x):
  182. if data==0:
  183. return expr
  184. if data==1:
  185. return cls(SYMBOL, x)
  186. return cls(TERM_COEFF, (cls(SYMBOL, x), data))
  187. def integrate_definite(self, cls, data, expr, x, a, b):
  188. if data==0:
  189. return expr
  190. if data==1:
  191. return b-a
  192. return (b-a)*data
  193. def algebra_pos(self, Algebra, expr):
  194. return expr
  195. def algebra_neg(self, Algebra, expr):
  196. if Algebra.algebra_options.get('evaluate_addition'):
  197. return Algebra(NUMBER, -expr.data)
  198. return Algebra(NEG, expr)
  199. def algebra_add_number(self, Algebra, lhs, rhs, inplace):
  200. if Algebra.algebra_options.get('evaluate_addition'):
  201. return Algebra(NUMBER, lhs.data + rhs)
  202. return Algebra(ADD, [lhs, Algebra(NUMBER, rhs)])
  203. def algebra_add(self, Algebra, lhs, rhs, inplace):
  204. ldata = lhs.data
  205. rhead, rdata = rhs.pair
  206. if Algebra.algebra_options.get('is_additive_group_commutative'):
  207. if Algebra.algebra_options.get('evaluate_addition'):
  208. if rhead is ADD or rhead is EXP_COEFF_DICT or rhead is MUL or rhead is NEG:
  209. rhs = rhead.to_TERM_COEFF_DICT(Algebra, rdata, rhs)
  210. rhead, rdata = rhs.pair
  211. if not ldata:
  212. return rhs
  213. if rhead is NUMBER:
  214. return Algebra(NUMBER, lhs.data + rdata)
  215. if rhead is SYMBOL:
  216. return Algebra(TERM_COEFF_DICT, {Algebra(NUMBER, 1): ldata, rhs:1})
  217. if rhead is TERM_COEFF or rhead is TERM_COEFF_DICT:
  218. return rhead.algebra_add_number(Algebra, rhs, ldata, inplace)
  219. return super(type(self), self).algebra_add(Algebra, lhs, rhs, inplace)
  220. return Algebra(ADD, [lhs, rhs])
  221. else:
  222. if rhead is ADD:
  223. data = [lhs] + rdata
  224. elif rhead is TERM_COEFF_DICT or rhead is EXP_COEFF_DICT:
  225. data = [lhs] + rhs.to(ADD).data
  226. else:
  227. data = [lhs, rhs]
  228. if Algebra.algebra_options.get('evaluate_addition'):
  229. ADD.combine_add_list(Algebra, data)
  230. return add_new(Algebra, data)
  231. def algebra_mul_number(self, Algebra, lhs, rhs, inplace):
  232. if Algebra.algebra_options.get('evaluate_addition'):
  233. return Algebra(NUMBER, lhs.data * rhs)
  234. return mul_new(Algebra, [lhs, Algebra(NUMBER, rhs)])
  235. def algebra_mul(self, Algebra, lhs, rhs, inplace):
  236. if Algebra.algebra_options.get('evaluate_addition'):
  237. return rhs.head.algebra_mul_number(Algebra, rhs, lhs.data, inplace)
  238. return mul_new(Algebra, [lhs, rhs])
  239. def algebra_pow_number(self, Algebra, lhs, rhs, inplace):
  240. if Algebra.algebra_options.get('evaluate_multiplication'):
  241. if rhs==1:
  242. return lhs
  243. if not rhs:
  244. return Algebra(NUMBER, 1)
  245. ldata = lhs.data
  246. if ldata==1:
  247. return lhs
  248. if not ldata:
  249. if rhs>0:
  250. return lhs
  251. return number_div(cls, 1, 0)
  252. r, l = try_power(ldata, rhs)
  253. if not l:
  254. return Algebra(NUMBER, r)
  255. if Algebra.algebra_options.get('is_multiplicative_group_commutative'):
  256. d = {}
  257. for b, e in l:
  258. b = Algebra(NUMBER, b)
  259. d[b] = e
  260. p = base_exp_dict_new(Algebra, d)
  261. return term_coeff_new(Algrbra, (p, r))
  262. else:
  263. d = []
  264. for b, e in l:
  265. b = Algebra(NUMBER, b)
  266. d.append(Algebra(POW, (b,e)))
  267. return mul_new(Algebra, d)
  268. return super(type(self), self).algebra_pow_number(Algebra, lhs, rhs, inplace)
  269. NUMBER = NumberHead()