Browse Source

update firefox, partially working.

Waldemar Brodkorb 11 năm trước cách đây
mục cha
commit
c481446c02
38 tập tin đã thay đổi với 149 bổ sung3908 xóa
  1. 30 22
      package/firefox/Makefile
  2. 1 1
      package/firefox/files/firefox
  3. 37 26
      package/firefox/patches/patch-configure
  4. 10 0
      package/firefox/patches/patch-gfx_angle_src_common_angleutils_cpp
  5. 0 10
      package/firefox/patches/patch-gfx_layers_BufferUnrotate_cpp
  6. 0 13
      package/firefox/patches/patch-ipc_chromium_src_base_debug_util_posix_cc
  7. 0 10
      package/firefox/patches/patch-ipc_chromium_src_base_file_util_h
  8. 0 48
      package/firefox/patches/patch-ipc_chromium_src_base_file_util_posix_cc
  9. 7 7
      package/firefox/patches/patch-js_src_Makefile_in
  10. 0 12
      package/firefox/patches/patch-js_src_assembler_wtf_Platform_h
  11. 0 31
      package/firefox/patches/patch-js_src_configure
  12. 0 11
      package/firefox/patches/patch-js_src_yarr_BumpPointerAllocator_h
  13. 0 43
      package/firefox/patches/patch-media_mtransport_third_party_nICEr_src_stun_addrs_c
  14. 0 12
      package/firefox/patches/patch-media_mtransport_third_party_nICEr_src_stun_stun_h
  15. 0 23
      package/firefox/patches/patch-media_webrtc_trunk_tools_gyp_pylib_gyp_common_py
  16. 0 26
      package/firefox/patches/patch-media_webrtc_trunk_tools_gyp_pylib_gyp_generator_mozmake_py
  17. 0 11
      package/firefox/patches/patch-media_webrtc_trunk_webrtc_modules_audio_device_audio_device_impl_cc
  18. 0 11
      package/firefox/patches/patch-media_webrtc_trunk_webrtc_modules_audio_device_linux_audio_device_alsa_linux_cc
  19. 0 11
      package/firefox/patches/patch-media_webrtc_trunk_webrtc_modules_audio_device_linux_audio_mixer_manager_alsa_linux_cc
  20. 0 23
      package/firefox/patches/patch-media_webrtc_trunk_webrtc_system_wrappers_source_cpu_info_cc
  21. 0 3385
      package/firefox/patches/patch-media_webrtc_trunk_webrtc_system_wrappers_source_spreadsortlib_spreadsort_hpp
  22. 0 15
      package/firefox/patches/patch-netwerk_sctp_src_netinet_sctp_bsd_addr_c
  23. 0 22
      package/firefox/patches/patch-netwerk_sctp_src_netinet_sctp_os_userspace_h
  24. 0 25
      package/firefox/patches/patch-netwerk_sctp_src_netinet_sctp_pcb_c
  25. 0 14
      package/firefox/patches/patch-netwerk_sctp_src_user_environment_c
  26. 0 12
      package/firefox/patches/patch-netwerk_sctp_src_user_queue_h
  27. 5 5
      package/firefox/patches/patch-python_mozbuild_mozbuild_backend_recursivemake_py
  28. 6 6
      package/firefox/patches/patch-tools_profiler_platform-linux_cc
  29. 0 11
      package/firefox/patches/patch-tools_profiler_shared-libraries-linux_cc
  30. 11 11
      package/firefox/patches/patch-xpcom_ds_nsMathUtils_h
  31. 18 13
      package/firefox/patches/patch-xpcom_io_nsLocalFileUnix_cpp
  32. 0 17
      package/firefox/patches/patch-xpcom_threads_nsThread_cpp
  33. 5 5
      package/nss/Makefile
  34. 3 3
      package/nss/patches/patch-nss_coreconf_Linux_mk
  35. 3 3
      package/nss/patches/patch-nss_coreconf_command_mk
  36. 6 3
      package/nss/patches/patch-nss_manifest_mn
  37. 3 3
      package/python2/Makefile
  38. 4 4
      package/sqlite/Makefile

+ 30 - 22
package/firefox/Makefile

@@ -4,9 +4,9 @@
 include $(ADK_TOPDIR)/rules.mk
 
 PKG_NAME:=		firefox
-PKG_VERSION:=		26.0
-PKG_RELEASE:=		4
-PKG_HASH:=		31c4fb2792df63ae450e350380a5e18cf1c51487011a9da0b6cc4bffb69d9812
+PKG_VERSION:=		35.0
+PKG_RELEASE:=		1
+PKG_HASH:=		bedeb5bbd8b49e5b286497ef7732542c6e7441088fd8cd577d7ca8af4c871e81
 PKG_DESCR:=		graphical webbrowser
 PKG_SECTION:=		x11/apps
 PKG_DEPENDS:=		libpthread alsa-lib glib libgtk libpng libtiff libxcursor libffi
@@ -18,20 +18,21 @@ PKG_BUILDDEP+=		nspr nss libjpeg-turbo libXt fontconfig sqlite atk libpng hicolo
 PKG_BUILDDEP+=		libvpx pango gettext-tiny bzip2 libevent bzip2-host python2-host yasm-host
 PKG_BUILDDEP+=		zip-host
 PKG_URL:=		http://www.mozilla.org/
-PKG_SITES:=		http://releases.mozilla.org/pub/mozilla.org/firefox/releases/${PKG_VERSION}/source/
+PKG_SITES:=		http://releases.mozilla.org/pub/mozilla.org/firefox/releases/$(PKG_VERSION)/source/
 PKG_NOPARALLEL:=	1
 
 PKG_ARCH_DEPENDS:=	arm x86 x86_64 mips
 PKG_HOST_DEPENDS:=	!netbsd !freebsd !openbsd !cygwin
-PKG_SYSTEM_DEPENDS:=	tarox-pc ibm-x40 lemote-yeelong qemu-i686 qemu-x86_64 qemu-mips64el raspberry-pi
+PKG_SYSTEM_DEPENDS:=	solidrun-imx6 ibm-x40 lemote-yeelong qemu-i686 qemu-x86_64 qemu-mips64el raspberry-pi
 
-DISTFILES:=             ${PKG_NAME}-${PKG_VERSION}.source.tar.bz2
-WRKDIST=		${WRKDIR}/mozilla-release
+DISTFILES:=		$(PKG_NAME)-$(PKG_VERSION).source.tar.bz2
+WRKDIST=		$(WRKDIR)/mozilla-release
+WRKBUILD=		$(WRKDIR)/$(PKG_NAME)-obj
 
 include $(ADK_TOPDIR)/mk/package.mk
 include $(ADK_TOPDIR)/mk/python.mk
 
-$(eval $(call PKG_template,FIREFOX,firefox,$(PKG_VERSION)-${PKG_RELEASE},${PKG_DEPENDS},${PKG_DESCR},${PKG_SECTION}))
+$(eval $(call PKG_template,FIREFOX,firefox,$(PKG_VERSION)-$(PKG_RELEASE),$(PKG_DEPENDS),$(PKG_DESCR),$(PKG_SECTION)))
 
 ifeq ($(ADK_DEBUG),y)
 CONFIGURE_ARGS+=	--enable-debug --enable-logging
@@ -42,14 +43,14 @@ endif
 
 CONFIGURE_ENV+=		CROSS_COMPILE=1 \
 			PYTHON="$(PYTHON)" \
-			HOST_CC="${HOST_CC}" \
-			HOST_CPPFLAGS="${HOST_CPPFLAGS}" \
-			HOST_CFLAGS="${HOST_CFLAGS}" \
-			HOST_LDFLAGS="${HOST_LDLAGS}" \
-			HOST_CXX="${HOST_CXX}" \
-			HOST_CXXFLAGS="${HOST_CXXFLAGS}" \
+			HOST_CC="$(HOST_CC)" \
+			HOST_CPPFLAGS="$(HOST_CPPFLAGS)" \
+			HOST_CFLAGS="$(HOST_CFLAGS)" \
+			HOST_LDFLAGS="$(HOST_LDLAGS)" \
+			HOST_CXX="$(HOST_CXX)" \
+			HOST_CXXFLAGS="$(HOST_CXXFLAGS)" \
 			HOST_RANLIB="ranlib" HOST_AR="ar" \
-			CPPFLAGS="-I${STAGING_TARGET_DIR}/usr/include/freetype2" \
+			CPPFLAGS="-I$(STAGING_TARGET_DIR)/usr/include/freetype2" \
 			ac_cv_sqlite_secure_delete=yes \
 			ac_cv_sqlite_threadsafe=yes \
 			ac_cv_sqlite_enable_fts3=yes \
@@ -66,19 +67,24 @@ CONFIGURE_ARGS+=	--enable-application=browser \
 			--with-system-nspr \
 			--with-system-pango \
 			--with-system-libvpx \
-			--with-system-libevent=${STAGING_TARGET_DIR}/usr \
+			--with-system-libevent=$(STAGING_TARGET_DIR)/usr \
 			--enable-system-ffi \
 			--enable-system-sqlite \
 			--disable-libnotify \
-			--with-libIDL-prefix=${STAGING_TARGET_DIR}/usr \
-			--with-glib-prefix=${STAGING_TARGET_DIR}/usr \
+			--with-libIDL-prefix=$(STAGING_TARGET_DIR)/usr \
+			--with-glib-prefix=$(STAGING_TARGET_DIR)/usr \
 			--enable-chrome-format=jar \
 			--enable-necko-protocols=all \
 			--enable-libxul \
 			--enable-alsa \
+			--disable-profiling \
+			--disable-jprof \
+			--disable-shark \
+			--disable-systrace \
 			--disable-pulseaudio \
 			--disable-gstreamer \
 			--disable-gio \
+			--disable-gold \
 			--disable-gconf \
 			--disable-accessibility \
 			--disable-smil \
@@ -98,6 +104,8 @@ CONFIGURE_ARGS+=	--enable-application=browser \
 			--disable-mathml \
 			--disable-jemalloc \
 			--disable-crashreporter \
+			--disable-printing \
+			--disable-pie \
 			--disable-updater \
 			--disable-xpcom-fastload \
 			--disable-url-classifier \
@@ -109,17 +117,17 @@ TARGET_CFLAGS:=		$(subst Os,g3,$(TARGET_CFLAGS))
 endif
 
 XAKE_FLAGS+=		OS_RELEASE="2.6" HOST_CC=$(HOST_CC) HOST_LDFLAGS=$(HOST_LDFLAGS)
-XAKE_FLAGS+=            ARCHFLAG="${TARGET_CFLAGS} ${TARGET_CPPFLAGS} ${TARGET_LDFLAGS} -lnss3 -lnssutil3 -lsmime3 -lssl3 -fPIC"
+XAKE_FLAGS+=            ARCHFLAG="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS) $(TARGET_LDFLAGS) -lnss3 -lnssutil3 -lsmime3 -lssl3 -fPIC"
 
 pre-build:
-	-mkdir ${WRKBUILD}/js/src/.deps
+	-mkdir $(WRKBUILD)/js/src/.deps
 
 firefox-install:
 	$(INSTALL_DIR) $(IDIR_FIREFOX)/usr/bin
 	$(INSTALL_DIR) $(IDIR_FIREFOX)/usr/lib
-	$(CP) $(WRKINST)/usr/lib/firefox-${PKG_VERSION} \
+	$(CP) $(WRKINST)/usr/lib/firefox-$(PKG_VERSION) \
 		$(IDIR_FIREFOX)/usr/lib
 	$(CP) ./files/firefox \
 		$(IDIR_FIREFOX)/usr/bin
 
-include ${ADK_TOPDIR}/mk/pkg-bottom.mk
+include $(ADK_TOPDIR)/mk/pkg-bottom.mk

+ 1 - 1
package/firefox/files/firefox

@@ -1,2 +1,2 @@
 #!/bin/sh
-env LD_LIBRARY_PATH=/usr/lib/firefox-26.0 /usr/lib/firefox-26.0/firefox
+env LD_LIBRARY_PATH=/usr/lib/firefox-35.0 /usr/lib/firefox-35.0/firefox

+ 37 - 26
package/firefox/patches/patch-configure

@@ -1,30 +1,41 @@
---- mozilla-release.orig/configure	2013-12-05 17:08:46.000000000 +0100
-+++ mozilla-release/configure	2014-01-06 18:17:43.008094174 +0100
-@@ -9787,27 +9787,6 @@ if test -z "$GNU_CC"; then
-     esac
+--- mozilla-release.orig/configure	2015-01-09 05:39:04.000000000 +0100
++++ mozilla-release/configure	2015-02-04 11:49:00.000000000 +0100
+@@ -8156,38 +8156,6 @@ EOF
+ 
  fi
  
--if test "$GNU_CC" -a -n "$DEVELOPER_OPTIONS"; then
--            if $CC -Wl,--version 2>&1 | grep -q "GNU ld"; then
--        GOLD=$($CC -print-prog-name=ld.gold)
--        case "$GOLD" in
--        /*)
--            ;;
--        *)
--            GOLD=$(which $GOLD)
--            ;;
--        esac
--        if test -n "$GOLD"; then
--            mkdir -p $_objdir/build/unix/gold
--            ln -s "$GOLD" $_objdir/build/unix/gold/ld
--            if $CC -B $_objdir/build/unix/gold -Wl,--version 2>&1 | grep -q "GNU gold"; then
--                LDFLAGS="$LDFLAGS -B $_objdir/build/unix/gold"
--            else
--                rm -rf $_objdir/build/unix/gold
--            fi
--        fi
--    fi
+-MOZ_ENABLE_PROFILER_SPS=1
+-
+-case "${OS_TARGET}" in
+-Android)
+-    case "${CPU_ARCH}" in
+-    x86 | arm) ;;
+-    *)
+-        MOZ_ENABLE_PROFILER_SPS=
+-    esac
+-    ;;
+-Linux)
+-    case "${CPU_ARCH}" in
+-    x86 | x86_64) ;;
+-    *)
+-        MOZ_ENABLE_PROFILER_SPS=
+-    esac
+-    ;;
+-WINNT|Darwin) ;;
+-*)
+-    MOZ_ENABLE_PROFILER_SPS=
+-    ;;
+-esac
+-
+-if test -n "$MOZ_ENABLE_PROFILER_SPS"; then
+-    cat >> confdefs.pytmp <<\EOF
+-    (''' MOZ_ENABLE_PROFILER_SPS ''', ' 1 ')
+-EOF
+-cat >> confdefs.h <<\EOF
+-#define MOZ_ENABLE_PROFILER_SPS 1
+-EOF
+-
 -fi
  
- if test "$GNU_CC"; then
-     if test -z "$DEVELOPER_OPTIONS"; then
+ # Check whether --enable-shark or --disable-shark was given.
+ if test "${enable_shark+set}" = set; then

+ 10 - 0
package/firefox/patches/patch-gfx_angle_src_common_angleutils_cpp

@@ -0,0 +1,10 @@
+--- mozilla-release.orig/gfx/angle/src/common/angleutils.cpp	2015-01-09 05:38:28.000000000 +0100
++++ mozilla-release/gfx/angle/src/common/angleutils.cpp	2015-02-03 04:42:10.000000000 +0100
+@@ -7,6 +7,7 @@
+ #include "common/angleutils.h"
+ 
+ #include <vector>
++#include <cstdio>
+ 
+ std::string FormatString(const char *fmt, va_list vararg)
+ {

+ 0 - 10
package/firefox/patches/patch-gfx_layers_BufferUnrotate_cpp

@@ -1,10 +0,0 @@
---- mozilla-release.orig/gfx/layers/BufferUnrotate.cpp	2013-12-05 17:07:31.000000000 +0100
-+++ mozilla-release/gfx/layers/BufferUnrotate.cpp	2014-01-06 21:27:39.000000000 +0100
-@@ -8,6 +8,7 @@
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
-+#include <string.h>
- 
- void BufferUnrotate(uint8_t* aBuffer, int aByteWidth, int aHeight,
-                     int aByteStride, int aXBoundary, int aYBoundary)

+ 0 - 13
package/firefox/patches/patch-ipc_chromium_src_base_debug_util_posix_cc

@@ -1,13 +0,0 @@
---- mozilla-release.orig/ipc/chromium/src/base/debug_util_posix.cc	2013-09-11 01:15:04.000000000 +0200
-+++ mozilla-release/ipc/chromium/src/base/debug_util_posix.cc	2013-10-23 16:28:38.000000000 +0200
-@@ -5,7 +5,9 @@
- #include "build/build_config.h"
- #include "base/debug_util.h"
- 
--#define MOZ_HAVE_EXECINFO_H (defined(OS_LINUX) && !defined(ANDROID))
-+#include <features.h>
-+
-+#define MOZ_HAVE_EXECINFO_H (defined(OS_LINUX) && !defined(ANDROID) && !defined(__UCLIBC__)) && defined(__GLIBC__)
- 
- #include <errno.h>
- #include <fcntl.h>

+ 0 - 10
package/firefox/patches/patch-ipc_chromium_src_base_file_util_h

@@ -1,10 +0,0 @@
---- mozilla-release.orig/ipc/chromium/src/base/file_util.h	2013-12-05 17:07:35.000000000 +0100
-+++ mozilla-release/ipc/chromium/src/base/file_util.h	2014-01-02 15:01:42.000000000 +0100
-@@ -16,7 +16,6 @@
- #include <sys/stat.h>
- #elif defined(OS_POSIX) 
- #include <sys/types.h>
--#include <fts.h>
- #include <sys/stat.h>
- #endif
- 

+ 0 - 48
package/firefox/patches/patch-ipc_chromium_src_base_file_util_posix_cc

@@ -1,48 +0,0 @@
---- mozilla-release.orig/ipc/chromium/src/base/file_util_posix.cc	2013-12-05 17:07:35.000000000 +0100
-+++ mozilla-release/ipc/chromium/src/base/file_util_posix.cc	2014-01-02 14:53:44.000000000 +0100
-@@ -8,13 +8,16 @@
- #include <errno.h>
- #include <fcntl.h>
- #include <fnmatch.h>
--#ifndef ANDROID
-+#ifndef __GLIBC__
-+#define NO_FTS
-+#endif
-+#ifndef NO_FTS
- #include <fts.h>
- #endif
- #include <libgen.h>
- #include <stdio.h>
- #include <string.h>
--#include <sys/errno.h>
-+#include <errno.h>
- #include <sys/mman.h>
- #define _DARWIN_USE_64_BIT_INODE // Use 64-bit inode data structures
- #include <sys/stat.h>
-@@ -67,7 +70,7 @@ bool Delete(const FilePath& path, bool r
-   if (!recursive)
-     return (rmdir(path_str) == 0);
- 
--#ifdef ANDROID
-+#ifdef NO_FTS
-   // XXX Need ftsless impl for bionic
-   return false;
- #else
-@@ -140,7 +143,7 @@ bool CopyDirectory(const FilePath& from_
-     return false;
-   }
- 
--#ifdef ANDROID
-+#ifdef NO_FTS
-   // XXX Need ftsless impl for bionic
-   return false;
- #else
-@@ -333,7 +336,7 @@ bool CreateNewTempDirectory(const FilePa
-     return false;
-   tmpdir = tmpdir.Append(kTempFileName);
-   std::string tmpdir_string = tmpdir.value();
--#ifdef ANDROID
-+#ifdef NO_FTS
-   char* dtemp = NULL;
- #else
-   // this should be OK since mkdtemp just replaces characters in place

+ 7 - 7
package/firefox/patches/patch-js_src_Makefile_in

@@ -1,11 +1,11 @@
---- mozilla-release.orig/js/src/Makefile.in	2013-12-05 17:07:35.000000000 +0100
-+++ mozilla-release/js/src/Makefile.in	2014-01-02 14:53:44.000000000 +0100
-@@ -103,7 +103,7 @@ ifdef JS_HAS_CTYPES
- VPATH += $(srcdir)/ctypes
+--- mozilla-release.orig/js/src/Makefile.in	2015-01-09 05:38:17.000000000 +0100
++++ mozilla-release/js/src/Makefile.in	2015-01-29 17:03:28.000000000 +0100
+@@ -21,7 +21,7 @@ NO_EXPAND_LIBS = 1
  
+ ifdef JS_HAS_CTYPES
  ifdef MOZ_NATIVE_FFI
 -LOCAL_INCLUDES = $(MOZ_FFI_CFLAGS)
-+LOCAL_INCLUDES =
- else
- LOCAL_INCLUDES = -Ictypes/libffi/include
++LOCAL_INCLUDES = 
  endif
+ 
+ # Windows needs this to be linked with a static library.

+ 0 - 12
package/firefox/patches/patch-js_src_assembler_wtf_Platform_h

@@ -1,12 +0,0 @@
---- mozilla-release.orig/js/src/assembler/wtf/Platform.h	2013-09-11 01:15:04.000000000 +0200
-+++ mozilla-release/js/src/assembler/wtf/Platform.h	2013-10-28 12:43:50.000000000 +0100
-@@ -139,8 +139,7 @@
- 
- /* WTF_CPU_MIPS - MIPS 32-bit */
- /* Note: Only O32 ABI is tested, so we enable it for O32 ABI for now.  */
--#if (defined(mips) || defined(__mips__) || defined(MIPS) || defined(_MIPS_)) \
--    && defined(_ABIO32)
-+#if (defined(mips) || defined(__mips__) || defined(MIPS) || defined(_MIPS_))
- #define WTF_CPU_MIPS 1
- #if defined(__MIPSEB__)
- #define WTF_CPU_BIG_ENDIAN 1

+ 0 - 31
package/firefox/patches/patch-js_src_configure

@@ -1,31 +0,0 @@
---- mozilla-release.orig/js/src/configure	2013-12-05 17:08:46.000000000 +0100
-+++ mozilla-release/js/src/configure	2014-01-07 19:30:38.660353287 +0100
-@@ -8652,28 +8652,6 @@ if test -z "$GNU_CC"; then
-     esac
- fi
- 
--if test "$GNU_CC" -a -n "$DEVELOPER_OPTIONS"; then
--            if $CC -Wl,--version 2>&1 | grep -q "GNU ld"; then
--        GOLD=$($CC -print-prog-name=ld.gold)
--        case "$GOLD" in
--        /*)
--            ;;
--        *)
--            GOLD=$(which $GOLD)
--            ;;
--        esac
--        if test -n "$GOLD"; then
--            mkdir -p $_objdir/build/unix/gold
--            ln -s "$GOLD" $_objdir/build/unix/gold/ld
--            if $CC -B $_objdir/build/unix/gold -Wl,--version 2>&1 | grep -q "GNU gold"; then
--                LDFLAGS="$LDFLAGS -B $_objdir/build/unix/gold"
--            else
--                rm -rf $_objdir/build/unix/gold
--            fi
--        fi
--    fi
--fi
--
- if test "$GNU_CC"; then
-     if test -z "$DEVELOPER_OPTIONS"; then
-         CFLAGS="$CFLAGS -ffunction-sections -fdata-sections"

+ 0 - 11
package/firefox/patches/patch-js_src_yarr_BumpPointerAllocator_h

@@ -1,11 +0,0 @@
---- mozilla-release.orig/js/src/yarr/BumpPointerAllocator.h	2013-09-11 01:15:09.000000000 +0200
-+++ mozilla-release/js/src/yarr/BumpPointerAllocator.h	2013-10-28 12:44:10.000000000 +0100
-@@ -38,6 +38,8 @@ namespace WTF {
- #define MINIMUM_BUMP_POOL_SIZE 0x2000
- #elif WTF_CPU_IA64
- #define MINIMUM_BUMP_POOL_SIZE 0x4000
-+#elif WTF_CPU_MIPS
-+#define MINIMUM_BUMP_POOL_SIZE 0x4000
- #else
- #define MINIMUM_BUMP_POOL_SIZE 0x1000
- #endif

+ 0 - 43
package/firefox/patches/patch-media_mtransport_third_party_nICEr_src_stun_addrs_c

@@ -1,43 +0,0 @@
---- mozilla-release.orig/media/mtransport/third_party/nICEr/src/stun/addrs.c	2013-12-05 17:07:48.000000000 +0100
-+++ mozilla-release/media/mtransport/third_party/nICEr/src/stun/addrs.c	2014-03-16 18:41:03.000000000 +0100
-@@ -45,7 +45,9 @@ static char *RCSSTRING __UNUSED__="$Id:
- #include <sys/param.h>
- #include <sys/socket.h>
- #ifndef ANDROID
-+#ifdef __GLIBC__
- #include <sys/sysctl.h>
-+#endif
- #include <sys/syslog.h>
- #else
- #include <syslog.h>
-@@ -53,7 +55,9 @@ static char *RCSSTRING __UNUSED__="$Id:
- #undef __unused
- #include <linux/sysctl.h>
- #endif
-+#if defined(__GLIBC__)
- #include <net/if.h>
-+#endif
- #ifndef LINUX
- #if !defined(__OpenBSD__) && !defined(__NetBSD__)
- #include <net/if_var.h>
-@@ -61,14 +65,17 @@ static char *RCSSTRING __UNUSED__="$Id:
- #include <net/if_dl.h>
- #include <net/if_types.h>
- #include <sys/sockio.h>
--#else
-+#elif defined(__GLIBC__)
- #include <linux/sockios.h>
- #include <linux/if.h>
- #include <linux/kernel.h>
- #include <linux/wireless.h>
--#ifndef ANDROID
- #include <linux/ethtool.h>
--#endif
-+#else
-+#include <linux/sockios.h>
-+#include <linux/kernel.h>
-+#include <linux/wireless.h>
-+#include <linux/ethtool.h>
- #endif
- #include <net/route.h>
- 

+ 0 - 12
package/firefox/patches/patch-media_mtransport_third_party_nICEr_src_stun_stun_h

@@ -1,12 +0,0 @@
---- mozilla-release.orig/media/mtransport/third_party/nICEr/src/stun/stun.h	2013-12-05 17:07:48.000000000 +0100
-+++ mozilla-release/media/mtransport/third_party/nICEr/src/stun/stun.h	2014-01-03 17:19:05.000000000 +0100
-@@ -39,7 +39,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- #else
- #include <sys/param.h>
- #include <sys/socket.h>
-+#if defined(__GLIBC__)
- #include <net/if.h>
-+#endif
- #ifndef LINUX
- #if !defined(__OpenBSD__) && !defined(__NetBSD__)
- #include <net/if_var.h>

+ 0 - 23
package/firefox/patches/patch-media_webrtc_trunk_tools_gyp_pylib_gyp_common_py

@@ -1,23 +0,0 @@
---- mozilla-release.orig/media/webrtc/trunk/tools/gyp/pylib/gyp/common.py	2013-12-05 17:07:48.000000000 +0100
-+++ mozilla-release/media/webrtc/trunk/tools/gyp/pylib/gyp/common.py	2014-02-05 08:12:49.000000000 +0100
-@@ -364,20 +364,6 @@ def WriteOnDiff(filename):
- 
- def GetFlavor(params):
-   """Returns |params.flavor| if it's set, the system's default flavor else."""
--  flavors = {
--    'cygwin': 'win',
--    'win32': 'win',
--    'darwin': 'mac',
--  }
--
--  if 'flavor' in params:
--    return params['flavor']
--  if sys.platform in flavors:
--    return flavors[sys.platform]
--  if sys.platform.startswith('sunos'):
--    return 'solaris'
--  if sys.platform.startswith('freebsd'):
--    return 'freebsd'
- 
-   return 'linux'
- 

+ 0 - 26
package/firefox/patches/patch-media_webrtc_trunk_tools_gyp_pylib_gyp_generator_mozmake_py

@@ -1,26 +0,0 @@
---- mozilla-release.orig/media/webrtc/trunk/tools/gyp/pylib/gyp/generator/mozmake.py	2013-12-05 17:07:48.000000000 +0100
-+++ mozilla-release/media/webrtc/trunk/tools/gyp/pylib/gyp/generator/mozmake.py	2014-02-05 08:13:30.000000000 +0100
-@@ -118,23 +118,6 @@ def ensure_directory_exists(path):
- 
- def GetFlavor(params):
-   """Returns |params.flavor| if it's set, the system's default flavor else."""
--  system = platform.system().lower()
--  flavors = {
--    'microsoft': 'win',
--    'windows'  : 'win',
--    'cygwin'   : 'win',
--    'darwin'   : 'mac',
--    'sunos'    : 'solaris',
--    'dragonfly': 'dragonfly',
--    'freebsd'  : 'freebsd',
--    'netbsd'   : 'netbsd',
--    'openbsd'  : 'openbsd',
--  }
--
--  if 'flavor' in params:
--    return params['flavor']
--  if system in flavors:
--    return flavors[system]
- 
-   return 'linux'
- 

+ 0 - 11
package/firefox/patches/patch-media_webrtc_trunk_webrtc_modules_audio_device_audio_device_impl_cc

@@ -1,11 +0,0 @@
---- mozilla-release.orig/media/webrtc/trunk/webrtc/modules/audio_device/audio_device_impl.cc	2013-09-11 01:15:17.000000000 +0200
-+++ mozilla-release/media/webrtc/trunk/webrtc/modules/audio_device/audio_device_impl.cc	2013-10-23 16:28:38.000000000 +0200
-@@ -8,6 +8,8 @@
-  *  be found in the AUTHORS file in the root of the source tree.
-  */
- 
-+#define _POSIX_SOURCE
-+
- #include "audio_device_impl.h"
- #include "audio_device_config.h"
- #include "common_audio/signal_processing/include/signal_processing_library.h"

