# HG changeset patch
# User Burcin Erocal <burcin@erocal.org>
# Date 1239396878 -7200
# Node ID 4971202c8eabfbeddde99672b17f7c7f7b1e5770
# Parent  975c0a9dadeb575ef03af8c4bd8823edc84b5825
Add .find() method to sage.symbolic.expression.Expression.

diff --git a/sage/libs/ginac/decl.pxi b/sage/libs/ginac/decl.pxi
--- a/sage/libs/ginac/decl.pxi
+++ b/sage/libs/ginac/decl.pxi
@@ -34,6 +34,18 @@
     ctypedef struct GExMap "exmap":
         void insert(GExPair e)
 
+    # forward declaration of GEx
+    ctypedef struct GEx "ex"
+
+    ctypedef struct GExListIter "GiNaC::lst::const_iterator":
+        void inc "operator++" ()
+        GEx obj "operator*" ()
+        bint is_not_equal "operator!=" (GExListIter i)
+
+    ctypedef struct GExList "GiNaC::lst":
+        GExListIter begin()
+        GExListIter end()
+
     ctypedef struct GEx "ex":
         unsigned int gethash()        except +
         int compare(GEx other)        except +
@@ -43,6 +55,7 @@
         GEx series(GEx s, int order, unsigned options) except +
         bint is_zero()                except +
         bint match(GEx pattern)       except +
+        bint find(GEx pattern, GExList s) except +
         bint has(GEx pattern)         except +
         GEx subs(GEx expr)            except +
         GEx subs_map "subs" (GExMap map) except +
diff --git a/sage/symbolic/expression.pyx b/sage/symbolic/expression.pyx
--- a/sage/symbolic/expression.pyx
+++ b/sage/symbolic/expression.pyx
@@ -950,6 +950,47 @@
         cdef Expression p = self.coerce_in(pattern)
         return self._gobj.match(p._gobj)
 
+    def find(self, pattern):
+        """
+        Find all occurences of the given pattern in this expression.
+
+        Note that once a subexpression matches the pattern, the search doesn't
+        extend to subexpressions of it.
+
+        EXAMPLES::
+
+            sage: var('x,y,z,a,b',ns=1); S = parent(x)
+            (x, y, z, a, b)
+            sage: w0 = S.wild(0); w1 = S.wild(1)
+
+            sage: (sin(x)*sin(y)).find(sin(w0))
+            [sin(x), sin(y)]
+
+            sage: ((sin(x)+sin(y))*(a+b)).expand().find(sin(w0))
+            [sin(x), sin(y)]
+
+            sage: (1+x+x^2+x^3).find(x)
+            [x]
+            sage: (1+x+x^2+x^3).find(x^w0)
+            [x^3, x^2]
+
+            sage: (1+x+x^2+x^3).find(y)
+            []
+
+            # subexpressions of a match are not listed
+            sage: ((x^y)^z).find(w0^w1)
+            [(x^y)^z]
+        """
+        cdef Expression p = self.coerce_in(pattern)
+        cdef GExList found
+        self._gobj.find(p._gobj, found)
+        res = []
+        cdef GExListIter itr = found.begin()
+        while itr.is_not_equal(found.end()):
+            res.append(new_Expression_from_GEx(itr.obj()))
+            itr.inc()
+        return res
+
     def has(self, pattern):
         """
         EXAMPLES:
