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