+ 0 - 11
package/firefox/patches/patch-media_webrtc_trunk_webrtc_modules_audio_device_linux_audio_device_alsa_linux_cc

@@ -1,11 +0,0 @@
---- mozilla-release.orig/media/webrtc/trunk/webrtc/modules/audio_device/linux/audio_device_alsa_linux.cc	2013-09-11 01:15:17.000000000 +0200
-+++ mozilla-release/media/webrtc/trunk/webrtc/modules/audio_device/linux/audio_device_alsa_linux.cc	2013-10-23 16:28:38.000000000 +0200
-@@ -8,6 +8,8 @@
-  *  be found in the AUTHORS file in the root of the source tree.
-  */
- 
-+#define _POSIX_SOURCE
-+
- #include <cassert>
- 
- #include "audio_device_utility.h"

+ 0 - 11
package/firefox/patches/patch-media_webrtc_trunk_webrtc_modules_audio_device_linux_audio_mixer_manager_alsa_linux_cc

@@ -1,11 +0,0 @@
---- mozilla-release.orig/media/webrtc/trunk/webrtc/modules/audio_device/linux/audio_mixer_manager_alsa_linux.cc	2013-09-11 01:15:17.000000000 +0200
-+++ mozilla-release/media/webrtc/trunk/webrtc/modules/audio_device/linux/audio_mixer_manager_alsa_linux.cc	2013-10-23 16:28:38.000000000 +0200
-@@ -8,6 +8,8 @@
-  *  be found in the AUTHORS file in the root of the source tree.
-  */
- 
-+#define _POSIX_SOURCE
-+
- #include <cassert>
- 
- #include "audio_mixer_manager_alsa_linux.h"

+ 0 - 23
package/firefox/patches/patch-media_webrtc_trunk_webrtc_system_wrappers_source_cpu_info_cc

@@ -1,23 +0,0 @@
---- mozilla-release.orig/media/webrtc/trunk/webrtc/system_wrappers/source/cpu_info.cc	2013-12-05 17:07:50.000000000 +0100
-+++ mozilla-release/media/webrtc/trunk/webrtc/system_wrappers/source/cpu_info.cc	2014-03-16 10:56:09.000000000 +0100
-@@ -36,11 +36,6 @@ uint32_t CpuInfo::DetectNumberOfCores()
-     WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
-                  "Available number of cores:%d", number_of_cores_);
- 
--#elif defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID) && !defined(WEBRTC_GONK)
--    number_of_cores_ = static_cast<uint32_t>(sysconf(_SC_NPROCESSORS_ONLN));
--    WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
--                 "Available number of cores:%d", number_of_cores_);
--
- #elif defined(WEBRTC_BSD) || defined(WEBRTC_MAC)
-     int name[] = {
-       CTL_HW,
-@@ -61,8 +56,6 @@ uint32_t CpuInfo::DetectNumberOfCores()
-                    "Failed to get number of cores");
-       number_of_cores_ = 1;
-     }
--#elif defined(_SC_NPROCESSORS_ONLN)
--    number_of_cores_ = sysconf(_SC_NPROCESSORS_ONLN);
- #else
-     WEBRTC_TRACE(kTraceWarning, kTraceUtility, -1,
-                  "No function to get number of cores");

+ 0 - 3385
package/firefox/patches/patch-media_webrtc_trunk_webrtc_system_wrappers_source_spreadsortlib_spreadsort_hpp

