comparison src/fns.c @ 5470:0af042a0c116

Merge with trunk.
author Mats Lidell <matsl@xemacs.org>
date Mon, 07 Feb 2011 21:22:17 +0100
parents a9094f28f9a9 94bbd4792049
children 00e79bbbe48f
comparison
equal deleted inserted replaced
5469:2a8a04f73c15 5470:0af042a0c116
59 Lisp_Object Qsome, Qevery, Qmaplist, Qmapl, Qmapcon, Qreduce, Qsubstitute; 59 Lisp_Object Qsome, Qevery, Qmaplist, Qmapl, Qmapcon, Qreduce, Qsubstitute;
60 Lisp_Object Q_start1, Q_start2, Q_end1, Q_end2, Q_if_, Q_if_not, Q_stable; 60 Lisp_Object Q_start1, Q_start2, Q_end1, Q_end2, Q_if_, Q_if_not, Q_stable;
61 Lisp_Object Q_test_not, Q_count, Qnsubstitute, Qdelete_duplicates, Qmismatch; 61 Lisp_Object Q_test_not, Q_count, Qnsubstitute, Qdelete_duplicates, Qmismatch;
62 62
63 Lisp_Object Qintersection, Qset_difference, Qnset_difference; 63 Lisp_Object Qintersection, Qset_difference, Qnset_difference;
64 Lisp_Object Qnunion, Qnintersection, Qsubsetp; 64 Lisp_Object Qnunion, Qnintersection, Qsubsetp, Qcar_less_than_car;
65 65
66 Lisp_Object Qbase64_conversion_error; 66 Lisp_Object Qbase64_conversion_error;
67 67
68 Lisp_Object Vpath_separator; 68 Lisp_Object Vpath_separator;
69 69
206 Lisp_Bit_Vector); 206 Lisp_Bit_Vector);
207 207
208 /* Various test functions for #'member*, #'assoc* and the other functions 208 /* Various test functions for #'member*, #'assoc* and the other functions
209 that take both TEST and KEY arguments. */ 209 that take both TEST and KEY arguments. */
210 210
211 typedef Boolint (*check_test_func_t) (Lisp_Object test, Lisp_Object key,
212 Lisp_Object item, Lisp_Object elt);
213
214 static Boolint 211 static Boolint
215 check_eq_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key), 212 check_eq_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key),
216 Lisp_Object item, Lisp_Object elt) 213 Lisp_Object item, Lisp_Object elt)
217 { 214 {
218 return EQ (item, elt); 215 return EQ (item, elt);
435 elt1 = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args)); 432 elt1 = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args));
436 UNGCPRO; 433 UNGCPRO;
437 434
438 return !NILP (elt1); 435 return !NILP (elt1);
439 } 436 }
440 437
438 static Boolint
439 check_lss_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key),
440 Lisp_Object elt1, Lisp_Object elt2)
441 {
442 return bytecode_arithcompare (elt1, elt2) < 0;
443 }
444
445 static Boolint
446 check_lss_key (Lisp_Object UNUSED (test), Lisp_Object key,
447 Lisp_Object elt1, Lisp_Object elt2)
448 {
449 Lisp_Object args[] = { key, elt1, elt2 };
450 struct gcpro gcpro1;
451
452 GCPRO1 (args[0]);
453 gcpro1.nvars = countof (args);
454 args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args));
455 args[1] = key;
456 args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1));
457 UNGCPRO;
458
459 return bytecode_arithcompare (args[0], args[1]) < 0;
460 }
461
462 Boolint
463 check_lss_key_car (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key),
464 Lisp_Object elt1, Lisp_Object elt2)
465 {
466 struct gcpro gcpro1, gcpro2;
467
468 GCPRO2 (elt1, elt2);
469 elt1 = CONSP (elt1) ? XCAR (elt1) : Fcar (elt1);
470 elt2 = CONSP (elt2) ? XCAR (elt2) : Fcar (elt2);
471 UNGCPRO;
472
473 return bytecode_arithcompare (elt1, elt2) < 0;
474 }
475
476 Boolint
477 check_string_lessp_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key),
478 Lisp_Object elt1, Lisp_Object elt2)
479 {
480 return !NILP (Fstring_lessp (elt1, elt2));
481 }
482
483 static Boolint
484 check_string_lessp_key (Lisp_Object UNUSED (test), Lisp_Object key,
485 Lisp_Object elt1, Lisp_Object elt2)
486 {
487 Lisp_Object args[] = { key, elt1, elt2 };
488 struct gcpro gcpro1;
489
490 GCPRO1 (args[0]);
491 gcpro1.nvars = countof (args);
492 args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args));
493 args[1] = key;
494 args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1));
495 UNGCPRO;
496
497 return !NILP (Fstring_lessp (args[0], args[1]));
498 }
499
500 static Boolint
501 check_string_lessp_key_car (Lisp_Object UNUSED (test),
502 Lisp_Object UNUSED (key),
503 Lisp_Object elt1, Lisp_Object elt2)
504 {
505 struct gcpro gcpro1, gcpro2;
506
507 GCPRO2 (elt1, elt2);
508 elt1 = CONSP (elt1) ? XCAR (elt1) : Fcar (elt1);
509 elt2 = CONSP (elt2) ? XCAR (elt2) : Fcar (elt2);
510 UNGCPRO;
511
512 return !NILP (Fstring_lessp (elt1, elt2));
513 }
514
441 static check_test_func_t 515 static check_test_func_t
442 get_check_match_function_1 (Lisp_Object item, 516 get_check_match_function_1 (Lisp_Object item,
443 Lisp_Object *test_inout, Lisp_Object test_not, 517 Lisp_Object *test_inout, Lisp_Object test_not,
444 Lisp_Object if_, Lisp_Object if_not, 518 Lisp_Object if_, Lisp_Object if_not,
445 Lisp_Object key, Boolint *test_not_unboundp_out, 519 Lisp_Object key, Boolint *test_not_unboundp_out,
642 return get_check_match_function_1 (Qunbound, test_inout, test_not, 716 return get_check_match_function_1 (Qunbound, test_inout, test_not,
643 if_, if_not, key, 717 if_, if_not, key,
644 test_not_unboundp_out, test_func_out); 718 test_not_unboundp_out, test_func_out);
645 } 719 }
646 720
721 /* Given PREDICATE and KEY, return a C function pointer appropriate for use
722 in deciding whether one given elements of a sequence is less than
723 another. */
724
725 static check_test_func_t
726 get_merge_predicate (Lisp_Object predicate, Lisp_Object key)
727 {
728 predicate = indirect_function (predicate, 1);
729
730 if (NILP (key))
731 {
732 key = Qidentity;
733 }
734 else
735 {
736 key = indirect_function (key, 1);
737 if (EQ (key, XSYMBOL_FUNCTION (Qidentity)))
738 {
739 key = Qidentity;
740 }
741 }
742
743 if (EQ (key, Qidentity) && EQ (predicate,
744 XSYMBOL_FUNCTION (Qcar_less_than_car)))
745 {
746 key = XSYMBOL_FUNCTION (Qcar);
747 predicate = XSYMBOL_FUNCTION (Qlss);
748 }
749
750 if (EQ (predicate, XSYMBOL_FUNCTION (Qlss)))
751 {
752 if (EQ (key, Qidentity))
753 {
754 return check_lss_nokey;
755 }
756
757 if (EQ (key, XSYMBOL_FUNCTION (Qcar)))
758 {
759 return check_lss_key_car;
760 }
761
762 return check_lss_key;
763 }
764
765 if (EQ (predicate, XSYMBOL_FUNCTION (Qstring_lessp)))
766 {
767 if (EQ (key, Qidentity))
768 {
769 return check_string_lessp_nokey;
770 }
771
772 if (EQ (key, XSYMBOL_FUNCTION (Qcar)))
773 {
774 return check_string_lessp_key_car;
775 }
776
777 return check_string_lessp_key;
778 }
779
780 if (EQ (key, Qidentity))
781 {
782 return check_other_nokey;
783 }
784
785 return check_match_other_key;
786 }
647 787
648 DEFUN ("identity", Fidentity, 1, 1, 0, /* 788 DEFUN ("identity", Fidentity, 1, 1, 0, /*
649 Return the argument unchanged. 789 Return the argument unchanged.
650 */ 790 */
651 (arg)) 791 (arg))
4690 } 4830 }
4691 4831
4692 return result; 4832 return result;
4693 } 4833 }
4694 4834
4695 static Lisp_Object
4696 c_merge_predicate_key (Lisp_Object obj1, Lisp_Object obj2,
4697 Lisp_Object pred, Lisp_Object key_func)
4698 {
4699 struct gcpro gcpro1;
4700 Lisp_Object args[3];
4701
4702 /* We could use call2() and call3() here, but we're called O(nlogn) times
4703 for a sequence of length n, it make some sense to inline them. */
4704 args[0] = key_func;
4705 args[1] = obj1;
4706 args[2] = Qnil;
4707
4708 GCPRO1 (args[0]);
4709 gcpro1.nvars = countof (args);
4710
4711 obj1 = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args));
4712
4713 args[1] = obj2;
4714 obj2 = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args));
4715
4716 args[0] = pred;
4717 args[1] = obj1;
4718 args[2] = obj2;
4719
4720 RETURN_UNGCPRO (IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args)));
4721 }
4722
4723 static Lisp_Object
4724 c_merge_predicate_nokey (Lisp_Object obj1, Lisp_Object obj2,
4725 Lisp_Object pred, Lisp_Object UNUSED (key_func))
4726 {
4727 struct gcpro gcpro1;
4728 Lisp_Object args[3];
4729
4730 /* This is (almost) the implementation of call2, it makes some sense to
4731 inline it here. */
4732 args[0] = pred;
4733 args[1] = obj1;
4734 args[2] = obj2;
4735
4736 GCPRO1 (args[0]);
4737 gcpro1.nvars = countof (args);
4738
4739 RETURN_UNGCPRO (IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args)));
4740 }
4741
4742 Lisp_Object 4835 Lisp_Object
4743 list_merge (Lisp_Object org_l1, Lisp_Object org_l2, 4836 list_merge (Lisp_Object org_l1, Lisp_Object org_l2,
4744 Lisp_Object (*c_predicate) (Lisp_Object, Lisp_Object, 4837 check_test_func_t check_merge,
4745 Lisp_Object, Lisp_Object), 4838 Lisp_Object predicate, Lisp_Object key)
4746 Lisp_Object predicate, Lisp_Object key_func)
4747 { 4839 {
4748 Lisp_Object value; 4840 Lisp_Object value;
4749 Lisp_Object tail; 4841 Lisp_Object tail;
4750 Lisp_Object tem; 4842 Lisp_Object tem;
4751 Lisp_Object l1, l2; 4843 Lisp_Object l1, l2;
4758 tail = Qnil; 4850 tail = Qnil;
4759 value = Qnil; 4851 value = Qnil;
4760 tortoises[0] = org_l1; 4852 tortoises[0] = org_l1;
4761 tortoises[1] = org_l2; 4853 tortoises[1] = org_l2;
4762 4854
4763 if (NULL == c_predicate) 4855 /* It is sufficient to protect org_l1 and org_l2. When l1 and l2 are
4764 { 4856 updated, we copy the new values back into the org_ vars. */
4765 c_predicate = EQ (key_func, Qidentity) ?
4766 c_merge_predicate_nokey : c_merge_predicate_key;
4767 }
4768
4769 /* It is sufficient to protect org_l1 and org_l2.
4770 When l1 and l2 are updated, we copy the new values
4771 back into the org_ vars. */
4772 4857
4773 GCPRO5 (org_l1, org_l2, predicate, value, tortoises[0]); 4858 GCPRO5 (org_l1, org_l2, predicate, value, tortoises[0]);
4774 gcpro5.nvars = 2; 4859 gcpro5.nvars = 2;
4775 4860
4776 while (1) 4861 while (1)
4790 return l1; 4875 return l1;
4791 Fsetcdr (tail, l1); 4876 Fsetcdr (tail, l1);
4792 return value; 4877 return value;
4793 } 4878 }
4794 4879
4795 if (NILP (c_predicate (Fcar (l2), Fcar (l1), predicate, key_func))) 4880 if (check_merge (predicate, key, Fcar (l2), Fcar (l1)) == 0)
4796 { 4881 {
4797 tem = l1; 4882 tem = l1;
4798 l1 = Fcdr (l1); 4883 l1 = Fcdr (l1);
4799 org_l1 = l1; 4884 org_l1 = l1;
4800 4885
4852 4937
4853 static void 4938 static void
4854 array_merge (Lisp_Object *dest, Elemcount dest_len, 4939 array_merge (Lisp_Object *dest, Elemcount dest_len,
4855 Lisp_Object *front, Elemcount front_len, 4940 Lisp_Object *front, Elemcount front_len,
4856 Lisp_Object *back, Elemcount back_len, 4941 Lisp_Object *back, Elemcount back_len,
4857 Lisp_Object (*c_predicate) (Lisp_Object, Lisp_Object, 4942 check_test_func_t check_merge,
4858 Lisp_Object, Lisp_Object), 4943 Lisp_Object predicate, Lisp_Object key)
4859 Lisp_Object predicate, Lisp_Object key_func)
4860 { 4944 {
4861 Elemcount ii, fronting, backing; 4945 Elemcount ii, fronting, backing;
4862 Lisp_Object *front_staging = front; 4946 Lisp_Object *front_staging = front;
4863 Lisp_Object *back_staging = back; 4947 Lisp_Object *back_staging = back;
4864 struct gcpro gcpro1, gcpro2; 4948 struct gcpro gcpro1, gcpro2;
4916 } 5000 }
4917 UNGCPRO; 5001 UNGCPRO;
4918 return; 5002 return;
4919 } 5003 }
4920 5004
4921 if (NILP (c_predicate (back_staging[backing], front_staging[fronting], 5005 if (check_merge (predicate, key, back_staging[backing],
4922 predicate, key_func))) 5006 front_staging[fronting]) == 0)
4923 { 5007 {
4924 dest[ii] = front_staging[fronting]; 5008 dest[ii] = front_staging[fronting];
4925 ++fronting; 5009 ++fronting;
4926 } 5010 }
4927 else 5011 else
4935 } 5019 }
4936 5020
4937 static Lisp_Object 5021 static Lisp_Object
4938 list_array_merge_into_list (Lisp_Object list, 5022 list_array_merge_into_list (Lisp_Object list,
4939 Lisp_Object *array, Elemcount array_len, 5023 Lisp_Object *array, Elemcount array_len,
4940 Lisp_Object (*c_predicate) (Lisp_Object, 5024 check_test_func_t check_merge,
4941 Lisp_Object, 5025 Lisp_Object predicate, Lisp_Object key,
4942 Lisp_Object,
4943 Lisp_Object),
4944 Lisp_Object predicate, Lisp_Object key_func,
4945 Boolint reverse_order) 5026 Boolint reverse_order)
4946 { 5027 {
4947 Lisp_Object tail = Qnil, value = Qnil, tortoise = list; 5028 Lisp_Object tail = Qnil, value = Qnil, tortoise = list;
4948 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; 5029 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
4949 Elemcount array_index = 0; 5030 Elemcount array_index = 0;
4978 return value; 5059 return value;
4979 } 5060 }
4980 5061
4981 5062
4982 if (reverse_order ? 5063 if (reverse_order ?
4983 !NILP (c_predicate (Fcar (list), array [array_index], predicate, 5064 check_merge (predicate, key, Fcar (list), array [array_index])
4984 key_func)) : 5065 : !check_merge (predicate, key, array [array_index], Fcar (list)))
4985 NILP (c_predicate (array [array_index], Fcar (list), predicate,
4986 key_func)))
4987 { 5066 {
4988 if (NILP (tail)) 5067 if (NILP (tail))
4989 { 5068 {
4990 value = tail = list; 5069 value = tail = list;
4991 } 5070 }
5027 } 5106 }
5028 5107
5029 static void 5108 static void
5030 list_list_merge_into_array (Lisp_Object *output, Elemcount output_len, 5109 list_list_merge_into_array (Lisp_Object *output, Elemcount output_len,
5031 Lisp_Object list_one, Lisp_Object list_two, 5110 Lisp_Object list_one, Lisp_Object list_two,
5032 Lisp_Object (*c_predicate) (Lisp_Object, 5111 check_test_func_t check_merge,
5033 Lisp_Object, 5112 Lisp_Object predicate, Lisp_Object key)
5034 Lisp_Object,
5035 Lisp_Object),
5036 Lisp_Object predicate, Lisp_Object key_func)
5037 { 5113 {
5038 Elemcount output_index = 0; 5114 Elemcount output_index = 0;
5039 5115
5040 while (output_index < output_len) 5116 while (output_index < output_len)
5041 { 5117 {
5057 list_one = Fcdr (list_one), ++output_index; 5133 list_one = Fcdr (list_one), ++output_index;
5058 } 5134 }
5059 return; 5135 return;
5060 } 5136 }
5061 5137
5062 if (NILP (c_predicate (Fcar (list_two), Fcar (list_one), predicate, 5138 if (check_merge (predicate, key, Fcar (list_two), Fcar (list_one))
5063 key_func))) 5139 == 0)
5064 { 5140 {
5065 output [output_index] = XCAR (list_one); 5141 output [output_index] = XCAR (list_one);
5066 list_one = XCDR (list_one); 5142 list_one = XCDR (list_one);
5067 } 5143 }
5068 else 5144 else
5079 5155
5080 static void 5156 static void
5081 list_array_merge_into_array (Lisp_Object *output, Elemcount output_len, 5157 list_array_merge_into_array (Lisp_Object *output, Elemcount output_len,
5082 Lisp_Object list, 5158 Lisp_Object list,
5083 Lisp_Object *array, Elemcount array_len, 5159 Lisp_Object *array, Elemcount array_len,
5084 Lisp_Object (*c_predicate) (Lisp_Object, 5160 check_test_func_t check_merge,
5085 Lisp_Object, 5161 Lisp_Object predicate, Lisp_Object key,
5086 Lisp_Object,
5087 Lisp_Object),
5088 Lisp_Object predicate, Lisp_Object key_func,
5089 Boolint reverse_order) 5162 Boolint reverse_order)
5090 { 5163 {
5091 Elemcount output_index = 0, array_index = 0; 5164 Elemcount output_index = 0, array_index = 0;
5092 5165
5093 while (output_index < output_len) 5166 while (output_index < output_len)
5117 5190
5118 return; 5191 return;
5119 } 5192 }
5120 5193
5121 if (reverse_order ? 5194 if (reverse_order ?
5122 !NILP (c_predicate (Fcar (list), array [array_index], predicate, 5195 check_merge (predicate, key, Fcar (list), array [array_index]) :
5123 key_func)) : 5196 !check_merge (predicate, key, array [array_index], Fcar (list)))
5124 NILP (c_predicate (array [array_index], Fcar (list), predicate,
5125 key_func)))
5126 { 5197 {
5127 output [output_index] = XCAR (list); 5198 output [output_index] = XCAR (list);
5128 list = XCDR (list); 5199 list = XCDR (list);
5129 } 5200 }
5130 else 5201 else
5168 */ 5239 */
5169 (int nargs, Lisp_Object *args)) 5240 (int nargs, Lisp_Object *args))
5170 { 5241 {
5171 Lisp_Object type = args[0], sequence_one = args[1], sequence_two = args[2], 5242 Lisp_Object type = args[0], sequence_one = args[1], sequence_two = args[2],
5172 predicate = args[3], result = Qnil; 5243 predicate = args[3], result = Qnil;
5173 Lisp_Object (*c_predicate) (Lisp_Object, Lisp_Object, Lisp_Object, 5244 check_test_func_t check_merge = NULL;
5174 Lisp_Object);
5175 5245
5176 PARSE_KEYWORDS (Fmerge, nargs, args, 1, (key), NULL); 5246 PARSE_KEYWORDS (Fmerge, nargs, args, 1, (key), NULL);
5177 5247
5178 CHECK_SEQUENCE (sequence_one); 5248 CHECK_SEQUENCE (sequence_one);
5179 CHECK_SEQUENCE (sequence_two); 5249 CHECK_SEQUENCE (sequence_two);
5180 5250
5181 CHECK_KEY_ARGUMENT (key); 5251 CHECK_KEY_ARGUMENT (key);
5182 5252
5183 c_predicate = EQ (key, Qidentity) ? 5253 check_merge = get_merge_predicate (predicate, key);
5184 c_merge_predicate_nokey : c_merge_predicate_key;
5185 5254
5186 if (EQ (type, Qlist) && (LISTP (sequence_one) || LISTP (sequence_two))) 5255 if (EQ (type, Qlist) && (LISTP (sequence_one) || LISTP (sequence_two)))
5187 { 5256 {
5188 if (NILP (sequence_two)) 5257 if (NILP (sequence_two))
5189 { 5258 {
5195 protection, but that doesn't matter. */ 5264 protection, but that doesn't matter. */
5196 result = Fappend (2, args + 2); 5265 result = Fappend (2, args + 2);
5197 } 5266 }
5198 else if (CONSP (sequence_one) && CONSP (sequence_two)) 5267 else if (CONSP (sequence_one) && CONSP (sequence_two))
5199 { 5268 {
5200 result = list_merge (sequence_one, sequence_two, c_predicate, 5269 result = list_merge (sequence_one, sequence_two, check_merge,
5201 predicate, key); 5270 predicate, key);
5202 } 5271 }
5203 else 5272 else
5204 { 5273 {
5205 Lisp_Object *array_storage, swap; 5274 Lisp_Object *array_storage, swap;
5237 BIT_VECTOR_TO_OBJECT_ARRAY (v, array_storage, i, array_length); 5306 BIT_VECTOR_TO_OBJECT_ARRAY (v, array_storage, i, array_length);
5238 } 5307 }
5239 5308
5240 result = list_array_merge_into_list (sequence_one, 5309 result = list_array_merge_into_list (sequence_one,
5241 array_storage, array_length, 5310 array_storage, array_length,
5242 c_predicate, 5311 check_merge, predicate, key,
5243 predicate, key,
5244 reverse_order); 5312 reverse_order);
5245 } 5313 }
5246 } 5314 }
5247 else 5315 else
5248 { 5316 {
5302 5370
5303 if (LISTP (sequence_one) && LISTP (sequence_two)) 5371 if (LISTP (sequence_one) && LISTP (sequence_two))
5304 { 5372 {
5305 list_list_merge_into_array (output + 1, output_len - 1, 5373 list_list_merge_into_array (output + 1, output_len - 1,
5306 sequence_one, sequence_two, 5374 sequence_one, sequence_two,
5307 c_predicate, predicate, 5375 check_merge, predicate, key);
5308 key);
5309 } 5376 }
5310 else if (LISTP (sequence_one)) 5377 else if (LISTP (sequence_one))
5311 { 5378 {
5312 list_array_merge_into_array (output + 1, output_len - 1, 5379 list_array_merge_into_array (output + 1, output_len - 1,
5313 sequence_one, 5380 sequence_one,
5314 sequence_two_storage, 5381 sequence_two_storage,
5315 sequence_two_len, 5382 sequence_two_len,
5316 c_predicate, predicate, 5383 check_merge, predicate, key, 0);
5317 key, 0);
5318 } 5384 }
5319 else if (LISTP (sequence_two)) 5385 else if (LISTP (sequence_two))
5320 { 5386 {
5321 list_array_merge_into_array (output + 1, output_len - 1, 5387 list_array_merge_into_array (output + 1, output_len - 1,
5322 sequence_two, 5388 sequence_two,
5323 sequence_one_storage, 5389 sequence_one_storage,
5324 sequence_one_len, 5390 sequence_one_len,
5325 c_predicate, predicate, 5391 check_merge, predicate, key, 1);
5326 key, 1);
5327 } 5392 }
5328 else 5393 else
5329 { 5394 {
5330 array_merge (output + 1, output_len - 1, 5395 array_merge (output + 1, output_len - 1,
5331 sequence_one_storage, sequence_one_len, 5396 sequence_one_storage, sequence_one_len,
5332 sequence_two_storage, sequence_two_len, 5397 sequence_two_storage, sequence_two_len,
5333 c_predicate, predicate, 5398 check_merge, predicate,
5334 key); 5399 key);
5335 } 5400 }
5336 5401
5337 result = Ffuncall (output_len, output); 5402 result = Ffuncall (output_len, output);
5338 5403
5345 } 5410 }
5346 5411
5347 return result; 5412 return result;
5348 } 5413 }
5349 5414
5350 /* The sort function should return non-nil if OBJ1 < OBJ2, nil otherwise.
5351 NOTE: This is backwards from the way qsort() works. */
5352 Lisp_Object 5415 Lisp_Object
5353 list_sort (Lisp_Object list, 5416 list_sort (Lisp_Object list, check_test_func_t check_merge,
5354 Lisp_Object (*c_predicate) (Lisp_Object, Lisp_Object, 5417 Lisp_Object predicate, Lisp_Object key)
5355 Lisp_Object, Lisp_Object),
5356 Lisp_Object predicate, Lisp_Object key_func)
5357 { 5418 {
5358 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; 5419 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
5359 Lisp_Object back, tem; 5420 Lisp_Object back, tem;
5360 Lisp_Object front = list; 5421 Lisp_Object front = list;
5361 Lisp_Object len = Flength (list); 5422 Lisp_Object len = Flength (list);
5362 5423
5363 if (XINT (len) < 2) 5424 if (XINT (len) < 2)
5364 return list; 5425 return list;
5365 5426
5366 if (NULL == c_predicate)
5367 {
5368 c_predicate = EQ (key_func, Qidentity) ? c_merge_predicate_nokey :
5369 c_merge_predicate_key;
5370 }
5371
5372 len = make_int (XINT (len) / 2 - 1); 5427 len = make_int (XINT (len) / 2 - 1);
5373 tem = Fnthcdr (len, list); 5428 tem = Fnthcdr (len, list);
5374 back = Fcdr (tem); 5429 back = Fcdr (tem);
5375 Fsetcdr (tem, Qnil); 5430 Fsetcdr (tem, Qnil);
5376 5431
5377 GCPRO4 (front, back, predicate, key_func); 5432 GCPRO4 (front, back, predicate, key);
5378 front = list_sort (front, c_predicate, predicate, key_func); 5433 front = list_sort (front, check_merge, predicate, key);
5379 back = list_sort (back, c_predicate, predicate, key_func); 5434 back = list_sort (back, check_merge, predicate, key);
5380 5435
5381 RETURN_UNGCPRO (list_merge (front, back, c_predicate, predicate, key_func)); 5436 RETURN_UNGCPRO (list_merge (front, back, check_merge, predicate, key));
5382 } 5437 }
5383 5438
5384 static void 5439 static void
5385 array_sort (Lisp_Object *array, Elemcount array_len, 5440 array_sort (Lisp_Object *array, Elemcount array_len,
5386 Lisp_Object (*c_predicate) (Lisp_Object, Lisp_Object, 5441 check_test_func_t check_merge,
5387 Lisp_Object, Lisp_Object), 5442 Lisp_Object predicate, Lisp_Object key)
5388 Lisp_Object predicate, Lisp_Object key_func)
5389 { 5443 {
5390 Elemcount split; 5444 Elemcount split;
5391 5445
5392 if (array_len < 2) 5446 if (array_len < 2)
5393 return; 5447 return;
5394 5448
5395 split = array_len / 2; 5449 split = array_len / 2;
5396 5450
5397 array_sort (array, split, c_predicate, predicate, key_func); 5451 array_sort (array, split, check_merge, predicate, key);
5398 array_sort (array + split, array_len - split, c_predicate, predicate, 5452 array_sort (array + split, array_len - split, check_merge, predicate,
5399 key_func); 5453 key);
5400 array_merge (array, array_len, array, split, array + split, 5454 array_merge (array, array_len, array, split, array + split,
5401 array_len - split, c_predicate, predicate, key_func); 5455 array_len - split, check_merge, predicate, key);
5402 } 5456 }
5403 5457
5404 DEFUN ("sort*", FsortX, 2, MANY, 0, /* 5458 DEFUN ("sort*", FsortX, 2, MANY, 0, /*
5405 Sort SEQUENCE, comparing elements using PREDICATE. 5459 Sort SEQUENCE, comparing elements using PREDICATE.
5406 Returns the sorted sequence. SEQUENCE is modified by side effect. 5460 Returns the sorted sequence. SEQUENCE is modified by side effect.
5419 */ 5473 */
5420 (int nargs, Lisp_Object *args)) 5474 (int nargs, Lisp_Object *args))
5421 { 5475 {
5422 Lisp_Object sequence = args[0], predicate = args[1]; 5476 Lisp_Object sequence = args[0], predicate = args[1];
5423 Lisp_Object *sequence_carray; 5477 Lisp_Object *sequence_carray;
5424 Lisp_Object (*c_predicate) (Lisp_Object, Lisp_Object, Lisp_Object, 5478 check_test_func_t check_merge = NULL;
5425 Lisp_Object);
5426 Elemcount sequence_len, i; 5479 Elemcount sequence_len, i;
5427 5480
5428 PARSE_KEYWORDS (FsortX, nargs, args, 1, (key), NULL); 5481 PARSE_KEYWORDS (FsortX, nargs, args, 1, (key), NULL);
5429 5482
5430 CHECK_SEQUENCE (sequence); 5483 CHECK_SEQUENCE (sequence);
5431 5484
5432 CHECK_KEY_ARGUMENT (key); 5485 CHECK_KEY_ARGUMENT (key);
5433 5486
5434 c_predicate = EQ (key, Qidentity) ? 5487 check_merge = get_merge_predicate (predicate, key);
5435 c_merge_predicate_nokey : c_merge_predicate_key;
5436 5488
5437 if (LISTP (sequence)) 5489 if (LISTP (sequence))
5438 { 5490 {
5439 sequence = list_sort (sequence, c_predicate, predicate, key); 5491 sequence = list_sort (sequence, check_merge, predicate, key);
5440 } 5492 }
5441 else if (VECTORP (sequence)) 5493 else if (VECTORP (sequence))
5442 { 5494 {
5443 array_sort (XVECTOR_DATA (sequence), XVECTOR_LENGTH (sequence), 5495 array_sort (XVECTOR_DATA (sequence), XVECTOR_LENGTH (sequence),
5444 c_predicate, predicate, key); 5496 check_merge, predicate, key);
5445 } 5497 }
5446 else if (STRINGP (sequence)) 5498 else if (STRINGP (sequence))
5447 { 5499 {
5448 Ibyte *strdata = XSTRING_DATA (sequence); 5500 Ibyte *strdata = XSTRING_DATA (sequence);
5449 5501
5450 sequence_len = string_char_length (sequence); 5502 sequence_len = string_char_length (sequence);
5451 5503
5452 STRING_DATA_TO_OBJECT_ARRAY (strdata, sequence_carray, i, sequence_len); 5504 STRING_DATA_TO_OBJECT_ARRAY (strdata, sequence_carray, i, sequence_len);
5453 5505
5454 /* No GCPRO necessary, characters are immediate. */ 5506 /* No GCPRO necessary, characters are immediate. */
5455 array_sort (sequence_carray, sequence_len, c_predicate, predicate, key); 5507 array_sort (sequence_carray, sequence_len, check_merge, predicate, key);
5456 5508
5457 strdata = XSTRING_DATA (sequence); 5509 strdata = XSTRING_DATA (sequence);
5458 5510
5459 CHECK_LISP_WRITEABLE (sequence); 5511 CHECK_LISP_WRITEABLE (sequence);
5460 for (i = 0; i < sequence_len; ++i) 5512 for (i = 0; i < sequence_len; ++i)
5472 sequence_len = bit_vector_length (v); 5524 sequence_len = bit_vector_length (v);
5473 5525
5474 BIT_VECTOR_TO_OBJECT_ARRAY (v, sequence_carray, i, sequence_len); 5526 BIT_VECTOR_TO_OBJECT_ARRAY (v, sequence_carray, i, sequence_len);
5475 5527
5476 /* No GCPRO necessary, bits are immediate. */ 5528 /* No GCPRO necessary, bits are immediate. */
5477 array_sort (sequence_carray, sequence_len, c_predicate, predicate, key); 5529 array_sort (sequence_carray, sequence_len, check_merge, predicate, key);
5478 5530
5479 for (i = 0; i < sequence_len; ++i) 5531 for (i = 0; i < sequence_len; ++i)
5480 { 5532 {
5481 set_bit_vector_bit (v, i, XINT (sequence_carray [i])); 5533 set_bit_vector_bit (v, i, XINT (sequence_carray [i]));
5482 } 5534 }
11694 DEFSYMBOL (Qsubstitute); 11746 DEFSYMBOL (Qsubstitute);
11695 DEFSYMBOL (Qmismatch); 11747 DEFSYMBOL (Qmismatch);
11696 DEFSYMBOL (Qintersection); 11748 DEFSYMBOL (Qintersection);
11697 DEFSYMBOL (Qnintersection); 11749 DEFSYMBOL (Qnintersection);
11698 DEFSYMBOL (Qsubsetp); 11750 DEFSYMBOL (Qsubsetp);
11751 DEFSYMBOL (Qcar_less_than_car);
11699 DEFSYMBOL (Qset_difference); 11752 DEFSYMBOL (Qset_difference);
11700 DEFSYMBOL (Qnset_difference); 11753 DEFSYMBOL (Qnset_difference);
11701 DEFSYMBOL (Qnunion); 11754 DEFSYMBOL (Qnunion);
11702 11755
11703 DEFKEYWORD (Q_from_end); 11756 DEFKEYWORD (Q_from_end);