mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 09:04:13 +00:00
Sort algorithms should always be built, and be selectable at runtime
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@39998 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
356eed4226
commit
0ce90c6221
12 changed files with 100 additions and 108 deletions
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
|||
2016-07-15 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* configure.ac:
|
||||
* Headers/GNUstepBase/config.h.in:
|
||||
* Source/GSQuickSort.m:
|
||||
* Source/GSShellSort.m:
|
||||
* Source/GSSorting.h:
|
||||
* Source/GSTimSort.m:
|
||||
* Source/NSSortDescriptor.m:
|
||||
Make sorting algorithms selectable at runtime rather than compile
|
||||
time.
|
||||
|
||||
2016-07-13 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSRunLoop.m (-acceptInputForMode:beforeDate:):
|
||||
|
|
|
@ -200,6 +200,18 @@ notice and this notice are preserved.
|
|||
environment variables.
|
||||
</p>
|
||||
</desc>
|
||||
<term>GSSortAlgorithm</term>
|
||||
<desc>
|
||||
<p>
|
||||
May be used to specify the sort algorithm used for sorting
|
||||
arrays etc. The current options are QuickSort, ShellSort, and
|
||||
TimSort, with TimSort being the default.<br />
|
||||
NB. The QuickSort and ShellSort are 'unstable' algorithms,
|
||||
which means that the order of equal objects may be changed
|
||||
by a sort. Selecting these may break code which assumes that
|
||||
sorting is stable.
|
||||
</p>
|
||||
</desc>
|
||||
<term>Local Time Zone</term>
|
||||
<desc>
|
||||
<p>
|
||||
|
|
|
@ -39,6 +39,9 @@ notice and this notice are preserved.
|
|||
OpenSSL bundle removed since it didn't match GNUTLS support.<br />
|
||||
Improved support for 64bit little-endian systems.<br />
|
||||
Ported to Debian/Hurd.<br />
|
||||
ICU string (regexp in particular) fixes.<br />
|
||||
OSX compatibity changes in NSRunLoop behavior.<br />
|
||||
Alterntive sort algorithms selectable at runtime.<br />
|
||||
As usual, this release also contains an update to include the
|
||||
most recent international timezone data.
|
||||
</p>
|
||||
|
|
|
@ -17,6 +17,9 @@ See the @url{ReleaseNotes.html} document for more information.
|
|||
@item Support for Debian style multi-architecture installations added
|
||||
@item OpenSSL bundle removed since it didn't match GNUTLS support
|
||||
@item Ported to Debian/Hurd
|
||||
@item ICU string (regexp in particular) fixes
|
||||
@item OSX compatibity changes in NSRunLoop behavior
|
||||
@item Alterntive sort algorithms selectable at runtime
|
||||
@item As usual, this release also contains an update to include the
|
||||
most recent international timezone data.
|
||||
@end itemize
|
||||
|
|
|
@ -171,15 +171,6 @@
|
|||
/* Built in default value for GNUstep user_dir web apps */
|
||||
#undef GNUSTEP_TARGET_USER_DIR_WEB_APPS
|
||||
|
||||
/* Build in/use quicksort */
|
||||
#undef GS_USE_QUICKSORT
|
||||
|
||||
/* Build in/use shellsort */
|
||||
#undef GS_USE_SHELLSORT
|
||||
|
||||
/* Build in/use timsort */
|
||||
#undef GS_USE_TIMSORT
|
||||
|
||||
/* Define to 1 if you have the <alloca.h> header file. */
|
||||
#undef HAVE_ALLOCA_H
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
* Sorts the provided object array's sortRange according to sortDescriptor.
|
||||
*/
|
||||
// Quicksort algorithm copied from Wikipedia :-).
|
||||
#if GS_USE_QUICKSORT
|
||||
|
||||
static inline void
|
||||
SwapObjects(id * o1, id * o2)
|
||||
|
@ -84,12 +83,12 @@ _GSQuickSort(id *objects,
|
|||
}
|
||||
|
||||
@interface GSQuickSortPlaceHolder : NSObject
|
||||
+ (void) setUnstable;
|
||||
@end
|
||||
|
||||
@implementation GSQuickSortPlaceHolder
|
||||
+ (void) load
|
||||
+ (void) setUnstable
|
||||
{
|
||||
_GSSortUnstable = _GSQuickSort;
|
||||
}
|
||||
@end
|
||||
#endif
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#import "Foundation/NSObjCRuntime.h"
|
||||
#import "GSSorting.h"
|
||||
|
||||
#if GS_USE_SHELLSORT
|
||||
void
|
||||
_GSShellSort(id *objects,
|
||||
NSRange sortRange,
|
||||
|
@ -114,13 +113,13 @@ _GSShellSort(id *objects,
|
|||
|
||||
|
||||
@interface GSShellSortPlaceHolder : NSObject
|
||||
|
||||
+ (void) setUnstable;
|
||||
@end
|
||||
|
||||
@implementation GSShellSortPlaceHolder
|
||||
+ (void) load
|
||||
+ (void) setUnstable
|
||||
{
|
||||
_GSSortUnstable = _GSShellSort;
|
||||
}
|
||||
@end
|
||||
#endif
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
enum
|
||||
{
|
||||
GSComparisonTypeSortDescriptor = 0, /** Comparison using an NSSortDescriptor */
|
||||
GSComparisonTypeSortDescriptor = 0, /** Comparison using NSSortDescriptor */
|
||||
GSComparisonTypeComparatorBlock, /** Comparison using an NSComparator */
|
||||
GSComparisonTypeFunction, /** Comparison using a comparison function of type
|
||||
* NSInteger(*)(id,id,void*) */
|
||||
|
@ -130,7 +130,7 @@ GSRightInsertionPointForKeyInSortedRange(id key, id *buffer,
|
|||
* This function is provided using the implementation of the timsort algorithm.
|
||||
*/
|
||||
NSUInteger
|
||||
GSLeftInsertionPointForKeyInSortedRange(id key, id* buffer,
|
||||
GSLeftInsertionPointForKeyInSortedRange(id key, id *buffer,
|
||||
NSRange range, NSComparator comparator);
|
||||
|
||||
/**
|
||||
|
@ -139,7 +139,7 @@ GSLeftInsertionPointForKeyInSortedRange(id key, id* buffer,
|
|||
*/
|
||||
static inline NSComparisonResult
|
||||
GSCompareUsingDescriptorOrComparator(id first, id second, id descOrComp,
|
||||
GSComparisonType cmprType, void* context)
|
||||
GSComparisonType cmprType, void *context)
|
||||
{
|
||||
|
||||
switch (cmprType)
|
||||
|
|
|
@ -295,8 +295,6 @@ NSRange range, NSComparator cmptr)
|
|||
GSComparisonTypeComparatorBlock, NULL);
|
||||
}
|
||||
|
||||
#if GS_USE_TIMSORT
|
||||
|
||||
static inline void
|
||||
reverseRange(id *buffer, NSRange r)
|
||||
{
|
||||
|
@ -476,7 +474,7 @@ static IMP mergeLowImp;
|
|||
static IMP mergeHighImp;
|
||||
static IMP ensureCapImp;
|
||||
|
||||
@interface GSTimSortDescriptor : NSObject
|
||||
@interface GSTimSortPlaceHolder : NSObject
|
||||
{
|
||||
id *objects;
|
||||
NSRange sortRange;
|
||||
|
@ -511,7 +509,7 @@ _GSTimSort(id *objects,
|
|||
GSComparisonType comparisonType,
|
||||
void *context);
|
||||
|
||||
@implementation GSTimSortDescriptor
|
||||
@implementation GSTimSortPlaceHolder
|
||||
+ (void) load
|
||||
{
|
||||
_GSSortStable = _GSTimSort;
|
||||
|
@ -519,7 +517,7 @@ _GSTimSort(id *objects,
|
|||
|
||||
+ (void) initialize
|
||||
{
|
||||
if ([GSTimSortDescriptor class] == [self class])
|
||||
if ([GSTimSortPlaceHolder class] == [self class])
|
||||
{
|
||||
// We need to be fast, so we cache a lot of IMPs
|
||||
pushRunImp =
|
||||
|
@ -539,6 +537,11 @@ _GSTimSort(id *objects,
|
|||
}
|
||||
}
|
||||
|
||||
+ (void) setUnstable
|
||||
{
|
||||
_GSSortUnstable = _GSTimSort; // Use for unstable even though we are stable
|
||||
}
|
||||
|
||||
- (id) initWithObjects: (id*)theObjects
|
||||
sortRange: (NSRange)theSortRange
|
||||
descriptorOrComparator: (id)descriptorOrComparator
|
||||
|
@ -552,7 +555,7 @@ descriptorOrComparator: (id)descriptorOrComparator
|
|||
{
|
||||
return nil;
|
||||
}
|
||||
/* GSTimSortDescriptors are ephemeral objects that just track state, so we
|
||||
/* GSTimSortPlaceHolders are ephemeral objects that just track state, so we
|
||||
* don't bother making sure that the objects don't go away.
|
||||
*/
|
||||
objects = theObjects;
|
||||
|
@ -1107,7 +1110,7 @@ _GSTimSort(id *objects,
|
|||
NSUInteger sortEnd = NSMaxRange(sortRange);
|
||||
NSUInteger sortLen = sortRange.length;
|
||||
NSUInteger minimalRunLen = 0;
|
||||
GSTimSortDescriptor *desc = nil;
|
||||
GSTimSortPlaceHolder *desc = nil;
|
||||
if (sortLen < 2)
|
||||
{
|
||||
// Don't sort anything that doesn't contain at least two elements.
|
||||
|
@ -1116,16 +1119,17 @@ _GSTimSort(id *objects,
|
|||
|
||||
if (sortLen < GS_MIN_MERGE)
|
||||
{
|
||||
miniTimSort(objects, sortRange, sortDescriptorOrComparator, comparisonType, context);
|
||||
miniTimSort(objects, sortRange,
|
||||
sortDescriptorOrComparator, comparisonType, context);
|
||||
return;
|
||||
}
|
||||
|
||||
// Now we need a timsort descriptor for state-tracking.
|
||||
desc = [[GSTimSortDescriptor alloc] initWithObjects: objects
|
||||
sortRange: sortRange
|
||||
descriptorOrComparator: sortDescriptorOrComparator
|
||||
comparisonType: comparisonType
|
||||
functionContext: context];
|
||||
desc = [[GSTimSortPlaceHolder alloc] initWithObjects: objects
|
||||
sortRange: sortRange
|
||||
descriptorOrComparator: sortDescriptorOrComparator
|
||||
comparisonType: comparisonType
|
||||
functionContext: context];
|
||||
|
||||
NS_DURING
|
||||
{
|
||||
|
@ -1172,4 +1176,3 @@ _GSTimSort(id *objects,
|
|||
[desc release];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
#import "Foundation/NSCoder.h"
|
||||
#import "Foundation/NSException.h"
|
||||
#import "Foundation/NSKeyValueCoding.h"
|
||||
#import "Foundation/NSNotification.h"
|
||||
#import "Foundation/NSUserDefaults.h"
|
||||
|
||||
#import "GNUstepBase/GSObjCRuntime.h"
|
||||
#import "GSPrivate.h"
|
||||
|
@ -41,34 +43,61 @@ static BOOL initialized = NO;
|
|||
#pragma clang diagnostic ignored "-Wreceiver-forward-class"
|
||||
#endif
|
||||
|
||||
#if GS_USE_TIMSORT
|
||||
@interface GSTimSortDescriptor : NSObject
|
||||
@interface GSTimSortPlaceHolder : NSObject
|
||||
+ (void) setUnstable;
|
||||
@end
|
||||
#endif
|
||||
#if GS_USE_QUICKSORT
|
||||
@interface GSQuickSortPlaceHolder : NSObject
|
||||
+ (void) setUnstable;
|
||||
@end
|
||||
#endif
|
||||
#if GS_USE_SHELLSORT
|
||||
@interface GSShellSortPlaceHolder : NSObject
|
||||
+ (void) setUnstable;
|
||||
@end
|
||||
#endif
|
||||
|
||||
@implementation NSSortDescriptor
|
||||
|
||||
+ (void) defaultsChanged: (NSNotification*)n
|
||||
{
|
||||
NSUserDefaults *defs = (NSUserDefaults*)[n object];
|
||||
NSString *algorithm;
|
||||
|
||||
algorithm = [defs stringForKey: @"GSSortAlgorithm"];
|
||||
if ([algorithm isEqual: @"QuickSort"])
|
||||
{
|
||||
[GSQuickSortPlaceHolder setUnstable];
|
||||
}
|
||||
else if ([algorithm isEqual: @"ShellSort"])
|
||||
{
|
||||
[GSShellSortPlaceHolder setUnstable];
|
||||
}
|
||||
else if ([algorithm isEqual: @"TimSort"])
|
||||
{
|
||||
[GSTimSortPlaceHolder setUnstable];
|
||||
}
|
||||
else
|
||||
{
|
||||
[GSTimSortPlaceHolder setUnstable];
|
||||
if (nil != algorithm)
|
||||
{
|
||||
NSLog(@"GSSortAlgorithm default unknown value (%@)", algorithm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (NO == initialized)
|
||||
{
|
||||
#if GS_USE_TIMSORT
|
||||
[GSTimSortDescriptor class];
|
||||
#endif
|
||||
#if GS_USE_QUICKSORT
|
||||
[GSQuickSortPlaceHolder class];
|
||||
#endif
|
||||
#if GS_USE_SHELLSORT
|
||||
[GSShellSortPlaceHolder class];
|
||||
#endif
|
||||
NSNotificationCenter *nc;
|
||||
NSUserDefaults *defs;
|
||||
|
||||
[GSTimSortPlaceHolder class]; // default stable sort
|
||||
nc = [NSNotificationCenter defaultCenter];
|
||||
defs = [NSUserDefaults standardUserDefaults];
|
||||
[nc addObserver: self
|
||||
selector: @selector(defaultsChanged:)
|
||||
name: NSUserDefaultsDidChangeNotification
|
||||
object: defs];
|
||||
[self defaultsChanged: nil]; // set unstable sort
|
||||
initialized = YES;
|
||||
}
|
||||
}
|
||||
|
|
36
configure
vendored
36
configure
vendored
|
@ -821,7 +821,6 @@ with_icu_library
|
|||
enable_libdispatch
|
||||
with_gmp_include
|
||||
with_gmp_library
|
||||
with_sort_algorithm
|
||||
with_gdomap_port
|
||||
enable_setuid_gdomap
|
||||
'
|
||||
|
@ -1572,9 +1571,6 @@ Optional Packages:
|
|||
if not using icu-config)
|
||||
--with-gmp-include=PATH include path for gmp headers
|
||||
--with-gmp-library=PATH library path for gmp libraries
|
||||
--with-sort-algorithm=ALG force use of a specific sorting algorithm.
|
||||
Possible values are timsort, quicksort, and shellsort.
|
||||
Defaults to shellsort (others broken).
|
||||
--with-gdomap-port=PORT alternative port for gdomap
|
||||
|
||||
Some influential environment variables:
|
||||
|
@ -12521,38 +12517,6 @@ fi
|
|||
|
||||
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Check which sorting algorithm to use.
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
# Check whether --with-sort-algorithm was given.
|
||||
if test "${with_sort_algorithm+set}" = set; then :
|
||||
withval=$with_sort_algorithm; sort_algorithm="$withval"
|
||||
else
|
||||
sort_algorithm="shellsort"
|
||||
fi
|
||||
|
||||
|
||||
if test "$sort_algorithm" = "timsort"; then
|
||||
|
||||
$as_echo "#define GS_USE_TIMSORT 1" >>confdefs.h
|
||||
|
||||
else
|
||||
if test "$sort_algorithm" = "quicksort"; then
|
||||
|
||||
$as_echo "#define GS_USE_QUICKSORT 1" >>confdefs.h
|
||||
|
||||
else
|
||||
if test "$sort_algorithm" = "shellsort"; then
|
||||
|
||||
$as_echo "#define GS_USE_SHELLSORT 1" >>confdefs.h
|
||||
|
||||
else
|
||||
as_fn_error $? "Unknown sort_algorithm defined!" "$LINENO" 5
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Check whether nl_langinfo(CODESET) is supported, needed by Unicode.m.
|
||||
#--------------------------------------------------------------------
|
||||
|
|
23
configure.ac
23
configure.ac
|
@ -3430,29 +3430,6 @@ fi
|
|||
AC_SUBST(USE_GMP)
|
||||
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Check which sorting algorithm to use.
|
||||
#--------------------------------------------------------------------
|
||||
AC_ARG_WITH(sort-algorithm,
|
||||
[ --with-sort-algorithm=ALG force use of a specific sorting algorithm.
|
||||
Possible values are timsort, quicksort, and shellsort.
|
||||
Defaults to shellsort (others broken).],
|
||||
sort_algorithm="$withval", sort_algorithm="shellsort")
|
||||
|
||||
if test "$sort_algorithm" = "timsort"; then
|
||||
AC_DEFINE(GS_USE_TIMSORT,1,[Build in/use timsort])
|
||||
else
|
||||
if test "$sort_algorithm" = "quicksort"; then
|
||||
AC_DEFINE(GS_USE_QUICKSORT,1,[Build in/use quicksort])
|
||||
else
|
||||
if test "$sort_algorithm" = "shellsort"; then
|
||||
AC_DEFINE(GS_USE_SHELLSORT,1,[Build in/use shellsort])
|
||||
else
|
||||
AC_MSG_ERROR([Unknown sort_algorithm defined!])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Check whether nl_langinfo(CODESET) is supported, needed by Unicode.m.
|
||||
#--------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in a new issue