@@ -1,3385 +0,0 @@
---- mozilla-release.orig/media/webrtc/trunk/webrtc/system_wrappers/source/spreadsortlib/spreadsort.hpp	2013-12-05 17:07:50.000000000 +0100
-+++ mozilla-release/media/webrtc/trunk/webrtc/system_wrappers/source/spreadsortlib/spreadsort.hpp	2014-02-05 09:52:11.000000000 +0100
-@@ -1,1688 +1,1694 @@
--//Templated spread_sort library
--
--//          Copyright Steven J. Ross 2001 - 2009.
--// Distributed under the Boost Software License, Version 1.0.
--//    (See accompanying file LICENSE_1_0.txt or copy at
--//          http://www.boost.org/LICENSE_1_0.txt)
--
--//  See http://www.boost.org/ for updates, documentation, and revision history.
--		  
--/*
--Some improvements suggested by:
--Phil Endecott and Frank Gennari
--Cygwin fix provided by:
--Scott McMurray
--*/
--
--#ifndef BOOST_SPREAD_SORT_H
--#define BOOST_SPREAD_SORT_H
--#include <algorithm>
--#include <cstring>
--#include <vector>
--#include "webrtc/system_wrappers/source/spreadsortlib/constants.hpp"
--
--namespace boost {
--  namespace detail {
--  	//This only works on unsigned data types
--  	template <typename T>
--  	inline unsigned 
--  	rough_log_2_size(const T& input) 
--  	{
--  		unsigned result = 0;
--  		//The && is necessary on some compilers to avoid infinite loops; it doesn't significantly impair performance
--  		while((input >> result) && (result < (8*sizeof(T)))) ++result;
--  		return result;
--  	}
--
--  	//Gets the maximum size which we'll call spread_sort on to control worst-case performance
--  	//Maintains both a minimum size to recurse and a check of distribution size versus count
--  	//This is called for a set of bins, instead of bin-by-bin, to avoid performance overhead
--  	inline size_t
--  	get_max_count(unsigned log_range, size_t count)
--  	{
--  		unsigned divisor = rough_log_2_size(count);
--  		//Making sure the divisor is positive
--  		if(divisor > LOG_MEAN_BIN_SIZE)
--  			divisor -= LOG_MEAN_BIN_SIZE;
--  		else
--  			divisor = 1;
--  		unsigned relative_width = (LOG_CONST * log_range)/((divisor > MAX_SPLITS) ? MAX_SPLITS : divisor);
--  		//Don't try to bitshift more than the size of an element
--  		if((8*sizeof(size_t)) <= relative_width)
--  			relative_width = (8*sizeof(size_t)) - 1;
--  		return (size_t)1 << ((relative_width < (LOG_MEAN_BIN_SIZE + LOG_MIN_SPLIT_COUNT)) ? 
--  			(LOG_MEAN_BIN_SIZE + LOG_MIN_SPLIT_COUNT) :  relative_width);
--  	}
--
--  	//Find the minimum and maximum using <
--  	template <class RandomAccessIter>
--  	inline void 
--  	find_extremes(RandomAccessIter current, RandomAccessIter last, RandomAccessIter & max, RandomAccessIter & min)
--  	{
--  		min = max = current;
--  		//Start from the second item, as max and min are initialized to the first
--  		while(++current < last) {
--  			if(*max < *current)
--  				max = current;
--  			else if(*current < *min)
--  				min = current;
--  		}
--  	}
--
--  	//Uses a user-defined comparison operator to find minimum and maximum
--  	template <class RandomAccessIter, class compare>
--  	inline void 
--  	find_extremes(RandomAccessIter current, RandomAccessIter last, RandomAccessIter & max, RandomAccessIter & min, compare comp)
--  	{
--  		min = max = current;
--  		while(++current < last) {
--  			if(comp(*max, *current))
--  				max = current;
--  			else if(comp(*current, *min))
--  				min = current;
--  		}
--  	}
--
--  	//Gets a non-negative right bit shift to operate as a logarithmic divisor
--  	inline int
--  	get_log_divisor(size_t count, unsigned log_range)
--  	{
--  		int log_divisor;
--  		//If we can finish in one iteration without exceeding either (2 to the MAX_SPLITS) or n bins, do so
--  		if((log_divisor = log_range - rough_log_2_size(count)) <= 0 && log_range < MAX_SPLITS)
--  			log_divisor = 0;
--  		else {
--  			//otherwise divide the data into an optimized number of pieces
--  			log_divisor += LOG_MEAN_BIN_SIZE;
--  			if(log_divisor < 0)
--  				log_divisor = 0;
--  			//Cannot exceed MAX_SPLITS or cache misses slow down bin lookups dramatically
--  			if((log_range - log_divisor) > MAX_SPLITS)
--  				log_divisor = log_range - MAX_SPLITS;
--  		}
--  		return log_divisor;
--  	}
--
--  	template <class RandomAccessIter>
--  	inline RandomAccessIter * 
--  	size_bins(std::vector<size_t> &bin_sizes, std::vector<RandomAccessIter> &bin_cache, unsigned cache_offset, unsigned &cache_end, unsigned bin_count)
--  	{
--  		//Assure space for the size of each bin, followed by initializing sizes
--  		if(bin_count > bin_sizes.size())
--  			bin_sizes.resize(bin_count);
--  		for(size_t u = 0; u < bin_count; u++)
--  			bin_sizes[u] = 0;
--  		//Make sure there is space for the bins
--  		cache_end = cache_offset + bin_count;
--  		if(cache_end > bin_cache.size())
--  			bin_cache.resize(cache_end);
--  		return &(bin_cache[cache_offset]);
--  	}
--
--  	//Implementation for recursive integer sorting
--  	template <class RandomAccessIter, class div_type, class data_type>
--  	inline void 
--  	spread_sort_rec(RandomAccessIter first, RandomAccessIter last, std::vector<RandomAccessIter> &bin_cache, unsigned cache_offset
--  				  , std::vector<size_t> &bin_sizes)
--  	{
--  		//This step is roughly 10% of runtime, but it helps avoid worst-case behavior and improve behavior with real data
--  		//If you know the maximum and minimum ahead of time, you can pass those values in and skip this step for the first iteration
--  		RandomAccessIter max, min;
--  		find_extremes(first, last, max, min);
--  		//max and min will be the same (the first item) iff all values are equivalent
--  		if(max == min)
--  			return;
--  		RandomAccessIter * target_bin;
--  		unsigned log_divisor = get_log_divisor(last - first, rough_log_2_size((size_t)(*max >> 0) - (*min >> 0)));
--  		div_type div_min = *min >> log_divisor;
--  		div_type div_max = *max >> log_divisor;
--  		unsigned bin_count = div_max - div_min + 1;
--  		unsigned cache_end;
--  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, bin_count);
--  	
--  		//Calculating the size of each bin; this takes roughly 10% of runtime
--  		for (RandomAccessIter current = first; current != last;)
--  			bin_sizes[(*(current++) >> log_divisor) - div_min]++;
--  		//Assign the bin positions
--  		bins[0] = first;
--  		for(unsigned u = 0; u < bin_count - 1; u++)
--  			bins[u + 1] = bins[u] + bin_sizes[u];
--  
--  		//Swap into place
--  		//This dominates runtime, mostly in the swap and bin lookups
--  		RandomAccessIter nextbinstart = first;
--  		for(unsigned u = 0; u < bin_count - 1; ++u) {
--  			RandomAccessIter * local_bin = bins + u;
--  			nextbinstart += bin_sizes[u];
--  			//Iterating over each element in this bin
--  			for(RandomAccessIter current = *local_bin; current < nextbinstart; ++current) {
--  				//Swapping elements in current into place until the correct element has been swapped in
--  				for(target_bin = (bins + ((*current >> log_divisor) - div_min));  target_bin != local_bin; 
--  					target_bin = bins + ((*current >> log_divisor) - div_min)) {
--  					//3-way swap; this is about 1% faster than a 2-way swap with integers
--  					//The main advantage is less copies are involved per item put in the correct place
--  					data_type tmp;
--  					RandomAccessIter b = (*target_bin)++;
--  					RandomAccessIter * b_bin = bins + ((*b >> log_divisor) - div_min);
--  					if (b_bin != local_bin) {
--  						RandomAccessIter c = (*b_bin)++;
--  						tmp = *c;
--  						*c = *b;
--  					} 
--  					else
--  						tmp = *b;
--  					*b = *current;
--  					*current = tmp;
--  				}
--  			}
--  			*local_bin = nextbinstart;
--  		}
--  		bins[bin_count - 1] = last;
--  
--  		//If we've bucketsorted, the array is sorted and we should skip recursion
--  		if(!log_divisor)
--  			return;
--  
--  		//Recursing; log_divisor is the remaining range
--  		size_t max_count = get_max_count(log_divisor, last - first);
--  		RandomAccessIter lastPos = first;
--  		for(unsigned u = cache_offset; u < cache_end; lastPos = bin_cache[u], ++u) {
--  			size_t count = bin_cache[u] - lastPos;
--  			//don't sort unless there are at least two items to compare
--  			if(count < 2)
--  				continue;
--  			//using std::sort if its worst-case is better
--  			if(count < max_count)
--  				std::sort(lastPos, bin_cache[u]);
--  			else
--  				spread_sort_rec<RandomAccessIter, div_type, data_type>(lastPos, bin_cache[u], bin_cache, cache_end, bin_sizes);
--  		}
--  	}
--
--  	//Generic bitshift-based 3-way swapping code
--  	template <class RandomAccessIter, class div_type, class data_type, class right_shift>
--  	inline void inner_swap_loop(RandomAccessIter * bins, const RandomAccessIter & nextbinstart, unsigned ii, right_shift &shift
--  		, const unsigned log_divisor, const div_type div_min) 
--  	{
--  		RandomAccessIter * local_bin = bins + ii;
--  		for(RandomAccessIter current = *local_bin; current < nextbinstart; ++current) {
--  			for(RandomAccessIter * target_bin = (bins + (shift(*current, log_divisor) - div_min));  target_bin != local_bin; 
--  				target_bin = bins + (shift(*current, log_divisor) - div_min)) {
--  				data_type tmp;
--  				RandomAccessIter b = (*target_bin)++;
--  				RandomAccessIter * b_bin = bins + (shift(*b, log_divisor) - div_min);
--  				//Three-way swap; if the item to be swapped doesn't belong in the current bin, swap it to where it belongs
--  				if (b_bin != local_bin) {
--  					RandomAccessIter c = (*b_bin)++;
--  					tmp = *c;
--  					*c = *b;
--  				} 
--  				//Note: we could increment current once the swap is done in this case, but that seems to impair performance
--  				else
--  					tmp = *b;
--  				*b = *current;
--  				*current = tmp;
--  			}
--  		}
--  		*local_bin = nextbinstart;
--  	}
--
--  	//Standard swapping wrapper for ascending values
--  	template <class RandomAccessIter, class div_type, class data_type, class right_shift>
--  	inline void swap_loop(RandomAccessIter * bins, RandomAccessIter & nextbinstart, unsigned ii, right_shift &shift
--  		, const std::vector<size_t> &bin_sizes, const unsigned log_divisor, const div_type div_min) 
--  	{
--  		nextbinstart += bin_sizes[ii];
--  		inner_swap_loop<RandomAccessIter, div_type, data_type, right_shift>(bins, nextbinstart, ii, shift, log_divisor, div_min);
--  	}
--
--  	//Functor implementation for recursive sorting
--  	template <class RandomAccessIter, class div_type, class data_type, class right_shift, class compare>
--  	inline void 
--  	spread_sort_rec(RandomAccessIter first, RandomAccessIter last, std::vector<RandomAccessIter> &bin_cache, unsigned cache_offset
--  					, std::vector<size_t> &bin_sizes, right_shift shift, compare comp)
--  	{
--  		RandomAccessIter max, min;
--  		find_extremes(first, last, max, min, comp);
--  		if(max == min)
--  			return;
--  		unsigned log_divisor = get_log_divisor(last - first, rough_log_2_size((size_t)(shift(*max, 0)) - (shift(*min, 0))));
--  		div_type div_min = shift(*min, log_divisor);
--  		div_type div_max = shift(*max, log_divisor);
--  		unsigned bin_count = div_max - div_min + 1;
--  		unsigned cache_end;
--  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, bin_count);
--  			
--  		//Calculating the size of each bin
--  		for (RandomAccessIter current = first; current != last;)
--  			bin_sizes[shift(*(current++), log_divisor) - div_min]++;
--  		bins[0] = first;
--  		for(unsigned u = 0; u < bin_count - 1; u++)
--  			bins[u + 1] = bins[u] + bin_sizes[u];
--  		
--  		//Swap into place
--  		RandomAccessIter nextbinstart = first;
--  		for(unsigned u = 0; u < bin_count - 1; ++u)
--  			swap_loop<RandomAccessIter, div_type, data_type, right_shift>(bins, nextbinstart, u, shift, bin_sizes, log_divisor, div_min);
--  		bins[bin_count - 1] = last;
--  		
--  		//If we've bucketsorted, the array is sorted and we should skip recursion
--  		if(!log_divisor)
--  			return;
--  		
--  		//Recursing
--  		size_t max_count = get_max_count(log_divisor, last - first);
--  		RandomAccessIter lastPos = first;
--  		for(unsigned u = cache_offset; u < cache_end; lastPos = bin_cache[u], ++u) {
--  			size_t count = bin_cache[u] - lastPos;
--  			if(count < 2)
--  				continue;
--  			if(count < max_count)
--  				std::sort(lastPos, bin_cache[u], comp);
--  			else
--  				spread_sort_rec<RandomAccessIter, div_type, data_type, right_shift, compare>(lastPos, bin_cache[u], bin_cache, cache_end, bin_sizes, shift, comp);
--  		}
--  	}
--
--  	//Functor implementation for recursive sorting with only Shift overridden
--  	template <class RandomAccessIter, class div_type, class data_type, class right_shift>
--  	inline void 
--  	spread_sort_rec(RandomAccessIter first, RandomAccessIter last, std::vector<RandomAccessIter> &bin_cache, unsigned cache_offset
--  					, std::vector<size_t> &bin_sizes, right_shift shift)
--  	{
--  		RandomAccessIter max, min;
--  		find_extremes(first, last, max, min);
--  		if(max == min)
--  			return;
--  		unsigned log_divisor = get_log_divisor(last - first, rough_log_2_size((size_t)(shift(*max, 0)) - (shift(*min, 0))));
--  		div_type div_min = shift(*min, log_divisor);
--  		div_type div_max = shift(*max, log_divisor);
--  		unsigned bin_count = div_max - div_min + 1;
--  		unsigned cache_end;
--  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, bin_count);
--  			
--  		//Calculating the size of each bin
--  		for (RandomAccessIter current = first; current != last;)
--  			bin_sizes[shift(*(current++), log_divisor) - div_min]++;
--  		bins[0] = first;
--  		for(unsigned u = 0; u < bin_count - 1; u++)
--  			bins[u + 1] = bins[u] + bin_sizes[u];
--  		
--  		//Swap into place
--  		RandomAccessIter nextbinstart = first;
--  		for(unsigned ii = 0; ii < bin_count - 1; ++ii)
--  			swap_loop<RandomAccessIter, div_type, data_type, right_shift>(bins, nextbinstart, ii, shift, bin_sizes, log_divisor, div_min);
--  		bins[bin_count - 1] = last;
--  		
--  		//If we've bucketsorted, the array is sorted and we should skip recursion
--  		if(!log_divisor)
--  			return;
--  		
--  		//Recursing
--  		size_t max_count = get_max_count(log_divisor, last - first);
--  		RandomAccessIter lastPos = first;
--  		for(unsigned u = cache_offset; u < cache_end; lastPos = bin_cache[u], ++u) {
--  			size_t count = bin_cache[u] - lastPos;
--  			if(count < 2)
--  				continue;
--  			if(count < max_count)
--  				std::sort(lastPos, bin_cache[u]);
--  			else
--  				spread_sort_rec<RandomAccessIter, div_type, data_type, right_shift>(lastPos, bin_cache[u], bin_cache, cache_end, bin_sizes, shift);
--  		}
--  	}
--
--  	//Holds the bin vector and makes the initial recursive call
--  	template <class RandomAccessIter, class div_type, class data_type>
--  	inline void 
--  	spread_sort(RandomAccessIter first, RandomAccessIter last, div_type, data_type)
--  	{
--  		std::vector<size_t> bin_sizes;
--  		std::vector<RandomAccessIter> bin_cache;
--  		spread_sort_rec<RandomAccessIter, div_type, data_type>(first, last, bin_cache, 0, bin_sizes);
--  	}
--
--  	template <class RandomAccessIter, class div_type, class data_type, class right_shift, class compare>
--  	inline void 
--  	spread_sort(RandomAccessIter first, RandomAccessIter last, div_type, data_type, right_shift shift, compare comp)
--  	{
--  		std::vector<size_t> bin_sizes;
--  		std::vector<RandomAccessIter> bin_cache;
--  		spread_sort_rec<RandomAccessIter, div_type, data_type, right_shift, compare>(first, last, bin_cache, 0, bin_sizes, shift, comp);
--  	}
--
--  	template <class RandomAccessIter, class div_type, class data_type, class right_shift>
--  	inline void 
--  	spread_sort(RandomAccessIter first, RandomAccessIter last, div_type, data_type, right_shift shift)
--  	{
--  		std::vector<size_t> bin_sizes;
--  		std::vector<RandomAccessIter> bin_cache;
--  		spread_sort_rec<RandomAccessIter, div_type, data_type, right_shift>(first, last, bin_cache, 0, bin_sizes, shift);
--  	}
--  }
--
--  //Top-level sorting call for integers
--  template <class RandomAccessIter>
--  inline void integer_sort(RandomAccessIter first, RandomAccessIter last) 
--  {
--  	//Don't sort if it's too small to optimize
--  	if(last - first < detail::MIN_SORT_SIZE)
--  		std::sort(first, last);
--  	else
--  		detail::spread_sort(first, last, *first >> 0, *first);
--  }
--
--  //integer_sort with functors
--  template <class RandomAccessIter, class right_shift, class compare>
--  inline void integer_sort(RandomAccessIter first, RandomAccessIter last,
--  						right_shift shift, compare comp) {
--  	if(last - first < detail::MIN_SORT_SIZE)
--  		std::sort(first, last, comp);
--  	else
--  		detail::spread_sort(first, last, shift(*first, 0), *first, shift, comp);
--  }
--
--  //integer_sort with right_shift functor
--  template <class RandomAccessIter, class right_shift>
--  inline void integer_sort(RandomAccessIter first, RandomAccessIter last,
--  						right_shift shift) {
--  	if(last - first < detail::MIN_SORT_SIZE)
--  		std::sort(first, last);
--  	else
--  		detail::spread_sort(first, last, shift(*first, 0), *first, shift);
--  }
--
--  //------------------------------------------------------ float_sort source --------------------------------------
--  //Casts a RandomAccessIter to the specified data type
--  template<class cast_type, class RandomAccessIter>
--  inline cast_type
--  cast_float_iter(const RandomAccessIter & floatiter)
--  {
--  	cast_type result;
--  	std::memcpy(&result, &(*floatiter), sizeof(cast_type));
--  	return result;
--  }
--
--  //Casts a data element to the specified datinner_float_a type
--  template<class data_type, class cast_type>
--  inline cast_type
--  mem_cast(const data_type & data)
--  {
--  	cast_type result;
--  	std::memcpy(&result, &data, sizeof(cast_type));
--  	return result;
--  }
--
--  namespace detail {
--  	template <class RandomAccessIter, class div_type, class right_shift>
--  	inline void 
--  	find_extremes(RandomAccessIter current, RandomAccessIter last, div_type & max, div_type & min, right_shift shift)
--  	{
--  		min = max = shift(*current, 0);
--  		while(++current < last) {
--  			div_type value = shift(*current, 0);
--  			if(max < value)
--  				max = value;
--  			else if(value < min)
--  				min = value;
--  		}
--  	}
--
--  	//Specialized swap loops for floating-point casting
--  	template <class RandomAccessIter, class div_type, class data_type>
--  	inline void inner_float_swap_loop(RandomAccessIter * bins, const RandomAccessIter & nextbinstart, unsigned ii
--  		, const unsigned log_divisor, const div_type div_min) 
--  	{
--  		RandomAccessIter * local_bin = bins + ii;
--  		for(RandomAccessIter current = *local_bin; current < nextbinstart; ++current) {
--  			for(RandomAccessIter * target_bin = (bins + ((cast_float_iter<div_type, RandomAccessIter>(current) >> log_divisor) - div_min));  target_bin != local_bin; 
--  				target_bin = bins + ((cast_float_iter<div_type, RandomAccessIter>(current) >> log_divisor) - div_min)) {
--  				data_type tmp;
--  				RandomAccessIter b = (*target_bin)++;
--  				RandomAccessIter * b_bin = bins + ((cast_float_iter<div_type, RandomAccessIter>(b) >> log_divisor) - div_min);
--  				//Three-way swap; if the item to be swapped doesn't belong in the current bin, swap it to where it belongs
--  				if (b_bin != local_bin) {
--  					RandomAccessIter c = (*b_bin)++;
--  					tmp = *c;
--  					*c = *b;
--  				} 
--  				else
--  					tmp = *b;
--  				*b = *current;
--  				*current = tmp;
--  			}
--  		}
--  		*local_bin = nextbinstart;
--  	}
--
--  	template <class RandomAccessIter, class div_type, class data_type>
--  	inline void float_swap_loop(RandomAccessIter * bins, RandomAccessIter & nextbinstart, unsigned ii
--  		, const std::vector<size_t> &bin_sizes, const unsigned log_divisor, const div_type div_min) 
--  	{
--  		nextbinstart += bin_sizes[ii];
--  		inner_float_swap_loop<RandomAccessIter, div_type, data_type>(bins, nextbinstart, ii, log_divisor, div_min);
--  	}
--
--  	template <class RandomAccessIter, class cast_type>
--  	inline void 
--  	find_extremes(RandomAccessIter current, RandomAccessIter last, cast_type & max, cast_type & min)
--  	{
--  		min = max = cast_float_iter<cast_type, RandomAccessIter>(current);
--  		while(++current < last) {
--  			cast_type value = cast_float_iter<cast_type, RandomAccessIter>(current);
--  			if(max < value)
--  				max = value;
--  			else if(value < min)
--  				min = value;
--  		}
--  	}
--
--  	//Special-case sorting of positive floats with casting instead of a right_shift
--  	template <class RandomAccessIter, class div_type, class data_type>
--  	inline void 
--  	positive_float_sort_rec(RandomAccessIter first, RandomAccessIter last, std::vector<RandomAccessIter> &bin_cache, unsigned cache_offset
--  					, std::vector<size_t> &bin_sizes)
--  	{
--  		div_type max, min;
--  		find_extremes(first, last, max, min);
--  		if(max == min)
--  			return;
--  		unsigned log_divisor = get_log_divisor(last - first, rough_log_2_size((size_t)(max) - min));
--  		div_type div_min = min >> log_divisor;
--  		div_type div_max = max >> log_divisor;
--  		unsigned bin_count = div_max - div_min + 1;
--  		unsigned cache_end;
--  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, bin_count);
--  			
--  		//Calculating the size of each bin
--  		for (RandomAccessIter current = first; current != last;)
--  			bin_sizes[(cast_float_iter<div_type, RandomAccessIter>(current++) >> log_divisor) - div_min]++;
--  		bins[0] = first;
--  		for(unsigned u = 0; u < bin_count - 1; u++)
--  			bins[u + 1] = bins[u] + bin_sizes[u];
--  		
--  		//Swap into place
--  		RandomAccessIter nextbinstart = first;
--  		for(unsigned u = 0; u < bin_count - 1; ++u)
--  			float_swap_loop<RandomAccessIter, div_type, data_type>(bins, nextbinstart, u, bin_sizes, log_divisor, div_min);
--  		bins[bin_count - 1] = last;
--  		
--  		//Return if we've completed bucketsorting
--  		if(!log_divisor)
--  			return;
--  		
--  		//Recursing
--  		size_t max_count = get_max_count(log_divisor, last - first);
--  		RandomAccessIter lastPos = first;
--  		for(unsigned u = cache_offset; u < cache_end; lastPos = bin_cache[u], ++u) {
--  			size_t count = bin_cache[u] - lastPos;
--  			if(count < 2)
--  				continue;
--  			if(count < max_count)
--  				std::sort(lastPos, bin_cache[u]);
--  			else
--  				positive_float_sort_rec<RandomAccessIter, div_type, data_type>(lastPos, bin_cache[u], bin_cache, cache_end, bin_sizes);
--  		}
--  	}
--
--  	//Sorting negative_ float_s
--  	//Note that bins are iterated in reverse order because max_neg_float = min_neg_int
--  	template <class RandomAccessIter, class div_type, class data_type>
--  	inline void 
--  	negative_float_sort_rec(RandomAccessIter first, RandomAccessIter last, std::vector<RandomAccessIter> &bin_cache, unsigned cache_offset
--  					, std::vector<size_t> &bin_sizes)
--  	{
--  		div_type max, min;
--  		find_extremes(first, last, max, min);
--  		if(max == min)
--  			return;
--  		unsigned log_divisor = get_log_divisor(last - first, rough_log_2_size((size_t)(max) - min));
--  		div_type div_min = min >> log_divisor;
--  		div_type div_max = max >> log_divisor;
--  		unsigned bin_count = div_max - div_min + 1;
--  		unsigned cache_end;
--  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, bin_count);
--  			
--  		//Calculating the size of each bin
--  		for (RandomAccessIter current = first; current != last;)
--  			bin_sizes[(cast_float_iter<div_type, RandomAccessIter>(current++) >> log_divisor) - div_min]++;
--  		bins[bin_count - 1] = first;
--  		for(int ii = bin_count - 2; ii >= 0; --ii)
--  			bins[ii] = bins[ii + 1] + bin_sizes[ii + 1];
--  		
--  		//Swap into place
--  		RandomAccessIter nextbinstart = first;
--  		//The last bin will always have the correct elements in it
--  		for(int ii = bin_count - 1; ii > 0; --ii)
--  			float_swap_loop<RandomAccessIter, div_type, data_type>(bins, nextbinstart, ii, bin_sizes, log_divisor, div_min);
--  		//Since we don't process the last bin, we need to update its end position
--  		bin_cache[cache_offset] = last;
--  		
--  		//Return if we've completed bucketsorting
--  		if(!log_divisor)
--  			return;
--  		
--  		//Recursing
--  		size_t max_count = get_max_count(log_divisor, last - first);
--  		RandomAccessIter lastPos = first;
--  		for(int ii = cache_end - 1; ii >= (int)cache_offset; lastPos = bin_cache[ii], --ii) {
--  			size_t count = bin_cache[ii] - lastPos;
--  			if(count < 2)
--  				continue;
--  			if(count < max_count)
--  				std::sort(lastPos, bin_cache[ii]);
--  			else
--  				negative_float_sort_rec<RandomAccessIter, div_type, data_type>(lastPos, bin_cache[ii], bin_cache, cache_end, bin_sizes);
--  		}
--  	}
--
--  	//Sorting negative_ float_s
--  	//Note that bins are iterated in reverse order because max_neg_float = min_neg_int
--  	template <class RandomAccessIter, class div_type, class data_type, class right_shift>
--  	inline void 
--  	negative_float_sort_rec(RandomAccessIter first, RandomAccessIter last, std::vector<RandomAccessIter> &bin_cache, unsigned cache_offset
--  					, std::vector<size_t> &bin_sizes, right_shift shift)
--  	{
--  		div_type max, min;
--  		find_extremes(first, last, max, min, shift);
--  		if(max == min)
--  			return;
--  		unsigned log_divisor = get_log_divisor(last - first, rough_log_2_size((size_t)(max) - min));
--  		div_type div_min = min >> log_divisor;
--  		div_type div_max = max >> log_divisor;
--  		unsigned bin_count = div_max - div_min + 1;
--  		unsigned cache_end;
--  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, bin_count);
--  			
--  		//Calculating the size of each bin
--  		for (RandomAccessIter current = first; current != last;)
--  			bin_sizes[shift(*(current++), log_divisor) - div_min]++;
--  		bins[bin_count - 1] = first;
--  		for(int ii = bin_count - 2; ii >= 0; --ii)
--  			bins[ii] = bins[ii + 1] + bin_sizes[ii + 1];
--  		
--  		//Swap into place
--  		RandomAccessIter nextbinstart = first;
--  		//The last bin will always have the correct elements in it
--  		for(int ii = bin_count - 1; ii > 0; --ii)
--  			swap_loop<RandomAccessIter, div_type, data_type, right_shift>(bins, nextbinstart, ii, shift, bin_sizes, log_divisor, div_min);
--  		//Since we don't process the last bin, we need to update its end position
--  		bin_cache[cache_offset] = last;
--  		
--  		//Return if we've completed bucketsorting
--  		if(!log_divisor)
--  			return;
--  		
--  		//Recursing
--  		size_t max_count = get_max_count(log_divisor, last - first);
--  		RandomAccessIter lastPos = first;
--  		for(int ii = cache_end - 1; ii >= (int)cache_offset; lastPos = bin_cache[ii], --ii) {
--  			size_t count = bin_cache[ii] - lastPos;
--  			if(count < 2)
--  				continue;
--  			if(count < max_count)
--  				std::sort(lastPos, bin_cache[ii]);
--  			else
--  				negative_float_sort_rec<RandomAccessIter, div_type, data_type, right_shift>(lastPos, bin_cache[ii], bin_cache, cache_end, bin_sizes, shift);
--  		}
--  	}
--
--  	template <class RandomAccessIter, class div_type, class data_type, class right_shift, class compare>
--  	inline void 
--  	negative_float_sort_rec(RandomAccessIter first, RandomAccessIter last, std::vector<RandomAccessIter> &bin_cache, unsigned cache_offset
--  					, std::vector<size_t> &bin_sizes, right_shift shift, compare comp)
--  	{
--  		div_type max, min;
--  		find_extremes(first, last, max, min, shift);
--  		if(max == min)
--  			return;
--  		unsigned log_divisor = get_log_divisor(last - first, rough_log_2_size((size_t)(max) - min));
--  		div_type div_min = min >> log_divisor;
--  		div_type div_max = max >> log_divisor;
--  		unsigned bin_count = div_max - div_min + 1;
--  		unsigned cache_end;
--  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, bin_count);
--  			
--  		//Calculating the size of each bin
--  		for (RandomAccessIter current = first; current != last;)
--  			bin_sizes[shift(*(current++), log_divisor) - div_min]++;
--  		bins[bin_count - 1] = first;
--  		for(int ii = bin_count - 2; ii >= 0; --ii)
--  			bins[ii] = bins[ii + 1] + bin_sizes[ii + 1];
--  		
--  		//Swap into place
--  		RandomAccessIter nextbinstart = first;
--  		//The last bin will always have the correct elements in it
--  		for(int ii = bin_count - 1; ii > 0; --ii)
--  			swap_loop<RandomAccessIter, div_type, data_type, right_shift>(bins, nextbinstart, ii, shift, bin_sizes, log_divisor, div_min);
--  		//Since we don't process the last bin, we need to update its end position
--  		bin_cache[cache_offset] = last;
--  		
--  		//Return if we've completed bucketsorting
--  		if(!log_divisor)
--  			return;
--  		
--  		//Recursing
--  		size_t max_count = get_max_count(log_divisor, last - first);
--  		RandomAccessIter lastPos = first;
--  		for(int ii = cache_end - 1; ii >= (int)cache_offset; lastPos = bin_cache[ii], --ii) {
--  			size_t count = bin_cache[ii] - lastPos;
--  			if(count < 2)
--  				continue;
--  			if(count < max_count)
--  				std::sort(lastPos, bin_cache[ii], comp);
--  			else
--  				negative_float_sort_rec<RandomAccessIter, div_type, data_type, right_shift, compare>(lastPos, bin_cache[ii], bin_cache, cache_end, bin_sizes, shift, comp);
--  		}
--  	}
--
--  	//Casting special-case for floating-point sorting
--  	template <class RandomAccessIter, class div_type, class data_type>
--  	inline void 
--  	float_sort_rec(RandomAccessIter first, RandomAccessIter last, std::vector<RandomAccessIter> &bin_cache, unsigned cache_offset
--  					, std::vector<size_t> &bin_sizes)
--  	{
--  		div_type max, min;
--  		find_extremes(first, last, max, min);
--  		if(max == min)
--  			return;
--  		unsigned log_divisor = get_log_divisor(last - first, rough_log_2_size((size_t)(max) - min));
--  		div_type div_min = min >> log_divisor;
--  		div_type div_max = max >> log_divisor;
--  		unsigned bin_count = div_max - div_min + 1;
--  		unsigned cache_end;
--  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, bin_count);
--  			
--  		//Calculating the size of each bin
--  		for (RandomAccessIter current = first; current != last;)
--  			bin_sizes[(cast_float_iter<div_type, RandomAccessIter>(current++) >> log_divisor) - div_min]++;
--  		//The index of the first positive bin
--  		div_type first_positive = (div_min < 0) ? -div_min : 0;
--  		//Resetting if all bins are negative
--  		if(cache_offset + first_positive > cache_end)
--  			first_positive = cache_end - cache_offset;
--  		//Reversing the order of the negative bins
--  		//Note that because of the negative/positive ordering direction flip
--  		//We can not depend upon bin order and positions matching up
--  		//so bin_sizes must be reused to contain the end of the bin
--  		if(first_positive > 0) {
--  			bins[first_positive - 1] = first;
--  			for(int ii = first_positive - 2; ii >= 0; --ii) {
--  				bins[ii] = first + bin_sizes[ii + 1];
--  				bin_sizes[ii] += bin_sizes[ii + 1];
--  			}
--  			//Handling positives following negatives
--  			if((unsigned)first_positive < bin_count) {
--  				bins[first_positive] = first + bin_sizes[0];
--  				bin_sizes[first_positive] += bin_sizes[0];
--  			}
--  		}
--  		else
--  			bins[0] = first;
--  		for(unsigned u = first_positive; u < bin_count - 1; u++) {
--  			bins[u + 1] = first + bin_sizes[u];
--  			bin_sizes[u + 1] += bin_sizes[u];
--  		}
--  		
--  		//Swap into place
--  		RandomAccessIter nextbinstart = first;
--  		for(unsigned u = 0; u < bin_count; ++u) {
--  			nextbinstart = first + bin_sizes[u];
--  			inner_float_swap_loop<RandomAccessIter, div_type, data_type>(bins, nextbinstart, u, log_divisor, div_min);
--  		}
--  		
--  		if(!log_divisor)
--  			return;
--  		
--  		//Handling negative values first
--  		size_t max_count = get_max_count(log_divisor, last - first);
--  		RandomAccessIter lastPos = first;
--  		for(int ii = cache_offset + first_positive - 1; ii >= (int)cache_offset ; lastPos = bin_cache[ii--]) {
--  			size_t count = bin_cache[ii] - lastPos;
--  			if(count < 2)
--  				continue;
--  			if(count < max_count)
--  				std::sort(lastPos, bin_cache[ii]);
--  			//sort negative values using reversed-bin spread_sort
--  			else
--  				negative_float_sort_rec<RandomAccessIter, div_type, data_type>(lastPos, bin_cache[ii], bin_cache, cache_end, bin_sizes);
--  		}
--  		
--  		for(unsigned u = cache_offset + first_positive; u < cache_end; lastPos = bin_cache[u], ++u) {
--  			size_t count = bin_cache[u] - lastPos;
--  			if(count < 2)
--  				continue;
--  			if(count < max_count)
--  				std::sort(lastPos, bin_cache[u]);
--  			//sort positive values using normal spread_sort
--  			else
--  				positive_float_sort_rec<RandomAccessIter, div_type, data_type>(lastPos, bin_cache[u], bin_cache, cache_end, bin_sizes);
--  		}
--  	}
--
--  	//Functor implementation for recursive sorting
--  	template <class RandomAccessIter, class div_type, class data_type, class right_shift>
--  	inline void 
--  	float_sort_rec(RandomAccessIter first, RandomAccessIter last, std::vector<RandomAccessIter> &bin_cache, unsigned cache_offset
--  					, std::vector<size_t> &bin_sizes, right_shift shift)
--  	{
--  		div_type max, min;
--  		find_extremes(first, last, max, min, shift);
--  		if(max == min)
--  			return;
--  		unsigned log_divisor = get_log_divisor(last - first, rough_log_2_size((size_t)(max) - min));
--  		div_type div_min = min >> log_divisor;
--  		div_type div_max = max >> log_divisor;
--  		unsigned bin_count = div_max - div_min + 1;
--  		unsigned cache_end;
--  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, bin_count);
--  			
--  		//Calculating the size of each bin
--  		for (RandomAccessIter current = first; current != last;)
--  			bin_sizes[shift(*(current++), log_divisor) - div_min]++;
--  		//The index of the first positive bin
--  		div_type first_positive = (div_min < 0) ? -div_min : 0;
--  		//Resetting if all bins are negative
--  		if(cache_offset + first_positive > cache_end)
--  			first_positive = cache_end - cache_offset;
--  		//Reversing the order of the negative bins
--  		//Note that because of the negative/positive ordering direction flip
--  		//We can not depend upon bin order and positions matching up
--  		//so bin_sizes must be reused to contain the end of the bin
--  		if(first_positive > 0) {
--  			bins[first_positive - 1] = first;
--  			for(int ii = first_positive - 2; ii >= 0; --ii) {
--  				bins[ii] = first + bin_sizes[ii + 1];
--  				bin_sizes[ii] += bin_sizes[ii + 1];
--  			}
--  			//Handling positives following negatives
--  			if((unsigned)first_positive < bin_count) {
--  				bins[first_positive] = first + bin_sizes[0];
--  				bin_sizes[first_positive] += bin_sizes[0];
--  			}
--  		}
--  		else
--  			bins[0] = first;
--  		for(unsigned u = first_positive; u < bin_count - 1; u++) {
--  			bins[u + 1] = first + bin_sizes[u];
--  			bin_sizes[u + 1] += bin_sizes[u];
--  		}
--  		
--  		//Swap into place
--  		RandomAccessIter nextbinstart = first;
--  		for(unsigned u = 0; u < bin_count; ++u) {
--  			nextbinstart = first + bin_sizes[u];
--  			inner_swap_loop<RandomAccessIter, div_type, data_type, right_shift>(bins, nextbinstart, u, shift, log_divisor, div_min);
--  		}
--  		
--  		//Return if we've completed bucketsorting
--  		if(!log_divisor)
--  			return;
--  		
--  		//Handling negative values first
--  		size_t max_count = get_max_count(log_divisor, last - first);
--  		RandomAccessIter lastPos = first;
--  		for(int ii = cache_offset + first_positive - 1; ii >= (int)cache_offset ; lastPos = bin_cache[ii--]) {
--  			size_t count = bin_cache[ii] - lastPos;
--  			if(count < 2)
--  				continue;
--  			if(count < max_count)
--  				std::sort(lastPos, bin_cache[ii]);
--  			//sort negative values using reversed-bin spread_sort
--  			else
--  				negative_float_sort_rec<RandomAccessIter, div_type, data_type, right_shift>(lastPos, bin_cache[ii], bin_cache, cache_end, bin_sizes, shift);
--  		}
--  		
--  		for(unsigned u = cache_offset + first_positive; u < cache_end; lastPos = bin_cache[u], ++u) {
--  			size_t count = bin_cache[u] - lastPos;
--  			if(count < 2)
--  				continue;
--  			if(count < max_count)
--  				std::sort(lastPos, bin_cache[u]);
--  			//sort positive values using normal spread_sort
--  			else
--  				spread_sort_rec<RandomAccessIter, div_type, data_type, right_shift>(lastPos, bin_cache[u], bin_cache, cache_end, bin_sizes, shift);
--  		}
--  	}
--
--  	template <class RandomAccessIter, class div_type, class data_type, class right_shift, class compare>
--  	inline void 
--  	float_sort_rec(RandomAccessIter first, RandomAccessIter last, std::vector<RandomAccessIter> &bin_cache, unsigned cache_offset
--  					, std::vector<size_t> &bin_sizes, right_shift shift, compare comp)
--  	{
--  		div_type max, min;
--  		find_extremes(first, last, max, min, shift);
--  		if(max == min)
--  			return;
--  		unsigned log_divisor = get_log_divisor(last - first, rough_log_2_size((size_t)(max) - min));
--  		div_type div_min = min >> log_divisor;
--  		div_type div_max = max >> log_divisor;
--  		unsigned bin_count = div_max - div_min + 1;
--  		unsigned cache_end;
--  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, bin_count);
--  			
--  		//Calculating the size of each bin
--  		for (RandomAccessIter current = first; current != last;)
--  			bin_sizes[shift(*(current++), log_divisor) - div_min]++;
--  		//The index of the first positive bin
--  		div_type first_positive = (div_min < 0) ? -div_min : 0;
--  		//Resetting if all bins are negative
--  		if(cache_offset + first_positive > cache_end)
--  			first_positive = cache_end - cache_offset;
--  		//Reversing the order of the negative bins
--  		//Note that because of the negative/positive ordering direction flip
--  		//We can not depend upon bin order and positions matching up
--  		//so bin_sizes must be reused to contain the end of the bin
--  		if(first_positive > 0) {
--  			bins[first_positive - 1] = first;
--  			for(int ii = first_positive - 2; ii >= 0; --ii) {
--  				bins[ii] = first + bin_sizes[ii + 1];
--  				bin_sizes[ii] += bin_sizes[ii + 1];
--  			}
--  			//Handling positives following negatives
--  			if((unsigned)first_positive < bin_count) {
--  				bins[first_positive] = first + bin_sizes[0];
--  				bin_sizes[first_positive] += bin_sizes[0];
--  			}
--  		}
--  		else
--  			bins[0] = first;
--  		for(unsigned u = first_positive; u < bin_count - 1; u++) {
--  			bins[u + 1] = first + bin_sizes[u];
--  			bin_sizes[u + 1] += bin_sizes[u];
--  		}
--  		
--  		//Swap into place
--  		RandomAccessIter nextbinstart = first;
--  		for(unsigned u = 0; u < bin_count; ++u) {
--  			nextbinstart = first + bin_sizes[u];
--  			inner_swap_loop<RandomAccessIter, div_type, data_type, right_shift>(bins, nextbinstart, u, shift, log_divisor, div_min);
--  		}
--  		
--  		//Return if we've completed bucketsorting
--  		if(!log_divisor)
--  			return;
--  		
--  		//Handling negative values first
--  		size_t max_count = get_max_count(log_divisor, last - first);
--  		RandomAccessIter lastPos = first;
--  		for(int ii = cache_offset + first_positive - 1; ii >= (int)cache_offset ; lastPos = bin_cache[ii--]) {
--  			size_t count = bin_cache[ii] - lastPos;
--  			if(count < 2)
--  				continue;
--  			if(count < max_count)
--  				std::sort(lastPos, bin_cache[ii]);
--  			//sort negative values using reversed-bin spread_sort
--  			else
--  				negative_float_sort_rec<RandomAccessIter, div_type, data_type, right_shift>(lastPos, bin_cache[ii], bin_cache, cache_end, bin_sizes, shift, comp);
--  		}
--  		
--  		for(unsigned u = cache_offset + first_positive; u < cache_end; lastPos = bin_cache[u], ++u) {
--  			size_t count = bin_cache[u] - lastPos;
--  			if(count < 2)
--  				continue;
--  			if(count < max_count)
--  				std::sort(lastPos, bin_cache[u]);
--  			//sort positive values using normal spread_sort
--  			else
--  				spread_sort_rec<RandomAccessIter, div_type, data_type, right_shift>(lastPos, bin_cache[u], bin_cache, cache_end, bin_sizes, shift, comp);
--  		}
--  	}
--
--  	template <class RandomAccessIter, class cast_type, class data_type>
--  	inline void 
--  	float_Sort(RandomAccessIter first, RandomAccessIter last, cast_type, data_type)
--  	{
--  		std::vector<size_t> bin_sizes;
--  		std::vector<RandomAccessIter> bin_cache;
--  		float_sort_rec<RandomAccessIter, cast_type, data_type>(first, last, bin_cache, 0, bin_sizes);
--  	}
--
--  	template <class RandomAccessIter, class div_type, class data_type, class right_shift>
--  	inline void 
--  	float_Sort(RandomAccessIter first, RandomAccessIter last, div_type, data_type, right_shift shift)
--  	{
--  		std::vector<size_t> bin_sizes;
--  		std::vector<RandomAccessIter> bin_cache;
--  		float_sort_rec<RandomAccessIter, div_type, data_type, right_shift>(first, last, bin_cache, 0, bin_sizes, shift);
--  	}
--
--  	template <class RandomAccessIter, class div_type, class data_type, class right_shift, class compare>
--  	inline void 
--  	float_Sort(RandomAccessIter first, RandomAccessIter last, div_type, data_type, right_shift shift, compare comp)
--  	{
--  		std::vector<size_t> bin_sizes;
--  		std::vector<RandomAccessIter> bin_cache;
--  		float_sort_rec<RandomAccessIter, div_type, data_type, right_shift>(first, last, bin_cache, 0, bin_sizes, shift, comp);
--  	}
--  }
--
--  //float_sort with casting
--  //The cast_type must be equal in size to the data type, and must be a signed integer
--  template <class RandomAccessIter, class cast_type>
--  inline void float_sort_cast(RandomAccessIter first, RandomAccessIter last, cast_type cVal) 
--  {
--  	if(last - first < detail::MIN_SORT_SIZE)
--  		std::sort(first, last);
--  	else
--  		detail::float_Sort(first, last, cVal, *first);
--  }
--
--  //float_sort with casting to an int
--  //Only use this with IEEE floating-point numbers
--  template <class RandomAccessIter>
--  inline void float_sort_cast_to_int(RandomAccessIter first, RandomAccessIter last) 
--  {
--  	int cVal = 0;
--  	float_sort_cast(first, last, cVal);
--  }
--
--  //float_sort with functors
--  template <class RandomAccessIter, class right_shift>
--  inline void float_sort(RandomAccessIter first, RandomAccessIter last, right_shift shift) 
--  {
--  	if(last - first < detail::MIN_SORT_SIZE)
--  		std::sort(first, last);
--  	else
--  		detail::float_Sort(first, last, shift(*first, 0), *first, shift);
--  }
--
--  template <class RandomAccessIter, class right_shift, class compare>
--  inline void float_sort(RandomAccessIter first, RandomAccessIter last, right_shift shift, compare comp) 
--  {
--  	if(last - first < detail::MIN_SORT_SIZE)
--  		std::sort(first, last, comp);
--  	else
--  		detail::float_Sort(first, last, shift(*first, 0), *first, shift, comp);
--  }
--
--  //------------------------------------------------- string_sort source ---------------------------------------------
--  namespace detail {
--  	//Offsetting on identical characters.  This function works a character at a time for optimal worst-case performance.
--  	template<class RandomAccessIter>
--  	inline void
--  	update_offset(RandomAccessIter first, RandomAccessIter finish, unsigned &char_offset)
--  	{
--  		unsigned nextOffset = char_offset;
--  		bool done = false;
--  		while(!done) {
--  			RandomAccessIter curr = first;
--  			do {
--  				//ignore empties, but if the nextOffset would exceed the length or not match, exit; we've found the last matching character
--  				if((*curr).size() > char_offset && ((*curr).size() <= (nextOffset + 1) || (*curr)[nextOffset] != (*first)[nextOffset])) {
--  					done = true;
--  					break;
--  				}
--  			} while(++curr != finish);
--  			if(!done)
--  				++nextOffset;
--  		} 
--  		char_offset = nextOffset;
--  	}
--
--  	//Offsetting on identical characters.  This function works a character at a time for optimal worst-case performance.
--  	template<class RandomAccessIter, class get_char, class get_length>
--  	inline void
--  	update_offset(RandomAccessIter first, RandomAccessIter finish, unsigned &char_offset, get_char getchar, get_length length)
--  	{
--  		unsigned nextOffset = char_offset;
--  		bool done = false;
--  		while(!done) {
--  			RandomAccessIter curr = first;
--  			do {
--  				//ignore empties, but if the nextOffset would exceed the length or not match, exit; we've found the last matching character
--  				if(length(*curr) > char_offset && (length(*curr) <= (nextOffset + 1) || getchar((*curr), nextOffset) != getchar((*first), nextOffset))) {
--  					done = true;
--  					break;
--  				}
--  			} while(++curr != finish);
--  			if(!done)
--  				++nextOffset;
--  		} 
--  		char_offset = nextOffset;
--  	}
--
--  	//A comparison functor for strings that assumes they are identical up to char_offset
--  	template<class data_type, class unsignedchar_type>
--  	struct offset_lessthan {
--  		offset_lessthan(unsigned char_offset) : fchar_offset(char_offset){}
--  		inline bool operator()(const data_type &x, const data_type &y) const 
--  		{
--  			unsigned minSize = std::min(x.size(), y.size());
--  			for(unsigned u = fchar_offset; u < minSize; ++u) {
--  				if(static_cast<unsignedchar_type>(x[u]) < static_cast<unsignedchar_type>(y[u]))
--  					return true;
--  				else if(static_cast<unsignedchar_type>(y[u]) < static_cast<unsignedchar_type>(x[u]))
--  					return false;
--  			}
--  			return x.size() < y.size();
--  		}
--  		unsigned fchar_offset;
--  	};
--
--  	//A comparison functor for strings that assumes they are identical up to char_offset
--  	template<class data_type, class unsignedchar_type>
--  	struct offset_greaterthan {
--  		offset_greaterthan(unsigned char_offset) : fchar_offset(char_offset){}
--  		inline bool operator()(const data_type &x, const data_type &y) const 
--  		{
--  			unsigned minSize = std::min(x.size(), y.size());
--  			for(unsigned u = fchar_offset; u < minSize; ++u) {
--  				if(static_cast<unsignedchar_type>(x[u]) > static_cast<unsignedchar_type>(y[u]))
--  					return true;
--  				else if(static_cast<unsignedchar_type>(y[u]) > static_cast<unsignedchar_type>(x[u]))
--  					return false;
--  			}
--  			return x.size() > y.size();
--  		}
--  		unsigned fchar_offset;
--  	};
--
--  	//A comparison functor for strings that assumes they are identical up to char_offset
--  	template<class data_type, class get_char, class get_length>
--  	struct offset_char_lessthan {
--  		offset_char_lessthan(unsigned char_offset) : fchar_offset(char_offset){}
--  		inline bool operator()(const data_type &x, const data_type &y) const 
--  		{
--  			unsigned minSize = std::min(length(x), length(y));
--  			for(unsigned u = fchar_offset; u < minSize; ++u) {
--  				if(getchar(x, u) < getchar(y, u))
--  					return true;
--  				else if(getchar(y, u) < getchar(x, u))
--  					return false;
--  			}
--  			return length(x) < length(y);
--  		}
--  		unsigned fchar_offset;
--  		get_char getchar;
--  		get_length length;
--  	};
--
--  	//String sorting recursive implementation
--  	template <class RandomAccessIter, class data_type, class unsignedchar_type>
--  	inline void 
--  	string_sort_rec(RandomAccessIter first, RandomAccessIter last, unsigned char_offset, std::vector<RandomAccessIter> &bin_cache
--  		, unsigned cache_offset, std::vector<size_t> &bin_sizes)
--  	{
--  		//This section is not strictly necessary, but makes handling of long identical substrings much faster, with a mild average performance impact.
--  		//Iterate to the end of the empties.  If all empty, return
--  		while((*first).size() <= char_offset) {
--  			if(++first == last)
--  				return;
--  		}
--  		RandomAccessIter finish = last - 1;
--  		//Getting the last non-empty
--  		for(;(*finish).size() <= char_offset; --finish) { }
--  		++finish;
--  		//Offsetting on identical characters.  This section works a character at a time for optimal worst-case performance.
--  		update_offset(first, finish, char_offset);
--  		
--  		const unsigned bin_count = (1 << (sizeof(unsignedchar_type)*8));
--  		//Equal worst-case between radix and comparison-based is when bin_count = n*log(n).
--  		const unsigned max_size = bin_count;
--  		const unsigned membin_count = bin_count + 1;
--  		unsigned cache_end;
--  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, membin_count) + 1;
--  			
--  		//Calculating the size of each bin; this takes roughly 10% of runtime
--  		for (RandomAccessIter current = first; current != last; ++current) {
--  			if((*current).size() <= char_offset) {
--  				bin_sizes[0]++;
--  			}
--  			else
--  				bin_sizes[static_cast<unsignedchar_type>((*current)[char_offset]) + 1]++;
--  		}
--  		//Assign the bin positions
--  		bin_cache[cache_offset] = first;
--  		for(unsigned u = 0; u < membin_count - 1; u++)
--  			bin_cache[cache_offset + u + 1] = bin_cache[cache_offset + u] + bin_sizes[u];
--  		
--  		//Swap into place
--  		RandomAccessIter nextbinstart = first;
--  		//handling empty bins
--  		RandomAccessIter * local_bin = &(bin_cache[cache_offset]);
--  		nextbinstart +=	bin_sizes[0];
--  		RandomAccessIter * target_bin;
--  		//Iterating over each element in the bin of empties
--  		for(RandomAccessIter current = *local_bin; current < nextbinstart; ++current) {
--  			//empties belong in this bin
--  			while((*current).size() > char_offset) {
--  				target_bin = bins + static_cast<unsignedchar_type>((*current)[char_offset]);
--  				iter_swap(current, (*target_bin)++);
--  			}
--  		}
--  		*local_bin = nextbinstart;
--  		//iterate backwards to find the last bin with elements in it; this saves iterations in multiple loops
--  		unsigned last_bin = bin_count - 1;
--  		for(; last_bin && !bin_sizes[last_bin + 1]; --last_bin) { }
--  		//This dominates runtime, mostly in the swap and bin lookups
--  		for(unsigned u = 0; u < last_bin; ++u) {
--  			local_bin = bins + u;
--  			nextbinstart += bin_sizes[u + 1];
--  			//Iterating over each element in this bin
--  			for(RandomAccessIter current = *local_bin; current < nextbinstart; ++current) {
--  				//Swapping elements in current into place until the correct element has been swapped in
--  				for(target_bin = bins + static_cast<unsignedchar_type>((*current)[char_offset]);  target_bin != local_bin; 
--  					target_bin = bins + static_cast<unsignedchar_type>((*current)[char_offset]))
--  					iter_swap(current, (*target_bin)++);
--  			}
--  			*local_bin = nextbinstart;
--  		}
--  		bins[last_bin] = last;
--  		//Recursing
--  		RandomAccessIter lastPos = bin_cache[cache_offset];
--  		//Skip this loop for empties
--  		for(unsigned u = cache_offset + 1; u < cache_offset + last_bin + 2; lastPos = bin_cache[u], ++u) {
--  			size_t count = bin_cache[u] - lastPos;
--  			//don't sort unless there are at least two items to compare
--  			if(count < 2)
--  				continue;
--  			//using std::sort if its worst-case is better
--  			if(count < max_size)
--  				std::sort(lastPos, bin_cache[u], offset_lessthan<data_type, unsignedchar_type>(char_offset + 1));
--  			else
--  				string_sort_rec<RandomAccessIter, data_type, unsignedchar_type>(lastPos, bin_cache[u], char_offset + 1, bin_cache, cache_end, bin_sizes);
--  		}
--  	}
--
--  	//Sorts strings in reverse order, with empties at the end
--  	template <class RandomAccessIter, class data_type, class unsignedchar_type>
--  	inline void 
--  	reverse_string_sort_rec(RandomAccessIter first, RandomAccessIter last, unsigned char_offset, std::vector<RandomAccessIter> &bin_cache
--  		, unsigned cache_offset, std::vector<size_t> &bin_sizes)
--  	{
--  		//This section is not strictly necessary, but makes handling of long identical substrings much faster, with a mild average performance impact.
--  		RandomAccessIter curr = first;
--  		//Iterate to the end of the empties.  If all empty, return
--  		while((*curr).size() <= char_offset) {
--  			if(++curr == last)
--  				return;
--  		}
--  		//Getting the last non-empty
--  		while((*(--last)).size() <= char_offset) { }
--  		++last;
--  		//Offsetting on identical characters.  This section works a character at a time for optimal worst-case performance.
--  		update_offset(curr, last, char_offset);
--  		RandomAccessIter * target_bin;
--  		
--  		const unsigned bin_count = (1 << (sizeof(unsignedchar_type)*8));
--  		//Equal worst-case between radix and comparison-based is when bin_count = n*log(n).
--  		const unsigned max_size = bin_count;
--  		const unsigned membin_count = bin_count + 1;
--  		const unsigned max_bin = bin_count - 1;
--  		unsigned cache_end;
--  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, membin_count);
--  		RandomAccessIter * end_bin = &(bin_cache[cache_offset + max_bin]);
--  			
--  		//Calculating the size of each bin; this takes roughly 10% of runtime
--  		for (RandomAccessIter current = first; current != last; ++current) {
--  			if((*current).size() <= char_offset) {
--  				bin_sizes[bin_count]++;
--  			}
--  			else
--  				bin_sizes[max_bin - static_cast<unsignedchar_type>((*current)[char_offset])]++;
--  		}
--  		//Assign the bin positions
--  		bin_cache[cache_offset] = first;
--  		for(unsigned u = 0; u < membin_count - 1; u++)
--  			bin_cache[cache_offset + u + 1] = bin_cache[cache_offset + u] + bin_sizes[u];
--  		
--  		//Swap into place
--  		RandomAccessIter nextbinstart = last;
--  		//handling empty bins
--  		RandomAccessIter * local_bin = &(bin_cache[cache_offset + bin_count]);
--  		RandomAccessIter lastFull = *local_bin;
--  		//Iterating over each element in the bin of empties
--  		for(RandomAccessIter current = *local_bin; current < nextbinstart; ++current) {
--  			//empties belong in this bin
--  			while((*current).size() > char_offset) {
--  				target_bin = end_bin - static_cast<unsignedchar_type>((*current)[char_offset]);
--  				iter_swap(current, (*target_bin)++);
--  			}
--  		}
--  		*local_bin = nextbinstart;
--  		nextbinstart = first;
--  		//iterate backwards to find the last bin with elements in it; this saves iterations in multiple loops
--  		unsigned last_bin = max_bin;
--  		for(; last_bin && !bin_sizes[last_bin]; --last_bin) { }
--  		//This dominates runtime, mostly in the swap and bin lookups
--  		for(unsigned u = 0; u < last_bin; ++u) {
--  			local_bin = bins + u;
--  			nextbinstart += bin_sizes[u];
--  			//Iterating over each element in this bin
--  			for(RandomAccessIter current = *local_bin; current < nextbinstart; ++current) {
--  				//Swapping elements in current into place until the correct element has been swapped in
--  				for(target_bin = end_bin - static_cast<unsignedchar_type>((*current)[char_offset]);  target_bin != local_bin; 
--  					target_bin = end_bin - static_cast<unsignedchar_type>((*current)[char_offset]))
--  					iter_swap(current, (*target_bin)++);
--  			}
--  			*local_bin = nextbinstart;
--  		}
--  		bins[last_bin] = lastFull;
--  		//Recursing
--  		RandomAccessIter lastPos = first;
--  		//Skip this loop for empties
--  		for(unsigned u = cache_offset; u <= cache_offset + last_bin; lastPos = bin_cache[u], ++u) {
--  			size_t count = bin_cache[u] - lastPos;
--  			//don't sort unless there are at least two items to compare
--  			if(count < 2)
--  				continue;
--  			//using std::sort if its worst-case is better
--  			if(count < max_size)
--  				std::sort(lastPos, bin_cache[u], offset_greaterthan<data_type, unsignedchar_type>(char_offset + 1));
--  			else
--  				reverse_string_sort_rec<RandomAccessIter, data_type, unsignedchar_type>(lastPos, bin_cache[u], char_offset + 1, bin_cache, cache_end, bin_sizes);
--  		}
--  	}
--
--  	//String sorting recursive implementation
--  	template <class RandomAccessIter, class data_type, class unsignedchar_type, class get_char, class get_length>
--  	inline void 
--  	string_sort_rec(RandomAccessIter first, RandomAccessIter last, unsigned char_offset, std::vector<RandomAccessIter> &bin_cache
--  		, unsigned cache_offset, std::vector<size_t> &bin_sizes, get_char getchar, get_length length)
--  	{
--  		//This section is not strictly necessary, but makes handling of long identical substrings much faster, with a mild average performance impact.
--  		//Iterate to the end of the empties.  If all empty, return
--  		while(length(*first) <= char_offset) {
--  			if(++first == last)
--  				return;
--  		}
--  		RandomAccessIter finish = last - 1;
--  		//Getting the last non-empty
--  		for(;length(*finish) <= char_offset; --finish) { }
--  		++finish;
--  		update_offset(first, finish, char_offset, getchar, length);
--  		
--  		const unsigned bin_count = (1 << (sizeof(unsignedchar_type)*8));
--  		//Equal worst-case between radix and comparison-based is when bin_count = n*log(n).
--  		const unsigned max_size = bin_count;
--  		const unsigned membin_count = bin_count + 1;
--  		unsigned cache_end;
--  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, membin_count) + 1;
--  			
--  		//Calculating the size of each bin; this takes roughly 10% of runtime
--  		for (RandomAccessIter current = first; current != last; ++current) {
--  			if(length(*current) <= char_offset) {
--  				bin_sizes[0]++;
--  			}
--  			else
--  				bin_sizes[getchar((*current), char_offset) + 1]++;
--  		}
--  		//Assign the bin positions
--  		bin_cache[cache_offset] = first;
--  		for(unsigned u = 0; u < membin_count - 1; u++)
--  			bin_cache[cache_offset + u + 1] = bin_cache[cache_offset + u] + bin_sizes[u];
--  		
--  		//Swap into place
--  		RandomAccessIter nextbinstart = first;
--  		//handling empty bins
--  		RandomAccessIter * local_bin = &(bin_cache[cache_offset]);
--  		nextbinstart +=	bin_sizes[0];
--  		RandomAccessIter * target_bin;
--  		//Iterating over each element in the bin of empties
--  		for(RandomAccessIter current = *local_bin; current < nextbinstart; ++current) {
--  			//empties belong in this bin
--  			while(length(*current) > char_offset) {
--  				target_bin = bins + getchar((*current), char_offset);
--  				iter_swap(current, (*target_bin)++);
--  			}
--  		}
--  		*local_bin = nextbinstart;
--  		//iterate backwards to find the last bin with elements in it; this saves iterations in multiple loops
--  		unsigned last_bin = bin_count - 1;
--  		for(; last_bin && !bin_sizes[last_bin + 1]; --last_bin) { }
--  		//This dominates runtime, mostly in the swap and bin lookups
--  		for(unsigned ii = 0; ii < last_bin; ++ii) {
--  			local_bin = bins + ii;
--  			nextbinstart += bin_sizes[ii + 1];
--  			//Iterating over each element in this bin
--  			for(RandomAccessIter current = *local_bin; current < nextbinstart; ++current) {
--  				//Swapping elements in current into place until the correct element has been swapped in
--  				for(target_bin = bins + getchar((*current), char_offset);  target_bin != local_bin; 
--  					target_bin = bins + getchar((*current), char_offset))
--  					iter_swap(current, (*target_bin)++);
--  			}
--  			*local_bin = nextbinstart;
--  		}
--  		bins[last_bin] = last;
--  		
--  		//Recursing
--  		RandomAccessIter lastPos = bin_cache[cache_offset];
--  		//Skip this loop for empties
--  		for(unsigned u = cache_offset + 1; u < cache_offset + last_bin + 2; lastPos = bin_cache[u], ++u) {
--  			size_t count = bin_cache[u] - lastPos;
--  			//don't sort unless there are at least two items to compare
--  			if(count < 2)
--  				continue;
--  			//using std::sort if its worst-case is better
--  			if(count < max_size)
--  				std::sort(lastPos, bin_cache[u], offset_char_lessthan<data_type, get_char, get_length>(char_offset + 1));
--  			else
--  				string_sort_rec<RandomAccessIter, data_type, unsignedchar_type, get_char, get_length>(lastPos, bin_cache[u], char_offset + 1, bin_cache, cache_end, bin_sizes, getchar, length);
--  		}
--  	}
--
--  	//String sorting recursive implementation
--  	template <class RandomAccessIter, class data_type, class unsignedchar_type, class get_char, class get_length, class compare>
--  	inline void 
--  	string_sort_rec(RandomAccessIter first, RandomAccessIter last, unsigned char_offset, std::vector<RandomAccessIter> &bin_cache
--  		, unsigned cache_offset, std::vector<size_t> &bin_sizes, get_char getchar, get_length length, compare comp)
--  	{
--  		//This section is not strictly necessary, but makes handling of long identical substrings much faster, with a mild average performance impact.
--  		//Iterate to the end of the empties.  If all empty, return
--  		while(length(*first) <= char_offset) {
--  			if(++first == last)
--  				return;
--  		}
--  		RandomAccessIter finish = last - 1;
--  		//Getting the last non-empty
--  		for(;length(*finish) <= char_offset; --finish) { }
--  		++finish;
--  		update_offset(first, finish, char_offset, getchar, length);
--  		
--  		const unsigned bin_count = (1 << (sizeof(unsignedchar_type)*8));
--  		//Equal worst-case between radix and comparison-based is when bin_count = n*log(n).
--  		const unsigned max_size = bin_count;
--  		const unsigned membin_count = bin_count + 1;
--  		unsigned cache_end;
--  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, membin_count) + 1;
--  			
--  		//Calculating the size of each bin; this takes roughly 10% of runtime
--  		for (RandomAccessIter current = first; current != last; ++current) {
--  			if(length(*current) <= char_offset) {
--  				bin_sizes[0]++;
--  			}
--  			else
--  				bin_sizes[getchar((*current), char_offset) + 1]++;
--  		}
--  		//Assign the bin positions
--  		bin_cache[cache_offset] = first;
--  		for(unsigned u = 0; u < membin_count - 1; u++)
--  			bin_cache[cache_offset + u + 1] = bin_cache[cache_offset + u] + bin_sizes[u];
--  		
--  		//Swap into place
--  		RandomAccessIter nextbinstart = first;
--  		//handling empty bins
--  		RandomAccessIter * local_bin = &(bin_cache[cache_offset]);
--  		nextbinstart +=	bin_sizes[0];
--  		RandomAccessIter * target_bin;
--  		//Iterating over each element in the bin of empties
--  		for(RandomAccessIter current = *local_bin; current < nextbinstart; ++current) {
--  			//empties belong in this bin
--  			while(length(*current) > char_offset) {
--  				target_bin = bins + getchar((*current), char_offset);
--  				iter_swap(current, (*target_bin)++);
--  			}
--  		}
--  		*local_bin = nextbinstart;
--  		//iterate backwards to find the last bin with elements in it; this saves iterations in multiple loops
--  		unsigned last_bin = bin_count - 1;
--  		for(; last_bin && !bin_sizes[last_bin + 1]; --last_bin) { }
--  		//This dominates runtime, mostly in the swap and bin lookups
--  		for(unsigned u = 0; u < last_bin; ++u) {
--  			local_bin = bins + u;
--  			nextbinstart += bin_sizes[u + 1];
--  			//Iterating over each element in this bin
--  			for(RandomAccessIter current = *local_bin; current < nextbinstart; ++current) {
--  				//Swapping elements in current into place until the correct element has been swapped in
--  				for(target_bin = bins + getchar((*current), char_offset);  target_bin != local_bin; 
--  					target_bin = bins + getchar((*current), char_offset))
--  					iter_swap(current, (*target_bin)++);
--  			}
--  			*local_bin = nextbinstart;
--  		}
--  		bins[last_bin] = last;
--  		
--  		//Recursing
--  		RandomAccessIter lastPos = bin_cache[cache_offset];
--  		//Skip this loop for empties
--  		for(unsigned u = cache_offset + 1; u < cache_offset + last_bin + 2; lastPos = bin_cache[u], ++u) {
--  			size_t count = bin_cache[u] - lastPos;
--  			//don't sort unless there are at least two items to compare
--  			if(count < 2)
--  				continue;
--  			//using std::sort if its worst-case is better
--  			if(count < max_size)
--  				std::sort(lastPos, bin_cache[u], comp);
--  			else
--  				string_sort_rec<RandomAccessIter, data_type, unsignedchar_type, get_char, get_length, compare>(lastPos
--  					, bin_cache[u], char_offset + 1, bin_cache, cache_end, bin_sizes, getchar, length, comp);
--  		}
--  	}
--
--  	//Sorts strings in reverse order, with empties at the end
--  	template <class RandomAccessIter, class data_type, class unsignedchar_type, class get_char, class get_length, class compare>
--  	inline void 
--  	reverse_string_sort_rec(RandomAccessIter first, RandomAccessIter last, unsigned char_offset, std::vector<RandomAccessIter> &bin_cache
--  		, unsigned cache_offset, std::vector<size_t> &bin_sizes, get_char getchar, get_length length, compare comp)
--  	{
--  		//This section is not strictly necessary, but makes handling of long identical substrings much faster, with a mild average performance impact.
--  		RandomAccessIter curr = first;
--  		//Iterate to the end of the empties.  If all empty, return
--  		while(length(*curr) <= char_offset) {
--  			if(++curr == last)
--  				return;
--  		}
--  		//Getting the last non-empty
--  		while(length(*(--last)) <= char_offset) { }
--  		++last;
--  		//Offsetting on identical characters.  This section works a character at a time for optimal worst-case performance.
--  		update_offset(first, last, char_offset, getchar, length);
--  		
--  		const unsigned bin_count = (1 << (sizeof(unsignedchar_type)*8));
--  		//Equal worst-case between radix and comparison-based is when bin_count = n*log(n).
--  		const unsigned max_size = bin_count;
--  		const unsigned membin_count = bin_count + 1;
--  		const unsigned max_bin = bin_count - 1;
--  		unsigned cache_end;
--  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, membin_count);
--  		RandomAccessIter *end_bin = &(bin_cache[cache_offset + max_bin]);
--  			
--  		//Calculating the size of each bin; this takes roughly 10% of runtime
--  		for (RandomAccessIter current = first; current != last; ++current) {
--  			if(length(*current) <= char_offset) {
--  				bin_sizes[bin_count]++;
--  			}
--  			else
--  				bin_sizes[max_bin - getchar((*current), char_offset)]++;
--  		}
--  		//Assign the bin positions
--  		bin_cache[cache_offset] = first;
--  		for(unsigned u = 0; u < membin_count - 1; u++)
--  			bin_cache[cache_offset + u + 1] = bin_cache[cache_offset + u] + bin_sizes[u];
--  		
--  		//Swap into place
--  		RandomAccessIter nextbinstart = last;
--  		//handling empty bins
--  		RandomAccessIter * local_bin = &(bin_cache[cache_offset + bin_count]);
--  		RandomAccessIter lastFull = *local_bin;
--  		RandomAccessIter * target_bin;
--  		//Iterating over each element in the bin of empties
--  		for(RandomAccessIter current = *local_bin; current < nextbinstart; ++current) {
--  			//empties belong in this bin
--  			while(length(*current) > char_offset) {
--  				target_bin = end_bin - getchar((*current), char_offset);
--  				iter_swap(current, (*target_bin)++);
--  			}
--  		}
--  		*local_bin = nextbinstart;
--  		nextbinstart = first;
--  		//iterate backwards to find the last bin with elements in it; this saves iterations in multiple loops
--  		unsigned last_bin = max_bin;
--  		for(; last_bin && !bin_sizes[last_bin]; --last_bin) { }
--  		//This dominates runtime, mostly in the swap and bin lookups
--  		for(unsigned u = 0; u < last_bin; ++u) {
--  			local_bin = bins + u;
--  			nextbinstart += bin_sizes[u];
--  			//Iterating over each element in this bin
--  			for(RandomAccessIter current = *local_bin; current < nextbinstart; ++current) {
--  				//Swapping elements in current into place until the correct element has been swapped in
--  				for(target_bin = end_bin - getchar((*current), char_offset);  target_bin != local_bin; 
--  					target_bin = end_bin - getchar((*current), char_offset))
--  					iter_swap(current, (*target_bin)++);
--  			}
--  			*local_bin = nextbinstart;
--  		}
--  		bins[last_bin] = lastFull;
--  		//Recursing
--  		RandomAccessIter lastPos = first;
--  		//Skip this loop for empties
--  		for(unsigned u = cache_offset; u <= cache_offset + last_bin; lastPos = bin_cache[u], ++u) {
--  			size_t count = bin_cache[u] - lastPos;
--  			//don't sort unless there are at least two items to compare
--  			if(count < 2)
--  				continue;
--  			//using std::sort if its worst-case is better
--  			if(count < max_size)
--  				std::sort(lastPos, bin_cache[u], comp);
--  			else
--  				reverse_string_sort_rec<RandomAccessIter, data_type, unsignedchar_type, get_char, get_length, compare>(lastPos
--  					, bin_cache[u], char_offset + 1, bin_cache, cache_end, bin_sizes, getchar, length, comp);
--  		}
--  	}
--
--  	//Holds the bin vector and makes the initial recursive call
--  	template <class RandomAccessIter, class data_type, class unsignedchar_type>
--  	inline void 
--  	string_sort(RandomAccessIter first, RandomAccessIter last, data_type, unsignedchar_type)
--  	{
--  		std::vector<size_t> bin_sizes;
--  		std::vector<RandomAccessIter> bin_cache;
--  		string_sort_rec<RandomAccessIter, data_type, unsignedchar_type>(first, last, 0, bin_cache, 0, bin_sizes);
--  	}
--
--  	//Holds the bin vector and makes the initial recursive call
--  	template <class RandomAccessIter, class data_type, class unsignedchar_type>
--  	inline void 
--  	reverse_string_sort(RandomAccessIter first, RandomAccessIter last, data_type, unsignedchar_type)
--  	{
--  		std::vector<size_t> bin_sizes;
--  		std::vector<RandomAccessIter> bin_cache;
--  		reverse_string_sort_rec<RandomAccessIter, data_type, unsignedchar_type>(first, last, 0, bin_cache, 0, bin_sizes);
--  	}
--
--  	//Holds the bin vector and makes the initial recursive call
--  	template <class RandomAccessIter, class get_char, class get_length, class data_type, class unsignedchar_type>
--  	inline void 
--  	string_sort(RandomAccessIter first, RandomAccessIter last, get_char getchar, get_length length, data_type, unsignedchar_type)
--  	{
--  		std::vector<size_t> bin_sizes;
--  		std::vector<RandomAccessIter> bin_cache;
--  		string_sort_rec<RandomAccessIter, data_type, unsignedchar_type, get_char, get_length>(first, last, 0, bin_cache, 0, bin_sizes, getchar, length);
--  	}
--
--  	//Holds the bin vector and makes the initial recursive call
--  	template <class RandomAccessIter, class get_char, class get_length, class compare, class data_type, class unsignedchar_type>
--  	inline void 
--  	string_sort(RandomAccessIter first, RandomAccessIter last, get_char getchar, get_length length, compare comp, data_type, unsignedchar_type)
--  	{
--  		std::vector<size_t> bin_sizes;
--  		std::vector<RandomAccessIter> bin_cache;
--  		string_sort_rec<RandomAccessIter, data_type, unsignedchar_type, get_char, get_length, compare>(first, last, 0, bin_cache, 0, bin_sizes, getchar, length, comp);
--  	}
--
--  	//Holds the bin vector and makes the initial recursive call
--  	template <class RandomAccessIter, class get_char, class get_length, class compare, class data_type, class unsignedchar_type>
--  	inline void 
--  	reverse_string_sort(RandomAccessIter first, RandomAccessIter last, get_char getchar, get_length length, compare comp, data_type, unsignedchar_type)
--  	{
--  		std::vector<size_t> bin_sizes;
--  		std::vector<RandomAccessIter> bin_cache;
--  		reverse_string_sort_rec<RandomAccessIter, data_type, unsignedchar_type, get_char, get_length, compare>(first, last, 0, bin_cache, 0, bin_sizes, getchar, length, comp);
--  	}
--  }
--
--  //Allows character-type overloads
--  template <class RandomAccessIter, class unsignedchar_type>
--  inline void string_sort(RandomAccessIter first, RandomAccessIter last, unsignedchar_type unused) 
--  {
--  	//Don't sort if it's too small to optimize
--  	if(last - first < detail::MIN_SORT_SIZE)
--  		std::sort(first, last);
--  	else
--  		detail::string_sort(first, last, *first, unused);
--  }
--
--  //Top-level sorting call; wraps using default of unsigned char
--  template <class RandomAccessIter>
--  inline void string_sort(RandomAccessIter first, RandomAccessIter last) 
--  {
--  	unsigned char unused = '\0';
--  	string_sort(first, last, unused);
--  }
--
--  //Allows character-type overloads
--  template <class RandomAccessIter, class compare, class unsignedchar_type>
--  inline void reverse_string_sort(RandomAccessIter first, RandomAccessIter last, compare comp, unsignedchar_type unused) 
--  {
--  	//Don't sort if it's too small to optimize
--  	if(last - first < detail::MIN_SORT_SIZE)
--  		std::sort(first, last, comp);
--  	else
--  		detail::reverse_string_sort(first, last, *first, unused);
--  }
--
--  //Top-level sorting call; wraps using default of unsigned char
--  template <class RandomAccessIter, class compare>
--  inline void reverse_string_sort(RandomAccessIter first, RandomAccessIter last, compare comp) 
--  {
--  	unsigned char unused = '\0';
--  	reverse_string_sort(first, last, comp, unused);
--  }
--
--  template <class RandomAccessIter, class get_char, class get_length>
--  inline void string_sort(RandomAccessIter first, RandomAccessIter last, get_char getchar, get_length length) 
--  {
--  	//Don't sort if it's too small to optimize
--  	if(last - first < detail::MIN_SORT_SIZE)
--  		std::sort(first, last);
--  	else {
--  		//skipping past empties at the beginning, which allows us to get the character type 
--  		//.empty() is not used so as not to require a user declaration of it
--  		while(!length(*first)) {
--  			if(++first == last)
--  				return;
--  		}
--  		detail::string_sort(first, last, getchar, length, *first, getchar((*first), 0));
--  	}
--  }
--
--  template <class RandomAccessIter, class get_char, class get_length, class compare>
--  inline void string_sort(RandomAccessIter first, RandomAccessIter last, get_char getchar, get_length length, compare comp) 
--  {
--  	//Don't sort if it's too small to optimize
--  	if(last - first < detail::MIN_SORT_SIZE)
--  		std::sort(first, last, comp);
--  	else {
--  		//skipping past empties at the beginning, which allows us to get the character type 
--  		//.empty() is not used so as not to require a user declaration of it
--  		while(!length(*first)) {
--  			if(++first == last)
--  				return;
--  		}
--  		detail::string_sort(first, last, getchar, length, comp, *first, getchar((*first), 0));
--  	}
--  }
--
--  template <class RandomAccessIter, class get_char, class get_length, class compare>
--  inline void reverse_string_sort(RandomAccessIter first, RandomAccessIter last, get_char getchar, get_length length, compare comp) 
--  {
--  	//Don't sort if it's too small to optimize
--  	if(last - first < detail::MIN_SORT_SIZE)
--  		std::sort(first, last, comp);
--  	else {
--  		//skipping past empties at the beginning, which allows us to get the character type 
--  		//.empty() is not used so as not to require a user declaration of it
--  		while(!length(*(--last))) {
--  			//Note: if there is just one non-empty, and it's at the beginning, then it's already in sorted order
--  			if(first == last)
--  				return;
--  		}
--  		//making last just after the end of the non-empty part of the array
--  		++last;
--  		detail::reverse_string_sort(first, last, getchar, length, comp, *first, getchar((*first), 0));
--  	}
--  }
--}
--
--#endif
-+//Templated spread_sort library
-+
-+//          Copyright Steven J. Ross 2001 - 2009.
-+// Distributed under the Boost Software License, Version 1.0.
-+//    (See accompanying file LICENSE_1_0.txt or copy at
-+//          http://www.boost.org/LICENSE_1_0.txt)
-+
-+//  See http://www.boost.org/ for updates, documentation, and revision history.
-+		  
-+/*
-+Some improvements suggested by:
-+Phil Endecott and Frank Gennari
-+Cygwin fix provided by:
-+Scott McMurray
-+*/
-+
-+#ifndef BOOST_SPREAD_SORT_H
-+#define BOOST_SPREAD_SORT_H
-+#include <algorithm>
-+#include <cstring>
-+#include <vector>
-+#include "webrtc/system_wrappers/source/spreadsortlib/constants.hpp"
-+
-+#include <features.h>
-+#if defined(__UCLIBC__)
-+#undef getchar
-+#endif
-+
-+
-+namespace boost {
-+  namespace detail {
-+  	//This only works on unsigned data types
-+  	template <typename T>
-+  	inline unsigned 
-+  	rough_log_2_size(const T& input) 
-+  	{
-+  		unsigned result = 0;
-+  		//The && is necessary on some compilers to avoid infinite loops; it doesn't significantly impair performance
-+  		while((input >> result) && (result < (8*sizeof(T)))) ++result;
-+  		return result;
-+  	}
-+
-+  	//Gets the maximum size which we'll call spread_sort on to control worst-case performance
-+  	//Maintains both a minimum size to recurse and a check of distribution size versus count
-+  	//This is called for a set of bins, instead of bin-by-bin, to avoid performance overhead
-+  	inline size_t
-+  	get_max_count(unsigned log_range, size_t count)
-+  	{
-+  		unsigned divisor = rough_log_2_size(count);
-+  		//Making sure the divisor is positive
-+  		if(divisor > LOG_MEAN_BIN_SIZE)
-+  			divisor -= LOG_MEAN_BIN_SIZE;
-+  		else
-+  			divisor = 1;
-+  		unsigned relative_width = (LOG_CONST * log_range)/((divisor > MAX_SPLITS) ? MAX_SPLITS : divisor);
-+  		//Don't try to bitshift more than the size of an element
-+  		if((8*sizeof(size_t)) <= relative_width)
-+  			relative_width = (8*sizeof(size_t)) - 1;
-+  		return (size_t)1 << ((relative_width < (LOG_MEAN_BIN_SIZE + LOG_MIN_SPLIT_COUNT)) ? 
-+  			(LOG_MEAN_BIN_SIZE + LOG_MIN_SPLIT_COUNT) :  relative_width);
-+  	}
-+
-+  	//Find the minimum and maximum using <
-+  	template <class RandomAccessIter>
-+  	inline void 
-+  	find_extremes(RandomAccessIter current, RandomAccessIter last, RandomAccessIter & max, RandomAccessIter & min)
-+  	{
-+  		min = max = current;
-+  		//Start from the second item, as max and min are initialized to the first
-+  		while(++current < last) {
-+  			if(*max < *current)
-+  				max = current;
-+  			else if(*current < *min)
-+  				min = current;
-+  		}
-+  	}
-+
-+  	//Uses a user-defined comparison operator to find minimum and maximum
-+  	template <class RandomAccessIter, class compare>
-+  	inline void 
-+  	find_extremes(RandomAccessIter current, RandomAccessIter last, RandomAccessIter & max, RandomAccessIter & min, compare comp)
-+  	{
-+  		min = max = current;
-+  		while(++current < last) {
-+  			if(comp(*max, *current))
-+  				max = current;
-+  			else if(comp(*current, *min))
-+  				min = current;
-+  		}
-+  	}
-+
-+  	//Gets a non-negative right bit shift to operate as a logarithmic divisor
-+  	inline int
-+  	get_log_divisor(size_t count, unsigned log_range)
-+  	{
-+  		int log_divisor;
-+  		//If we can finish in one iteration without exceeding either (2 to the MAX_SPLITS) or n bins, do so
-+  		if((log_divisor = log_range - rough_log_2_size(count)) <= 0 && log_range < MAX_SPLITS)
-+  			log_divisor = 0;
-+  		else {
-+  			//otherwise divide the data into an optimized number of pieces
-+  			log_divisor += LOG_MEAN_BIN_SIZE;
-+  			if(log_divisor < 0)
-+  				log_divisor = 0;
-+  			//Cannot exceed MAX_SPLITS or cache misses slow down bin lookups dramatically
-+  			if((log_range - log_divisor) > MAX_SPLITS)
-+  				log_divisor = log_range - MAX_SPLITS;
-+  		}
-+  		return log_divisor;
-+  	}
-+
-+  	template <class RandomAccessIter>
-+  	inline RandomAccessIter * 
-+  	size_bins(std::vector<size_t> &bin_sizes, std::vector<RandomAccessIter> &bin_cache, unsigned cache_offset, unsigned &cache_end, unsigned bin_count)
-+  	{
-+  		//Assure space for the size of each bin, followed by initializing sizes
-+  		if(bin_count > bin_sizes.size())
-+  			bin_sizes.resize(bin_count);
-+  		for(size_t u = 0; u < bin_count; u++)
-+  			bin_sizes[u] = 0;
-+  		//Make sure there is space for the bins
-+  		cache_end = cache_offset + bin_count;
-+  		if(cache_end > bin_cache.size())
-+  			bin_cache.resize(cache_end);
-+  		return &(bin_cache[cache_offset]);
-+  	}
-+
-+  	//Implementation for recursive integer sorting
-+  	template <class RandomAccessIter, class div_type, class data_type>
-+  	inline void 
-+  	spread_sort_rec(RandomAccessIter first, RandomAccessIter last, std::vector<RandomAccessIter> &bin_cache, unsigned cache_offset
-+  				  , std::vector<size_t> &bin_sizes)
-+  	{
-+  		//This step is roughly 10% of runtime, but it helps avoid worst-case behavior and improve behavior with real data
-+  		//If you know the maximum and minimum ahead of time, you can pass those values in and skip this step for the first iteration
-+  		RandomAccessIter max, min;
-+  		find_extremes(first, last, max, min);
-+  		//max and min will be the same (the first item) iff all values are equivalent
-+  		if(max == min)
-+  			return;
-+  		RandomAccessIter * target_bin;
-+  		unsigned log_divisor = get_log_divisor(last - first, rough_log_2_size((size_t)(*max >> 0) - (*min >> 0)));
-+  		div_type div_min = *min >> log_divisor;
-+  		div_type div_max = *max >> log_divisor;
-+  		unsigned bin_count = div_max - div_min + 1;
-+  		unsigned cache_end;
-+  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, bin_count);
-+  	
-+  		//Calculating the size of each bin; this takes roughly 10% of runtime
-+  		for (RandomAccessIter current = first; current != last;)
-+  			bin_sizes[(*(current++) >> log_divisor) - div_min]++;
-+  		//Assign the bin positions
-+  		bins[0] = first;
-+  		for(unsigned u = 0; u < bin_count - 1; u++)
-+  			bins[u + 1] = bins[u] + bin_sizes[u];
-+  
-+  		//Swap into place
-+  		//This dominates runtime, mostly in the swap and bin lookups
-+  		RandomAccessIter nextbinstart = first;
-+  		for(unsigned u = 0; u < bin_count - 1; ++u) {
-+  			RandomAccessIter * local_bin = bins + u;
-+  			nextbinstart += bin_sizes[u];
-+  			//Iterating over each element in this bin
-+  			for(RandomAccessIter current = *local_bin; current < nextbinstart; ++current) {
-+  				//Swapping elements in current into place until the correct element has been swapped in
-+  				for(target_bin = (bins + ((*current >> log_divisor) - div_min));  target_bin != local_bin; 
-+  					target_bin = bins + ((*current >> log_divisor) - div_min)) {
-+  					//3-way swap; this is about 1% faster than a 2-way swap with integers
-+  					//The main advantage is less copies are involved per item put in the correct place
-+  					data_type tmp;
-+  					RandomAccessIter b = (*target_bin)++;
-+  					RandomAccessIter * b_bin = bins + ((*b >> log_divisor) - div_min);
-+  					if (b_bin != local_bin) {
-+  						RandomAccessIter c = (*b_bin)++;
-+  						tmp = *c;
-+  						*c = *b;
-+  					} 
-+  					else
-+  						tmp = *b;
-+  					*b = *current;
-+  					*current = tmp;
-+  				}
-+  			}
-+  			*local_bin = nextbinstart;
-+  		}
-+  		bins[bin_count - 1] = last;
-+  
-+  		//If we've bucketsorted, the array is sorted and we should skip recursion
-+  		if(!log_divisor)
-+  			return;
-+  
-+  		//Recursing; log_divisor is the remaining range
-+  		size_t max_count = get_max_count(log_divisor, last - first);
-+  		RandomAccessIter lastPos = first;
-+  		for(unsigned u = cache_offset; u < cache_end; lastPos = bin_cache[u], ++u) {
-+  			size_t count = bin_cache[u] - lastPos;
-+  			//don't sort unless there are at least two items to compare
-+  			if(count < 2)
-+  				continue;
-+  			//using std::sort if its worst-case is better
-+  			if(count < max_count)
-+  				std::sort(lastPos, bin_cache[u]);
-+  			else
-+  				spread_sort_rec<RandomAccessIter, div_type, data_type>(lastPos, bin_cache[u], bin_cache, cache_end, bin_sizes);
-+  		}
-+  	}
-+
-+  	//Generic bitshift-based 3-way swapping code
-+  	template <class RandomAccessIter, class div_type, class data_type, class right_shift>
-+  	inline void inner_swap_loop(RandomAccessIter * bins, const RandomAccessIter & nextbinstart, unsigned ii, right_shift &shift
-+  		, const unsigned log_divisor, const div_type div_min) 
-+  	{
-+  		RandomAccessIter * local_bin = bins + ii;
-+  		for(RandomAccessIter current = *local_bin; current < nextbinstart; ++current) {
-+  			for(RandomAccessIter * target_bin = (bins + (shift(*current, log_divisor) - div_min));  target_bin != local_bin; 
-+  				target_bin = bins + (shift(*current, log_divisor) - div_min)) {
-+  				data_type tmp;
-+  				RandomAccessIter b = (*target_bin)++;
-+  				RandomAccessIter * b_bin = bins + (shift(*b, log_divisor) - div_min);
-+  				//Three-way swap; if the item to be swapped doesn't belong in the current bin, swap it to where it belongs
-+  				if (b_bin != local_bin) {
-+  					RandomAccessIter c = (*b_bin)++;
-+  					tmp = *c;
-+  					*c = *b;
-+  				} 
-+  				//Note: we could increment current once the swap is done in this case, but that seems to impair performance
-+  				else
-+  					tmp = *b;
-+  				*b = *current;
-+  				*current = tmp;
-+  			}
-+  		}
-+  		*local_bin = nextbinstart;
-+  	}
-+
-+  	//Standard swapping wrapper for ascending values
-+  	template <class RandomAccessIter, class div_type, class data_type, class right_shift>
-+  	inline void swap_loop(RandomAccessIter * bins, RandomAccessIter & nextbinstart, unsigned ii, right_shift &shift
-+  		, const std::vector<size_t> &bin_sizes, const unsigned log_divisor, const div_type div_min) 
-+  	{
-+  		nextbinstart += bin_sizes[ii];
-+  		inner_swap_loop<RandomAccessIter, div_type, data_type, right_shift>(bins, nextbinstart, ii, shift, log_divisor, div_min);
-+  	}
-+
-+  	//Functor implementation for recursive sorting
-+  	template <class RandomAccessIter, class div_type, class data_type, class right_shift, class compare>
-+  	inline void 
-+  	spread_sort_rec(RandomAccessIter first, RandomAccessIter last, std::vector<RandomAccessIter> &bin_cache, unsigned cache_offset
-+  					, std::vector<size_t> &bin_sizes, right_shift shift, compare comp)
-+  	{
-+  		RandomAccessIter max, min;
-+  		find_extremes(first, last, max, min, comp);
-+  		if(max == min)
-+  			return;
-+  		unsigned log_divisor = get_log_divisor(last - first, rough_log_2_size((size_t)(shift(*max, 0)) - (shift(*min, 0))));
-+  		div_type div_min = shift(*min, log_divisor);
-+  		div_type div_max = shift(*max, log_divisor);
-+  		unsigned bin_count = div_max - div_min + 1;
-+  		unsigned cache_end;
-+  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, bin_count);
-+  			
-+  		//Calculating the size of each bin
-+  		for (RandomAccessIter current = first; current != last;)
-+  			bin_sizes[shift(*(current++), log_divisor) - div_min]++;
-+  		bins[0] = first;
-+  		for(unsigned u = 0; u < bin_count - 1; u++)
-+  			bins[u + 1] = bins[u] + bin_sizes[u];
-+  		
-+  		//Swap into place
-+  		RandomAccessIter nextbinstart = first;
-+  		for(unsigned u = 0; u < bin_count - 1; ++u)
-+  			swap_loop<RandomAccessIter, div_type, data_type, right_shift>(bins, nextbinstart, u, shift, bin_sizes, log_divisor, div_min);
-+  		bins[bin_count - 1] = last;
-+  		
-+  		//If we've bucketsorted, the array is sorted and we should skip recursion
-+  		if(!log_divisor)
-+  			return;
-+  		
-+  		//Recursing
-+  		size_t max_count = get_max_count(log_divisor, last - first);
-+  		RandomAccessIter lastPos = first;
-+  		for(unsigned u = cache_offset; u < cache_end; lastPos = bin_cache[u], ++u) {
-+  			size_t count = bin_cache[u] - lastPos;
-+  			if(count < 2)
-+  				continue;
-+  			if(count < max_count)
-+  				std::sort(lastPos, bin_cache[u], comp);
-+  			else
-+  				spread_sort_rec<RandomAccessIter, div_type, data_type, right_shift, compare>(lastPos, bin_cache[u], bin_cache, cache_end, bin_sizes, shift, comp);
-+  		}
-+  	}
-+
-+  	//Functor implementation for recursive sorting with only Shift overridden
-+  	template <class RandomAccessIter, class div_type, class data_type, class right_shift>
-+  	inline void 
-+  	spread_sort_rec(RandomAccessIter first, RandomAccessIter last, std::vector<RandomAccessIter> &bin_cache, unsigned cache_offset
-+  					, std::vector<size_t> &bin_sizes, right_shift shift)
-+  	{
-+  		RandomAccessIter max, min;
-+  		find_extremes(first, last, max, min);
-+  		if(max == min)
-+  			return;
-+  		unsigned log_divisor = get_log_divisor(last - first, rough_log_2_size((size_t)(shift(*max, 0)) - (shift(*min, 0))));
-+  		div_type div_min = shift(*min, log_divisor);
-+  		div_type div_max = shift(*max, log_divisor);
-+  		unsigned bin_count = div_max - div_min + 1;
-+  		unsigned cache_end;
-+  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, bin_count);
-+  			
-+  		//Calculating the size of each bin
-+  		for (RandomAccessIter current = first; current != last;)
-+  			bin_sizes[shift(*(current++), log_divisor) - div_min]++;
-+  		bins[0] = first;
-+  		for(unsigned u = 0; u < bin_count - 1; u++)
-+  			bins[u + 1] = bins[u] + bin_sizes[u];
-+  		
-+  		//Swap into place
-+  		RandomAccessIter nextbinstart = first;
-+  		for(unsigned ii = 0; ii < bin_count - 1; ++ii)
-+  			swap_loop<RandomAccessIter, div_type, data_type, right_shift>(bins, nextbinstart, ii, shift, bin_sizes, log_divisor, div_min);
-+  		bins[bin_count - 1] = last;
-+  		
-+  		//If we've bucketsorted, the array is sorted and we should skip recursion
-+  		if(!log_divisor)
-+  			return;
-+  		
-+  		//Recursing
-+  		size_t max_count = get_max_count(log_divisor, last - first);
-+  		RandomAccessIter lastPos = first;
-+  		for(unsigned u = cache_offset; u < cache_end; lastPos = bin_cache[u], ++u) {
-+  			size_t count = bin_cache[u] - lastPos;
-+  			if(count < 2)
-+  				continue;
-+  			if(count < max_count)
-+  				std::sort(lastPos, bin_cache[u]);
-+  			else
-+  				spread_sort_rec<RandomAccessIter, div_type, data_type, right_shift>(lastPos, bin_cache[u], bin_cache, cache_end, bin_sizes, shift);
-+  		}
-+  	}
-+
-+  	//Holds the bin vector and makes the initial recursive call
-+  	template <class RandomAccessIter, class div_type, class data_type>
-+  	inline void 
-+  	spread_sort(RandomAccessIter first, RandomAccessIter last, div_type, data_type)
-+  	{
-+  		std::vector<size_t> bin_sizes;
-+  		std::vector<RandomAccessIter> bin_cache;
-+  		spread_sort_rec<RandomAccessIter, div_type, data_type>(first, last, bin_cache, 0, bin_sizes);
-+  	}
-+
-+  	template <class RandomAccessIter, class div_type, class data_type, class right_shift, class compare>
-+  	inline void 
-+  	spread_sort(RandomAccessIter first, RandomAccessIter last, div_type, data_type, right_shift shift, compare comp)
-+  	{
-+  		std::vector<size_t> bin_sizes;
-+  		std::vector<RandomAccessIter> bin_cache;
-+  		spread_sort_rec<RandomAccessIter, div_type, data_type, right_shift, compare>(first, last, bin_cache, 0, bin_sizes, shift, comp);
-+  	}
-+
-+  	template <class RandomAccessIter, class div_type, class data_type, class right_shift>
-+  	inline void 
-+  	spread_sort(RandomAccessIter first, RandomAccessIter last, div_type, data_type, right_shift shift)
-+  	{
-+  		std::vector<size_t> bin_sizes;
-+  		std::vector<RandomAccessIter> bin_cache;
-+  		spread_sort_rec<RandomAccessIter, div_type, data_type, right_shift>(first, last, bin_cache, 0, bin_sizes, shift);
-+  	}
-+  }
-+
-+  //Top-level sorting call for integers
-+  template <class RandomAccessIter>
-+  inline void integer_sort(RandomAccessIter first, RandomAccessIter last) 
-+  {
-+  	//Don't sort if it's too small to optimize
-+  	if(last - first < detail::MIN_SORT_SIZE)
-+  		std::sort(first, last);
-+  	else
-+  		detail::spread_sort(first, last, *first >> 0, *first);
-+  }
-+
-+  //integer_sort with functors
-+  template <class RandomAccessIter, class right_shift, class compare>
-+  inline void integer_sort(RandomAccessIter first, RandomAccessIter last,
-+  						right_shift shift, compare comp) {
-+  	if(last - first < detail::MIN_SORT_SIZE)
-+  		std::sort(first, last, comp);
-+  	else
-+  		detail::spread_sort(first, last, shift(*first, 0), *first, shift, comp);
-+  }
-+
-+  //integer_sort with right_shift functor
-+  template <class RandomAccessIter, class right_shift>
-+  inline void integer_sort(RandomAccessIter first, RandomAccessIter last,
-+  						right_shift shift) {
-+  	if(last - first < detail::MIN_SORT_SIZE)
-+  		std::sort(first, last);
-+  	else
-+  		detail::spread_sort(first, last, shift(*first, 0), *first, shift);
-+  }
-+
-+  //------------------------------------------------------ float_sort source --------------------------------------
-+  //Casts a RandomAccessIter to the specified data type
-+  template<class cast_type, class RandomAccessIter>
-+  inline cast_type
-+  cast_float_iter(const RandomAccessIter & floatiter)
-+  {
-+  	cast_type result;
-+  	std::memcpy(&result, &(*floatiter), sizeof(cast_type));
-+  	return result;
-+  }
-+
-+  //Casts a data element to the specified datinner_float_a type
-+  template<class data_type, class cast_type>
-+  inline cast_type
-+  mem_cast(const data_type & data)
-+  {
-+  	cast_type result;
-+  	std::memcpy(&result, &data, sizeof(cast_type));
-+  	return result;
-+  }
-+
-+  namespace detail {
-+  	template <class RandomAccessIter, class div_type, class right_shift>
-+  	inline void 
-+  	find_extremes(RandomAccessIter current, RandomAccessIter last, div_type & max, div_type & min, right_shift shift)
-+  	{
-+  		min = max = shift(*current, 0);
-+  		while(++current < last) {
-+  			div_type value = shift(*current, 0);
-+  			if(max < value)
-+  				max = value;
-+  			else if(value < min)
-+  				min = value;
-+  		}
-+  	}
-+
-+  	//Specialized swap loops for floating-point casting
-+  	template <class RandomAccessIter, class div_type, class data_type>
-+  	inline void inner_float_swap_loop(RandomAccessIter * bins, const RandomAccessIter & nextbinstart, unsigned ii
-+  		, const unsigned log_divisor, const div_type div_min) 
-+  	{
-+  		RandomAccessIter * local_bin = bins + ii;
-+  		for(RandomAccessIter current = *local_bin; current < nextbinstart; ++current) {
-+  			for(RandomAccessIter * target_bin = (bins + ((cast_float_iter<div_type, RandomAccessIter>(current) >> log_divisor) - div_min));  target_bin != local_bin; 
-+  				target_bin = bins + ((cast_float_iter<div_type, RandomAccessIter>(current) >> log_divisor) - div_min)) {
-+  				data_type tmp;
-+  				RandomAccessIter b = (*target_bin)++;
-+  				RandomAccessIter * b_bin = bins + ((cast_float_iter<div_type, RandomAccessIter>(b) >> log_divisor) - div_min);
-+  				//Three-way swap; if the item to be swapped doesn't belong in the current bin, swap it to where it belongs
-+  				if (b_bin != local_bin) {
-+  					RandomAccessIter c = (*b_bin)++;
-+  					tmp = *c;
-+  					*c = *b;
-+  				} 
-+  				else
-+  					tmp = *b;
-+  				*b = *current;
-+  				*current = tmp;
-+  			}
-+  		}
-+  		*local_bin = nextbinstart;
-+  	}
-+
-+  	template <class RandomAccessIter, class div_type, class data_type>
-+  	inline void float_swap_loop(RandomAccessIter * bins, RandomAccessIter & nextbinstart, unsigned ii
-+  		, const std::vector<size_t> &bin_sizes, const unsigned log_divisor, const div_type div_min) 
-+  	{
-+  		nextbinstart += bin_sizes[ii];
-+  		inner_float_swap_loop<RandomAccessIter, div_type, data_type>(bins, nextbinstart, ii, log_divisor, div_min);
-+  	}
-+
-+  	template <class RandomAccessIter, class cast_type>
-+  	inline void 
-+  	find_extremes(RandomAccessIter current, RandomAccessIter last, cast_type & max, cast_type & min)
-+  	{
-+  		min = max = cast_float_iter<cast_type, RandomAccessIter>(current);
-+  		while(++current < last) {
-+  			cast_type value = cast_float_iter<cast_type, RandomAccessIter>(current);
-+  			if(max < value)
-+  				max = value;
-+  			else if(value < min)
-+  				min = value;
-+  		}
-+  	}
-+
-+  	//Special-case sorting of positive floats with casting instead of a right_shift
-+  	template <class RandomAccessIter, class div_type, class data_type>
-+  	inline void 
-+  	positive_float_sort_rec(RandomAccessIter first, RandomAccessIter last, std::vector<RandomAccessIter> &bin_cache, unsigned cache_offset
-+  					, std::vector<size_t> &bin_sizes)
-+  	{
-+  		div_type max, min;
-+  		find_extremes(first, last, max, min);
-+  		if(max == min)
-+  			return;
-+  		unsigned log_divisor = get_log_divisor(last - first, rough_log_2_size((size_t)(max) - min));
-+  		div_type div_min = min >> log_divisor;
-+  		div_type div_max = max >> log_divisor;
-+  		unsigned bin_count = div_max - div_min + 1;
-+  		unsigned cache_end;
-+  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, bin_count);
-+  			
-+  		//Calculating the size of each bin
-+  		for (RandomAccessIter current = first; current != last;)
-+  			bin_sizes[(cast_float_iter<div_type, RandomAccessIter>(current++) >> log_divisor) - div_min]++;
-+  		bins[0] = first;
-+  		for(unsigned u = 0; u < bin_count - 1; u++)
-+  			bins[u + 1] = bins[u] + bin_sizes[u];
-+  		
-+  		//Swap into place
-+  		RandomAccessIter nextbinstart = first;
-+  		for(unsigned u = 0; u < bin_count - 1; ++u)
-+  			float_swap_loop<RandomAccessIter, div_type, data_type>(bins, nextbinstart, u, bin_sizes, log_divisor, div_min);
-+  		bins[bin_count - 1] = last;
-+  		
-+  		//Return if we've completed bucketsorting
-+  		if(!log_divisor)
-+  			return;
-+  		
-+  		//Recursing
-+  		size_t max_count = get_max_count(log_divisor, last - first);
-+  		RandomAccessIter lastPos = first;
-+  		for(unsigned u = cache_offset; u < cache_end; lastPos = bin_cache[u], ++u) {
-+  			size_t count = bin_cache[u] - lastPos;
-+  			if(count < 2)
-+  				continue;
-+  			if(count < max_count)
-+  				std::sort(lastPos, bin_cache[u]);
-+  			else
-+  				positive_float_sort_rec<RandomAccessIter, div_type, data_type>(lastPos, bin_cache[u], bin_cache, cache_end, bin_sizes);
-+  		}
-+  	}
-+
-+  	//Sorting negative_ float_s
-+  	//Note that bins are iterated in reverse order because max_neg_float = min_neg_int
-+  	template <class RandomAccessIter, class div_type, class data_type>
-+  	inline void 
-+  	negative_float_sort_rec(RandomAccessIter first, RandomAccessIter last, std::vector<RandomAccessIter> &bin_cache, unsigned cache_offset
-+  					, std::vector<size_t> &bin_sizes)
-+  	{
-+  		div_type max, min;
-+  		find_extremes(first, last, max, min);
-+  		if(max == min)
-+  			return;
-+  		unsigned log_divisor = get_log_divisor(last - first, rough_log_2_size((size_t)(max) - min));
-+  		div_type div_min = min >> log_divisor;
-+  		div_type div_max = max >> log_divisor;
-+  		unsigned bin_count = div_max - div_min + 1;
-+  		unsigned cache_end;
-+  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, bin_count);
-+  			
-+  		//Calculating the size of each bin
-+  		for (RandomAccessIter current = first; current != last;)
-+  			bin_sizes[(cast_float_iter<div_type, RandomAccessIter>(current++) >> log_divisor) - div_min]++;
-+  		bins[bin_count - 1] = first;
-+  		for(int ii = bin_count - 2; ii >= 0; --ii)
-+  			bins[ii] = bins[ii + 1] + bin_sizes[ii + 1];
-+  		
-+  		//Swap into place
-+  		RandomAccessIter nextbinstart = first;
-+  		//The last bin will always have the correct elements in it
-+  		for(int ii = bin_count - 1; ii > 0; --ii)
-+  			float_swap_loop<RandomAccessIter, div_type, data_type>(bins, nextbinstart, ii, bin_sizes, log_divisor, div_min);
-+  		//Since we don't process the last bin, we need to update its end position
-+  		bin_cache[cache_offset] = last;
-+  		
-+  		//Return if we've completed bucketsorting
-+  		if(!log_divisor)
-+  			return;
-+  		
-+  		//Recursing
-+  		size_t max_count = get_max_count(log_divisor, last - first);
-+  		RandomAccessIter lastPos = first;
-+  		for(int ii = cache_end - 1; ii >= (int)cache_offset; lastPos = bin_cache[ii], --ii) {
-+  			size_t count = bin_cache[ii] - lastPos;
-+  			if(count < 2)
-+  				continue;
-+  			if(count < max_count)
-+  				std::sort(lastPos, bin_cache[ii]);
-+  			else
-+  				negative_float_sort_rec<RandomAccessIter, div_type, data_type>(lastPos, bin_cache[ii], bin_cache, cache_end, bin_sizes);
-+  		}
-+  	}
-+
-+  	//Sorting negative_ float_s
-+  	//Note that bins are iterated in reverse order because max_neg_float = min_neg_int
-+  	template <class RandomAccessIter, class div_type, class data_type, class right_shift>
-+  	inline void 
-+  	negative_float_sort_rec(RandomAccessIter first, RandomAccessIter last, std::vector<RandomAccessIter> &bin_cache, unsigned cache_offset
-+  					, std::vector<size_t> &bin_sizes, right_shift shift)
-+  	{
-+  		div_type max, min;
-+  		find_extremes(first, last, max, min, shift);
-+  		if(max == min)
-+  			return;
-+  		unsigned log_divisor = get_log_divisor(last - first, rough_log_2_size((size_t)(max) - min));
-+  		div_type div_min = min >> log_divisor;
-+  		div_type div_max = max >> log_divisor;
-+  		unsigned bin_count = div_max - div_min + 1;
-+  		unsigned cache_end;
-+  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, bin_count);
-+  			
-+  		//Calculating the size of each bin
-+  		for (RandomAccessIter current = first; current != last;)
-+  			bin_sizes[shift(*(current++), log_divisor) - div_min]++;
-+  		bins[bin_count - 1] = first;
-+  		for(int ii = bin_count - 2; ii >= 0; --ii)
-+  			bins[ii] = bins[ii + 1] + bin_sizes[ii + 1];
-+  		
-+  		//Swap into place
-+  		RandomAccessIter nextbinstart = first;
-+  		//The last bin will always have the correct elements in it
-+  		for(int ii = bin_count - 1; ii > 0; --ii)
-+  			swap_loop<RandomAccessIter, div_type, data_type, right_shift>(bins, nextbinstart, ii, shift, bin_sizes, log_divisor, div_min);
-+  		//Since we don't process the last bin, we need to update its end position
-+  		bin_cache[cache_offset] = last;
-+  		
-+  		//Return if we've completed bucketsorting
-+  		if(!log_divisor)
-+  			return;
-+  		
-+  		//Recursing
-+  		size_t max_count = get_max_count(log_divisor, last - first);
-+  		RandomAccessIter lastPos = first;
-+  		for(int ii = cache_end - 1; ii >= (int)cache_offset; lastPos = bin_cache[ii], --ii) {
-+  			size_t count = bin_cache[ii] - lastPos;
-+  			if(count < 2)
-+  				continue;
-+  			if(count < max_count)
-+  				std::sort(lastPos, bin_cache[ii]);
-+  			else
-+  				negative_float_sort_rec<RandomAccessIter, div_type, data_type, right_shift>(lastPos, bin_cache[ii], bin_cache, cache_end, bin_sizes, shift);
-+  		}
-+  	}
-+
-+  	template <class RandomAccessIter, class div_type, class data_type, class right_shift, class compare>
-+  	inline void 
-+  	negative_float_sort_rec(RandomAccessIter first, RandomAccessIter last, std::vector<RandomAccessIter> &bin_cache, unsigned cache_offset
-+  					, std::vector<size_t> &bin_sizes, right_shift shift, compare comp)
-+  	{
-+  		div_type max, min;
-+  		find_extremes(first, last, max, min, shift);
-+  		if(max == min)
-+  			return;
-+  		unsigned log_divisor = get_log_divisor(last - first, rough_log_2_size((size_t)(max) - min));
-+  		div_type div_min = min >> log_divisor;
-+  		div_type div_max = max >> log_divisor;
-+  		unsigned bin_count = div_max - div_min + 1;
-+  		unsigned cache_end;
-+  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, bin_count);
-+  			
-+  		//Calculating the size of each bin
-+  		for (RandomAccessIter current = first; current != last;)
-+  			bin_sizes[shift(*(current++), log_divisor) - div_min]++;
-+  		bins[bin_count - 1] = first;
-+  		for(int ii = bin_count - 2; ii >= 0; --ii)
-+  			bins[ii] = bins[ii + 1] + bin_sizes[ii + 1];
-+  		
-+  		//Swap into place
-+  		RandomAccessIter nextbinstart = first;
-+  		//The last bin will always have the correct elements in it
-+  		for(int ii = bin_count - 1; ii > 0; --ii)
-+  			swap_loop<RandomAccessIter, div_type, data_type, right_shift>(bins, nextbinstart, ii, shift, bin_sizes, log_divisor, div_min);
-+  		//Since we don't process the last bin, we need to update its end position
-+  		bin_cache[cache_offset] = last;
-+  		
-+  		//Return if we've completed bucketsorting
-+  		if(!log_divisor)
-+  			return;
-+  		
-+  		//Recursing
-+  		size_t max_count = get_max_count(log_divisor, last - first);
-+  		RandomAccessIter lastPos = first;
-+  		for(int ii = cache_end - 1; ii >= (int)cache_offset; lastPos = bin_cache[ii], --ii) {
-+  			size_t count = bin_cache[ii] - lastPos;
-+  			if(count < 2)
-+  				continue;
-+  			if(count < max_count)
-+  				std::sort(lastPos, bin_cache[ii], comp);
-+  			else
-+  				negative_float_sort_rec<RandomAccessIter, div_type, data_type, right_shift, compare>(lastPos, bin_cache[ii], bin_cache, cache_end, bin_sizes, shift, comp);
-+  		}
-+  	}
-+
-+  	//Casting special-case for floating-point sorting
-+  	template <class RandomAccessIter, class div_type, class data_type>
-+  	inline void 
-+  	float_sort_rec(RandomAccessIter first, RandomAccessIter last, std::vector<RandomAccessIter> &bin_cache, unsigned cache_offset
-+  					, std::vector<size_t> &bin_sizes)
-+  	{
-+  		div_type max, min;
-+  		find_extremes(first, last, max, min);
-+  		if(max == min)
-+  			return;
-+  		unsigned log_divisor = get_log_divisor(last - first, rough_log_2_size((size_t)(max) - min));
-+  		div_type div_min = min >> log_divisor;
-+  		div_type div_max = max >> log_divisor;
-+  		unsigned bin_count = div_max - div_min + 1;
-+  		unsigned cache_end;
-+  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, bin_count);
-+  			
-+  		//Calculating the size of each bin
-+  		for (RandomAccessIter current = first; current != last;)
-+  			bin_sizes[(cast_float_iter<div_type, RandomAccessIter>(current++) >> log_divisor) - div_min]++;
-+  		//The index of the first positive bin
-+  		div_type first_positive = (div_min < 0) ? -div_min : 0;
-+  		//Resetting if all bins are negative
-+  		if(cache_offset + first_positive > cache_end)
-+  			first_positive = cache_end - cache_offset;
-+  		//Reversing the order of the negative bins
-+  		//Note that because of the negative/positive ordering direction flip
-+  		//We can not depend upon bin order and positions matching up
-+  		//so bin_sizes must be reused to contain the end of the bin
-+  		if(first_positive > 0) {
-+  			bins[first_positive - 1] = first;
-+  			for(int ii = first_positive - 2; ii >= 0; --ii) {
-+  				bins[ii] = first + bin_sizes[ii + 1];
-+  				bin_sizes[ii] += bin_sizes[ii + 1];
-+  			}
-+  			//Handling positives following negatives
-+  			if((unsigned)first_positive < bin_count) {
-+  				bins[first_positive] = first + bin_sizes[0];
-+  				bin_sizes[first_positive] += bin_sizes[0];
-+  			}
-+  		}
-+  		else
-+  			bins[0] = first;
-+  		for(unsigned u = first_positive; u < bin_count - 1; u++) {
-+  			bins[u + 1] = first + bin_sizes[u];
-+  			bin_sizes[u + 1] += bin_sizes[u];
-+  		}
-+  		
-+  		//Swap into place
-+  		RandomAccessIter nextbinstart = first;
-+  		for(unsigned u = 0; u < bin_count; ++u) {
-+  			nextbinstart = first + bin_sizes[u];
-+  			inner_float_swap_loop<RandomAccessIter, div_type, data_type>(bins, nextbinstart, u, log_divisor, div_min);
-+  		}
-+  		
-+  		if(!log_divisor)
-+  			return;
-+  		
-+  		//Handling negative values first
-+  		size_t max_count = get_max_count(log_divisor, last - first);
-+  		RandomAccessIter lastPos = first;
-+  		for(int ii = cache_offset + first_positive - 1; ii >= (int)cache_offset ; lastPos = bin_cache[ii--]) {
-+  			size_t count = bin_cache[ii] - lastPos;
-+  			if(count < 2)
-+  				continue;
-+  			if(count < max_count)
-+  				std::sort(lastPos, bin_cache[ii]);
-+  			//sort negative values using reversed-bin spread_sort
-+  			else
-+  				negative_float_sort_rec<RandomAccessIter, div_type, data_type>(lastPos, bin_cache[ii], bin_cache, cache_end, bin_sizes);
-+  		}
-+  		
-+  		for(unsigned u = cache_offset + first_positive; u < cache_end; lastPos = bin_cache[u], ++u) {
-+  			size_t count = bin_cache[u] - lastPos;
-+  			if(count < 2)
-+  				continue;
-+  			if(count < max_count)
-+  				std::sort(lastPos, bin_cache[u]);
-+  			//sort positive values using normal spread_sort
-+  			else
-+  				positive_float_sort_rec<RandomAccessIter, div_type, data_type>(lastPos, bin_cache[u], bin_cache, cache_end, bin_sizes);
-+  		}
-+  	}
-+
-+  	//Functor implementation for recursive sorting
-+  	template <class RandomAccessIter, class div_type, class data_type, class right_shift>
-+  	inline void 
-+  	float_sort_rec(RandomAccessIter first, RandomAccessIter last, std::vector<RandomAccessIter> &bin_cache, unsigned cache_offset
-+  					, std::vector<size_t> &bin_sizes, right_shift shift)
-+  	{
-+  		div_type max, min;
-+  		find_extremes(first, last, max, min, shift);
-+  		if(max == min)
-+  			return;
-+  		unsigned log_divisor = get_log_divisor(last - first, rough_log_2_size((size_t)(max) - min));
-+  		div_type div_min = min >> log_divisor;
-+  		div_type div_max = max >> log_divisor;
-+  		unsigned bin_count = div_max - div_min + 1;
-+  		unsigned cache_end;
-+  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, bin_count);
-+  			
-+  		//Calculating the size of each bin
-+  		for (RandomAccessIter current = first; current != last;)
-+  			bin_sizes[shift(*(current++), log_divisor) - div_min]++;
-+  		//The index of the first positive bin
-+  		div_type first_positive = (div_min < 0) ? -div_min : 0;
-+  		//Resetting if all bins are negative
-+  		if(cache_offset + first_positive > cache_end)
-+  			first_positive = cache_end - cache_offset;
-+  		//Reversing the order of the negative bins
-+  		//Note that because of the negative/positive ordering direction flip
-+  		//We can not depend upon bin order and positions matching up
-+  		//so bin_sizes must be reused to contain the end of the bin
-+  		if(first_positive > 0) {
-+  			bins[first_positive - 1] = first;
-+  			for(int ii = first_positive - 2; ii >= 0; --ii) {
-+  				bins[ii] = first + bin_sizes[ii + 1];
-+  				bin_sizes[ii] += bin_sizes[ii + 1];
-+  			}
-+  			//Handling positives following negatives
-+  			if((unsigned)first_positive < bin_count) {
-+  				bins[first_positive] = first + bin_sizes[0];
-+  				bin_sizes[first_positive] += bin_sizes[0];
-+  			}
-+  		}
-+  		else
-+  			bins[0] = first;
-+  		for(unsigned u = first_positive; u < bin_count - 1; u++) {
-+  			bins[u + 1] = first + bin_sizes[u];
-+  			bin_sizes[u + 1] += bin_sizes[u];
-+  		}
-+  		
-+  		//Swap into place
-+  		RandomAccessIter nextbinstart = first;
-+  		for(unsigned u = 0; u < bin_count; ++u) {
-+  			nextbinstart = first + bin_sizes[u];
-+  			inner_swap_loop<RandomAccessIter, div_type, data_type, right_shift>(bins, nextbinstart, u, shift, log_divisor, div_min);
-+  		}
-+  		
-+  		//Return if we've completed bucketsorting
-+  		if(!log_divisor)
-+  			return;
-+  		
-+  		//Handling negative values first
-+  		size_t max_count = get_max_count(log_divisor, last - first);
-+  		RandomAccessIter lastPos = first;
-+  		for(int ii = cache_offset + first_positive - 1; ii >= (int)cache_offset ; lastPos = bin_cache[ii--]) {
-+  			size_t count = bin_cache[ii] - lastPos;
-+  			if(count < 2)
-+  				continue;
-+  			if(count < max_count)
-+  				std::sort(lastPos, bin_cache[ii]);
-+  			//sort negative values using reversed-bin spread_sort
-+  			else
-+  				negative_float_sort_rec<RandomAccessIter, div_type, data_type, right_shift>(lastPos, bin_cache[ii], bin_cache, cache_end, bin_sizes, shift);
-+  		}
-+  		
-+  		for(unsigned u = cache_offset + first_positive; u < cache_end; lastPos = bin_cache[u], ++u) {
-+  			size_t count = bin_cache[u] - lastPos;
-+  			if(count < 2)
-+  				continue;
-+  			if(count < max_count)
-+  				std::sort(lastPos, bin_cache[u]);
-+  			//sort positive values using normal spread_sort
-+  			else
-+  				spread_sort_rec<RandomAccessIter, div_type, data_type, right_shift>(lastPos, bin_cache[u], bin_cache, cache_end, bin_sizes, shift);
-+  		}
-+  	}
-+
-+  	template <class RandomAccessIter, class div_type, class data_type, class right_shift, class compare>
-+  	inline void 
-+  	float_sort_rec(RandomAccessIter first, RandomAccessIter last, std::vector<RandomAccessIter> &bin_cache, unsigned cache_offset
-+  					, std::vector<size_t> &bin_sizes, right_shift shift, compare comp)
-+  	{
-+  		div_type max, min;
-+  		find_extremes(first, last, max, min, shift);
-+  		if(max == min)
-+  			return;
-+  		unsigned log_divisor = get_log_divisor(last - first, rough_log_2_size((size_t)(max) - min));
-+  		div_type div_min = min >> log_divisor;
-+  		div_type div_max = max >> log_divisor;
-+  		unsigned bin_count = div_max - div_min + 1;
-+  		unsigned cache_end;
-+  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, bin_count);
-+  			
-+  		//Calculating the size of each bin
-+  		for (RandomAccessIter current = first; current != last;)
-+  			bin_sizes[shift(*(current++), log_divisor) - div_min]++;
-+  		//The index of the first positive bin
-+  		div_type first_positive = (div_min < 0) ? -div_min : 0;
-+  		//Resetting if all bins are negative
-+  		if(cache_offset + first_positive > cache_end)
-+  			first_positive = cache_end - cache_offset;
-+  		//Reversing the order of the negative bins
-+  		//Note that because of the negative/positive ordering direction flip
-+  		//We can not depend upon bin order and positions matching up
-+  		//so bin_sizes must be reused to contain the end of the bin
-+  		if(first_positive > 0) {
-+  			bins[first_positive - 1] = first;
-+  			for(int ii = first_positive - 2; ii >= 0; --ii) {
-+  				bins[ii] = first + bin_sizes[ii + 1];
-+  				bin_sizes[ii] += bin_sizes[ii + 1];
-+  			}
-+  			//Handling positives following negatives
-+  			if((unsigned)first_positive < bin_count) {
-+  				bins[first_positive] = first + bin_sizes[0];
-+  				bin_sizes[first_positive] += bin_sizes[0];
-+  			}
-+  		}
-+  		else
-+  			bins[0] = first;
-+  		for(unsigned u = first_positive; u < bin_count - 1; u++) {
-+  			bins[u + 1] = first + bin_sizes[u];
-+  			bin_sizes[u + 1] += bin_sizes[u];
-+  		}
-+  		
-+  		//Swap into place
-+  		RandomAccessIter nextbinstart = first;
-+  		for(unsigned u = 0; u < bin_count; ++u) {
-+  			nextbinstart = first + bin_sizes[u];
-+  			inner_swap_loop<RandomAccessIter, div_type, data_type, right_shift>(bins, nextbinstart, u, shift, log_divisor, div_min);
-+  		}
-+  		
-+  		//Return if we've completed bucketsorting
-+  		if(!log_divisor)
-+  			return;
-+  		
-+  		//Handling negative values first
-+  		size_t max_count = get_max_count(log_divisor, last - first);
-+  		RandomAccessIter lastPos = first;
-+  		for(int ii = cache_offset + first_positive - 1; ii >= (int)cache_offset ; lastPos = bin_cache[ii--]) {
-+  			size_t count = bin_cache[ii] - lastPos;
-+  			if(count < 2)
-+  				continue;
-+  			if(count < max_count)
-+  				std::sort(lastPos, bin_cache[ii]);
-+  			//sort negative values using reversed-bin spread_sort
-+  			else
-+  				negative_float_sort_rec<RandomAccessIter, div_type, data_type, right_shift>(lastPos, bin_cache[ii], bin_cache, cache_end, bin_sizes, shift, comp);
-+  		}
-+  		
-+  		for(unsigned u = cache_offset + first_positive; u < cache_end; lastPos = bin_cache[u], ++u) {
-+  			size_t count = bin_cache[u] - lastPos;
-+  			if(count < 2)
-+  				continue;
-+  			if(count < max_count)
-+  				std::sort(lastPos, bin_cache[u]);
-+  			//sort positive values using normal spread_sort
-+  			else
-+  				spread_sort_rec<RandomAccessIter, div_type, data_type, right_shift>(lastPos, bin_cache[u], bin_cache, cache_end, bin_sizes, shift, comp);
-+  		}
-+  	}
-+
-+  	template <class RandomAccessIter, class cast_type, class data_type>
-+  	inline void 
-+  	float_Sort(RandomAccessIter first, RandomAccessIter last, cast_type, data_type)
-+  	{
-+  		std::vector<size_t> bin_sizes;
-+  		std::vector<RandomAccessIter> bin_cache;
-+  		float_sort_rec<RandomAccessIter, cast_type, data_type>(first, last, bin_cache, 0, bin_sizes);
-+  	}
-+
-+  	template <class RandomAccessIter, class div_type, class data_type, class right_shift>
-+  	inline void 
-+  	float_Sort(RandomAccessIter first, RandomAccessIter last, div_type, data_type, right_shift shift)
-+  	{
-+  		std::vector<size_t> bin_sizes;
-+  		std::vector<RandomAccessIter> bin_cache;
-+  		float_sort_rec<RandomAccessIter, div_type, data_type, right_shift>(first, last, bin_cache, 0, bin_sizes, shift);
-+  	}
-+
-+  	template <class RandomAccessIter, class div_type, class data_type, class right_shift, class compare>
-+  	inline void 
-+  	float_Sort(RandomAccessIter first, RandomAccessIter last, div_type, data_type, right_shift shift, compare comp)
-+  	{
-+  		std::vector<size_t> bin_sizes;
-+  		std::vector<RandomAccessIter> bin_cache;
-+  		float_sort_rec<RandomAccessIter, div_type, data_type, right_shift>(first, last, bin_cache, 0, bin_sizes, shift, comp);
-+  	}
-+  }
-+
-+  //float_sort with casting
-+  //The cast_type must be equal in size to the data type, and must be a signed integer
-+  template <class RandomAccessIter, class cast_type>
-+  inline void float_sort_cast(RandomAccessIter first, RandomAccessIter last, cast_type cVal) 
-+  {
-+  	if(last - first < detail::MIN_SORT_SIZE)
-+  		std::sort(first, last);
-+  	else
-+  		detail::float_Sort(first, last, cVal, *first);
-+  }
-+
-+  //float_sort with casting to an int
-+  //Only use this with IEEE floating-point numbers
-+  template <class RandomAccessIter>
-+  inline void float_sort_cast_to_int(RandomAccessIter first, RandomAccessIter last) 
-+  {
-+  	int cVal = 0;
-+  	float_sort_cast(first, last, cVal);
-+  }
-+
-+  //float_sort with functors
-+  template <class RandomAccessIter, class right_shift>
-+  inline void float_sort(RandomAccessIter first, RandomAccessIter last, right_shift shift) 
-+  {
-+  	if(last - first < detail::MIN_SORT_SIZE)
-+  		std::sort(first, last);
-+  	else
-+  		detail::float_Sort(first, last, shift(*first, 0), *first, shift);
-+  }
-+
-+  template <class RandomAccessIter, class right_shift, class compare>
-+  inline void float_sort(RandomAccessIter first, RandomAccessIter last, right_shift shift, compare comp) 
-+  {
-+  	if(last - first < detail::MIN_SORT_SIZE)
-+  		std::sort(first, last, comp);
-+  	else
-+  		detail::float_Sort(first, last, shift(*first, 0), *first, shift, comp);
-+  }
-+
-+  //------------------------------------------------- string_sort source ---------------------------------------------
-+  namespace detail {
-+  	//Offsetting on identical characters.  This function works a character at a time for optimal worst-case performance.
-+  	template<class RandomAccessIter>
-+  	inline void
-+  	update_offset(RandomAccessIter first, RandomAccessIter finish, unsigned &char_offset)
-+  	{
-+  		unsigned nextOffset = char_offset;
-+  		bool done = false;
-+  		while(!done) {
-+  			RandomAccessIter curr = first;
-+  			do {
-+  				//ignore empties, but if the nextOffset would exceed the length or not match, exit; we've found the last matching character
-+  				if((*curr).size() > char_offset && ((*curr).size() <= (nextOffset + 1) || (*curr)[nextOffset] != (*first)[nextOffset])) {
-+  					done = true;
-+  					break;
-+  				}
-+  			} while(++curr != finish);
-+  			if(!done)
-+  				++nextOffset;
-+  		} 
-+  		char_offset = nextOffset;
-+  	}
-+
-+  	//Offsetting on identical characters.  This function works a character at a time for optimal worst-case performance.
-+  	template<class RandomAccessIter, class get_char, class get_length>
-+  	inline void
-+  	update_offset(RandomAccessIter first, RandomAccessIter finish, unsigned &char_offset, get_char getchar, get_length length)
-+  	{
-+  		unsigned nextOffset = char_offset;
-+  		bool done = false;
-+  		while(!done) {
-+  			RandomAccessIter curr = first;
-+  			do {
-+  				//ignore empties, but if the nextOffset would exceed the length or not match, exit; we've found the last matching character
-+  				if(length(*curr) > char_offset && (length(*curr) <= (nextOffset + 1) || getchar((*curr), nextOffset) != getchar((*first), nextOffset))) {
-+  					done = true;
-+  					break;
-+  				}
-+  			} while(++curr != finish);
-+  			if(!done)
-+  				++nextOffset;
-+  		} 
-+  		char_offset = nextOffset;
-+  	}
-+
-+  	//A comparison functor for strings that assumes they are identical up to char_offset
-+  	template<class data_type, class unsignedchar_type>
-+  	struct offset_lessthan {
-+  		offset_lessthan(unsigned char_offset) : fchar_offset(char_offset){}
-+  		inline bool operator()(const data_type &x, const data_type &y) const 
-+  		{
-+  			unsigned minSize = std::min(x.size(), y.size());
-+  			for(unsigned u = fchar_offset; u < minSize; ++u) {
-+  				if(static_cast<unsignedchar_type>(x[u]) < static_cast<unsignedchar_type>(y[u]))
-+  					return true;
-+  				else if(static_cast<unsignedchar_type>(y[u]) < static_cast<unsignedchar_type>(x[u]))
-+  					return false;
-+  			}
-+  			return x.size() < y.size();
-+  		}
-+  		unsigned fchar_offset;
-+  	};
-+
-+  	//A comparison functor for strings that assumes they are identical up to char_offset
-+  	template<class data_type, class unsignedchar_type>
-+  	struct offset_greaterthan {
-+  		offset_greaterthan(unsigned char_offset) : fchar_offset(char_offset){}
-+  		inline bool operator()(const data_type &x, const data_type &y) const 
-+  		{
-+  			unsigned minSize = std::min(x.size(), y.size());
-+  			for(unsigned u = fchar_offset; u < minSize; ++u) {
-+  				if(static_cast<unsignedchar_type>(x[u]) > static_cast<unsignedchar_type>(y[u]))
-+  					return true;
-+  				else if(static_cast<unsignedchar_type>(y[u]) > static_cast<unsignedchar_type>(x[u]))
-+  					return false;
-+  			}
-+  			return x.size() > y.size();
-+  		}
-+  		unsigned fchar_offset;
-+  	};
-+
-+  	//A comparison functor for strings that assumes they are identical up to char_offset
-+  	template<class data_type, class get_char, class get_length>
-+  	struct offset_char_lessthan {
-+  		offset_char_lessthan(unsigned char_offset) : fchar_offset(char_offset){}
-+  		inline bool operator()(const data_type &x, const data_type &y) const 
-+  		{
-+  			unsigned minSize = std::min(length(x), length(y));
-+  			for(unsigned u = fchar_offset; u < minSize; ++u) {
-+  				if(getchar(x, u) < getchar(y, u))
-+  					return true;
-+  				else if(getchar(y, u) < getchar(x, u))
-+  					return false;
-+  			}
-+  			return length(x) < length(y);
-+  		}
-+  		unsigned fchar_offset;
-+  		get_char getchar;
-+  		get_length length;
-+  	};
-+
-+  	//String sorting recursive implementation
-+  	template <class RandomAccessIter, class data_type, class unsignedchar_type>
-+  	inline void 
-+  	string_sort_rec(RandomAccessIter first, RandomAccessIter last, unsigned char_offset, std::vector<RandomAccessIter> &bin_cache
-+  		, unsigned cache_offset, std::vector<size_t> &bin_sizes)
-+  	{
-+  		//This section is not strictly necessary, but makes handling of long identical substrings much faster, with a mild average performance impact.
-+  		//Iterate to the end of the empties.  If all empty, return
-+  		while((*first).size() <= char_offset) {
-+  			if(++first == last)
-+  				return;
-+  		}
-+  		RandomAccessIter finish = last - 1;
-+  		//Getting the last non-empty
-+  		for(;(*finish).size() <= char_offset; --finish) { }
-+  		++finish;
-+  		//Offsetting on identical characters.  This section works a character at a time for optimal worst-case performance.
-+  		update_offset(first, finish, char_offset);
-+  		
-+  		const unsigned bin_count = (1 << (sizeof(unsignedchar_type)*8));
-+  		//Equal worst-case between radix and comparison-based is when bin_count = n*log(n).
-+  		const unsigned max_size = bin_count;
-+  		const unsigned membin_count = bin_count + 1;
-+  		unsigned cache_end;
-+  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, membin_count) + 1;
-+  			
-+  		//Calculating the size of each bin; this takes roughly 10% of runtime
-+  		for (RandomAccessIter current = first; current != last; ++current) {
-+  			if((*current).size() <= char_offset) {
-+  				bin_sizes[0]++;
-+  			}
-+  			else
-+  				bin_sizes[static_cast<unsignedchar_type>((*current)[char_offset]) + 1]++;
-+  		}
-+  		//Assign the bin positions
-+  		bin_cache[cache_offset] = first;
-+  		for(unsigned u = 0; u < membin_count - 1; u++)
-+  			bin_cache[cache_offset + u + 1] = bin_cache[cache_offset + u] + bin_sizes[u];
-+  		
-+  		//Swap into place
-+  		RandomAccessIter nextbinstart = first;
-+  		//handling empty bins
-+  		RandomAccessIter * local_bin = &(bin_cache[cache_offset]);
-+  		nextbinstart +=	bin_sizes[0];
-+  		RandomAccessIter * target_bin;
-+  		//Iterating over each element in the bin of empties
-+  		for(RandomAccessIter current = *local_bin; current < nextbinstart; ++current) {
-+  			//empties belong in this bin
-+  			while((*current).size() > char_offset) {
-+  				target_bin = bins + static_cast<unsignedchar_type>((*current)[char_offset]);
-+  				iter_swap(current, (*target_bin)++);
-+  			}
-+  		}
-+  		*local_bin = nextbinstart;
-+  		//iterate backwards to find the last bin with elements in it; this saves iterations in multiple loops
-+  		unsigned last_bin = bin_count - 1;
-+  		for(; last_bin && !bin_sizes[last_bin + 1]; --last_bin) { }
-+  		//This dominates runtime, mostly in the swap and bin lookups
-+  		for(unsigned u = 0; u < last_bin; ++u) {
-+  			local_bin = bins + u;
-+  			nextbinstart += bin_sizes[u + 1];
-+  			//Iterating over each element in this bin
-+  			for(RandomAccessIter current = *local_bin; current < nextbinstart; ++current) {
-+  				//Swapping elements in current into place until the correct element has been swapped in
-+  				for(target_bin = bins + static_cast<unsignedchar_type>((*current)[char_offset]);  target_bin != local_bin; 
-+  					target_bin = bins + static_cast<unsignedchar_type>((*current)[char_offset]))
-+  					iter_swap(current, (*target_bin)++);
-+  			}
-+  			*local_bin = nextbinstart;
-+  		}
-+  		bins[last_bin] = last;
-+  		//Recursing
-+  		RandomAccessIter lastPos = bin_cache[cache_offset];
-+  		//Skip this loop for empties
-+  		for(unsigned u = cache_offset + 1; u < cache_offset + last_bin + 2; lastPos = bin_cache[u], ++u) {
-+  			size_t count = bin_cache[u] - lastPos;
-+  			//don't sort unless there are at least two items to compare
-+  			if(count < 2)
-+  				continue;
-+  			//using std::sort if its worst-case is better
-+  			if(count < max_size)
-+  				std::sort(lastPos, bin_cache[u], offset_lessthan<data_type, unsignedchar_type>(char_offset + 1));
-+  			else
-+  				string_sort_rec<RandomAccessIter, data_type, unsignedchar_type>(lastPos, bin_cache[u], char_offset + 1, bin_cache, cache_end, bin_sizes);
-+  		}
-+  	}
-+
-+  	//Sorts strings in reverse order, with empties at the end
-+  	template <class RandomAccessIter, class data_type, class unsignedchar_type>
-+  	inline void 
-+  	reverse_string_sort_rec(RandomAccessIter first, RandomAccessIter last, unsigned char_offset, std::vector<RandomAccessIter> &bin_cache
-+  		, unsigned cache_offset, std::vector<size_t> &bin_sizes)
-+  	{
-+  		//This section is not strictly necessary, but makes handling of long identical substrings much faster, with a mild average performance impact.
-+  		RandomAccessIter curr = first;
-+  		//Iterate to the end of the empties.  If all empty, return
-+  		while((*curr).size() <= char_offset) {
-+  			if(++curr == last)
-+  				return;
-+  		}
-+  		//Getting the last non-empty
-+  		while((*(--last)).size() <= char_offset) { }
-+  		++last;
-+  		//Offsetting on identical characters.  This section works a character at a time for optimal worst-case performance.
-+  		update_offset(curr, last, char_offset);
-+  		RandomAccessIter * target_bin;
-+  		
-+  		const unsigned bin_count = (1 << (sizeof(unsignedchar_type)*8));
-+  		//Equal worst-case between radix and comparison-based is when bin_count = n*log(n).
-+  		const unsigned max_size = bin_count;
-+  		const unsigned membin_count = bin_count + 1;
-+  		const unsigned max_bin = bin_count - 1;
-+  		unsigned cache_end;
-+  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, membin_count);
-+  		RandomAccessIter * end_bin = &(bin_cache[cache_offset + max_bin]);
-+  			
-+  		//Calculating the size of each bin; this takes roughly 10% of runtime
-+  		for (RandomAccessIter current = first; current != last; ++current) {
-+  			if((*current).size() <= char_offset) {
-+  				bin_sizes[bin_count]++;
-+  			}
-+  			else
-+  				bin_sizes[max_bin - static_cast<unsignedchar_type>((*current)[char_offset])]++;
-+  		}
-+  		//Assign the bin positions
-+  		bin_cache[cache_offset] = first;
-+  		for(unsigned u = 0; u < membin_count - 1; u++)
-+  			bin_cache[cache_offset + u + 1] = bin_cache[cache_offset + u] + bin_sizes[u];
-+  		
-+  		//Swap into place
-+  		RandomAccessIter nextbinstart = last;
-+  		//handling empty bins
-+  		RandomAccessIter * local_bin = &(bin_cache[cache_offset + bin_count]);
-+  		RandomAccessIter lastFull = *local_bin;
-+  		//Iterating over each element in the bin of empties
-+  		for(RandomAccessIter current = *local_bin; current < nextbinstart; ++current) {
-+  			//empties belong in this bin
-+  			while((*current).size() > char_offset) {
-+  				target_bin = end_bin - static_cast<unsignedchar_type>((*current)[char_offset]);
-+  				iter_swap(current, (*target_bin)++);
-+  			}
-+  		}
-+  		*local_bin = nextbinstart;
-+  		nextbinstart = first;
-+  		//iterate backwards to find the last bin with elements in it; this saves iterations in multiple loops
-+  		unsigned last_bin = max_bin;
-+  		for(; last_bin && !bin_sizes[last_bin]; --last_bin) { }
-+  		//This dominates runtime, mostly in the swap and bin lookups
-+  		for(unsigned u = 0; u < last_bin; ++u) {
-+  			local_bin = bins + u;
-+  			nextbinstart += bin_sizes[u];
-+  			//Iterating over each element in this bin
-+  			for(RandomAccessIter current = *local_bin; current < nextbinstart; ++current) {
-+  				//Swapping elements in current into place until the correct element has been swapped in
-+  				for(target_bin = end_bin - static_cast<unsignedchar_type>((*current)[char_offset]);  target_bin != local_bin; 
-+  					target_bin = end_bin - static_cast<unsignedchar_type>((*current)[char_offset]))
-+  					iter_swap(current, (*target_bin)++);
-+  			}
-+  			*local_bin = nextbinstart;
-+  		}
-+  		bins[last_bin] = lastFull;
-+  		//Recursing
-+  		RandomAccessIter lastPos = first;
-+  		//Skip this loop for empties
-+  		for(unsigned u = cache_offset; u <= cache_offset + last_bin; lastPos = bin_cache[u], ++u) {
-+  			size_t count = bin_cache[u] - lastPos;
-+  			//don't sort unless there are at least two items to compare
-+  			if(count < 2)
-+  				continue;
-+  			//using std::sort if its worst-case is better
-+  			if(count < max_size)
-+  				std::sort(lastPos, bin_cache[u], offset_greaterthan<data_type, unsignedchar_type>(char_offset + 1));
-+  			else
-+  				reverse_string_sort_rec<RandomAccessIter, data_type, unsignedchar_type>(lastPos, bin_cache[u], char_offset + 1, bin_cache, cache_end, bin_sizes);
-+  		}
-+  	}
-+
-+  	//String sorting recursive implementation
-+  	template <class RandomAccessIter, class data_type, class unsignedchar_type, class get_char, class get_length>
-+  	inline void 
-+  	string_sort_rec(RandomAccessIter first, RandomAccessIter last, unsigned char_offset, std::vector<RandomAccessIter> &bin_cache
-+  		, unsigned cache_offset, std::vector<size_t> &bin_sizes, get_char getchar, get_length length)
-+  	{
-+  		//This section is not strictly necessary, but makes handling of long identical substrings much faster, with a mild average performance impact.
-+  		//Iterate to the end of the empties.  If all empty, return
-+  		while(length(*first) <= char_offset) {
-+  			if(++first == last)
-+  				return;
-+  		}
-+  		RandomAccessIter finish = last - 1;
-+  		//Getting the last non-empty
-+  		for(;length(*finish) <= char_offset; --finish) { }
-+  		++finish;
-+  		update_offset(first, finish, char_offset, getchar, length);
-+  		
-+  		const unsigned bin_count = (1 << (sizeof(unsignedchar_type)*8));
-+  		//Equal worst-case between radix and comparison-based is when bin_count = n*log(n).
-+  		const unsigned max_size = bin_count;
-+  		const unsigned membin_count = bin_count + 1;
-+  		unsigned cache_end;
-+  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, membin_count) + 1;
-+  			
-+  		//Calculating the size of each bin; this takes roughly 10% of runtime
-+  		for (RandomAccessIter current = first; current != last; ++current) {
-+  			if(length(*current) <= char_offset) {
-+  				bin_sizes[0]++;
-+  			}
-+  			else
-+  				bin_sizes[getchar((*current), char_offset) + 1]++;
-+  		}
-+  		//Assign the bin positions
-+  		bin_cache[cache_offset] = first;
-+  		for(unsigned u = 0; u < membin_count - 1; u++)
-+  			bin_cache[cache_offset + u + 1] = bin_cache[cache_offset + u] + bin_sizes[u];
-+  		
-+  		//Swap into place
-+  		RandomAccessIter nextbinstart = first;
-+  		//handling empty bins
-+  		RandomAccessIter * local_bin = &(bin_cache[cache_offset]);
-+  		nextbinstart +=	bin_sizes[0];
-+  		RandomAccessIter * target_bin;
-+  		//Iterating over each element in the bin of empties
-+  		for(RandomAccessIter current = *local_bin; current < nextbinstart; ++current) {
-+  			//empties belong in this bin
-+  			while(length(*current) > char_offset) {
-+  				target_bin = bins + getchar((*current), char_offset);
-+  				iter_swap(current, (*target_bin)++);
-+  			}
-+  		}
-+  		*local_bin = nextbinstart;
-+  		//iterate backwards to find the last bin with elements in it; this saves iterations in multiple loops
-+  		unsigned last_bin = bin_count - 1;
-+  		for(; last_bin && !bin_sizes[last_bin + 1]; --last_bin) { }
-+  		//This dominates runtime, mostly in the swap and bin lookups
-+  		for(unsigned ii = 0; ii < last_bin; ++ii) {
-+  			local_bin = bins + ii;
-+  			nextbinstart += bin_sizes[ii + 1];
-+  			//Iterating over each element in this bin
-+  			for(RandomAccessIter current = *local_bin; current < nextbinstart; ++current) {
-+  				//Swapping elements in current into place until the correct element has been swapped in
-+  				for(target_bin = bins + getchar((*current), char_offset);  target_bin != local_bin; 
-+  					target_bin = bins + getchar((*current), char_offset))
-+  					iter_swap(current, (*target_bin)++);
-+  			}
-+  			*local_bin = nextbinstart;
-+  		}
-+  		bins[last_bin] = last;
-+  		
-+  		//Recursing
-+  		RandomAccessIter lastPos = bin_cache[cache_offset];
-+  		//Skip this loop for empties
-+  		for(unsigned u = cache_offset + 1; u < cache_offset + last_bin + 2; lastPos = bin_cache[u], ++u) {
-+  			size_t count = bin_cache[u] - lastPos;
-+  			//don't sort unless there are at least two items to compare
-+  			if(count < 2)
-+  				continue;
-+  			//using std::sort if its worst-case is better
-+  			if(count < max_size)
-+  				std::sort(lastPos, bin_cache[u], offset_char_lessthan<data_type, get_char, get_length>(char_offset + 1));
-+  			else
-+  				string_sort_rec<RandomAccessIter, data_type, unsignedchar_type, get_char, get_length>(lastPos, bin_cache[u], char_offset + 1, bin_cache, cache_end, bin_sizes, getchar, length);
-+  		}
-+  	}
-+
-+  	//String sorting recursive implementation
-+  	template <class RandomAccessIter, class data_type, class unsignedchar_type, class get_char, class get_length, class compare>
-+  	inline void 
-+  	string_sort_rec(RandomAccessIter first, RandomAccessIter last, unsigned char_offset, std::vector<RandomAccessIter> &bin_cache
-+  		, unsigned cache_offset, std::vector<size_t> &bin_sizes, get_char getchar, get_length length, compare comp)
-+  	{
-+  		//This section is not strictly necessary, but makes handling of long identical substrings much faster, with a mild average performance impact.
-+  		//Iterate to the end of the empties.  If all empty, return
-+  		while(length(*first) <= char_offset) {
-+  			if(++first == last)
-+  				return;
-+  		}
-+  		RandomAccessIter finish = last - 1;
-+  		//Getting the last non-empty
-+  		for(;length(*finish) <= char_offset; --finish) { }
-+  		++finish;
-+  		update_offset(first, finish, char_offset, getchar, length);
-+  		
-+  		const unsigned bin_count = (1 << (sizeof(unsignedchar_type)*8));
-+  		//Equal worst-case between radix and comparison-based is when bin_count = n*log(n).
-+  		const unsigned max_size = bin_count;
-+  		const unsigned membin_count = bin_count + 1;
-+  		unsigned cache_end;
-+  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, membin_count) + 1;
-+  			
-+  		//Calculating the size of each bin; this takes roughly 10% of runtime
-+  		for (RandomAccessIter current = first; current != last; ++current) {
-+  			if(length(*current) <= char_offset) {
-+  				bin_sizes[0]++;
-+  			}
-+  			else
-+  				bin_sizes[getchar((*current), char_offset) + 1]++;
-+  		}
-+  		//Assign the bin positions
-+  		bin_cache[cache_offset] = first;
-+  		for(unsigned u = 0; u < membin_count - 1; u++)
-+  			bin_cache[cache_offset + u + 1] = bin_cache[cache_offset + u] + bin_sizes[u];
-+  		
-+  		//Swap into place
-+  		RandomAccessIter nextbinstart = first;
-+  		//handling empty bins
-+  		RandomAccessIter * local_bin = &(bin_cache[cache_offset]);
-+  		nextbinstart +=	bin_sizes[0];
-+  		RandomAccessIter * target_bin;
-+  		//Iterating over each element in the bin of empties
-+  		for(RandomAccessIter current = *local_bin; current < nextbinstart; ++current) {
-+  			//empties belong in this bin
-+  			while(length(*current) > char_offset) {
-+  				target_bin = bins + getchar((*current), char_offset);
-+  				iter_swap(current, (*target_bin)++);
-+  			}
-+  		}
-+  		*local_bin = nextbinstart;
-+  		//iterate backwards to find the last bin with elements in it; this saves iterations in multiple loops
-+  		unsigned last_bin = bin_count - 1;
-+  		for(; last_bin && !bin_sizes[last_bin + 1]; --last_bin) { }
-+  		//This dominates runtime, mostly in the swap and bin lookups
-+  		for(unsigned u = 0; u < last_bin; ++u) {
-+  			local_bin = bins + u;
-+  			nextbinstart += bin_sizes[u + 1];
-+  			//Iterating over each element in this bin
-+  			for(RandomAccessIter current = *local_bin; current < nextbinstart; ++current) {
-+  				//Swapping elements in current into place until the correct element has been swapped in
-+  				for(target_bin = bins + getchar((*current), char_offset);  target_bin != local_bin; 
-+  					target_bin = bins + getchar((*current), char_offset))
-+  					iter_swap(current, (*target_bin)++);
-+  			}
-+  			*local_bin = nextbinstart;
-+  		}
-+  		bins[last_bin] = last;
-+  		
-+  		//Recursing
-+  		RandomAccessIter lastPos = bin_cache[cache_offset];
-+  		//Skip this loop for empties
-+  		for(unsigned u = cache_offset + 1; u < cache_offset + last_bin + 2; lastPos = bin_cache[u], ++u) {
-+  			size_t count = bin_cache[u] - lastPos;
-+  			//don't sort unless there are at least two items to compare
-+  			if(count < 2)
-+  				continue;
-+  			//using std::sort if its worst-case is better
-+  			if(count < max_size)
-+  				std::sort(lastPos, bin_cache[u], comp);
-+  			else
-+  				string_sort_rec<RandomAccessIter, data_type, unsignedchar_type, get_char, get_length, compare>(lastPos
-+  					, bin_cache[u], char_offset + 1, bin_cache, cache_end, bin_sizes, getchar, length, comp);
-+  		}
-+  	}
-+
-+  	//Sorts strings in reverse order, with empties at the end
-+  	template <class RandomAccessIter, class data_type, class unsignedchar_type, class get_char, class get_length, class compare>
-+  	inline void 
-+  	reverse_string_sort_rec(RandomAccessIter first, RandomAccessIter last, unsigned char_offset, std::vector<RandomAccessIter> &bin_cache
-+  		, unsigned cache_offset, std::vector<size_t> &bin_sizes, get_char getchar, get_length length, compare comp)
-+  	{
-+  		//This section is not strictly necessary, but makes handling of long identical substrings much faster, with a mild average performance impact.
-+  		RandomAccessIter curr = first;
-+  		//Iterate to the end of the empties.  If all empty, return
-+  		while(length(*curr) <= char_offset) {
-+  			if(++curr == last)
-+  				return;
-+  		}
-+  		//Getting the last non-empty
-+  		while(length(*(--last)) <= char_offset) { }
-+  		++last;
-+  		//Offsetting on identical characters.  This section works a character at a time for optimal worst-case performance.
-+  		update_offset(first, last, char_offset, getchar, length);
-+  		
-+  		const unsigned bin_count = (1 << (sizeof(unsignedchar_type)*8));
-+  		//Equal worst-case between radix and comparison-based is when bin_count = n*log(n).
-+  		const unsigned max_size = bin_count;
-+  		const unsigned membin_count = bin_count + 1;
-+  		const unsigned max_bin = bin_count - 1;
-+  		unsigned cache_end;
-+  		RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset, cache_end, membin_count);
-+  		RandomAccessIter *end_bin = &(bin_cache[cache_offset + max_bin]);
-+  			
-+  		//Calculating the size of each bin; this takes roughly 10% of runtime
-+  		for (RandomAccessIter current = first; current != last; ++current) {
-+  			if(length(*current) <= char_offset) {
-+  				bin_sizes[bin_count]++;
-+  			}
-+  			else
-+  				bin_sizes[max_bin - getchar((*current), char_offset)]++;
-+  		}
-+  		//Assign the bin positions
-+  		bin_cache[cache_offset] = first;
-+  		for(unsigned u = 0; u < membin_count - 1; u++)
-+  			bin_cache[cache_offset + u + 1] = bin_cache[cache_offset + u] + bin_sizes[u];
-+  		
-+  		//Swap into place
-+  		RandomAccessIter nextbinstart = last;
-+  		//handling empty bins
-+  		RandomAccessIter * local_bin = &(bin_cache[cache_offset + bin_count]);
-+  		RandomAccessIter lastFull = *local_bin;
-+  		RandomAccessIter * target_bin;
-+  		//Iterating over each element in the bin of empties
-+  		for(RandomAccessIter current = *local_bin; current < nextbinstart; ++current) {
-+  			//empties belong in this bin
-+  			while(length(*current) > char_offset) {
-+  				target_bin = end_bin - getchar((*current), char_offset);
-+  				iter_swap(current, (*target_bin)++);
-+  			}
-+  		}
-+  		*local_bin = nextbinstart;
-+  		nextbinstart = first;
-+  		//iterate backwards to find the last bin with elements in it; this saves iterations in multiple loops
-+  		unsigned last_bin = max_bin;
-+  		for(; last_bin && !bin_sizes[last_bin]; --last_bin) { }
-+  		//This dominates runtime, mostly in the swap and bin lookups
-+  		for(unsigned u = 0; u < last_bin; ++u) {
-+  			local_bin = bins + u;
-+  			nextbinstart += bin_sizes[u];
-+  			//Iterating over each element in this bin
-+  			for(RandomAccessIter current = *local_bin; current < nextbinstart; ++current) {
-+  				//Swapping elements in current into place until the correct element has been swapped in
-+  				for(target_bin = end_bin - getchar((*current), char_offset);  target_bin != local_bin; 
-+  					target_bin = end_bin - getchar((*current), char_offset))
-+  					iter_swap(current, (*target_bin)++);
-+  			}
-+  			*local_bin = nextbinstart;
-+  		}
-+  		bins[last_bin] = lastFull;
-+  		//Recursing
-+  		RandomAccessIter lastPos = first;
-+  		//Skip this loop for empties
-+  		for(unsigned u = cache_offset; u <= cache_offset + last_bin; lastPos = bin_cache[u], ++u) {
-+  			size_t count = bin_cache[u] - lastPos;
-+  			//don't sort unless there are at least two items to compare
-+  			if(count < 2)
-+  				continue;
-+  			//using std::sort if its worst-case is better
-+  			if(count < max_size)
-+  				std::sort(lastPos, bin_cache[u], comp);
-+  			else
-+  				reverse_string_sort_rec<RandomAccessIter, data_type, unsignedchar_type, get_char, get_length, compare>(lastPos
-+  					, bin_cache[u], char_offset + 1, bin_cache, cache_end, bin_sizes, getchar, length, comp);
-+  		}
-+  	}
-+
-+  	//Holds the bin vector and makes the initial recursive call
-+  	template <class RandomAccessIter, class data_type, class unsignedchar_type>
-+  	inline void 
-+  	string_sort(RandomAccessIter first, RandomAccessIter last, data_type, unsignedchar_type)
-+  	{
-+  		std::vector<size_t> bin_sizes;
-+  		std::vector<RandomAccessIter> bin_cache;
-+  		string_sort_rec<RandomAccessIter, data_type, unsignedchar_type>(first, last, 0, bin_cache, 0, bin_sizes);
-+  	}
-+
-+  	//Holds the bin vector and makes the initial recursive call
-+  	template <class RandomAccessIter, class data_type, class unsignedchar_type>
-+  	inline void 
-+  	reverse_string_sort(RandomAccessIter first, RandomAccessIter last, data_type, unsignedchar_type)
-+  	{
-+  		std::vector<size_t> bin_sizes;
-+  		std::vector<RandomAccessIter> bin_cache;
-+  		reverse_string_sort_rec<RandomAccessIter, data_type, unsignedchar_type>(first, last, 0, bin_cache, 0, bin_sizes);
-+  	}
-+
-+  	//Holds the bin vector and makes the initial recursive call
-+  	template <class RandomAccessIter, class get_char, class get_length, class data_type, class unsignedchar_type>
-+  	inline void 
-+  	string_sort(RandomAccessIter first, RandomAccessIter last, get_char getchar, get_length length, data_type, unsignedchar_type)
-+  	{
-+  		std::vector<size_t> bin_sizes;
-+  		std::vector<RandomAccessIter> bin_cache;
-+  		string_sort_rec<RandomAccessIter, data_type, unsignedchar_type, get_char, get_length>(first, last, 0, bin_cache, 0, bin_sizes, getchar, length);
-+  	}
-+
-+  	//Holds the bin vector and makes the initial recursive call
-+  	template <class RandomAccessIter, class get_char, class get_length, class compare, class data_type, class unsignedchar_type>
-+  	inline void 
-+  	string_sort(RandomAccessIter first, RandomAccessIter last, get_char getchar, get_length length, compare comp, data_type, unsignedchar_type)
-+  	{
-+  		std::vector<size_t> bin_sizes;
-+  		std::vector<RandomAccessIter> bin_cache;
-+  		string_sort_rec<RandomAccessIter, data_type, unsignedchar_type, get_char, get_length, compare>(first, last, 0, bin_cache, 0, bin_sizes, getchar, length, comp);
-+  	}
-+
-+  	//Holds the bin vector and makes the initial recursive call
-+  	template <class RandomAccessIter, class get_char, class get_length, class compare, class data_type, class unsignedchar_type>
-+  	inline void 
-+  	reverse_string_sort(RandomAccessIter first, RandomAccessIter last, get_char getchar, get_length length, compare comp, data_type, unsignedchar_type)
-+  	{
-+  		std::vector<size_t> bin_sizes;
-+  		std::vector<RandomAccessIter> bin_cache;
-+  		reverse_string_sort_rec<RandomAccessIter, data_type, unsignedchar_type, get_char, get_length, compare>(first, last, 0, bin_cache, 0, bin_sizes, getchar, length, comp);
-+  	}
-+  }
-+
-+  //Allows character-type overloads
-+  template <class RandomAccessIter, class unsignedchar_type>
-+  inline void string_sort(RandomAccessIter first, RandomAccessIter last, unsignedchar_type unused) 
-+  {
-+  	//Don't sort if it's too small to optimize
-+  	if(last - first < detail::MIN_SORT_SIZE)
-+  		std::sort(first, last);
-+  	else
-+  		detail::string_sort(first, last, *first, unused);
-+  }
-+
-+  //Top-level sorting call; wraps using default of unsigned char
-+  template <class RandomAccessIter>
-+  inline void string_sort(RandomAccessIter first, RandomAccessIter last) 
-+  {
-+  	unsigned char unused = '\0';
-+  	string_sort(first, last, unused);
-+  }
-+
-+  //Allows character-type overloads
-+  template <class RandomAccessIter, class compare, class unsignedchar_type>
-+  inline void reverse_string_sort(RandomAccessIter first, RandomAccessIter last, compare comp, unsignedchar_type unused) 
-+  {
-+  	//Don't sort if it's too small to optimize
-+  	if(last - first < detail::MIN_SORT_SIZE)
-+  		std::sort(first, last, comp);
-+  	else
-+  		detail::reverse_string_sort(first, last, *first, unused);
-+  }
-+
-+  //Top-level sorting call; wraps using default of unsigned char
-+  template <class RandomAccessIter, class compare>
-+  inline void reverse_string_sort(RandomAccessIter first, RandomAccessIter last, compare comp) 
-+  {
-+  	unsigned char unused = '\0';
-+  	reverse_string_sort(first, last, comp, unused);
-+  }
-+
-+  template <class RandomAccessIter, class get_char, class get_length>
-+  inline void string_sort(RandomAccessIter first, RandomAccessIter last, get_char getchar, get_length length) 
-+  {
-+  	//Don't sort if it's too small to optimize
-+  	if(last - first < detail::MIN_SORT_SIZE)
-+  		std::sort(first, last);
-+  	else {
-+  		//skipping past empties at the beginning, which allows us to get the character type 
-+  		//.empty() is not used so as not to require a user declaration of it
-+  		while(!length(*first)) {
-+  			if(++first == last)
-+  				return;
-+  		}
-+  		detail::string_sort(first, last, getchar, length, *first, getchar((*first), 0));
-+  	}
-+  }
-+
-+  template <class RandomAccessIter, class get_char, class get_length, class compare>
-+  inline void string_sort(RandomAccessIter first, RandomAccessIter last, get_char getchar, get_length length, compare comp) 
-+  {
-+  	//Don't sort if it's too small to optimize
-+  	if(last - first < detail::MIN_SORT_SIZE)
-+  		std::sort(first, last, comp);
-+  	else {
-+  		//skipping past empties at the beginning, which allows us to get the character type 
-+  		//.empty() is not used so as not to require a user declaration of it
-+  		while(!length(*first)) {
-+  			if(++first == last)
-+  				return;
-+  		}
-+  		detail::string_sort(first, last, getchar, length, comp, *first, getchar((*first), 0));
-+  	}
-+  }
-+
-+  template <class RandomAccessIter, class get_char, class get_length, class compare>
-+  inline void reverse_string_sort(RandomAccessIter first, RandomAccessIter last, get_char getchar, get_length length, compare comp) 
-+  {
-+  	//Don't sort if it's too small to optimize
-+  	if(last - first < detail::MIN_SORT_SIZE)
-+  		std::sort(first, last, comp);
-+  	else {
-+  		//skipping past empties at the beginning, which allows us to get the character type 
-+  		//.empty() is not used so as not to require a user declaration of it
-+  		while(!length(*(--last))) {
-+  			//Note: if there is just one non-empty, and it's at the beginning, then it's already in sorted order
-+  			if(first == last)
-+  				return;
-+  		}
-+  		//making last just after the end of the non-empty part of the array
-+  		++last;
-+  		detail::reverse_string_sort(first, last, getchar, length, comp, *first, getchar((*first), 0));
-+  	}
-+  }
-+}
-+
-+#endif

