Index: trunk/src/boot.clj
===================================================================
--- trunk/src/boot.clj	(revision 810)
+++ trunk/src/boot.clj	(working copy)
@@ -745,6 +745,13 @@
   [#^clojure.lang.Reversible rev]
     (. rev (rseq)))
 
+(defn seq-from
+  "Returns the in-order sequence of sortedmap entries >= key"
+  [sortedmap key] (. clojure.lang.RT (seqFrom sortedmap key)))
+(defn rseq-from
+  "Returns the reverse-order sequence of sortedmap entries <= key"
+  [sortedmap key] (. clojure.lang.RT (rseqFrom sortedmap key)))
+
 (defn name
   "Returns the name String of a symbol or keyword."
   [#^clojure.lang.Named x]
@@ -1133,8 +1140,56 @@
 		   (reduce merge-entry m1 (seq m2)))]
       (reduce merge2 maps)))
 
+(let
+	[get-comp
+		; Retrieves comparator from sorted map or returns default comparator.
+		(fn [smap]
+			(or
+				(. smap comp)
+				(fn [a b]
+					(. a (compareTo b)))))]
+	(defn seq-after
+		"Returns the in-order sequence of sortedmap entries > key"
+		[sortedmap skey]
+		(if sortedmap
+			(let [s (seq-from sortedmap skey)]
+				(if
+					(== 0 ((get-comp sortedmap) (key (first s)) skey))
+					(rest s)
+					s))))
+	(defn rseq-before
+	  "Returns the reverse-order sequence of sortedmap entries < key"
+		[sortedmap skey]
+		(if sortedmap
+			(let [s (rseq-from sortedmap skey)]
+				(if
+					(== 0 ((get-comp sortedmap) (key (first s)) skey))
+					(rest s)
+					s))))
+	(defn seq-from-to
+		"Returns an ordered sequence of items x from sortedmap such that from <= (key x) <= to."
+		[sortedmap from to]
+		(let [cmp (get-comp sortedmap)]
+			(take-while
+				(fn [x]
+					(<= (cmp (key x) to) 0))
+				(seq-from sortedmap from)))))
 
 
+(defn find<
+  "Returns the greatest sortedmap entry less than key, or nil if no match present."
+  [sortedmap key] (first (rseq-before sortedmap key)))
+(defn find<=
+  "Returns the greatest sortedmap entry less than or equal to key, or nil if no match present."
+  [sortedmap key] (first (rseq-from sortedmap key)))
+(defn find>
+  "Returns the smallest sortedmap entry greater than key, or nil if no match present."
+  [sortedmap key] (first (seq-after sortedmap key)))
+(defn find>=
+  "Returns the smallest sortedmap entry greater than or equal to key, or nil if no match present."
+  [sortedmap key] (first (seq-from sortedmap key)))
+
+
 (defn zipmap
   "Returns a map with the keys mapped to the corresponding vals."
   [keys vals]
Index: trunk/src/jvm/clojure/lang/RT.java
===================================================================
--- trunk/src/jvm/clojure/lang/RT.java	(revision 810)
+++ trunk/src/jvm/clojure/lang/RT.java	(working copy)
@@ -511,6 +511,17 @@
 	return ((Associative) coll).entryAt(key);
 }
 
+static public Object seqFrom(Object coll, Object key){
+	if(coll == null)
+		return null;
+	return ((PersistentTreeMap) coll).seqFrom(key);
+}
+static public Object rseqFrom(Object coll, Object key){
+	if(coll == null)
+		return null;
+	return ((PersistentTreeMap) coll).rseqFrom(key);
+}
+
 //takes a seq of key,val,key,val
 
 //returns tail starting at val of matching key if found, else null
Index: trunk/src/jvm/clojure/lang/PersistentTreeMap.java
===================================================================
--- trunk/src/jvm/clojure/lang/PersistentTreeMap.java	(revision 810)
+++ trunk/src/jvm/clojure/lang/PersistentTreeMap.java	(working copy)
@@ -126,13 +126,26 @@
 	return null;
 }
 
