Browse Source

update firefox, partially working.

Waldemar Brodkorb 10 years ago
parent
commit
c481446c02
38 changed files with 149 additions and 3908 deletions
  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