+ 0 - 15
package/firefox/patches/patch-netwerk_sctp_src_netinet_sctp_bsd_addr_c

@@ -1,15 +0,0 @@
---- mozilla-release.orig/netwerk/sctp/src/netinet/sctp_bsd_addr.c	2013-09-11 01:15:20.000000000 +0200
-+++ mozilla-release/netwerk/sctp/src/netinet/sctp_bsd_addr.c	2013-10-23 16:28:38.000000000 +0200
-@@ -49,11 +49,10 @@ __FBSDID("$FreeBSD: head/sys/netinet/sct
- #include <netinet/sctp_sysctl.h>
- #include <netinet/sctp_indata.h>
- #if !defined(__Userspace_os_Windows)
-+#include <unistd.h>
- #if defined(ANDROID)
- #include <unistd.h>
- #include <ifaddrs-android-ext.h>
--#else
--#include <sys/unistd.h>
- #endif
- #endif
- 

+ 0 - 22
package/firefox/patches/patch-netwerk_sctp_src_netinet_sctp_os_userspace_h

@@ -1,22 +0,0 @@
---- mozilla-release.orig/netwerk/sctp/src/netinet/sctp_os_userspace.h	2013-09-11 01:15:20.000000000 +0200
-+++ mozilla-release/netwerk/sctp/src/netinet/sctp_os_userspace.h	2013-10-23 16:28:38.000000000 +0200
-@@ -381,9 +381,8 @@ struct udphdr {
- };
- 
- #else /* !defined(Userspace_os_Windows) */
--#include <sys/cdefs.h> /* needed? added from old __FreeBSD__ */
- #include <sys/socket.h>
--#if defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_OpenBSD) || defined(ANDROID)
-+#if defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_OpenBSD) || defined(ANDROID) || 1
- #include <pthread.h>
- #endif
- typedef pthread_mutex_t userland_mutex_t;
-@@ -406,7 +405,7 @@ struct sx {int dummy;};
- /* #include <sys/param.h>  in FreeBSD defines MSIZE */
- /* #include <sys/ktr.h> */
- /* #include <sys/systm.h> */
--#if defined(__Userspace_os_Windows)
-+#if defined(__Userspace_os_Windows) || 1
- #include <user_queue.h>
- #else
- #include <sys/queue.h>

+ 0 - 25
package/firefox/patches/patch-netwerk_sctp_src_netinet_sctp_pcb_c

@@ -1,25 +0,0 @@
---- mozilla-release.orig/netwerk/sctp/src/netinet/sctp_pcb.c	2013-09-11 01:15:20.000000000 +0200
-+++ mozilla-release/netwerk/sctp/src/netinet/sctp_pcb.c	2013-10-23 16:28:38.000000000 +0200
-@@ -30,6 +30,8 @@
-  * THE POSSIBILITY OF SUCH DAMAGE.
-  */
- 
-+#define _BSD_SOURCE /* for IPPORT_RESERVED */
-+
- #ifdef __FreeBSD__
- #include <sys/cdefs.h>
- __FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.c 246687 2013-02-11 21:02:49Z tuexen $");
-@@ -69,11 +71,10 @@ __FBSDID("$FreeBSD: head/sys/netinet/sct
- #endif
- #if defined(__Userspace__)
- #if !defined(__Userspace_os_Windows)
--#if defined(ANDROID)
-+#include <netdb.h>
- #include <unistd.h>
-+#if defined(ANDROID)
- #include <ifaddrs-android-ext.h>
--#else
--#include <sys/unistd.h>
- #endif
- #endif
- #include <user_socketvar.h>

+ 0 - 14
package/firefox/patches/patch-netwerk_sctp_src_user_environment_c

@@ -1,14 +0,0 @@
---- mozilla-release.orig/netwerk/sctp/src/user_environment.c	2013-12-05 17:07:52.000000000 +0100
-+++ mozilla-release/netwerk/sctp/src/user_environment.c	2014-03-16 17:53:08.000000000 +0100
-@@ -35,9 +35,11 @@
- #include <stdint.h>
- #if !defined(__Userspace_os_FreeBSD)
- #if !defined(ANDROID)
-+#if defined(__GLIBC__)
- #include <sys/sysctl.h>
- #endif
- #endif
-+#endif
- #include <netinet/sctp_os_userspace.h>
- #endif
- #include <user_environment.h>

+ 0 - 12
package/firefox/patches/patch-netwerk_sctp_src_user_queue_h

@@ -1,12 +0,0 @@
---- mozilla-release.orig/netwerk/sctp/src/user_queue.h	2013-09-11 01:15:20.000000000 +0200
-+++ mozilla-release/netwerk/sctp/src/user_queue.h	2013-10-23 16:28:38.000000000 +0200
-@@ -31,9 +31,6 @@
- #ifndef _USER_QUEUE_H_
- #define	_USER_QUEUE_H_
- 
--#if !defined (__Userspace_os_Windows)
--#include <sys/cdefs.h>
--#endif
- /*
-  * This file defines four types of data structures: singly-linked lists,
-  * singly-linked tail queues, lists and tail queues.

+ 5 - 5
package/firefox/patches/patch-python_mozbuild_mozbuild_backend_recursivemake_py

@@ -1,11 +1,11 @@
---- mozilla-release.orig/python/mozbuild/mozbuild/backend/recursivemake.py	2013-12-05 17:07:53.000000000 +0100
-+++ mozilla-release/python/mozbuild/mozbuild/backend/recursivemake.py	2014-01-04 17:58:26.000000000 +0100
-@@ -421,7 +421,7 @@ class RecursiveMakeBackend(CommonBackend
+--- mozilla-release.orig/python/mozbuild/mozbuild/backend/recursivemake.py	2015-01-09 05:38:28.000000000 +0100
++++ mozilla-release/python/mozbuild/mozbuild/backend/recursivemake.py	2015-01-29 16:46:28.000000000 +0100
+@@ -940,7 +940,7 @@ INSTALL_TARGETS += %(prefix)s
      def _handle_idl_manager(self, manager):
-         build_files = self._purge_manifests['xpidl']
+         build_files = self._install_manifests['xpidl']
  
 -        for p in ('Makefile', 'backend.mk', '.deps/.mkdir.done',
 +        for p in ('Makefile.in', 'Makefile', 'backend.mk', '.deps/.mkdir.done',
              'xpt/.mkdir.done'):
-             build_files.add(p)
+             build_files.add_optional_exists(p)
  

+ 6 - 6
package/firefox/patches/patch-tools_profiler_platform-linux_cc

@@ -1,6 +1,6 @@
---- mozilla-release.orig/tools/profiler/platform-linux.cc	2013-12-05 17:07:58.000000000 +0100
-+++ mozilla-release/tools/profiler/platform-linux.cc	2014-01-02 14:59:20.000000000 +0100
-@@ -58,7 +58,7 @@
+--- mozilla-release.orig/tools/profiler/platform-linux.cc	2015-01-09 05:38:28.000000000 +0100
++++ mozilla-release/tools/profiler/platform-linux.cc	2015-01-29 16:46:28.000000000 +0100
+@@ -57,7 +57,7 @@
  #include <fcntl.h>      // open
  #include <unistd.h>     // sysconf
  #include <semaphore.h>
@@ -9,7 +9,7 @@
  #include <execinfo.h>   // backtrace, backtrace_symbols
  #endif  // def __GLIBC__
  #include <strings.h>    // index
-@@ -84,14 +84,12 @@
+@@ -92,14 +92,12 @@
  
  #define SIGNAL_SAVE_PROFILE SIGUSR2
  
@@ -23,5 +23,5 @@
  }
 -#endif
  
- #if !defined(ANDROID)
- // Keep track of when any of our threads calls fork(), so we can
+ /* static */ Thread::tid_t
+ Thread::GetCurrentId()

+ 0 - 11
package/firefox/patches/patch-tools_profiler_shared-libraries-linux_cc

@@ -1,11 +0,0 @@
---- mozilla-release.orig/tools/profiler/shared-libraries-linux.cc	2013-12-05 17:07:58.000000000 +0100
-+++ mozilla-release/tools/profiler/shared-libraries-linux.cc	2014-01-02 15:00:00.000000000 +0100
-@@ -14,7 +14,7 @@
- #include "platform.h"
- #include "shared-libraries.h"
- 
--#if !defined(__GLIBC__) && ANDROID_VERSION < 18
-+#if 0
- /* a crapy version of getline, because it's not included in old bionics */
- static ssize_t getline(char **lineptr, size_t *n, FILE *stream)
- {

+ 11 - 11
package/firefox/patches/patch-xpcom_ds_nsMathUtils_h

@@ -1,20 +1,20 @@
---- mozilla-release.orig/xpcom/ds/nsMathUtils.h	2013-09-11 01:15:27.000000000 +0200
-+++ mozilla-release/xpcom/ds/nsMathUtils.h	2013-10-23 16:28:38.000000000 +0200
-@@ -98,12 +98,16 @@ inline NS_HIDDEN_(bool) NS_finite(double
+--- mozilla-release.orig/xpcom/ds/nsMathUtils.h	2015-01-09 05:38:29.000000000 +0100
++++ mozilla-release/xpcom/ds/nsMathUtils.h	2015-01-29 21:37:27.000000000 +0100
+@@ -104,12 +104,16 @@ NS_finite(double aNum)
  #ifdef WIN32
-     // NOTE: '!!' casts an int to bool without spamming MSVC warning C4800.
-     return !!_finite(d);
+   // NOTE: '!!' casts an int to bool without spamming MSVC warning C4800.
+   return !!_finite(aNum);
 -#elif defined(XP_DARWIN)
 +#elif defined(XP_DARWIN) || defined(__UCLIBC__)
-     // Darwin has deprecated |finite| and recommends |isfinite|. The former is
-     // not present in the iOS SDK.
-     return std::isfinite(d);
+   // Darwin has deprecated |finite| and recommends |isfinite|. The former is
+   // not present in the iOS SDK.
+   return std::isfinite(aNum);
  #else
--    return finite(d);
+-  return finite(aNum);
 +#ifdef _GLIBCXX_CMATH
-+    return std::isfinite(d);
++  return std::isfinite(d);
 +#else
-+    return isfinite(d);
++  return isfinite(d);
 +#endif
  #endif
  }

+ 18 - 13
package/firefox/patches/patch-xpcom_io_nsLocalFileUnix_cpp

@@ -1,16 +1,21 @@
---- mozilla-release.orig/xpcom/io/nsLocalFileUnix.cpp	2013-12-05 17:08:00.000000000 +0100
-+++ mozilla-release/xpcom/io/nsLocalFileUnix.cpp	2014-01-02 14:53:47.000000000 +0100
-@@ -1234,8 +1234,13 @@ nsLocalFile::GetDiskSpaceAvailable(int64
-        && dq.dqb_bhardlimit)
-     {
-         int64_t QuotaSpaceAvailable = 0;
+--- mozilla-release.orig/xpcom/io/nsLocalFileUnix.cpp	2015-01-09 05:38:29.000000000 +0100
++++ mozilla-release/xpcom/io/nsLocalFileUnix.cpp	2015-01-30 14:13:49.000000000 +0100
+@@ -1407,10 +1407,18 @@ nsLocalFile::GetDiskSpaceAvailable(int64
+ #endif
+       && dq.dqb_bhardlimit) {
+     int64_t QuotaSpaceAvailable = 0;
 +#if defined(__UCLIBC__)
-+	if (dq.dqb_bhardlimit > dq.dqb_curblocks)
-+	    QuotaSpaceAvailable = PRInt64(fs_buf.f_bsize * (dq.dqb_bhardlimit - dq.dqb_curblocks));
++    if (dq.dqb_bhardlimit > dq.dqb_curblocks) {
++      QuotaSpaceAvailable =
++        int64_t(fs_buf.F_BSIZE * (dq.dqb_bhardlimit - dq.dqb_curblocks));
++    }
 +#else
-         if (dq.dqb_bhardlimit > dq.dqb_curspace)
-             QuotaSpaceAvailable = int64_t(fs_buf.F_BSIZE * (dq.dqb_bhardlimit - dq.dqb_curspace));
+     if (dq.dqb_bhardlimit > dq.dqb_curspace) {
+       QuotaSpaceAvailable =
+         int64_t(fs_buf.F_BSIZE * (dq.dqb_bhardlimit - dq.dqb_curspace));
+     }
 +#endif
-         if(QuotaSpaceAvailable < *aDiskSpaceAvailable) {
-             *aDiskSpaceAvailable = QuotaSpaceAvailable;
-         }
++
+     if (QuotaSpaceAvailable < *aDiskSpaceAvailable) {
+       *aDiskSpaceAvailable = QuotaSpaceAvailable;
+     }

+ 0 - 17
package/firefox/patches/patch-xpcom_threads_nsThread_cpp

@@ -1,17 +0,0 @@
---- mozilla-release.orig/xpcom/threads/nsThread.cpp	2013-12-05 17:08:00.000000000 +0100
-+++ mozilla-release/xpcom/threads/nsThread.cpp	2014-01-02 14:53:47.000000000 +0100
-@@ -23,11 +23,13 @@
-                       _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) &&           \
-                       !(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)
- 
-+#include <features.h>
- #if defined(XP_UNIX) && !defined(ANDROID) && !defined(DEBUG) && HAVE_UALARM \
-   && defined(_GNU_SOURCE)
--# define MOZ_CANARY
- # include <unistd.h>
-+#if !defined(__UCLIBC__)
- # include <execinfo.h>
-+#endif
- # include <signal.h>
- # include <fcntl.h>
- # include "nsXULAppAPI.h"

+ 5 - 5
package/nss/Makefile

@@ -4,12 +4,12 @@
 include $(ADK_TOPDIR)/rules.mk
 
 PKG_NAME:=		nss
-PKG_VERSION:=		3.16.1
-PKG_RELEASE:=		2
+PKG_VERSION:=		3.17.4
+PKG_RELEASE:=		1
 PKG_MAJ_VERSION:=	3
-PKG_MIN_VERSION:=	16
-PKG_PATCH_VERSION:=	1
-PKG_HASH:=		fab750f7d34c09cf34df25da1924a9a8f4c7f1768e2d456f8be767ecbbe84a6e
+PKG_MIN_VERSION:=	17
+PKG_PATCH_VERSION:=	4
+PKG_HASH:=		1d98ad1881a4237ec98cbe472fc851480f0b0e954dfe224d047811fb96ff9d79
 PKG_DESCR:=		network security services library
 PKG_SECTION:=		libs/crypto
 PKG_BUILDDEP:=		nspr zlib sqlite

+ 3 - 3
package/nss/patches/patch-nss_coreconf_Linux_mk

@@ -1,5 +1,5 @@
---- nss-3.16.1.orig/nss/coreconf/Linux.mk	2014-05-02 05:27:18.000000000 +0200
-+++ nss-3.16.1/nss/coreconf/Linux.mk	2014-06-19 14:09:55.000000000 +0200
+--- nss-3.17.4.orig/nss/coreconf/Linux.mk	2015-01-22 20:49:26.000000000 +0100
++++ nss-3.17.4/nss/coreconf/Linux.mk	2015-01-29 15:49:15.000000000 +0100
 @@ -16,9 +16,9 @@ ifeq ($(USE_PTHREADS),1)
  	IMPL_STRATEGY = _PTH
  endif
@@ -13,7 +13,7 @@
  
  DEFAULT_COMPILER = gcc
  
-@@ -146,7 +146,7 @@ DSO_LDOPTS		= -shared $(ARCHFLAG)
+@@ -146,7 +146,7 @@ DSO_LDOPTS		= -shared $(ARCHFLAG) -Wl,--
  # we don't use -z defs there.
  ZDEFS_FLAG		= -Wl,-z,defs
  DSO_LDOPTS		+= $(if $(findstring 2.11.90.0.8,$(shell ld -v)),,$(ZDEFS_FLAG))

+ 3 - 3
package/nss/patches/patch-nss_coreconf_command_mk

@@ -1,6 +1,6 @@
---- nss-3.15.2.orig/nss/coreconf/command.mk	2013-09-25 15:57:55.000000000 +0200
-+++ nss-3.15.2/nss/coreconf/command.mk	2013-09-27 19:07:39.000000000 +0200
-@@ -16,7 +16,7 @@ LINK_EXE      = $(LINK) $(OS_LFLAGS) $(L
+--- nss-3.17.4.orig/nss/coreconf/command.mk	2015-01-22 20:49:26.000000000 +0100
++++ nss-3.17.4/nss/coreconf/command.mk	2015-01-29 15:49:15.000000000 +0100
+@@ -15,7 +15,7 @@ LINK_DLL      = $(LINK) $(OS_DLLFLAGS) $
  CFLAGS        = $(OPTIMIZER) $(OS_CFLAGS) $(XP_DEFINE) $(DEFINES) $(INCLUDES) \
  		$(XCFLAGS)
  PERL          = perl

+ 6 - 3
package/nss/patches/patch-nss_manifest_mn

@@ -1,8 +1,11 @@
---- nss-3.15.2.orig/nss/manifest.mn	2013-09-25 15:57:55.000000000 +0200
-+++ nss-3.15.2/nss/manifest.mn	2013-09-30 16:02:15.000000000 +0200
-@@ -10,4 +10,4 @@ IMPORTS =	nspr20/v4.8 \
+--- nss-3.17.4.orig/nss/manifest.mn	2015-01-22 20:49:26.000000000 +0100
++++ nss-3.17.4/nss/manifest.mn	2015-01-29 15:57:46.000000000 +0100
+@@ -10,7 +10,7 @@ IMPORTS =	nspr20/v4.8 \
  
  RELEASE = nss
  
 -DIRS = coreconf lib cmd
 +DIRS = coreconf lib cmd config
+ 
+ ifdef NSS_BUILD_GTESTS
+ DIRS += external_tests

+ 3 - 3
package/python2/Makefile

@@ -5,12 +5,12 @@ include ${ADK_TOPDIR}/rules.mk
 
 PKG_NAME:=		python2
 PKG_VERSION:=		2.7.5
-PKG_RELEASE:=		12
+PKG_RELEASE:=		13
 PKG_HASH:=		8e1b5fa87b91835afb376a9c0d319d41feca07ffebc0288d97ab08d64f48afbf
 PKG_DESCR:=		python scripting language (Version 2)
 PKG_SECTION:=		dev/lang
 PKG_BUILDDEP:=		libffi python2-host 
-HOST_BUILDDEP:=		libffi-host bzip2-host
+HOST_BUILDDEP:=		libffi-host bzip2-host openssl-host
 PKG_DEPENDS:=		libpthread libffi
 PKG_URL:=		http://www.python.org/
 PKG_SITES:=		http://www.python.org/ftp/python/${PKG_VERSION}/
@@ -100,8 +100,8 @@ CONFIGURE_ARGS:=	--with-threads \
 
 HOST_CONFIGURE_ENV+=	MACOSX_DEPLOYMENT_TARGET=10.9
 HOST_CONFIGURE_ARGS+=	--with-threads \
+			--enable-shared \
 			--disable-ipv6 \
-			--disable-shared \
 			--disable-toolbox-glue \
 			--without-cxx-main
 

+ 4 - 4
package/sqlite/Makefile

@@ -4,7 +4,7 @@
 include ${ADK_TOPDIR}/rules.mk
 
 PKG_NAME:=		sqlite
-PKG_VERSION:=		3.8.5
+PKG_VERSION:=		3.8.8.1
 PKG_RELEASE:=		1
 PKG_HASH:=		98c33abe4106e508e73fda648b2657ac9e969fe24695f543dcde68cc71f3091b
 PKG_DESCR:=		embeddable sql database cli
@@ -12,12 +12,12 @@ PKG_SECTION:=		sys/misc
 PKG_BUILDDEP:=		ncurses readline
 PKG_DEPENDS:=		libsqlite
 PKG_URL:=		http://www.sqlite.org/
-PKG_SITES:=		http://www.sqlite.org/2014/
+PKG_SITES:=		http://www.sqlite.org/2015/
 PKG_LIBNAME:=		libsqlite
 PKG_OPTS:=		dev
 
-DISTFILES:=		sqlite-autoconf-3080500.tar.gz
-WRKDIST=		${WRKDIR}/sqlite-autoconf-3080500
+DISTFILES:=		sqlite-autoconf-3080801.tar.gz
+WRKDIST=		${WRKDIR}/sqlite-autoconf-3080801
 
 PKG_SUBPKGS:=		SQLITE_CLI LIBSQLITE
 PKGSD_LIBSQLITE:=	emeddable sql library