| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  | /*************************************************************************
 | 
					
						
							|  |  |  | *									 * | 
					
						
							|  |  |  | *	 YAP Prolog 							 * | 
					
						
							|  |  |  | *									 * | 
					
						
							|  |  |  | *	Yap Prolog was developed at NCCUP - Universidade do Porto	 * | 
					
						
							|  |  |  | *									 * | 
					
						
							|  |  |  | * Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997	 * | 
					
						
							|  |  |  | *									 * | 
					
						
							|  |  |  | ************************************************************************** | 
					
						
							|  |  |  | *									 * | 
					
						
							|  |  |  | * File:		sort.c							 * | 
					
						
							|  |  |  | * Last rev:								 * | 
					
						
							|  |  |  | * mods:									 * | 
					
						
							|  |  |  | * comments:	sorting in Prolog					 * | 
					
						
							|  |  |  | *									 * | 
					
						
							|  |  |  | *************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* for the moment, follow Prolog's traditional mergesort */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "Yap.h"
 | 
					
						
							|  |  |  | #include "Yatom.h"
 | 
					
						
							| 
									
										
										
										
											2009-10-23 14:22:17 +01:00
										 |  |  | #include "YapHeap.h"
 | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  | #ifndef NULL
 | 
					
						
							|  |  |  | #define NULL (void *)0
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* fill in the even or the odd elements */ | 
					
						
							|  |  |  | #define M_EVEN  0
 | 
					
						
							|  |  |  | #define M_ODD   1
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-07 16:02:55 +00:00
										 |  |  | STATIC_PROTO(Int build_new_list, (CELL *, Term CACHE_TYPE)); | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  | STATIC_PROTO(void simple_mergesort, (CELL *, Int, int)); | 
					
						
							|  |  |  | STATIC_PROTO(Int compact_mergesort, (CELL *, Int, int)); | 
					
						
							|  |  |  | STATIC_PROTO(int key_mergesort, (CELL *, Int, int, Functor)); | 
					
						
							|  |  |  | STATIC_PROTO(void adjust_vector, (CELL *, Int)); | 
					
						
							| 
									
										
										
										
											2011-03-07 16:02:55 +00:00
										 |  |  | STATIC_PROTO(Int p_sort, ( USES_REGS1 )); | 
					
						
							|  |  |  | STATIC_PROTO(Int p_msort, ( USES_REGS1 )); | 
					
						
							|  |  |  | STATIC_PROTO(Int p_ksort, ( USES_REGS1 )); | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* copy to a new list of terms */ | 
					
						
							|  |  |  | static Int | 
					
						
							| 
									
										
										
										
											2011-03-07 16:02:55 +00:00
										 |  |  | build_new_list(CELL *pt, Term t USES_REGS) | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   Int out = 0; | 
					
						
							|  |  |  |   if (IsVarTerm(t)) | 
					
						
							|  |  |  |     return(-1); | 
					
						
							|  |  |  |   if (t == TermNil) | 
					
						
							|  |  |  |     return(0); | 
					
						
							|  |  |  |  restart: | 
					
						
							|  |  |  |   while (IsPairTerm(t)) { | 
					
						
							|  |  |  |     out++; | 
					
						
							|  |  |  |     pt[0] = HeadOfTerm(t); | 
					
						
							|  |  |  |     t = TailOfTerm(t); | 
					
						
							|  |  |  |     if (IsVarTerm(t)) | 
					
						
							|  |  |  |       return(-1); | 
					
						
							|  |  |  |     if (t == TermNil) { | 
					
						
							|  |  |  |       return(out); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     pt += 2; | 
					
						
							|  |  |  |     if (pt > ASP - 4096) { | 
					
						
							| 
									
										
										
										
											2008-08-28 04:43:00 +01:00
										 |  |  |       if (!Yap_gcl((ASP-H)*sizeof(CELL), 2, ENV, gc_P(P,CP))) { | 
					
						
							| 
									
										
										
										
											2011-05-23 16:19:47 +01:00
										 |  |  | 	Yap_Error(OUT_OF_STACK_ERROR, TermNil, LOCAL_ErrorMessage); | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  | 	return(FALSE); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       t = Deref(ARG1); | 
					
						
							|  |  |  |       pt = H; | 
					
						
							|  |  |  |       out = 0; | 
					
						
							|  |  |  |       goto restart; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return(-1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* copy to a new list of terms */ | 
					
						
							|  |  |  | static | 
					
						
							|  |  |  | void simple_mergesort(CELL *pt, Int size, int my_p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (size > 2) { | 
					
						
							|  |  |  |     Int half_size = size / 2; | 
					
						
							|  |  |  |     CELL *pt_left, *pt_right, *end_pt, *end_pt_left; | 
					
						
							|  |  |  |     int left_p, right_p; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pt_right = pt + half_size*2; | 
					
						
							|  |  |  |     left_p = my_p^1; | 
					
						
							|  |  |  |     right_p = my_p; | 
					
						
							|  |  |  |     simple_mergesort(pt, half_size, left_p); | 
					
						
							|  |  |  |     simple_mergesort(pt_right, size-half_size, right_p); | 
					
						
							|  |  |  |     /* now implement a simple merge routine */ | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     /* pointer to after the end of the list */ | 
					
						
							|  |  |  |     end_pt = pt + 2*size; | 
					
						
							|  |  |  |     /* pointer to the element after the last element to the left */ | 
					
						
							|  |  |  |     end_pt_left = pt+half_size*2; | 
					
						
							|  |  |  |     /* where is left list */ | 
					
						
							|  |  |  |     pt_left = pt+left_p; | 
					
						
							|  |  |  |     /* where is right list */ | 
					
						
							|  |  |  |     pt_right += right_p; | 
					
						
							|  |  |  |     /* where is new list */ | 
					
						
							|  |  |  |     pt += my_p; | 
					
						
							|  |  |  |     /* while there are elements in the left or right vector do compares */ | 
					
						
							|  |  |  |     while (pt_left < end_pt_left && pt_right < end_pt) { | 
					
						
							|  |  |  |       /* if the element to the left is larger than the one to the right */ | 
					
						
							| 
									
										
										
										
											2002-11-18 18:18:05 +00:00
										 |  |  |       if (Yap_compare_terms(pt_left[0], pt_right[0]) <= 0) { | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  | 	/* copy the one to the left */ | 
					
						
							|  |  |  | 	pt[0] = pt_left[0]; | 
					
						
							|  |  |  | 	/* and avance the two pointers */ | 
					
						
							|  |  |  | 	pt += 2; | 
					
						
							|  |  |  | 	pt_left += 2; | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  | 	/* otherwise, copy the one to the right */ | 
					
						
							|  |  |  | 	pt[0] = pt_right[0]; | 
					
						
							|  |  |  | 	pt += 2; | 
					
						
							|  |  |  | 	pt_right += 2; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* if any elements were left in the left vector just copy them */ | 
					
						
							|  |  |  |     while (pt_left < end_pt_left) { | 
					
						
							|  |  |  |       pt[0] = pt_left[0]; | 
					
						
							|  |  |  |       pt += 2; | 
					
						
							|  |  |  |       pt_left += 2; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* if any elements were left in the right vector
 | 
					
						
							|  |  |  |        and they are in the wrong place, just copy them */ | 
					
						
							|  |  |  |     if (my_p != right_p) { | 
					
						
							|  |  |  |       while(pt_right < end_pt) { | 
					
						
							|  |  |  | 	pt[0] = pt_right[0]; | 
					
						
							|  |  |  | 	pt += 2; | 
					
						
							|  |  |  | 	pt_right += 2; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } else { | 
					
						
							| 
									
										
										
										
											2002-11-18 18:18:05 +00:00
										 |  |  |     if (size > 1 && (Yap_compare_terms(pt[0],pt[2]) > 0)) { | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  |       CELL t = pt[2]; | 
					
						
							|  |  |  |       pt[2+my_p] = pt[0]; | 
					
						
							|  |  |  |       pt[my_p] = t; | 
					
						
							|  |  |  |     } else if (my_p) { | 
					
						
							|  |  |  |       pt[1] = pt[0]; | 
					
						
							|  |  |  |       if (size > 1) | 
					
						
							|  |  |  | 	pt[3] = pt[2]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* copy to a new list of terms */ | 
					
						
							|  |  |  | static | 
					
						
							|  |  |  | int key_mergesort(CELL *pt, Int size, int my_p, Functor FuncDMinus) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (size > 2) { | 
					
						
							|  |  |  |     Int half_size = size / 2; | 
					
						
							|  |  |  |     CELL *pt_left, *pt_right, *end_pt, *end_pt_left; | 
					
						
							|  |  |  |     int left_p, right_p; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pt_right = pt + half_size*2; | 
					
						
							|  |  |  |     left_p = my_p^1; | 
					
						
							|  |  |  |     right_p = my_p; | 
					
						
							|  |  |  |     if (!key_mergesort(pt, half_size, left_p, FuncDMinus)) | 
					
						
							|  |  |  |       return(FALSE); | 
					
						
							|  |  |  |     if (!key_mergesort(pt_right, size-half_size, right_p, FuncDMinus)) | 
					
						
							|  |  |  |       return(FALSE); | 
					
						
							|  |  |  |     /* now implement a simple merge routine */ | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     /* pointer to after the end of the list */ | 
					
						
							|  |  |  |     end_pt = pt + 2*size; | 
					
						
							|  |  |  |     /* pointer to the element after the last element to the left */ | 
					
						
							|  |  |  |     end_pt_left = pt+half_size*2; | 
					
						
							|  |  |  |     /* where is left list */ | 
					
						
							|  |  |  |     pt_left = pt+left_p; | 
					
						
							|  |  |  |     /* where is right list */ | 
					
						
							|  |  |  |     pt_right += right_p; | 
					
						
							|  |  |  |     /* where is new list */ | 
					
						
							|  |  |  |     pt += my_p; | 
					
						
							|  |  |  |     /* while there are elements in the left or right vector do compares */ | 
					
						
							|  |  |  |     while (pt_left < end_pt_left && pt_right < end_pt) { | 
					
						
							|  |  |  |       /* if the element to the left is larger than the one to the right */ | 
					
						
							|  |  |  |       Term t0 = pt_left[0] , t1 = pt_right[0]; | 
					
						
							|  |  |  |       if (IsVarTerm(t0) || !IsApplTerm(t0) || FunctorOfTerm(t0) != FuncDMinus) | 
					
						
							|  |  |  | 	return(FALSE); | 
					
						
							|  |  |  |       t0 = ArgOfTerm(1,t0); | 
					
						
							|  |  |  |       if (IsVarTerm(t1) || !IsApplTerm(t1) || FunctorOfTerm(t1) != FuncDMinus) | 
					
						
							|  |  |  | 	return(FALSE); | 
					
						
							|  |  |  |       t1 = ArgOfTerm(1,t1); | 
					
						
							| 
									
										
										
										
											2002-11-18 18:18:05 +00:00
										 |  |  |       if (Yap_compare_terms(t0, t1) <= 0) { | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  | 	/* copy the one to the left */ | 
					
						
							|  |  |  | 	pt[0] = pt_left[0]; | 
					
						
							|  |  |  | 	/* and avance the two pointers */ | 
					
						
							|  |  |  | 	pt += 2; | 
					
						
							|  |  |  | 	pt_left += 2; | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  | 	/* otherwise, copy the one to the right */ | 
					
						
							|  |  |  | 	pt[0] = pt_right[0]; | 
					
						
							|  |  |  | 	pt += 2; | 
					
						
							|  |  |  | 	pt_right += 2; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* if any elements were left in the left vector just copy them */ | 
					
						
							|  |  |  |     while (pt_left < end_pt_left) { | 
					
						
							|  |  |  |       pt[0] = pt_left[0]; | 
					
						
							|  |  |  |       pt += 2; | 
					
						
							|  |  |  |       pt_left += 2; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* if any elements were left in the right vector
 | 
					
						
							|  |  |  |        and they are in the wrong place, just copy them */ | 
					
						
							|  |  |  |     if (my_p != right_p) { | 
					
						
							|  |  |  |       while(pt_right < end_pt) { | 
					
						
							|  |  |  | 	pt[0] = pt_right[0]; | 
					
						
							|  |  |  | 	pt += 2; | 
					
						
							|  |  |  | 	pt_right += 2; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  |     if (size > 1) { | 
					
						
							|  |  |  |       Term t0 = pt[0], t1 = pt[2]; | 
					
						
							|  |  |  |       if (IsVarTerm(t0) || !IsApplTerm(t0) || FunctorOfTerm(t0) != FuncDMinus) | 
					
						
							|  |  |  | 	return(FALSE); | 
					
						
							|  |  |  |       t0 = ArgOfTerm(1,t0); | 
					
						
							|  |  |  |       if (IsVarTerm(t1) || !IsApplTerm(t1) || FunctorOfTerm(t1) != FuncDMinus) | 
					
						
							|  |  |  | 	return(FALSE); | 
					
						
							|  |  |  |       t1 = ArgOfTerm(1,t1); | 
					
						
							| 
									
										
										
										
											2002-11-18 18:18:05 +00:00
										 |  |  |       if (Yap_compare_terms(t0,t1) > 0) { | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  | 	CELL t = pt[2]; | 
					
						
							|  |  |  | 	pt[2+my_p] = pt[0]; | 
					
						
							|  |  |  | 	pt[my_p] = t; | 
					
						
							|  |  |  |       } else if (my_p) { | 
					
						
							|  |  |  | 	pt[1] = pt[0]; | 
					
						
							|  |  |  | 	pt[3] = pt[2]; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       if (my_p)  | 
					
						
							|  |  |  | 	pt[1] = pt[0]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return(TRUE); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* copy to a new list of terms and compress duplicates */ | 
					
						
							|  |  |  | static | 
					
						
							|  |  |  | Int compact_mergesort(CELL *pt, Int size, int my_p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (size > 2) { | 
					
						
							|  |  |  |     Int half_size = size / 2; | 
					
						
							|  |  |  |     CELL *pt_left, *pt_right, *end_pt_right, *end_pt_left; | 
					
						
							|  |  |  |     int left_p, right_p; | 
					
						
							|  |  |  |     Int lsize, rsize; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pt_right = pt + half_size*2; | 
					
						
							|  |  |  |     left_p = my_p^1; | 
					
						
							|  |  |  |     right_p = my_p; | 
					
						
							|  |  |  |     lsize = compact_mergesort(pt, half_size, left_p); | 
					
						
							|  |  |  |     rsize = compact_mergesort(pt_right, size-half_size, right_p); | 
					
						
							|  |  |  |     /* now implement a simple merge routine */ | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     /* where is left list */ | 
					
						
							|  |  |  |     pt_left = pt+left_p; | 
					
						
							|  |  |  |     /* pointer to the element after the last element to the left */ | 
					
						
							|  |  |  |     end_pt_left = pt+2*lsize; | 
					
						
							|  |  |  |     /* where is right list */ | 
					
						
							|  |  |  |     pt_right += right_p; | 
					
						
							|  |  |  |     /* pointer to after the end of the list */ | 
					
						
							|  |  |  |     end_pt_right = pt_right + 2*rsize; | 
					
						
							|  |  |  |     /* where is new list */ | 
					
						
							|  |  |  |     pt += my_p; | 
					
						
							|  |  |  |     size = 0; | 
					
						
							|  |  |  |     /* while there are elements in the left or right vector do compares */ | 
					
						
							|  |  |  |     while (pt_left < end_pt_left && pt_right < end_pt_right) { | 
					
						
							|  |  |  |       /* if the element to the left is larger than the one to the right */ | 
					
						
							| 
									
										
										
										
											2002-11-18 18:18:05 +00:00
										 |  |  |       Int cmp = Yap_compare_terms(pt_left[0], pt_right[0]); | 
					
						
							| 
									
										
										
										
											2011-11-04 11:41:35 +09:00
										 |  |  |       if (cmp < (Int)0) { | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  | 	/* copy the one to the left */ | 
					
						
							|  |  |  | 	pt[0] = pt_left[0]; | 
					
						
							|  |  |  | 	/* and avance the two pointers */ | 
					
						
							|  |  |  | 	pt += 2; | 
					
						
							|  |  |  | 	size ++; | 
					
						
							|  |  |  | 	pt_left += 2; | 
					
						
							| 
									
										
										
										
											2011-11-04 11:41:35 +09:00
										 |  |  |       } else if (cmp == (Int)0) { | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  | 	/* otherwise, just skip one of them, anyone */ | 
					
						
							|  |  |  | 	pt_left += 2; | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  | 	/* otherwise, copy the one to the right */ | 
					
						
							|  |  |  | 	pt[0] = pt_right[0]; | 
					
						
							|  |  |  | 	pt += 2; | 
					
						
							|  |  |  | 	pt_right += 2; | 
					
						
							|  |  |  | 	size++; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* if any elements were left in the left vector just copy them */ | 
					
						
							|  |  |  |     while (pt_left < end_pt_left) { | 
					
						
							|  |  |  |       pt[0] = pt_left[0]; | 
					
						
							|  |  |  |       pt += 2; | 
					
						
							|  |  |  |       pt_left += 2; | 
					
						
							|  |  |  |       size++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* if any elements were left in the right vector
 | 
					
						
							|  |  |  |        and they are in the wrong place, just copy them */ | 
					
						
							|  |  |  |     while(pt_right < end_pt_right) { | 
					
						
							|  |  |  |       pt[0] = pt_right[0]; | 
					
						
							|  |  |  |       pt += 2; | 
					
						
							|  |  |  |       pt_right += 2; | 
					
						
							|  |  |  |       size++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return(size); | 
					
						
							|  |  |  |   } else if (size == 2) { | 
					
						
							| 
									
										
										
										
											2002-11-18 18:18:05 +00:00
										 |  |  |     Int cmp = Yap_compare_terms(pt[0],pt[2]); | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  |     if (cmp > 0) { | 
					
						
							|  |  |  |       /* swap */ | 
					
						
							|  |  |  |       CELL t = pt[2]; | 
					
						
							|  |  |  |       pt[2+my_p] = pt[0]; | 
					
						
							|  |  |  |       pt[my_p] = t; | 
					
						
							|  |  |  |       return(2); | 
					
						
							|  |  |  |     } else if (cmp == 0) { | 
					
						
							|  |  |  |       if (my_p) | 
					
						
							|  |  |  | 	pt[1] = pt[0]; | 
					
						
							|  |  |  |       return(1); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       if (my_p) { | 
					
						
							|  |  |  | 	pt[1] = pt[0]; | 
					
						
							|  |  |  | 	pt[3] = pt[2]; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return(2); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  |     /* size = 1 */ | 
					
						
							|  |  |  |     if (my_p) | 
					
						
							|  |  |  |       pt[1] = pt[0]; | 
					
						
							|  |  |  |     return(1); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | adjust_vector(CELL *pt, Int size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* the elements are where they should be */ | 
					
						
							|  |  |  |   CELL *ptf = pt + 2*(size-1); | 
					
						
							|  |  |  |   pt ++; | 
					
						
							|  |  |  |   while (pt < ptf) { | 
					
						
							|  |  |  |     pt[0] = AbsPair(pt+1); | 
					
						
							|  |  |  |     pt += 2; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   /* close the list */ | 
					
						
							|  |  |  |   pt[0] = TermNil; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static Int | 
					
						
							| 
									
										
										
										
											2011-03-07 16:02:55 +00:00
										 |  |  | p_sort( USES_REGS1 ) | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   /* use the heap to build a new list */ | 
					
						
							|  |  |  |   CELL *pt = H; | 
					
						
							|  |  |  |   Term out; | 
					
						
							|  |  |  |   /* list size */ | 
					
						
							|  |  |  |   Int size; | 
					
						
							| 
									
										
										
										
											2011-03-07 16:02:55 +00:00
										 |  |  |   size = build_new_list(pt, Deref(ARG1) PASS_REGS); | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  |   if (size < 0) | 
					
						
							|  |  |  |     return(FALSE); | 
					
						
							|  |  |  |   if (size < 2) | 
					
						
							| 
									
										
										
										
											2002-11-18 18:18:05 +00:00
										 |  |  |      return(Yap_unify(ARG1, ARG2)); | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  |   pt = H;            /* because of possible garbage collection */ | 
					
						
							|  |  |  |   /* make sure no one writes on our temp data structure */ | 
					
						
							|  |  |  |   H += size*2; | 
					
						
							|  |  |  |   /* reserve the necessary space */ | 
					
						
							|  |  |  |   size = compact_mergesort(pt, size, M_EVEN); | 
					
						
							|  |  |  |   /* reajust space */ | 
					
						
							|  |  |  |   H = pt+size*2; | 
					
						
							|  |  |  |   adjust_vector(pt, size); | 
					
						
							|  |  |  |   out = AbsPair(pt); | 
					
						
							| 
									
										
										
										
											2002-11-18 18:18:05 +00:00
										 |  |  |   return(Yap_unify(out, ARG2)); | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static Int | 
					
						
							| 
									
										
										
										
											2011-03-07 16:02:55 +00:00
										 |  |  | p_msort( USES_REGS1 ) | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   /* use the heap to build a new list */ | 
					
						
							|  |  |  |   CELL *pt = H; | 
					
						
							|  |  |  |   Term out; | 
					
						
							|  |  |  |   /* list size */ | 
					
						
							|  |  |  |   Int size; | 
					
						
							| 
									
										
										
										
											2011-03-07 16:02:55 +00:00
										 |  |  |   size = build_new_list(pt, Deref(ARG1) PASS_REGS); | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  |   if (size < 0) | 
					
						
							|  |  |  |     return(FALSE); | 
					
						
							|  |  |  |   if (size < 2) | 
					
						
							| 
									
										
										
										
											2002-11-18 18:18:05 +00:00
										 |  |  |      return(Yap_unify(ARG1, ARG2)); | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  |   pt = H;            /* because of possible garbage collection */ | 
					
						
							|  |  |  |   /* reserve the necessary space */ | 
					
						
							|  |  |  |   H += size*2; | 
					
						
							|  |  |  |   simple_mergesort(pt, size, M_EVEN); | 
					
						
							|  |  |  |   adjust_vector(pt, size); | 
					
						
							|  |  |  |   out = AbsPair(pt); | 
					
						
							| 
									
										
										
										
											2002-11-18 18:18:05 +00:00
										 |  |  |   return(Yap_unify(out, ARG2)); | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static Int | 
					
						
							| 
									
										
										
										
											2011-03-07 16:02:55 +00:00
										 |  |  | p_ksort( USES_REGS1 ) | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   /* use the heap to build a new list */ | 
					
						
							|  |  |  |   CELL *pt = H; | 
					
						
							|  |  |  |   Term out; | 
					
						
							|  |  |  |   /* list size */ | 
					
						
							|  |  |  |   Int size; | 
					
						
							| 
									
										
										
										
											2011-03-07 16:02:55 +00:00
										 |  |  |   size = build_new_list(pt, Deref(ARG1) PASS_REGS); | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  |   if (size < 0) | 
					
						
							|  |  |  |     return(FALSE); | 
					
						
							|  |  |  |   if (size < 2) | 
					
						
							| 
									
										
										
										
											2002-11-18 18:18:05 +00:00
										 |  |  |      return(Yap_unify(ARG1, ARG2)); | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  |   /* reserve the necessary space */ | 
					
						
							|  |  |  |   pt = H;            /* because of possible garbage collection */ | 
					
						
							|  |  |  |   H += size*2; | 
					
						
							| 
									
										
										
										
											2008-12-24 09:04:44 +00:00
										 |  |  |   if (!key_mergesort(pt, size, M_EVEN, FunctorMinus)) | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  |     return(FALSE); | 
					
						
							|  |  |  |   adjust_vector(pt, size); | 
					
						
							|  |  |  |   out = AbsPair(pt); | 
					
						
							| 
									
										
										
										
											2002-11-18 18:18:05 +00:00
										 |  |  |   return(Yap_unify(out, ARG2)); | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void  | 
					
						
							| 
									
										
										
										
											2002-11-18 18:18:05 +00:00
										 |  |  | Yap_InitSortPreds(void) | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2004-11-18 22:32:40 +00:00
										 |  |  |   Yap_InitCPred("$sort", 2, p_sort, HiddenPredFlag); | 
					
						
							|  |  |  |   Yap_InitCPred("$msort", 2, p_msort, HiddenPredFlag); | 
					
						
							|  |  |  |   Yap_InitCPred("$keysort", 2, p_ksort, HiddenPredFlag); | 
					
						
							| 
									
										
										
										
											2001-04-09 19:54:03 +00:00
										 |  |  | } |