+public ISeq seqFrom(Object key){
+	if(_count > 0)
+		return SearchSeq.create(searchGreaterEq(key), true);
+	return null;
+}
+
+
 public ISeq rseq() throws Exception{
 	if(_count > 0)
 		return Seq.create(tree, false, _count);
 	return null;
 }
 
+public ISeq rseqFrom(Object key){
+	if(_count > 0)
+		return SearchSeq.create(searchLessEq(key), false);
+	return null;
+}
 
+
 public NodeIterator iterator(){
 	return new NodeIterator(tree, true);
 }
@@ -229,6 +242,49 @@
 	return t;
 }
 
+ISeq searchGreaterEq(Object key){
+	ISeq stack = null;
+	Node t = tree;
+	while(t != null)
+		{
+		int c = doCompare(key, t.key);
+		if(c == 0)
+			{
+			stack = RT.cons(t, stack);
+			return stack;
+			}
+		else if(c < 0)
+			{
+			stack = RT.cons(t, stack);
+			t = t.left();
+			}
+		else
+			t = t.right();
+		}
+	return stack;
+}
+ISeq searchLessEq(Object key){
+	ISeq stack = null;
+	Node t = tree;
+	while(t != null)
+		{
+		int c = doCompare(key, t.key);
+		if(c == 0)
+			{
+			stack = RT.cons(t, stack);
+			return stack;
+			}
+		else if(c > 0)
+			{
+			stack = RT.cons(t, stack);
+			t = t.right();
+			}
+		else
+			t = t.left();
+		}
+	return stack;
+}
+
 public int doCompare(Object k1, Object k2){
 	if(comp != null)
 		return comp.compare(k1, k2);
@@ -711,14 +767,16 @@
 	public Object first(){
 		return stack.first();
 	}
-
+	
+	protected ISeq restStack(){
+		Node t = (Node) stack.first();
+		return push(asc ? t.right() : t.left(), stack.rest(), asc);
+	}
+	
 	public ISeq rest(){
-		Node t = (Node) stack.first();
-		ISeq nextstack = push(asc ? t.right() : t.left(), stack.rest(), asc);
+		ISeq nextstack = restStack();
 		if(nextstack != null)
-			{
 			return new Seq(nextstack, asc, cnt - 1);
-			}
 		return null;
 	}
 
@@ -731,6 +789,61 @@
 	}
 }
 
+static public class SearchSeq extends Seq{
+	/// Is the cachedCount valid?
+	boolean gotCount;
+	/// If count() has been called previously, its value is cached.
+	int cachedCount;
+	
+	SearchSeq(IPersistentMap meta, ISeq stack, boolean asc){
+		super(meta, stack, asc, 0);
+		this.gotCount = false;
+		this.cachedCount = 0;
+	}
+	
+	public SearchSeq(ISeq stack, boolean asc)
+	{
+		super(stack, asc, 0);
+		this.gotCount = false;
+		this.cachedCount = 0;
+	}
+	SearchSeq(ISeq stack, boolean asc, boolean gotCount, int cachedCount)
+	{
+		super(stack, asc, 0);
+		this.gotCount = gotCount;
+		this.cachedCount = cachedCount;
+	}
+	
+	static SearchSeq create(ISeq stack, boolean asc){
+		if (stack == null)
+			return null;
+		return new SearchSeq(stack, asc);
+	}
+	
+	public int count(){
+		if(gotCount)
+			return cachedCount;
+		
+		int c = 0;
+		ISeq pos = this;
+		while (pos != null)
+			{
+			pos = pos.rest();
+			++c;
+			}
+		cachedCount = c;
+		gotCount = true;
+		return c;
+	}
+	
+	public ISeq rest(){
+		ISeq nextstack = restStack();
+		if(nextstack != null)
+			return new SearchSeq(nextstack, asc, gotCount, cachedCount - 1);
+		return null;
+	}
+}
+
 static public class NodeIterator implements Iterator{
 	Stack stack = new Stack();
 	boolean asc;
