Index: thirdparty/blosc/.gitignore
===================================================================
--- thirdparty/blosc/.gitignore	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
+++ thirdparty/blosc/.gitignore	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
@@ -0,0 +1,1 @@
+bench/bench
Index: thirdparty/blosc/ANNOUNCE.rst
===================================================================
--- thirdparty/blosc/ANNOUNCE.rst	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
+++ thirdparty/blosc/ANNOUNCE.rst	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
@@ -0,0 +1,73 @@
+===============================================================
+ Announcing Blosc 1.2.3
+ A blocking, shuffling and lossless compression library
+===============================================================
+
+What is new?
+============
+
+New `blosc_init()` and `blosc_destroy()` functions have been added so
+that the global lock can be initialized safely. These new functions
+will also allow for other kind of initializations/destructions in the
+future.
+
+Existing applications using Blosc do not need to start using the new
+functions right away, as long as they calling `blosc_set_nthreads()`
+previous to anything else.  However, using them is highly recommended.
+
+Thanks to Oscar Villellas for the init/destroy suggestion, it is a
+nice idea indeed!
+
+For more info, please see the release notes in:
+
+https://github.com/FrancescAlted/blosc/wiki/Release-notes
+
+What is it?
+===========
+
+Blosc (http://www.blosc.org) is a high performance compressor
+optimized for binary data.  It has been designed to transmit data to
+the processor cache faster than the traditional, non-compressed,
+direct memory fetch approach via a memcpy() OS call.
+
+Blosc is the first compressor (that I'm aware of) that is meant not
+only to reduce the size of large datasets on-disk or in-memory, but
+also to accelerate object manipulations that are memory-bound.
+
+There is also a handy command line for Blosc called Bloscpack
+(https://github.com/esc/bloscpack) that allows you to compress large
+binary datafiles on-disk.  Although the format for Bloscpack has not
+stabilized yet, it allows you to effectively use Blosc from you
+favorite shell.
+
+Download sources
+================
+
+Please go to main web site:
+
+http://www.blosc.org/
+
+and proceed from there.  The github repository is over here:
+
+https://github.com/FrancescAlted/blosc
+
+Blosc is distributed using the MIT license, see LICENSES/BLOSC.txt for
+details.
+
+Mailing list
+============
+
+There is an official Blosc mailing list at:
+
+blosc@googlegroups.com
+http://groups.google.es/group/blosc
+
+
+Enjoy Data!
+
+
+.. Local Variables:
+.. mode: rst
+.. coding: utf-8
+.. fill-column: 70
+.. End:
Index: thirdparty/blosc/LICENSES/BLOSC.txt
===================================================================
--- thirdparty/blosc/LICENSES/BLOSC.txt	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
+++ thirdparty/blosc/LICENSES/BLOSC.txt	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
@@ -0,0 +1,23 @@
+Blosc - A blocking, shuffling and lossless compression library
+
+Copyright (C) 2009-2012 Francesc Alted <faltet@gmail.com>
+Copyright (C) 2013      Francesc Alted <faltet@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
Index: thirdparty/blosc/LICENSES/FASTLZ.txt
===================================================================
--- thirdparty/blosc/LICENSES/FASTLZ.txt	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
+++ thirdparty/blosc/LICENSES/FASTLZ.txt	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
@@ -0,0 +1,24 @@
+FastLZ - lightning-fast lossless compression library
+
+Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
+Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
+Copyright (C) 2005 Ariya Hidayat (ariya@kde.org)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
Index: thirdparty/blosc/LICENSES/H5PY.txt
===================================================================
--- thirdparty/blosc/LICENSES/H5PY.txt	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
+++ thirdparty/blosc/LICENSES/H5PY.txt	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
@@ -0,0 +1,34 @@
+Copyright Notice and Statement for the h5py Project
+
+Copyright (c) 2008 Andrew Collette
+http://h5py.alfven.org
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+a. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+b. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the
+   distribution.
+
+c. Neither the name of the author nor the names of contributors may 
+   be used to endorse or promote products derived from this software 
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
Index: thirdparty/blosc/LICENSES/STDINT.txt
===================================================================
--- thirdparty/blosc/LICENSES/STDINT.txt	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
+++ thirdparty/blosc/LICENSES/STDINT.txt	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
@@ -0,0 +1,25 @@
+Copyright (c) 2006-2008 Alexander Chemeris
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  1. Redistributions of source code must retain the above copyright notice,
+     this list of conditions and the following disclaimer.
+
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+
+  3. The name of the author may be used to endorse or promote products
+     derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Index: thirdparty/blosc/README.rst
===================================================================
--- thirdparty/blosc/README.rst	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
+++ thirdparty/blosc/README.rst	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
@@ -0,0 +1,221 @@
+===============================================================
+ Blosc: A blocking, shuffling and lossless compression library
+===============================================================
+
+:Author: Francesc Alted
+:Contact: faltet@gmail.com
+:URL: http://www.blosc.org
+
+What is it?
+===========
+
+Blosc [1]_ is a high performance compressor optimized for binary data.
+It has been designed to transmit data to the processor cache faster
+than the traditional, non-compressed, direct memory fetch approach via
+a memcpy() OS call.  Blosc is the first compressor (that I'm aware of)
+that is meant not only to reduce the size of large datasets on-disk or
+in-memory, but also to accelerate memory-bound computations.
+
+It uses the blocking technique (as described in [2]_) to reduce
+activity on the memory bus as much as possible.  In short, this
+technique works by dividing datasets in blocks that are small enough
+to fit in caches of modern processors and perform compression /
+decompression there.  It also leverages, if available, SIMD
+instructions (SSE2) and multi-threading capabilities of CPUs, in order
+to accelerate the compression / decompression process to a maximum.
+
+You can see some recent benchmarks about Blosc performance in [3]_
+
+Blosc is distributed using the MIT license, see LICENSES/BLOSC.txt for
+details.
+
+.. [1] http://www.blosc.org
+.. [2] http://blosc.org/docs/StarvingCPUs-CISE-2010.pdf
+.. [3] http://blosc.org/trac/wiki/SyntheticBenchmarks
+
+Meta-compression and other advantages over existing compressors
+===============================================================
+
+Blosc is not like other compressors: it should rather be called a
+meta-compressor.  This is so because it can use different compressors
+and pre-conditioners (programs that generally improve compression
+ratio).  At any rate, it can also be called a compressor because it
+happens that it already integrates one compressor and one
+pre-conditioner, so it can actually work like so.
+
+Currently it uses BloscLZ, a compressor heavily based on FastLZ
+(http://fastlz.org/), and a highly optimized (it can use SSE2
+instructions, if available) Shuffle pre-conditioner. However,
+different compressors or pre-conditioners may be added in the future.
+
+Blosc is in charge of coordinating the compressor and pre-conditioners
+so that they can leverage the blocking technique (described above) as
+well as multi-threaded execution (if several cores are available)
+automatically. That makes that every compressor and pre-conditioner
+will work at very high speeds, even if it was not initially designed
+for doing blocking or multi-threading.
+
+Other advantages of Blosc are:
+
+* Meant for binary data: can take advantage of the type size
+  meta-information for improved compression ratio (using the
+  integrated shuffle pre-conditioner).
+
+* Small overhead on non-compressible data: only a maximum of 16
+  additional bytes over the source buffer length are needed to
+  compress *every* input.
+
+* Maximum destination length: contrarily to many other
+  compressors, both compression and decompression routines have
+  support for maximum size lengths for the destination buffer.
+
+* Replacement for memcpy(): it supports a 0 compression level that
+  does not compress at all and only adds 16 bytes of overhead. In
+  this mode Blosc can copy memory usually faster than a plain
+  memcpy().
+
+When taken together, all these features set Blosc apart from other
+similar solutions.
+
+Compiling your application with Blosc
+=====================================
+
+Blosc consists of the next files (in blosc/ directory)::
+
+    blosc.h and blosc.c      -- the main routines
+    blosclz.h and blosclz.c  -- the actual compressor
+    shuffle.h and shuffle.c  -- the shuffle code
+
+Just add these files to your project in order to use Blosc.  For
+information on compression and decompression routines, see blosc.h.
+
+To compile using GCC (4.4 or higher recommended) on Unix:
+
+.. code-block:: console
+
+   $ gcc -O3 -msse2 -o myprog myprog.c blosc/*.c -lpthread
+
+Using Windows and MINGW:
+
+.. code-block:: console
+
+   $ gcc -O3 -msse2 -o myprog myprog.c blosc\*.c
+
+Using Windows and MSVC (2008 or higher recommended):
+
+.. code-block:: console
+
+  $ cl /Ox /Femyprog.exe myprog.c blosc\*.c
+
+A simple usage example is the benchmark in the bench/bench.c file.
+Also, another example for using Blosc as a generic HDF5 filter is in
+the hdf5/ directory.
+
+I have not tried to compile this with compilers other than GCC, MINGW,
+Intel ICC or MSVC yet. Please report your experiences with your own
+platforms.
+
+Testing Blosc
+=============
+
+Go to the test/ directory and issue:
+
+.. code-block:: console
+
+  $ make test
+
+These tests are very basic, and only valid for platforms where GNU
+make/gcc tools are available.  If you really want to test Blosc the
+hard way, look at:
+
+http://blosc.org/trac/wiki/SyntheticBenchmarks
+
+where instructions on how to intensively test (and benchmark) Blosc
+are given.  If while running these tests you get some error, please
+report it back!
+
+Compiling the Blosc library with CMake
+======================================
+
+Blosc can also be built, tested and installed using CMake_.
+The following procedure describes the "out of source" build.
+
+Create the build directory and move into it:
+
+.. code-block:: console
+
+  $ mkdir build
+  $ cd build
+
+Configure Blosc in release mode (enable optimizations) specifying the
+installation directory:
+
+.. code-block:: console
+
+  $ cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=INSTALL_DIR \
+      PATH_TO_BLOSC_SOURCE_DIR
+
+Please note that configuration can also be performed using UI tools
+provided by CMake_ (ccmake or cmake-gui):
+
+.. code-block:: console
+
+  $ cmake-gui PATH_TO_BLOSC_SOURCE_DIR
+
+Build, test and install Blosc:
+
+.. code-block:: console
+
+  $ make
+  $ make test
+  $ make install 
+
+The static and dynamic version of the Blosc library, together with
+header files, will be installed into the specified INSTALL_DIR.
+
+.. _CMake: http://www.cmake.org
+
+Wrapper for Python
+==================
+
+Blosc has an official wrapper for Python.  See:
+
+https://github.com/FrancescAlted/python-blosc
+
+Filter for HDF5
+===============
+
+For those that want to use Blosc as a filter in the HDF5 library,
+there is a sample implementation in the hdf5/ directory.
+
+Mailing list
+============
+
+There is an official mailing list for Blosc at:
+
+blosc@googlegroups.com
+http://groups.google.es/group/blosc
+
+Acknowledgments
+===============
+
+I'd like to thank the PyTables community that have collaborated in the
+exhaustive testing of Blosc.  With an aggregate amount of more than 300 TB of
+different datasets compressed *and* decompressed successfully, I can say that
+Blosc is pretty safe now and ready for production purposes.
+
+Other important contributions:
+
+* Thibault North contributed a way to call Blosc from different threads in a
+  safe way.
+
+* The cmake support was a contribution of Thibault North, Antonio Valentino
+  and Mark Wiebe.
+
+* Valentin Haenel did a terrific work fixing typos and improving docs and the
+  plotting script.
+
+
+----
+
+  **Enjoy data!**
Index: thirdparty/blosc/README_HEADER.rst
===================================================================
--- thirdparty/blosc/README_HEADER.rst	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
+++ thirdparty/blosc/README_HEADER.rst	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
@@ -0,0 +1,40 @@
+Blosc Header Format
+===================
+
+Blosc (as of Version 1.0.0) has the following 16 byte header that stores
+information about the compressed buffer::
+
+    |-0-|-1-|-2-|-3-|-4-|-5-|-6-|-7-|-8-|-9-|-A-|-B-|-C-|-D-|-E-|-F-|
+      ^   ^   ^   ^ |     nbytes    |   blocksize   |    ctbytes    |
+      |   |   |   |
+      |   |   |   +--typesize
+      |   |   +------flags
+      |   +----------versionlz
+      +--------------version
+
+Datatypes of the Header Entries
+-------------------------------
+
+All entries are little endian.
+
+:version:
+    (``uint8``) Blosc format version.
+:versionlz:
+    (``uint8``) Blosclz format  version (internal Lempel-Ziv algorithm).
+:flags:
+    (``bitfield``) The flags of the buffer.
+
+    :bit 0 (``0x01``):
+        Whether the shuffle filter has been applied or not.
+    :bit 1 (``0x02``):
+        Whether the internal buffer is a pure memcpy or not.
+
+:typesize:
+    (``uint8``) Number of bytes for the atomic type.
+:nbytes:
+    (``uint32``) Uncompressed size of the buffer.
+:blocksize:
+    (``uint32``) Size of internal blocks.
+:ctbytes:
+    (``uint32``) Compressed size of the buffer.
+
Index: thirdparty/blosc/README_THREADED.rst
===================================================================
--- thirdparty/blosc/README_THREADED.rst	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
+++ thirdparty/blosc/README_THREADED.rst	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
@@ -0,0 +1,33 @@
+Blosc supports threading
+========================
+
+Threads are the most efficient way to program parallel code for
+multi-core processors, but also the more difficult to program well.
+Also, they has a non-negligible start-up time that does not fit well
+with a high-performance compressor as Blosc tries to be.
+
+In order to reduce the overhead of threads as much as possible, I've
+decided to implement a pool of threads (the workers) that are waiting
+for the main process (the master) to send them jobs (basically,
+compressing and decompressing small blocks of the initial buffer).
+
+Despite this and many other internal optimizations in the threaded
+code, it does not work faster than the serial version for buffer sizes
+around 64/128 KB or less.  This is for Intel Quad Core2 (Q8400 @ 2.66
+GHz) / Linux (openSUSE 11.2, 64 bit), but your mileage may vary (and
+will vary!) for other processors / operating systems.
+
+In contrast, for buffers larger than 64/128 KB, the threaded version
+starts to perform significantly better, being the sweet point at 1 MB
+(again, this is with my setup).  For larger buffer sizes than 1 MB,
+the threaded code slows down again, but it is probably due to a cache
+size issue and besides, it is still considerably faster than serial
+code.
+
+This is why Blosc falls back to use the serial version for such a
+'small' buffers.  So, you don't have to worry too much about deciding
+whether you should set the number of threads to 1 (serial) or more
+(parallel).  Just set it to the number of cores in your processor and
+your are done!
+
+Francesc Alted
Index: thirdparty/blosc/RELEASE_NOTES.rst
===================================================================
--- thirdparty/blosc/RELEASE_NOTES.rst	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
+++ thirdparty/blosc/RELEASE_NOTES.rst	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
@@ -0,0 +1,255 @@
+===============================
+ Release notes for Blosc 1.2.3
+===============================
+
+:Author: Francesc Alted
+:Contact: faltet@gmail.com
+:URL: http://www.blosc.org
+
+
+Changes from 1.2.2 to 1.2.3
+===========================
+
+- Added a `blosc_init()` and `blosc_destroy()` so that the global lock
+  can be initialized safely.  These new functions will also allow other
+  kind of initializations/destructions in the future.
+
+  Existing applications using Blosc do not need to start using the new
+  functions right away, as long as they calling `blosc_set_nthreads()`
+  previous to anything else.  However, using them is highly recommended.
+
+  Thanks to Oscar Villellas for the init/destroy suggestion, it is a
+  nice idea!
+
+
+Changes from 1.2.1 to 1.2.2
+===========================
+
+- All important warnings removed for all tested platforms.  This will
+  allow less intrusiveness compilation experiences with applications
+  including Blosc source code.
+
+- The `bench/bench.c` has been updated so that it can be compiled on
+  Windows again.
+
+- The new web site has been set to: http://www.blosc.org
+
+
+Changes from 1.2 to 1.2.1
+=========================
+
+- Fixed a problem with global lock not being initialized.  This
+  affected mostly to Windows platforms.  Thanks to Christoph
+  Gohlke for finding the cure!
+
+
+Changes from 1.1.5 to 1.2
+=========================
+
+- Now it is possible to call Blosc simultaneously from a parent threaded
+  application without problems.  This has been solved by setting a
+  global lock so that the different calling threads do not execute Blosc
+  routines at the same time.  Of course, real threading work is still
+  available *inside* Blosc itself.  Thanks to Thibault North.
+
+- Support for cmake is now included.  Linux, Mac OSX and Windows
+  platforms are supported.  Thanks to Thibault North, Antonio Valentino
+  and Mark Wiebe.
+
+- Fixed many compilers warnings (specially about unused variables).
+
+- As a consequence of the above, as minimal change in the API has been
+  introduced.  That is, the previous API::
+
+    void blosc_free_resources(void)
+
+  has changed to::
+
+    int blosc_free_resources(void)
+
+  Now, a return value of 0 means that the resources have been released
+  successfully.  If the return value is negative, then it is not
+  guaranteed that all the resources have been freed.
+
+- Many typos were fixed and docs have been improved.  The script for
+  generating nice plots for the included benchmarks has been improved
+  too.  Thanks to Valetin Haenel.
+
+
+Changes from 1.1.4 to 1.1.5
+===========================
+
+- Fix compile error with msvc compilers (Christoph Gohlke)
+
+
+Changes from 1.1.3 to 1.1.4
+===========================
+
+- Redefinition of the BLOSC_MAX_BUFFERSIZE constant as (INT_MAX -
+  BLOSC_MAX_OVERHEAD) instead of just INT_MAX.  This prevents to produce
+  outputs larger than INT_MAX, which is not supported.
+
+- `exit()` call has been replaced by a ``return -1`` in blosc_compress()
+  when checking for buffer sizes.  Now programs will not just exit when
+  the buffer is too large, but return a negative code.
+
+- Improvements in explicit casts.  Blosc compiles without warnings
+  (with GCC) now.
+
+- Lots of improvements in docs, in particular a nice ascii-art diagram
+  of the Blosc format (Valentin Haenel).
+
+- Improvements to the plot-speeds.py (Valentin Haenel).
+
+- [HDF5 filter] Adapted HDF5 filter to use HDF5 1.8 by default
+  (Antonio Valentino).
+
+- [HDF5 filter] New version of H5Z_class_t definition (Antonio Valentino).
+
+
+Changes from 1.1.2 to 1.1.3
+===========================
+
+- Much improved compression ratio when using large blocks (> 64 KB) and
+  high compression levels (> 6) under some circumstances (special data
+  distribution).  Closes #7.
+
+
+Changes from 1.1.1 to 1.1.2
+===========================
+
+- Fixes for small typesizes (#6 and #1 of python-blosc).
+
+
+Changes from 1.1 to 1.1.1
+=========================
+
+- Added code to avoid calling blosc_set_nthreads more than necessary.
+  That will improve performance up to 3x or more, specially for small
+  chunksizes (< 1 MB).
+
+
+Changes from 1.0 to 1.1
+=======================
+
+- Added code for emulating pthreads API on Windows.  No need to link
+  explicitly with pthreads lib on Windows anymore.  However, performance
+  is a somewhat worse because the new emulation layer does not support
+  the `pthread_barrier_wait()` call natively.  But the big improvement
+  in installation easiness is worth this penalty (most specially on
+  64-bit Windows, where pthreads-win32 support is flaky).
+
+- New BLOSC_MAX_BUFFERSIZE, BLOSC_MAX_TYPESIZE and BLOSC_MAX_THREADS
+  symbols are available in blosc.h.  These can be useful for validating
+  parameters in clients.  Thanks to Robert Smallshire for suggesting
+  that.
+
+- A new BLOSC_MIN_HEADER_LENGTH symbol in blosc.h tells how many bytes
+  long is the minimum length of a Blosc header.  `blosc_cbuffer_sizes()`
+  only needs these bytes to be passed to work correctly.
+
+- Removed many warnings (related with potentially dangerous type-casting
+  code) issued by MSVC 2008 in 64-bit mode.
+
+- Fixed a problem with the computation of the blocksize in the Blosc
+  filter for HDF5.
+
+- Fixed a problem with large datatypes.  See
+  http://www.pytables.org/trac/ticket/288 for more info.
+
+- Now Blosc is able to work well even if you fork an existing process
+  with a pool of threads.  Bug discovered when PyTables runs in
+  multiprocess environments.  See http://pytables.org/trac/ticket/295
+  for details.
+
+- Added a new `blosc_getitem()` call to allow the retrieval of items in
+  sizes smaller than the complete buffer.  That is useful for the carray
+  project, but certainly for others too.
+
+
+Changes from 0.9.5 to 1.0
+=========================
+
+- Added a filter for HDF5 so that people can use Blosc outside PyTables,
+  if they want to.
+
+- Many small improvements, specially in README files.
+
+- Do not assume that size_t is uint_32 for every platform.
+
+- Added more protection for large buffers or in allocation memory
+  routines.
+
+- The src/ directory has been renamed to blosc/.
+
+- The `maxbytes` parameter in `blosc_compress()` has been renamed to
+  `destsize`.  This is for consistency with the `blosc_decompress()`
+  parameters.
+
+
+Changes from 0.9.4 to 0.9.5
+===========================
+
+- Now, compression level 0 is allowed, meaning not compression at all.
+  The overhead of this mode will be always BLOSC_MAX_OVERHEAD (16)
+  bytes.  This mode actually represents using Blosc as a basic memory
+  container.
+
+- Supported a new parameter `maxbytes` for ``blosc_compress()``.  It
+  represents a maximum of bytes for output.  Tests unit added too.
+
+- Added 3 new functions for querying different metadata on compressed
+  buffers.  A test suite for testing the new API has been added too.
+
+
+Changes from 0.9.3 to 0.9.4
+===========================
+
+- Support for cross-platform big/little endian compatibility in Blosc
+  headers has been added.
+
+- Fixed several failures exposed by the extremesuite.  The problem was a
+  bad check for limits in the buffer size while compressing.
+
+- Added a new suite in bench.c called ``debugsuite`` that is
+  appropriate for debugging purposes.  Now, the ``extremesuite`` can be
+  used for running the complete (and extremely long) suite.
+
+
+Changes from 0.9.0 to 0.9.3
+===========================
+
+- Fixed several nasty bugs uncovered by the new suites in bench.c.
+  Thanks to Tony Theodore and Gabriel Beckers for their (very)
+  responsive beta testing and feedback.
+
+- Added several modes (suites), namely ``suite``, ``hardsuite`` and
+  ``extremehardsuite`` in bench.c so as to allow different levels of
+  testing.
+
+
+Changes from 0.8.0 to 0.9
+=========================
+
+- Internal format version bumped to 2 in order to allow an easy way to
+  indicate that a buffer is being saved uncompressed.  This is not
+  supported yet, but it might be in the future.
+
+- Blosc can use threads now for leveraging the increasing number of
+  multi-core processors out there.  See README-threaded.txt for more
+  info.
+
+- Added a protection for MacOSX so that it has to not link against
+  posix_memalign() funtion, which seems not available in old versions of
+  MacOSX (for example, Tiger).  At nay rate, posix_memalign() is not
+  necessary on Mac because 16 bytes alignment is ensured by default.
+  Thanks to Ivan Vilata.  Fixes #3.
+
+
+
+
+.. Local Variables:
+.. mode: rst
+.. coding: utf-8
+.. fill-column: 72
+.. End:
Index: thirdparty/blosc/RELEASING.rst
===================================================================
--- thirdparty/blosc/RELEASING.rst	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
+++ thirdparty/blosc/RELEASING.rst	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
@@ -0,0 +1,102 @@
+================
+Releasing Blosc
+================
+
+:Author: Francesc Alted
+:Contact: faltet@gmail.com
+:Date: 2012-09-16
+
+
+Preliminaries
+-------------
+
+- Make sure that ``RELEASE_NOTES.rst`` and ``ANNOUNCE.rst`` are up to
+  date with the latest news in the release.
+
+- Check that *VERSION* symbols in blosc/blosc.h contains the correct info.
+
+Testing
+-------
+
+Go to the test/ directory and issue::
+
+  $ make test
+
+These tests are very basic, and only valid for platforms where GNU
+make/gcc tools are available.  To actually test Blosc the hard way,
+look at the end of:
+
+http://blosc.org/trac/wiki/SyntheticBenchmarks
+
+where instructions on how to intensively test (and benchmark) Blosc
+are given.
+
+Packaging
+---------
+
+- Unpack the archive of the repository in a temporary directory::
+
+  $ export VERSION="the version number"
+  $ mkdir /tmp/blosc-$VERSION
+  # IMPORTANT: make sure that you are at the root of the repo now!
+  $ git archive master | tar -x -C /tmp/blosc-$VERSION
+
+- And package the repo::
+
+  $ cd /tmp
+  $ tar cvfz blosc-$VERSION.tar.gz blosc-$VERSION
+
+Do a quick check that the tarball is sane.
+
+
+Uploading
+---------
+
+- Go to the downloads section in blosc.org and upload the source
+  tarball.
+
+
+Tagging
+-------
+
+- Create a tag ``X.Y.Z`` from ``master``.  Use the next message::
+
+    $ git tag -a vX.Y.Z -m "Tagging version X.Y.Z"
+
+- Push the tag to the github repo::
+
+    $ git push --tags
+
+
+Announcing
+----------
+
+- Update the release notes in the github wiki:
+
+https://github.com/FrancescAlted/blosc/wiki/Release-notes
+
+- Send an announcement to the blosc, pytables, carray and
+  comp.compression lists.  Use the ``ANNOUNCE.rst`` file as skeleton
+  (possibly as the definitive version).
+
+Post-release actions
+--------------------
+
+- Edit *VERSION* symbols in blosc/blosc.h in master to increment the
+  version to the next minor one (i.e. X.Y.Z --> X.Y.(Z+1).dev).
+
+- Create new headers for adding new features in ``RELEASE_NOTES.rst``
+  and empty the release-specific information in ``ANNOUNCE.rst`` and
+  add this place-holder instead:
+
+  #XXX version-specific blurb XXX#
+
+
+That's all folks!
+
+
+.. Local Variables:
+.. mode: rst
+.. coding: utf-8
+.. fill-column: 70
+.. End:
Index: thirdparty/blosc/blosc.c
===================================================================
--- thirdparty/blosc/blosc.c	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
+++ thirdparty/blosc/blosc.c	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
@@ -0,0 +1,1415 @@
+/*********************************************************************
+  Blosc - Blocked Suffling and Compression Library
+
+  Author: Francesc Alted <faltet@gmail.com>
+  Creation date: 2009-05-20
+
+  See LICENSES/BLOSC.txt for details about copyright and rights to use.
+**********************************************************************/
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <assert.h>
+#include "blosc.h"
+#include "blosclz.h"
+#include "shuffle.h"
+
+#if defined(_WIN32) && !defined(__MINGW32__)
+  #include <windows.h>
+  #include "win32/stdint-windows.h"
+  #include <process.h>
+  #define getpid _getpid
+#else
+  #include <stdint.h>
+  #include <unistd.h>
+  #include <inttypes.h>
+#endif  /* _WIN32 */
+
+#if defined(_WIN32)
+  #include "win32/pthread.h"
+  #include "win32/pthread.c"
+#else
+  #include <pthread.h>
+#endif
+
+
+/* Some useful units */
+#define KB 1024
+#define MB (1024*KB)
+
+/* Minimum buffer size to be compressed */
+#define MIN_BUFFERSIZE 128       /* Cannot be smaller than 66 */
+
+/* The maximum number of splits in a block for compression */
+#define MAX_SPLITS 16            /* Cannot be larger than 128 */
+
+/* The size of L1 cache.  32 KB is quite common nowadays. */
+#define L1 (32*KB)
+
+/* Wrapped function to adjust the number of threads used by blosc */
+int blosc_set_nthreads_(int);
+
+/* Global variables for main logic */
+static int32_t init_temps_done = 0;    /* temp for compr/decompr initialized? */
+static int32_t force_blocksize = 0;    /* force the use of a blocksize? */
+static int pid = 0;                    /* the PID for this process */
+static int init_lib = 0;               /* is library initalized? */
+
+/* Global variables for threads */
+static int32_t nthreads = 1;            /* number of desired threads in pool */
+static int32_t init_threads_done = 0;   /* pool of threads initialized? */
+static int32_t end_threads = 0;         /* should exisiting threads end? */
+static int32_t init_sentinels_done = 0; /* sentinels initialized? */
+static int32_t giveup_code;             /* error code when give up */
+static int32_t nblock;                  /* block counter */
+static pthread_t threads[BLOSC_MAX_THREADS];  /* opaque structure for threads */
+static int32_t tids[BLOSC_MAX_THREADS];       /* ID per each thread */
+#if !defined(_WIN32)
+static pthread_attr_t ct_attr;          /* creation time attrs for threads */
+#endif
+
+/* Have problems using posix barriers when symbol value is 200112L */
+/* This requires more investigation, but will work for the moment */
+#if defined(_POSIX_BARRIERS) && ( (_POSIX_BARRIERS - 20012L) >= 0 && _POSIX_BARRIERS != 200112L)
+#define _POSIX_BARRIERS_MINE
+#endif
+
+/* Synchronization variables */
+static pthread_mutex_t count_mutex;
+static pthread_mutex_t global_comp_mutex;
+#ifdef _POSIX_BARRIERS_MINE
+static pthread_barrier_t barr_init;
+static pthread_barrier_t barr_finish;
+#else
+static int32_t count_threads;
+static pthread_mutex_t count_threads_mutex;
+static pthread_cond_t count_threads_cv;
+#endif
+
+
+/* Structure for parameters in (de-)compression threads */
+static struct thread_data {
+  int32_t typesize;
+  int32_t blocksize;
+  int32_t compress;
+  int32_t clevel;
+  int32_t flags;
+  int32_t memcpyed;
+  int32_t ntbytes;
+  int32_t nbytes;
+  int32_t maxbytes;
+  int32_t nblocks;
+  int32_t leftover;
+  int32_t *bstarts;             /* start pointers for each block */
+  uint8_t *src;
+  uint8_t *dest;
+  uint8_t *tmp[BLOSC_MAX_THREADS];
+  uint8_t *tmp2[BLOSC_MAX_THREADS];
+} params;
+
+
+/* Structure for parameters meant for keeping track of current temporaries */
+static struct temp_data {
+  int32_t nthreads;
+  int32_t typesize;
+  int32_t blocksize;
+} current_temp;
+
+
+/* Macros for synchronization */
+
+/* Wait until all threads are initialized */
+#ifdef _POSIX_BARRIERS_MINE
+static int rc;
+#define WAIT_INIT \
+  rc = pthread_barrier_wait(&barr_init); \
+  if (rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) { \
+    printf("Could not wait on barrier (init)\n"); \
+    return(-1); \
+  }
+#else
+#define WAIT_INIT \
+  pthread_mutex_lock(&count_threads_mutex); \
+  if (count_threads < nthreads) { \
+    count_threads++; \
+    pthread_cond_wait(&count_threads_cv, &count_threads_mutex); \
+  } \
+  else { \
+    pthread_cond_broadcast(&count_threads_cv); \
+  } \
+  pthread_mutex_unlock(&count_threads_mutex);
+#endif
+
+/* Wait for all threads to finish */
+#ifdef _POSIX_BARRIERS_MINE
+#define WAIT_FINISH \
+  rc = pthread_barrier_wait(&barr_finish); \
+  if (rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) { \
+    printf("Could not wait on barrier (finish)\n"); \
+    return(-1);                                       \
+  }
+#else
+#define WAIT_FINISH \
+  pthread_mutex_lock(&count_threads_mutex); \
+  if (count_threads > 0) { \
+    count_threads--; \
+    pthread_cond_wait(&count_threads_cv, &count_threads_mutex); \
+  } \
+  else { \
+    pthread_cond_broadcast(&count_threads_cv); \
+  } \
+  pthread_mutex_unlock(&count_threads_mutex);
+#endif
+
+
+/* A function for aligned malloc that is portable */
+static uint8_t *my_malloc(size_t size)
+{
+  void *block = NULL;
+  int res = 0;
+
+#if defined(_WIN32)
+  /* A (void *) cast needed for avoiding a warning with MINGW :-/ */
+  block = (void *)_aligned_malloc(size, 16);
+#elif defined __APPLE__
+  /* Mac OS X guarantees 16-byte alignment in small allocs */
+  block = malloc(size);
+#elif _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600
+  /* Platform does have an implementation of posix_memalign */
+  res = posix_memalign(&block, 16, size);
+#else
+  block = malloc(size);
+#endif  /* _WIN32 */
+
+  if (block == NULL || res != 0) {
+    printf("Error allocating memory!");
+    return NULL;
+  }
+
+  return (uint8_t *)block;
+}
+
+
+/* Release memory booked by my_malloc */
+static void my_free(void *block)
+{
+#if defined(_WIN32)
+    _aligned_free(block);
+#else
+    free(block);
+#endif  /* _WIN32 */
+}
+
+
+/* If `a` is little-endian, return it as-is.  If not, return a copy,
+   with the endianness changed */
+static int32_t sw32(int32_t a)
+{
+  int32_t tmp;
+  char *pa = (char *)&a;
+  char *ptmp = (char *)&tmp;
+  int i = 1;                    /* for big/little endian detection */
+  char *p = (char *)&i;
+
+  if (p[0] != 1) {
+    /* big endian */
+    ptmp[0] = pa[3];
+    ptmp[1] = pa[2];
+    ptmp[2] = pa[1];
+    ptmp[3] = pa[0];
+    return tmp;
+  }
+  else {
+    /* little endian */
+    return a;
+  }
+}
+
+
+/* Shuffle & compress a single block */
+static int blosc_c(int32_t blocksize, int32_t leftoverblock,
+                   int32_t ntbytes, int32_t maxbytes,
+                   uint8_t *src, uint8_t *dest, uint8_t *tmp)
+{
+  int32_t j, neblock, nsplits;
+  int32_t cbytes;                   /* number of compressed bytes in split */
+  int32_t ctbytes = 0;              /* number of compressed bytes in block */
+  int32_t maxout;
+  int32_t typesize = params.typesize;
+  uint8_t *_tmp;
+
+  if ((params.flags & BLOSC_DOSHUFFLE) && (typesize > 1)) {
+    /* Shuffle this block (this makes sense only if typesize > 1) */
+    shuffle(typesize, blocksize, src, tmp);
+    _tmp = tmp;
+  }
+  else {
+    _tmp = src;
+  }
+
+  /* Compress for each shuffled slice split for this block. */
+  /* If typesize is too large, neblock is too small or we are in a
+     leftover block, do not split at all. */
+  if ((typesize <= MAX_SPLITS) && (blocksize/typesize) >= MIN_BUFFERSIZE &&
+      (!leftoverblock)) {
+    nsplits = typesize;
+  }
+  else {
+    nsplits = 1;
+  }
+  neblock = blocksize / nsplits;
+  for (j = 0; j < nsplits; j++) {
+    dest += sizeof(int32_t);
+    ntbytes += (int32_t)sizeof(int32_t);
+    ctbytes += (int32_t)sizeof(int32_t);
+    maxout = neblock;
+    if (ntbytes+maxout > maxbytes) {
+      maxout = maxbytes - ntbytes;   /* avoid buffer overrun */
+      if (maxout <= 0) {
+        return 0;                  /* non-compressible block */
+      }
+    }
+    cbytes = blosclz_compress(params.clevel, _tmp+j*neblock, neblock,
+                              dest, maxout);
+    if (cbytes >= maxout) {
+      /* Buffer overrun caused by blosclz_compress (should never happen) */
+      return -1;
+    }
+    else if (cbytes < 0) {
+      /* cbytes should never be negative */
+      return -2;
+    }
+    else if (cbytes == 0) {
+      /* The compressor has been unable to compress data significantly. */
+      /* Before doing the copy, check that we are not running into a
+         buffer overflow. */
+      if ((ntbytes+neblock) > maxbytes) {
+        return 0;    /* Non-compressible data */
+      }
+      memcpy(dest, _tmp+j*neblock, neblock);
+      cbytes = neblock;
+    }
+    ((int32_t *)(dest))[-1] = sw32(cbytes);
+    dest += cbytes;
+    ntbytes += cbytes;
+    ctbytes += cbytes;
+  }  /* Closes j < nsplits */
+
+  return ctbytes;
+}
+
+
+/* Decompress & unshuffle a single block */
+static int blosc_d(int32_t blocksize, int32_t leftoverblock,
+                   uint8_t *src, uint8_t *dest, uint8_t *tmp, uint8_t *tmp2)
+{
+  int32_t j, neblock, nsplits;
+  int32_t nbytes;                /* number of decompressed bytes in split */
+  int32_t cbytes;                /* number of compressed bytes in split */
+  int32_t ctbytes = 0;           /* number of compressed bytes in block */
+  int32_t ntbytes = 0;           /* number of uncompressed bytes in block */
+  uint8_t *_tmp;
+  int32_t typesize = params.typesize;
+
+  if ((params.flags & BLOSC_DOSHUFFLE) && (typesize > 1)) {
+    _tmp = tmp;
+  }
+  else {
+    _tmp = dest;
+  }
+
+  /* Compress for each shuffled slice split for this block. */
+  if ((typesize <= MAX_SPLITS) && (blocksize/typesize) >= MIN_BUFFERSIZE &&
+      (!leftoverblock)) {
+    nsplits = typesize;
+  }
+  else {
+    nsplits = 1;
+  }
+  neblock = blocksize / nsplits;
+  for (j = 0; j < nsplits; j++) {
+    cbytes = sw32(((int32_t *)(src))[0]);   /* amount of compressed bytes */
+    src += sizeof(int32_t);
+    ctbytes += (int32_t)sizeof(int32_t);
+    /* Uncompress */
+    if (cbytes == neblock) {
+      memcpy(_tmp, src, neblock);
+      nbytes = neblock;
+    }
+    else {
+      nbytes = blosclz_decompress(src, cbytes, _tmp, neblock);
+      if (nbytes != neblock) {
+        return -2;
+      }
+    }
+    src += cbytes;
+    ctbytes += cbytes;
+    _tmp += nbytes;
+    ntbytes += nbytes;
+  } /* Closes j < nsplits */
+
+  if ((params.flags & BLOSC_DOSHUFFLE) && (typesize > 1)) {
+    if ((uintptr_t)dest % 16 == 0) {
+      /* 16-bytes aligned dest.  SSE2 unshuffle will work. */
+      unshuffle(typesize, blocksize, tmp, dest);
+    }
+    else {
+      /* dest is not aligned.  Use tmp2, which is aligned, and copy. */
+      unshuffle(typesize, blocksize, tmp, tmp2);
+      if (tmp2 != dest) {
+        /* Copy only when dest is not tmp2 (e.g. not blosc_getitem())  */
+        memcpy(dest, tmp2, blocksize);
+      }
+    }
+  }
+
+  /* Return the number of uncompressed bytes */
+  return ntbytes;
+}
+
+
+/* Serial version for compression/decompression */
+static int serial_blosc(void)
+{
+  int32_t j, bsize, leftoverblock;
+  int32_t cbytes;
+  int32_t compress = params.compress;
+  int32_t blocksize = params.blocksize;
+  int32_t ntbytes = params.ntbytes;
+  int32_t flags = params.flags;
+  int32_t maxbytes = params.maxbytes;
+  int32_t nblocks = params.nblocks;
+  int32_t leftover = params.nbytes % params.blocksize;
+  int32_t *bstarts = params.bstarts;
+  uint8_t *src = params.src;
+  uint8_t *dest = params.dest;
+  uint8_t *tmp = params.tmp[0];     /* tmp for thread 0 */
+  uint8_t *tmp2 = params.tmp2[0];   /* tmp2 for thread 0 */
+
+  for (j = 0; j < nblocks; j++) {
+    if (compress && !(flags & BLOSC_MEMCPYED)) {
+      bstarts[j] = sw32(ntbytes);
+    }
+    bsize = blocksize;
+    leftoverblock = 0;
+    if ((j == nblocks - 1) && (leftover > 0)) {
+      bsize = leftover;
+      leftoverblock = 1;
+    }
+    if (compress) {
+      if (flags & BLOSC_MEMCPYED) {
+        /* We want to memcpy only */
+        memcpy(dest+BLOSC_MAX_OVERHEAD+j*blocksize, src+j*blocksize, bsize);
+        cbytes = bsize;
+      }
+      else {
+        /* Regular compression */
+        cbytes = blosc_c(bsize, leftoverblock, ntbytes, maxbytes,
+                         src+j*blocksize, dest+ntbytes, tmp);
+        if (cbytes == 0) {
+          ntbytes = 0;              /* uncompressible data */
+          break;
+        }
+      }
+    }
+    else {
+      if (flags & BLOSC_MEMCPYED) {
+        /* We want to memcpy only */
+        memcpy(dest+j*blocksize, src+BLOSC_MAX_OVERHEAD+j*blocksize, bsize);
+        cbytes = bsize;
+      }
+      else {
+        /* Regular decompression */
+        cbytes = blosc_d(bsize, leftoverblock,
+                         src+sw32(bstarts[j]), dest+j*blocksize, tmp, tmp2);
+      }
+    }
+    if (cbytes < 0) {
+      ntbytes = cbytes;         /* error in blosc_c or blosc_d */
+      break;
+    }
+    ntbytes += cbytes;
+  }
+
+  return ntbytes;
+}
+
+
+/* Threaded version for compression/decompression */
+static int parallel_blosc(void)
+{
+
+  /* Check whether we need to restart threads */
+  if (!init_threads_done || pid != getpid()) {
+    blosc_set_nthreads_(nthreads);
+  }
+
+  /* Synchronization point for all threads (wait for initialization) */
+  WAIT_INIT;
+  /* Synchronization point for all threads (wait for finalization) */
+  WAIT_FINISH;
+
+  if (giveup_code > 0) {
+    /* Return the total bytes (de-)compressed in threads */
+    return params.ntbytes;
+  }
+  else {
+    /* Compression/decompression gave up.  Return error code. */
+    return giveup_code;
+  }
+}
+
+
+/* Convenience functions for creating and releasing temporaries */
+static int create_temporaries(void)
+{
+  int32_t tid;
+  int32_t typesize = params.typesize;
+  int32_t blocksize = params.blocksize;
+  /* Extended blocksize for temporary destination.  Extended blocksize
+   is only useful for compression in parallel mode, but it doesn't
+   hurt serial mode either. */
+  int32_t ebsize = blocksize + typesize*(int32_t)sizeof(int32_t);
+
+  /* Create temporary area for each thread */
+  for (tid = 0; tid < nthreads; tid++) {
+    uint8_t *tmp = my_malloc(blocksize);
+    uint8_t *tmp2;
+    if (tmp == NULL) {
+      return -1;
+    }
+    params.tmp[tid] = tmp;
+    tmp2 = my_malloc(ebsize);
+    if (tmp2 == NULL) {
+      return -1;
+    }
+    params.tmp2[tid] = tmp2;
+  }
+
+  init_temps_done = 1;
+  /* Update params for current temporaries */
+  current_temp.nthreads = nthreads;
+  current_temp.typesize = typesize;
+  current_temp.blocksize = blocksize;
+  return 0;
+}
+
+
+static void release_temporaries(void)
+{
+  int32_t tid;
+
+  /* Release buffers */
+  for (tid = 0; tid < nthreads; tid++) {
+    my_free(params.tmp[tid]);
+    my_free(params.tmp2[tid]);
+  }
+
+  init_temps_done = 0;
+}
+
+
+/* Do the compression or decompression of the buffer depending on the
+   global params. */
+static int do_job(void)
+{
+  int32_t ntbytes;
+
+  /* Initialize/reset temporaries if needed */
+  if (!init_temps_done) {
+    int ret;
+    ret = create_temporaries();
+    if (ret < 0) {
+      return -1;
+    }
+  }
+  else if (current_temp.nthreads != nthreads ||
+           current_temp.typesize != params.typesize ||
+           current_temp.blocksize != params.blocksize) {
+    int ret;
+    release_temporaries();
+    ret = create_temporaries();
+    if (ret < 0) {
+      return -1;
+    }
+  }
+
+  /* Run the serial version when nthreads is 1 or when the buffers are
+     not much larger than blocksize */
+  if (nthreads == 1 || (params.nbytes / params.blocksize) <= 1) {
+    ntbytes = serial_blosc();
+  }
+  else {
+    ntbytes = parallel_blosc();
+  }
+
+  return ntbytes;
+}
+
+
+static int32_t compute_blocksize(int32_t clevel, int32_t typesize,
+                                 int32_t nbytes)
+{
+  int32_t blocksize;
+
+  /* Protection against very small buffers */
+  if (nbytes < (int32_t)typesize) {
+    return 1;
+  }
+
+  blocksize = nbytes;           /* Start by a whole buffer as blocksize */
+
+  if (force_blocksize) {
+    blocksize = force_blocksize;
+    /* Check that forced blocksize is not too small nor too large */
+    if (blocksize < MIN_BUFFERSIZE) {
+      blocksize = MIN_BUFFERSIZE;
+    }
+  }
+  else if (nbytes >= L1*4) {
+    blocksize = L1 * 4;
+    if (clevel == 0) {
+      blocksize /= 16;
+    }
+    else if (clevel <= 3) {
+      blocksize /= 8;
+    }
+    else if (clevel <= 5) {
+      blocksize /= 4;
+    }
+    else if (clevel <= 6) {
+      blocksize /= 2;
+    }
+    else if (clevel < 9) {
+      blocksize *= 1;
+    }
+    else {
+      blocksize *= 2;
+    }
+  }
+
+  /* Check that blocksize is not too large */
+  if (blocksize > (int32_t)nbytes) {
+    blocksize = nbytes;
+  }
+
+  /* blocksize must be a multiple of the typesize */
+  if (blocksize > typesize) {
+    blocksize = blocksize / typesize * typesize;
+  }
+
+  /* blocksize must not exceed (64 KB * typesize) in order to allow
+     BloscLZ to achieve better compression ratios (the ultimate reason
+     for this is that hash_log in BloscLZ cannot be larger than 15) */
+  if ((blocksize / typesize) > 64*KB) {
+    blocksize = 64 * KB * typesize;
+  }
+
+  return blocksize;
+}
+
+
+/* The public routine for compression.  See blosc.h for docstrings. */
+int blosc_compress(int clevel, int doshuffle, size_t typesize, size_t nbytes,
+      const void *src, void *dest, size_t destsize)
+{
+  uint8_t *_dest=NULL;         /* current pos for destination buffer */
+  uint8_t *flags;              /* flags for header.  Currently booked:
+                                  - 0: shuffled?
+                                  - 1: memcpy'ed? */
+  int32_t nbytes_;            /* number of bytes in source buffer */
+  int32_t nblocks;            /* number of total blocks in buffer */
+  int32_t leftover;           /* extra bytes at end of buffer */
+  int32_t *bstarts;           /* start pointers for each block */
+  int32_t blocksize;          /* length of the block in bytes */
+  int32_t ntbytes = 0;        /* the number of compressed bytes */
+  int32_t *ntbytes_;          /* placeholder for bytes in output buffer */
+  int32_t maxbytes = (int32_t)destsize;  /* maximum size for dest buffer */
+
+  /* Check buffer size limits */
+  if (nbytes > BLOSC_MAX_BUFFERSIZE) {
+    /* If buffer is too large, give up. */
+    fprintf(stderr, "Input buffer size cannot exceed %d bytes\n",
+            BLOSC_MAX_BUFFERSIZE);
+    return -1;
+  }
+
+  /* We can safely do this assignation now */
+  nbytes_ = (int32_t)nbytes;
+
+  /* Compression level */
+  if (clevel < 0 || clevel > 9) {
+    /* If clevel not in 0..9, print an error */
+    fprintf(stderr, "`clevel` parameter must be between 0 and 9!\n");
+    return -10;
+  }
+
+  /* Shuffle */
+  if (doshuffle != 0 && doshuffle != 1) {
+    fprintf(stderr, "`shuffle` parameter must be either 0 or 1!\n");
+    return -10;
+  }
+
+  /* Check typesize limits */
+  if (typesize > BLOSC_MAX_TYPESIZE) {
+    /* If typesize is too large, treat buffer as an 1-byte stream. */
+    typesize = 1;
+  }
+
+  /* Get the blocksize */
+  blocksize = compute_blocksize(clevel, (int32_t)typesize, nbytes_);
+
+  /* Compute number of blocks in buffer */
+  nblocks = nbytes_ / blocksize;
+  leftover = nbytes_ % blocksize;
+  nblocks = (leftover>0)? nblocks+1: nblocks;
+
+  _dest = (uint8_t *)(dest);
+  /* Write header for this block */
+  _dest[0] = BLOSC_VERSION_FORMAT;         /* blosc format version */
+  _dest[1] = BLOSCLZ_VERSION_FORMAT;       /* blosclz format version */
+  flags = _dest+2;                         /* flags */
+  _dest[2] = 0;                            /* zeroes flags */
+  _dest[3] = (uint8_t)typesize;            /* type size */
+  _dest += 4;
+  ((int32_t *)_dest)[0] = sw32(nbytes_);  /* size of the buffer */
+  ((int32_t *)_dest)[1] = sw32(blocksize);/* block size */
+  ntbytes_ = (int32_t *)(_dest+8);        /* compressed buffer size */
+  _dest += sizeof(int32_t)*3;
+  bstarts = (int32_t *)_dest;             /* starts for every block */
+  _dest += sizeof(int32_t)*nblocks;        /* space for pointers to blocks */
+  ntbytes = (int32_t)(_dest - (uint8_t *)dest);
+
+  if (clevel == 0) {
+    /* Compression level 0 means buffer to be memcpy'ed */
+    *flags |= BLOSC_MEMCPYED;
+  }
+
+  if (nbytes_ < MIN_BUFFERSIZE) {
+    /* Buffer is too small.  Try memcpy'ing. */
+    *flags |= BLOSC_MEMCPYED;
+  }
+
+  if (doshuffle == 1) {
+    /* Shuffle is active */
+    *flags |= BLOSC_DOSHUFFLE;              /* bit 0 set to one in flags */
+  }
+
+  /* Take global lock for the time of compression */
+  pthread_mutex_lock(&global_comp_mutex);
+  /* Populate parameters for compression routines */
+  params.compress = 1;
+  params.clevel = clevel;
+  params.flags = (int32_t)*flags;
+  params.typesize = (int32_t)typesize;
+  params.blocksize = blocksize;
+  params.ntbytes = ntbytes;
+  params.nbytes = nbytes_;
+  params.maxbytes = maxbytes;
+  params.nblocks = nblocks;
+  params.leftover = leftover;
+  params.bstarts = bstarts;
+  params.src = (uint8_t *)src;
+  params.dest = (uint8_t *)dest;
+
+  if (!(*flags & BLOSC_MEMCPYED)) {
+    /* Do the actual compression */
+    ntbytes = do_job();
+    if (ntbytes < 0) {
+      return -1;
+    }
+    if ((ntbytes == 0) && (nbytes_+BLOSC_MAX_OVERHEAD <= maxbytes)) {
+      /* Last chance for fitting `src` buffer in `dest`.  Update flags
+       and do a memcpy later on. */
+      *flags |= BLOSC_MEMCPYED;
+      params.flags |= BLOSC_MEMCPYED;
+    }
+  }
+
+  if (*flags & BLOSC_MEMCPYED) {
+    if (nbytes_+BLOSC_MAX_OVERHEAD > maxbytes) {
+      /* We are exceeding maximum output size */
+      ntbytes = 0;
+    }
+    else if (((nbytes_ % L1) == 0) || (nthreads > 1)) {
+      /* More effective with large buffers that are multiples of the
+       cache size or multi-cores */
+      params.ntbytes = BLOSC_MAX_OVERHEAD;
+      ntbytes = do_job();
+      if (ntbytes < 0) {
+	return -1;
+      }
+    }
+    else {
+      memcpy((uint8_t *)dest+BLOSC_MAX_OVERHEAD, src, nbytes_);
+      ntbytes = nbytes_ + BLOSC_MAX_OVERHEAD;
+    }
+  }
+
+  /* Set the number of compressed bytes in header */
+  *ntbytes_ = sw32(ntbytes);
+
+  /* Release global lock */
+  pthread_mutex_unlock(&global_comp_mutex);
+  
+  assert((int32_t)ntbytes <= (int32_t)maxbytes);
+  return ntbytes;
+}
+
+
+/* The public routine for decompression.  See blosc.h for docstrings. */
+int blosc_decompress(const void *src, void *dest, size_t destsize)
+{
+  uint8_t *_src=NULL;            /* current pos for source buffer */
+  uint8_t version, versionlz;    /* versions for compressed header */
+  uint8_t flags;                 /* flags for header */
+  int32_t ntbytes;               /* the number of uncompressed bytes */
+  int32_t nblocks;              /* number of total blocks in buffer */
+  int32_t leftover;             /* extra bytes at end of buffer */
+  int32_t *bstarts;             /* start pointers for each block */
+  int32_t typesize, blocksize, nbytes, ctbytes;
+
+  _src = (uint8_t *)(src);
+
+  /* Read the header block */
+  version = _src[0];                         /* blosc format version */
+  versionlz = _src[1];                       /* blosclz format version */
+  flags = _src[2];                           /* flags */
+  typesize = (int32_t)_src[3];              /* typesize */
+  _src += 4;
+  nbytes = sw32(((int32_t *)_src)[0]);      /* buffer size */
+  blocksize = sw32(((int32_t *)_src)[1]);   /* block size */
+  ctbytes = sw32(((int32_t *)_src)[2]);     /* compressed buffer size */
+
+  version += 0;                             /* shut up compiler warning */
+  versionlz += 0;                           /* shut up compiler warning */
+  ctbytes += 0;                             /* shut up compiler warning */
+
+  _src += sizeof(int32_t)*3;
+  bstarts = (int32_t *)_src;
+  /* Compute some params */
+  /* Total blocks */
+  nblocks = nbytes / blocksize;
+  leftover = nbytes % blocksize;
+  nblocks = (leftover>0)? nblocks+1: nblocks;
+  _src += sizeof(int32_t)*nblocks;
+
+  /* Check that we have enough space to decompress */
+  if (nbytes > (int32_t)destsize) {
+    return -1;
+  }
+
+  /* Take global lock for the time of decompression */
+  pthread_mutex_lock(&global_comp_mutex);
+  
+  /* Populate parameters for decompression routines */
+  params.compress = 0;
+  params.clevel = 0;            /* specific for compression */
+  params.flags = (int32_t)flags;
+  params.typesize = typesize;
+  params.blocksize = blocksize;
+  params.ntbytes = 0;
+  params.nbytes = nbytes;
+  params.nblocks = nblocks;
+  params.leftover = leftover;
+  params.bstarts = bstarts;
+  params.src = (uint8_t *)src;
+  params.dest = (uint8_t *)dest;
+
+  /* Check whether this buffer is memcpy'ed */
+  if (flags & BLOSC_MEMCPYED) {
+    if (((nbytes % L1) == 0) || (nthreads > 1)) {
+      /* More effective with large buffers that are multiples of the
+       cache size or multi-cores */
+      ntbytes = do_job();
+      if (ntbytes < 0) {
+	return -1;
+      }
+    }
+    else {
+      memcpy(dest, (uint8_t *)src+BLOSC_MAX_OVERHEAD, nbytes);
+      ntbytes = nbytes;
+    }
+  }
+  else {
+    /* Do the actual decompression */
+    ntbytes = do_job();
+    if (ntbytes < 0) {
+      return -1;
+    }
+  }
+  /* Release global lock */
+  pthread_mutex_unlock(&global_comp_mutex);
+  
+  assert(ntbytes <= (int32_t)destsize);
+  return ntbytes;
+}
+
+
+/* Specific routine optimized for decompression a small number of
+   items out of a compressed chunk.  This does not use threads because
+   it would affect negatively to performance. */
+int blosc_getitem(const void *src, int start, int nitems, void *dest)
+{
+  uint8_t *_src=NULL;               /* current pos for source buffer */
+  uint8_t version, versionlz;       /* versions for compressed header */
+  uint8_t flags;                    /* flags for header */
+  int32_t ntbytes = 0;              /* the number of uncompressed bytes */
+  int32_t nblocks;                 /* number of total blocks in buffer */
+  int32_t leftover;                /* extra bytes at end of buffer */
+  int32_t *bstarts;                /* start pointers for each block */
+  uint8_t *tmp = params.tmp[0];     /* tmp for thread 0 */
+  uint8_t *tmp2 = params.tmp2[0];   /* tmp2 for thread 0 */
+  int tmp_init = 0;
+  int32_t typesize, blocksize, nbytes, ctbytes;
+  int32_t j, bsize, bsize2, leftoverblock;
+  int32_t cbytes, startb, stopb;
+  int stop = start + nitems;
+
+  _src = (uint8_t *)(src);
+
+  /* Take global lock  */
+  pthread_mutex_lock(&global_comp_mutex);
+  
+  /* Read the header block */
+  version = _src[0];                         /* blosc format version */
+  versionlz = _src[1];                       /* blosclz format version */
+  flags = _src[2];                           /* flags */
+  typesize = (int32_t)_src[3];              /* typesize */
+  _src += 4;
+  nbytes = sw32(((int32_t *)_src)[0]);      /* buffer size */
+  blocksize = sw32(((int32_t *)_src)[1]);   /* block size */
+  ctbytes = sw32(((int32_t *)_src)[2]);     /* compressed buffer size */
+
+  version += 0;                             /* shut up compiler warning */
+  versionlz += 0;                           /* shut up compiler warning */
+  ctbytes += 0;                             /* shut up compiler warning */
+
+  _src += sizeof(int32_t)*3;
+  bstarts = (int32_t *)_src;
+  /* Compute some params */
+  /* Total blocks */
+  nblocks = nbytes / blocksize;
+  leftover = nbytes % blocksize;
+  nblocks = (leftover>0)? nblocks+1: nblocks;
+  _src += sizeof(int32_t)*nblocks;
+
+  /* Check region boundaries */
+  if ((start < 0) || (start*typesize > nbytes)) {
+    fprintf(stderr, "`start` out of bounds");
+    return (-1);
+  }
+
+  if ((stop < 0) || (stop*typesize > nbytes)) {
+    fprintf(stderr, "`start`+`nitems` out of bounds");
+    return (-1);
+  }
+
+  /* Parameters needed by blosc_d */
+  params.typesize = typesize;
+  params.flags = flags;
+
+  /* Initialize temporaries if needed */
+  if (tmp == NULL || tmp2 == NULL || current_temp.blocksize < blocksize) {
+    tmp = my_malloc(blocksize);
+    if (tmp == NULL) {
+      return -1;
+    }
+    tmp2 = my_malloc(blocksize);
+    if (tmp2 == NULL) {
+      return -1;
+    }
+    tmp_init = 1;
+  }
+
+  for (j = 0; j < nblocks; j++) {
+    bsize = blocksize;
+    leftoverblock = 0;
+    if ((j == nblocks - 1) && (leftover > 0)) {
+      bsize = leftover;
+      leftoverblock = 1;
+    }
+
+    /* Compute start & stop for each block */
+    startb = start * typesize - j * blocksize;
+    stopb = stop * typesize - j * blocksize;
+    if ((startb >= (int)blocksize) || (stopb <= 0)) {
+      continue;
+    }
+    if (startb < 0) {
+      startb = 0;
+    }
+    if (stopb > (int)blocksize) {
+      stopb = blocksize;
+    }
+    bsize2 = stopb - startb;
+
+    /* Do the actual data copy */
+    if (flags & BLOSC_MEMCPYED) {
+      /* We want to memcpy only */
+      memcpy((uint8_t *)dest + ntbytes,
+          (uint8_t *)src + BLOSC_MAX_OVERHEAD + j*blocksize + startb,
+             bsize2);
+      cbytes = bsize2;
+    }
+    else {
+      /* Regular decompression.  Put results in tmp2. */
+      cbytes = blosc_d(bsize, leftoverblock,
+                       (uint8_t *)src+sw32(bstarts[j]), tmp2, tmp, tmp2);
+      if (cbytes < 0) {
+        ntbytes = cbytes;
+        break;
+      }
+      /* Copy to destination */
+      memcpy((uint8_t *)dest + ntbytes, tmp2 + startb, bsize2);
+      cbytes = bsize2;
+    }
+    ntbytes += cbytes;
+  }
+  
+  /* Release global lock */
+  pthread_mutex_unlock(&global_comp_mutex);
+
+  if (tmp_init) {
+    my_free(tmp);
+    my_free(tmp2);
+  }
+
+  return ntbytes;
+}
+
+
+/* Decompress & unshuffle several blocks in a single thread */
+static int t_blosc(void *tids)
+{
+  int32_t tid = *(int32_t *)tids;
+  int32_t cbytes, ntdest;
+  int32_t tblocks;              /* number of blocks per thread */
+  int32_t leftover2;
+  int32_t tblock;               /* limit block on a thread */
+  int32_t nblock_;              /* private copy of nblock */
+  int32_t bsize, leftoverblock;
+  /* Parameters for threads */
+  int32_t blocksize;
+  int32_t ebsize;
+  int32_t compress;
+  int32_t maxbytes;
+  int32_t ntbytes;
+  int32_t flags;
+  int32_t nblocks;
+  int32_t leftover;
+  int32_t *bstarts;
+  uint8_t *src;
+  uint8_t *dest;
+  uint8_t *tmp;
+  uint8_t *tmp2;
+
+  while (1) {
+
+    init_sentinels_done = 0;     /* sentinels have to be initialised yet */
+
+    /* Synchronization point for all threads (wait for initialization) */
+    WAIT_INIT;
+
+    /* Check if thread has been asked to return */
+    if (end_threads) {
+      return(0);
+    }
+
+    pthread_mutex_lock(&count_mutex);
+    if (!init_sentinels_done) {
+      /* Set sentinels and other global variables */
+      giveup_code = 1;            /* no error code initially */
+      nblock = -1;                /* block counter */
+      init_sentinels_done = 1;    /* sentinels have been initialised */
+    }
+    pthread_mutex_unlock(&count_mutex);
+
+    /* Get parameters for this thread before entering the main loop */
+    blocksize = params.blocksize;
+    ebsize = blocksize + params.typesize*(int32_t)sizeof(int32_t);
+    compress = params.compress;
+    flags = params.flags;
+    maxbytes = params.maxbytes;
+    nblocks = params.nblocks;
+    leftover = params.leftover;
+    bstarts = params.bstarts;
+    src = params.src;
+    dest = params.dest;
+    tmp = params.tmp[tid];
+    tmp2 = params.tmp2[tid];
+
+    ntbytes = 0;                /* only useful for decompression */
+
+    if (compress && !(flags & BLOSC_MEMCPYED)) {
+      /* Compression always has to follow the block order */
+      pthread_mutex_lock(&count_mutex);
+      nblock++;
+      nblock_ = nblock;
+      pthread_mutex_unlock(&count_mutex);
+      tblock = nblocks;
+    }
+    else {
+      /* Decompression can happen using any order.  We choose
+       sequential block order on each thread */
+
+      /* Blocks per thread */
+      tblocks = nblocks / nthreads;
+      leftover2 = nblocks % nthreads;
+      tblocks = (leftover2>0)? tblocks+1: tblocks;
+
+      nblock_ = tid*tblocks;
+      tblock = nblock_ + tblocks;
+      if (tblock > nblocks) {
+        tblock = nblocks;
+      }
+    }
+
+    /* Loop over blocks */
+    leftoverblock = 0;
+    while ((nblock_ < tblock) && giveup_code > 0) {
+      bsize = blocksize;
+      if (nblock_ == (nblocks - 1) && (leftover > 0)) {
+        bsize = leftover;
+        leftoverblock = 1;
+      }
+      if (compress) {
+        if (flags & BLOSC_MEMCPYED) {
+          /* We want to memcpy only */
+          memcpy(dest+BLOSC_MAX_OVERHEAD+nblock_*blocksize,
+                 src+nblock_*blocksize, bsize);
+          cbytes = bsize;
+        }
+        else {
+          /* Regular compression */
+          cbytes = blosc_c(bsize, leftoverblock, 0, ebsize,
+                           src+nblock_*blocksize, tmp2, tmp);
+        }
+      }
+      else {
+        if (flags & BLOSC_MEMCPYED) {
+          /* We want to memcpy only */
+          memcpy(dest+nblock_*blocksize,
+                 src+BLOSC_MAX_OVERHEAD+nblock_*blocksize, bsize);
+          cbytes = bsize;
+        }
+        else {
+          cbytes = blosc_d(bsize, leftoverblock,
+                           src+sw32(bstarts[nblock_]), dest+nblock_*blocksize,
+                           tmp, tmp2);
+        }
+      }
+
+      /* Check whether current thread has to giveup */
+      if (giveup_code <= 0) {
+        break;
+      }
+
+      /* Check results for the compressed/decompressed block */
+      if (cbytes < 0) {            /* compr/decompr failure */
+        /* Set giveup_code error */
+        pthread_mutex_lock(&count_mutex);
+        giveup_code = cbytes;
+        pthread_mutex_unlock(&count_mutex);
+        break;
+      }
+
+      if (compress && !(flags & BLOSC_MEMCPYED)) {
+        /* Start critical section */
+        pthread_mutex_lock(&count_mutex);
+        ntdest = params.ntbytes;
+        bstarts[nblock_] = sw32(ntdest);    /* update block start counter */
+        if ( (cbytes == 0) || (ntdest+cbytes > (int32_t)maxbytes) ) {
+          giveup_code = 0;                  /* uncompressible buffer */
+          pthread_mutex_unlock(&count_mutex);
+          break;
+        }
+        nblock++;
+        nblock_ = nblock;
+        params.ntbytes += cbytes;           /* update return bytes counter */
+        pthread_mutex_unlock(&count_mutex);
+        /* End of critical section */
+
+        /* Copy the compressed buffer to destination */
+        memcpy(dest+ntdest, tmp2, cbytes);
+      }
+      else {
+        nblock_++;
+        /* Update counter for this thread */
+        ntbytes += cbytes;
+      }
+
+    } /* closes while (nblock_) */
+
+    /* Sum up all the bytes decompressed */
+    if ((!compress || (flags & BLOSC_MEMCPYED)) && giveup_code > 0) {
+      /* Update global counter for all threads (decompression only) */
+      pthread_mutex_lock(&count_mutex);
+      params.ntbytes += ntbytes;
+      pthread_mutex_unlock(&count_mutex);
+    }
+
+    /* Meeting point for all threads (wait for finalization) */
+    WAIT_FINISH;
+
+  }  /* closes while(1) */
+
+  /* This should never be reached, but anyway */
+  return(0);
+}
+
+
+static int init_threads(void)
+{
+  int32_t tid;
+  int rc2;
+
+  /* Initialize mutex and condition variable objects */
+  pthread_mutex_init(&count_mutex, NULL);
+
+  /* Barrier initialization */
+#ifdef _POSIX_BARRIERS_MINE
+  pthread_barrier_init(&barr_init, NULL, nthreads+1);
+  pthread_barrier_init(&barr_finish, NULL, nthreads+1);
+#else
+  pthread_mutex_init(&count_threads_mutex, NULL);
+  pthread_cond_init(&count_threads_cv, NULL);
+  count_threads = 0;      /* Reset threads counter */
+#endif
+
+#if !defined(_WIN32)
+  /* Initialize and set thread detached attribute */
+  pthread_attr_init(&ct_attr);
+  pthread_attr_setdetachstate(&ct_attr, PTHREAD_CREATE_JOINABLE);
+#endif
+
+  /* Finally, create the threads in detached state */
+  for (tid = 0; tid < nthreads; tid++) {
+    tids[tid] = tid;
+#if !defined(_WIN32)
+    rc2 = pthread_create(&threads[tid], &ct_attr, (void*)t_blosc,
+			(void *)&tids[tid]);
+#else
+    rc2 = pthread_create(&threads[tid], NULL, (void*)t_blosc,
+			(void *)&tids[tid]);
+#endif
+    if (rc2) {
+      fprintf(stderr, "ERROR; return code from pthread_create() is %d\n", rc2);
+      fprintf(stderr, "\tError detail: %s\n", strerror(rc2));
+      return(-1);
+    }
+  }
+
+  init_threads_done = 1;                 /* Initialization done! */
+  pid = (int)getpid();                   /* save the PID for this process */
+
+  return(0);
+}
+
+void blosc_init(void) {
+  /* Init global lock  */
+  pthread_mutex_init(&global_comp_mutex, NULL);
+  init_lib = 1;
+}
+
+int blosc_set_nthreads(int nthreads_new) 
+{
+  int ret;
+
+  /* Check if should initialize (implementing previous 1.2.3 behaviour,
+     where calling blosc_set_nthreads was enough) */
+  if (!init_lib) blosc_init();
+
+  /* Take global lock  */
+  pthread_mutex_lock(&global_comp_mutex);
+  
+  ret = blosc_set_nthreads_(nthreads_new);
+  /* Release global lock  */
+  pthread_mutex_unlock(&global_comp_mutex);
+  
+  return ret;
+}
+
+int blosc_set_nthreads_(int nthreads_new)
+{
+  int32_t nthreads_old = nthreads;
+  int32_t t;
+  int rc2;
+  void *status;
+
+  if (nthreads_new > BLOSC_MAX_THREADS) {
+    fprintf(stderr,
+            "Error.  nthreads cannot be larger than BLOSC_MAX_THREADS (%d)",
+            BLOSC_MAX_THREADS);
+    return -1;
+  }
+  else if (nthreads_new <= 0) {
+    fprintf(stderr, "Error.  nthreads must be a positive integer");
+    return -1;
+  }
+
+  /* Only join threads if they are not initialized or if our PID is
+     different from that in pid var (probably means that we are a
+     subprocess, and thus threads are non-existent). */
+  if (nthreads > 1 && init_threads_done && pid == getpid()) {
+      /* Tell all existing threads to finish */
+      end_threads = 1;
+      /* Synchronization point for all threads (wait for initialization) */
+      WAIT_INIT;
+      /* Join exiting threads */
+      for (t=0; t<nthreads; t++) {
+        rc2 = pthread_join(threads[t], &status);
+        if (rc2) {
+          fprintf(stderr, "ERROR; return code from pthread_join() is %d\n", rc2);
+          fprintf(stderr, "\tError detail: %s\n", strerror(rc2));
+          return(-1);
+        }
+      }
+      init_threads_done = 0;
+      end_threads = 0;
+    }
+
+  /* Launch a new pool of threads (if necessary) */
+  nthreads = nthreads_new;
+  if (nthreads > 1 && (!init_threads_done || pid != getpid())) {
+    init_threads();
+  }
+
+  return nthreads_old;
+}
+
+
+/* Free possible memory temporaries and thread resources */
+int blosc_free_resources(void)
+{
+  int32_t t;
+  int rc2;
+  void *status;
+ 
+   /* Take global lock  */
+  pthread_mutex_lock(&global_comp_mutex);
+
+  /* Release temporaries */
+  if (init_temps_done) {
+    release_temporaries();
+  }
+
+  /* Finish the possible thread pool */
+  if (nthreads > 1 && init_threads_done) {
+    /* Tell all existing threads to finish */
+    end_threads = 1;
+    /* Synchronization point for all threads (wait for initialization) */
+    WAIT_INIT;
+    /* Join exiting threads */
+    for (t=0; t<nthreads; t++) {
+      rc2 = pthread_join(threads[t], &status);
+      if (rc2) {
+        fprintf(stderr, "ERROR; return code from pthread_join() is %d\n", rc2);
+        fprintf(stderr, "\tError detail: %s\n", strerror(rc2));
+        return(-1);
+      }
+    }
+
+    /* Release mutex and condition variable objects */
+    pthread_mutex_destroy(&count_mutex);
+
+    /* Barriers */
+#ifdef _POSIX_BARRIERS_MINE
+    pthread_barrier_destroy(&barr_init);
+    pthread_barrier_destroy(&barr_finish);
+#else
+    pthread_mutex_destroy(&count_threads_mutex);
+    pthread_cond_destroy(&count_threads_cv);
+#endif
+
+    /* Thread attributes */
+#if !defined(_WIN32)
+    pthread_attr_destroy(&ct_attr);
+#endif
+
+    init_threads_done = 0;
+    end_threads = 0;
+  }
+   /* Release global lock  */
+  pthread_mutex_unlock(&global_comp_mutex);
+  return(0);
+
+}
+
+void blosc_destroy(void) {
+  /* Free the resources */
+  blosc_free_resources();
+  /* Destroy global lock */
+  pthread_mutex_destroy(&global_comp_mutex);
+}
+
+/* Return `nbytes`, `cbytes` and `blocksize` from a compressed buffer. */
+void blosc_cbuffer_sizes(const void *cbuffer, size_t *nbytes,
+                         size_t *cbytes, size_t *blocksize)
+{
+  uint8_t *_src = (uint8_t *)(cbuffer);    /* current pos for source buffer */
+  uint8_t version, versionlz;              /* versions for compressed header */
+
+  /* Read the version info (could be useful in the future) */
+  version = _src[0];                         /* blosc format version */
+  versionlz = _src[1];                       /* blosclz format version */
+
+  version += 0;                             /* shut up compiler warning */
+  versionlz += 0;                           /* shut up compiler warning */
+
+  /* Read the interesting values */
+  _src += 4;
+  *nbytes = (size_t)sw32(((int32_t *)_src)[0]);  /* uncompressed buffer size */
+  *blocksize = (size_t)sw32(((int32_t *)_src)[1]);   /* block size */
+  *cbytes = (size_t)sw32(((int32_t *)_src)[2]);  /* compressed buffer size */
+}
+
+
+/* Return `typesize` and `flags` from a compressed buffer. */
+void blosc_cbuffer_metainfo(const void *cbuffer, size_t *typesize,
+                            int *flags)
+{
+  uint8_t *_src = (uint8_t *)(cbuffer);  /* current pos for source buffer */
+  uint8_t version, versionlz;            /* versions for compressed header */
+
+  /* Read the version info (could be useful in the future) */
+  version = _src[0];                     /* blosc format version */
+  versionlz = _src[1];                   /* blosclz format version */
+
+  version += 0;                             /* shut up compiler warning */
+  versionlz += 0;                           /* shut up compiler warning */
+
+  /* Read the interesting values */
+  *flags = (int)_src[2];                 /* flags */
+  *typesize = (size_t)_src[3];           /* typesize */
+}
+
+
+/* Return version information from a compressed buffer. */
+void blosc_cbuffer_versions(const void *cbuffer, int *version,
+                            int *versionlz)
+{
+  uint8_t *_src = (uint8_t *)(cbuffer);  /* current pos for source buffer */
+
+  /* Read the version info */
+  *version = (int)_src[0];             /* blosc format version */
+  *versionlz = (int)_src[1];           /* blosclz format version */
+}
+
+
+/* Force the use of a specific blocksize.  If 0, an automatic
+   blocksize will be used (the default). */
+void blosc_set_blocksize(size_t size)
+{
+  /* Take global lock  */
+  pthread_mutex_lock(&global_comp_mutex);
+  
+  force_blocksize = (int32_t)size;
+  
+   /* Release global lock  */
+  pthread_mutex_unlock(&global_comp_mutex);
+}
Index: thirdparty/blosc/blosc.h
===================================================================
--- thirdparty/blosc/blosc.h	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
+++ thirdparty/blosc/blosc.h	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
@@ -0,0 +1,222 @@
+/*********************************************************************
+  Blosc - Blocked Suffling and Compression Library
+
+  Author: Francesc Alted <faltet@gmail.com>
+
+  See LICENSES/BLOSC.txt for details about copyright and rights to use.
+**********************************************************************/
+
+#include <limits.h>
+
+#ifndef BLOSC_H
+#define BLOSC_H
+
+/* Version numbers */
+#define BLOSC_VERSION_MAJOR    1    /* for major interface/format changes  */
+#define BLOSC_VERSION_MINOR    2    /* for minor interface/format changes  */
+#define BLOSC_VERSION_RELEASE  3    /* for tweaks, bug-fixes, or development */
+
+#define BLOSC_VERSION_STRING   "1.2.3"  /* string version.  Sync with above! */
+#define BLOSC_VERSION_REVISION "$Rev$"   /* revision version */
+#define BLOSC_VERSION_DATE     "$Date:: 2013-05-17 #$"    /* date version */
+
+/* The *_VERS_FORMAT should be just 1-byte long */
+#define BLOSC_VERSION_FORMAT    2   /* Blosc format version, starting at 1 */
+#define BLOSCLZ_VERSION_FORMAT  1   /* Blosclz format version, starting at 1 */
+
+/* The combined blosc and blosclz formats */
+#define BLOSC_VERSION_CFORMAT (BLOSC_VERSION_FORMAT << 8) & (BLOSCLZ_VERSION_FORMAT)
+
+/* Minimum header length */
+#define BLOSC_MIN_HEADER_LENGTH 16
+
+/* The maximum overhead during compression in bytes.  This equals to
+   BLOSC_MIN_HEADER_LENGTH now, but can be higher in future
+   implementations */
+#define BLOSC_MAX_OVERHEAD BLOSC_MIN_HEADER_LENGTH
+
+/* Maximum buffer size to be compressed */
+#define BLOSC_MAX_BUFFERSIZE (INT_MAX - BLOSC_MAX_OVERHEAD)
+
+/* Maximum typesize before considering buffer as a stream of bytes */
+#define BLOSC_MAX_TYPESIZE 255         /* Cannot be larger than 255 */
+
+/* The maximum number of threads (for some static arrays) */
+#define BLOSC_MAX_THREADS 256
+
+/* Codes for internal flags (see blosc_cbuffer_metainfo) */
+#define BLOSC_DOSHUFFLE 0x1
+#define BLOSC_MEMCPYED  0x2
+
+
+
+/**
+  Initialize the Blosc library. You must call this previous to any other
+  Blosc call, and make sure that you call this in a non-threaded environment.
+  Other Blosc calls can be called in a threaded environment, if desired.
+
+ */
+
+void blosc_init(void);
+
+
+/**
+
+  Destroy the Blosc library environment. You must call this after to you are
+  done with all the Blosc calls, and make sure that you call this in a
+  non-threaded environment.
+
+ */
+
+void blosc_destroy(void);
+
+
+/**
+  Compress a block of data in the `src` buffer and returns the size of
+  compressed block.  The size of `src` buffer is specified by
+  `nbytes`.  There is not a minimum for `src` buffer size (`nbytes`).
+
+  `clevel` is the desired compression level and must be a number
+  between 0 (no compression) and 9 (maximum compression).
+
+  `doshuffle` specifies whether the shuffle compression preconditioner
+  should be applied or not.  0 means not applying it and 1 means
+  applying it.
+
+  `typesize` is the number of bytes for the atomic type in binary
+  `src` buffer.  This is mainly useful for the shuffle preconditioner.
+  Only a typesize > 1 will allow the shuffle to work.
+
+  The `dest` buffer must have at least the size of `destsize`.  Blosc
+  guarantees that if you set `destsize` to, at least,
+  (`nbytes`+BLOSC_MAX_OVERHEAD), the compression will always succeed.
+  The `src` buffer and the `dest` buffer can not overlap.
+
+  If `src` buffer cannot be compressed into `destsize`, the return
+  value is zero and you should discard the contents of the `dest`
+  buffer.
+
+  A negative return value means that an internal error happened.  This
+  should never happen.  If you see this, please report it back
+  together with the buffer data causing this and compression settings.
+
+  Compression is memory safe and guaranteed not to write the `dest`
+  buffer more than what is specified in `destsize`.  However, it is
+  not re-entrant and not thread-safe (despite the fact that it uses
+  threads internally).
+ */
+
+int blosc_compress(int clevel, int doshuffle, size_t typesize, size_t nbytes,
+                   const void *src, void *dest, size_t destsize);
+
+
+/**
+  Decompress a block of compressed data in `src`, put the result in
+  `dest` and returns the size of the decompressed block. If error
+  occurs, e.g. the compressed data is corrupted or the output buffer
+  is not large enough, then 0 (zero) or a negative value will be
+  returned instead.
+
+  The `src` buffer and the `dest` buffer can not overlap.
+
+  Decompression is memory safe and guaranteed not to write the `dest`
+  buffer more than what is specified in `destsize`.  However, it is
+  not re-entrant and not thread-safe (despite the fact that it uses
+  threads internally).
+*/
+
+int blosc_decompress(const void *src, void *dest, size_t destsize);
+
+
+/**
+  Get `nitems` (of typesize size) in `src` buffer starting in `start`.
+  The items are returned in `dest` buffer, which has to have enough
+  space for storing all items.  Returns the number of bytes copied to
+  `dest` or a negative value if some error happens.
+ */
+
+int blosc_getitem(const void *src, int start, int nitems, void *dest);
+
+
+/**
+  Initialize a pool of threads for compression/decompression.  If
+  `nthreads` is 1, then the serial version is chosen and a possible
+  previous existing pool is ended.  Returns the previous number of
+  threads.  If this is not called, `nthreads` is set to 1 internally.
+*/
+
+int blosc_set_nthreads(int nthreads);
+
+
+/**
+  Free possible memory temporaries and thread resources.  Use this when you
+  are not going to use Blosc for a long while.  In case of problems releasing
+  the resources, it returns a negative number, else it returns 0.
+*/
+
+int blosc_free_resources(void);
+
+
+/**
+  Return information about a compressed buffer, namely the number of
+  uncompressed bytes (`nbytes`) and compressed (`cbytes`).  It also
+  returns the `blocksize` (which is used internally for doing the
+  compression by blocks).
+
+  You only need to pass the first BLOSC_MIN_HEADER_LENGTH bytes of a
+  compressed buffer for this call to work.
+
+  This function should always succeed.
+*/
+
+void blosc_cbuffer_sizes(const void *cbuffer, size_t *nbytes,
+                         size_t *cbytes, size_t *blocksize);
+
+
+/**
+  Return information about a compressed buffer, namely the type size
+  (`typesize`), as well as some internal `flags`.
+
+  The `flags` is a set of bits, where the currently used ones are:
+    * bit 0: whether the shuffle filter has been applied or not
+    * bit 1: whether the internal buffer is a pure memcpy or not
+
+  You can use the `BLOSC_DOSHUFFLE` and `BLOSC_MEMCPYED` symbols for
+  extracting the interesting bits (e.g. ``flags & BLOSC_DOSHUFFLE``
+  says whether the buffer is shuffled or not).
+
+  This function should always succeed.
+*/
+
+void blosc_cbuffer_metainfo(const void *cbuffer, size_t *typesize,
+                            int *flags);
+
+
+/**
+  Return information about a compressed buffer, namely the internal
+  Blosc format version (`version`) and the format for the internal
+  Lempel-Ziv algorithm (`versionlz`).  This function should always
+  succeed.
+*/
+
+void blosc_cbuffer_versions(const void *cbuffer, int *version,
+                            int *versionlz);
+
+
+
+/*********************************************************************
+
+  Low-level functions follows.  Use them only if you are an expert!
+
+*********************************************************************/
+
+
+/**
+  Force the use of a specific blocksize.  If 0, an automatic
+  blocksize will be used (the default).
+*/
+
+void blosc_set_blocksize(size_t blocksize);
+
+
+#endif
Index: thirdparty/blosc/blosclz.c
===================================================================
--- thirdparty/blosc/blosclz.c	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
+++ thirdparty/blosc/blosclz.c	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
@@ -0,0 +1,463 @@
+/*********************************************************************
+  Blosc - Blocked Suffling and Compression Library
+
+  Author: Francesc Alted <faltet@gmail.com>
+  Creation date: 2009-05-20
+
+  See LICENSES/BLOSC.txt for details about copyright and rights to use.
+**********************************************************************/
+
+/*********************************************************************
+  The code in this file is heavily based on FastLZ, a lightning-fast
+  lossless compression library.  See LICENSES/FASTLZ.txt for details.
+**********************************************************************/
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "blosclz.h"
+
+#if defined(_WIN32) && !defined(__MINGW32__)
+  #include <windows.h>
+  #include "win32/stdint-windows.h"
+#else
+  #include <stdint.h>
+#endif  /* _WIN32 */
+
+
+/*
+ * Prevent accessing more than 8-bit at once, except on x86 architectures.
+ */
+#if !defined(BLOSCLZ_STRICT_ALIGN)
+#define BLOSCLZ_STRICT_ALIGN
+#if defined(__i386__) || defined(__386) || defined (__amd64)  /* GNU C, Sun Studio */
+#undef BLOSCLZ_STRICT_ALIGN
+#elif defined(__i486__) || defined(__i586__) || defined(__i686__)  /* GNU C */
+#undef BLOSCLZ_STRICT_ALIGN
+#elif defined(_M_IX86) /* Intel, MSVC */
+#undef BLOSCLZ_STRICT_ALIGN
+#elif defined(__386)
+#undef BLOSCLZ_STRICT_ALIGN
+#elif defined(_X86_) /* MinGW */
+#undef BLOSCLZ_STRICT_ALIGN
+#elif defined(__I86__) /* Digital Mars */
+#undef BLOSCLZ_STRICT_ALIGN
+#endif
+#endif
+
+/*
+ * Always check for bound when decompressing.
+ * Generally it is best to leave it defined.
+ */
+#define BLOSCLZ_SAFE
+
+/*
+ * Give hints to the compiler for branch prediction optimization.
+ */
+#if defined(__GNUC__) && (__GNUC__ > 2)
+#define BLOSCLZ_EXPECT_CONDITIONAL(c)    (__builtin_expect((c), 1))
+#define BLOSCLZ_UNEXPECT_CONDITIONAL(c)  (__builtin_expect((c), 0))
+#else
+#define BLOSCLZ_EXPECT_CONDITIONAL(c)    (c)
+#define BLOSCLZ_UNEXPECT_CONDITIONAL(c)  (c)
+#endif
+
+/*
+ * Use inlined functions for supported systems.
+ */
+#if defined(__GNUC__) || defined(__DMC__) || defined(__POCC__) || defined(__WATCOMC__) || defined(__SUNPRO_C)
+#define BLOSCLZ_INLINE inline
+#elif defined(__BORLANDC__) || defined(_MSC_VER) || defined(__LCC__)
+#define BLOSCLZ_INLINE __inline
+#else
+#define BLOSCLZ_INLINE
+#endif
+
+#define MAX_COPY       32
+#define MAX_LEN       264  /* 256 + 8 */
+#define MAX_DISTANCE 8191
+#define MAX_FARDISTANCE (65535+MAX_DISTANCE-1)
+
+#ifdef BLOSCLZ_STRICT_ALIGN
+  #define BLOSCLZ_READU16(p) ((p)[0] | (p)[1]<<8)
+#else
+  #define BLOSCLZ_READU16(p) *((const uint16_t*)(p))
+#endif
+
+
+static BLOSCLZ_INLINE int32_t hash_function(uint8_t* p, uint8_t hash_log)
+{
+  int32_t v;
+
+  v = BLOSCLZ_READU16(p);
+  v ^= BLOSCLZ_READU16(p+1)^(v>>(16-hash_log));
+  v &= (1 << hash_log) - 1;
+  return v;
+}
+
+
+#define IP_BOUNDARY 2
+
+int blosclz_compress(int opt_level, const void* input,
+                     int length, void* output, int maxout)
+{
+  uint8_t* ip = (uint8_t*) input;
+  uint8_t* ibase = (uint8_t*) input;
+  uint8_t* ip_bound = ip + length - IP_BOUNDARY;
+  uint8_t* ip_limit = ip + length - 12;
+  uint8_t* op = (uint8_t*) output;
+
+  /* Hash table depends on the opt level.  Hash_log cannot be larger than 15. */
+  uint8_t hash_log_[10] = {-1, 8, 9, 9, 11, 11, 12, 13, 14, 15};
+  uint8_t hash_log = hash_log_[opt_level];
+  uint16_t hash_size = 1 << hash_log;
+  uint16_t *htab;
+  uint8_t* op_limit;
+
+  int32_t hslot;
+  int32_t hval;
+  uint8_t copy;
+
+  double maxlength_[10] = {-1, .1, .15, .2, .5, .7, .85, .925, .975, 1.0};
+  int32_t maxlength = (int32_t) (length * maxlength_[opt_level]);
+  if (maxlength > (int32_t) maxout) {
+    maxlength = (int32_t) maxout;
+  }
+  op_limit = op + maxlength;
+
+  /* output buffer cannot be less than 66 bytes or we can get into problems.
+     As output is usually the same length than input, we take input length. */
+  if (length < 66) {
+    return 0;                   /* Mark this as uncompressible */
+  }
+
+  htab = (uint16_t *) malloc(hash_size*sizeof(uint16_t));
+
+  /* sanity check */
+  if(BLOSCLZ_UNEXPECT_CONDITIONAL(length < 4)) {
+    if(length) {
+      /* create literal copy only */
+      *op++ = length-1;
+      ip_bound++;
+      while(ip <= ip_bound)
+        *op++ = *ip++;
+      free(htab);
+      return length+1;
+    }
+    else goto out;
+  }
+
+  /* initializes hash table */
+  for (hslot = 0; hslot < hash_size; hslot++)
+    htab[hslot] = 0;
+
+  /* we start with literal copy */
+  copy = 2;
+  *op++ = MAX_COPY-1;
+  *op++ = *ip++;
+  *op++ = *ip++;
+
+  /* main loop */
+  while(BLOSCLZ_EXPECT_CONDITIONAL(ip < ip_limit)) {
+    const uint8_t* ref;
+    int32_t distance;
+    int32_t len = 3;         /* minimum match length */
+    uint8_t* anchor = ip;  /* comparison starting-point */
+
+    /* check for a run */
+    if(ip[0] == ip[-1] && BLOSCLZ_READU16(ip-1)==BLOSCLZ_READU16(ip+1)) {
+      distance = 1;
+      ip += 3;
+      ref = anchor - 1 + 3;
+      goto match;
+    }
+
+    /* find potential match */
+    hval = hash_function(ip, hash_log);
+    ref = ibase + htab[hval];
+    /* update hash table */
+    htab[hval] = (uint16_t)(anchor - ibase);
+
+    /* calculate distance to the match */
+    distance = (int32_t)(anchor - ref);
+
+    /* is this a match? check the first 3 bytes */
+    if (distance==0 || (distance >= MAX_FARDISTANCE) ||
+        *ref++ != *ip++ || *ref++!=*ip++ || *ref++!=*ip++)
+      goto literal;
+
+    /* far, needs at least 5-byte match */
+    if (distance >= MAX_DISTANCE) {
+      if (*ip++ != *ref++ || *ip++ != *ref++)
+        goto literal;
+      len += 2;
+    }
+
+    match:
+
+    /* last matched byte */
+    ip = anchor + len;
+
+    /* distance is biased */
+    distance--;
+
+    if(!distance) {
+      /* zero distance means a run */
+      uint8_t x = ip[-1];
+      int64_t value, value2;
+      /* Broadcast the value for every byte in a 64-bit register */
+      memset(&value, x, 8);
+      /* safe because the outer check against ip limit */
+      while (ip < (ip_bound - (sizeof(int64_t) - IP_BOUNDARY))) {
+        value2 = ((int64_t *)ref)[0];
+        if (value != value2) {
+          /* Find the byte that starts to differ */
+          while (ip < ip_bound) {
+            if (*ref++ != x) break; else ip++;
+          }
+          break;
+        }
+        else {
+          ip += 8;
+          ref += 8;
+        }
+      }
+      if (ip > ip_bound) {
+        long l = (long)(ip - ip_bound);
+        ip -= l;
+        ref -= l;
+      }   /* End of optimization */
+    }
+    else {
+      for(;;) {
+        /* safe because the outer check against ip limit */
+        while (ip < (ip_bound - (sizeof(int64_t) - IP_BOUNDARY))) {
+          if (*ref++ != *ip++) break;
+          if (((int64_t *)ref)[0] != ((int64_t *)ip)[0]) {
+            /* Find the byte that starts to differ */
+            while (ip < ip_bound) {
+              if (*ref++ != *ip++) break;
+            }
+            break;
+          }
+          else {
+            ip += 8;
+            ref += 8;
+          }
+        }
+        /* Last correction before exiting loop */
+        if (ip > ip_bound) {
+          int32_t l = (int32_t)(ip - ip_bound);
+          ip -= l;
+          ref -= l;
+        }   /* End of optimization */
+        break;
+      }
+    }
+
+    /* if we have copied something, adjust the copy count */
+    if (copy)
+      /* copy is biased, '0' means 1 byte copy */
+      *(op-copy-1) = copy-1;
+    else
+      /* back, to overwrite the copy count */
+      op--;
+
+    /* reset literal counter */
+    copy = 0;
+
+    /* length is biased, '1' means a match of 3 bytes */
+    ip -= 3;
+    len = (int32_t)(ip - anchor);
+
+    /* check that we have space enough to encode the match for all the cases */
+    if (BLOSCLZ_UNEXPECT_CONDITIONAL(op+(len/255)+6 > op_limit)) goto out;
+
+    /* encode the match */
+    if(distance < MAX_DISTANCE) {
+      if(len < 7) {
+        *op++ = (len << 5) + (distance >> 8);
+        *op++ = (distance & 255);
+      }
+      else {
+        *op++ = (uint8_t)((7 << 5) + (distance >> 8));
+        for(len-=7; len >= 255; len-= 255)
+          *op++ = 255;
+        *op++ = len;
+        *op++ = (distance & 255);
+      }
+    }
+    else {
+      /* far away, but not yet in the another galaxy... */
+      if(len < 7) {
+        distance -= MAX_DISTANCE;
+        *op++ = (uint8_t)((len << 5) + 31);
+        *op++ = 255;
+        *op++ = (uint8_t)(distance >> 8);
+        *op++ = distance & 255;
+      }
+      else {
+        distance -= MAX_DISTANCE;
+        *op++ = (7 << 5) + 31;
+        for(len-=7; len >= 255; len-= 255)
+          *op++ = 255;
+        *op++ = len;
+        *op++ = 255;
+        *op++ = (uint8_t)(distance >> 8);
+        *op++ = distance & 255;
+      }
+    }
+
+    /* update the hash at match boundary */
+    hval = hash_function(ip, hash_log);
+    htab[hval] = (uint16_t)(ip++ - ibase);
+    hval = hash_function(ip, hash_log);
+    htab[hval] = (uint16_t)(ip++ - ibase);
+
+    /* assuming literal copy */
+    *op++ = MAX_COPY-1;
+
+    continue;
+
+  literal:
+    if (BLOSCLZ_UNEXPECT_CONDITIONAL(op+2 > op_limit)) goto out;
+    *op++ = *anchor++;
+    ip = anchor;
+    copy++;
+    if(BLOSCLZ_UNEXPECT_CONDITIONAL(copy == MAX_COPY)) {
+      copy = 0;
+      *op++ = MAX_COPY-1;
+    }
+  }
+
+  /* left-over as literal copy */
+  ip_bound++;
+  while(ip <= ip_bound) {
+    if (BLOSCLZ_UNEXPECT_CONDITIONAL(op+2 > op_limit)) goto out;
+    *op++ = *ip++;
+    copy++;
+    if(copy == MAX_COPY) {
+      copy = 0;
+      *op++ = MAX_COPY-1;
+    }
+  }
+
+  /* if we have copied something, adjust the copy length */
+  if(copy)
+    *(op-copy-1) = copy-1;
+  else
+    op--;
+
+  /* marker for blosclz */
+  *(uint8_t*)output |= (1 << 5);
+
+  free(htab);
+  return (int)(op - (uint8_t*)output);
+
+ out:
+  free(htab);
+  return 0;
+
+}
+
+
+int blosclz_decompress(const void* input, int length, void* output, int maxout)
+{
+  const uint8_t* ip = (const uint8_t*) input;
+  const uint8_t* ip_limit  = ip + length;
+  uint8_t* op = (uint8_t*) output;
+  uint8_t* op_limit = op + maxout;
+  int32_t ctrl = (*ip++) & 31;
+  int32_t loop = 1;
+
+  do {
+    const uint8_t* ref = op;
+    int32_t len = ctrl >> 5;
+    int32_t ofs = (ctrl & 31) << 8;
+
+    if(ctrl >= 32) {
+      uint8_t code;
+      len--;
+      ref -= ofs;
+      if (len == 7-1)
+        do {
+          code = *ip++;
+          len += code;
+        } while (code==255);
+      code = *ip++;
+      ref -= code;
+
+      /* match from 16-bit distance */
+      if(BLOSCLZ_UNEXPECT_CONDITIONAL(code==255))
+      if(BLOSCLZ_EXPECT_CONDITIONAL(ofs==(31 << 8))) {
+        ofs = (*ip++) << 8;
+        ofs += *ip++;
+        ref = op - ofs - MAX_DISTANCE;
+      }
+
+#ifdef BLOSCLZ_SAFE
+      if (BLOSCLZ_UNEXPECT_CONDITIONAL(op + len + 3 > op_limit)) {
+        return 0;
+      }
+
+      if (BLOSCLZ_UNEXPECT_CONDITIONAL(ref-1 < (uint8_t *)output)) {
+        return 0;
+      }
+#endif
+
+      if(BLOSCLZ_EXPECT_CONDITIONAL(ip < ip_limit))
+        ctrl = *ip++;
+      else
+        loop = 0;
+
+      if(ref == op) {
+        /* optimize copy for a run */
+        uint8_t b = ref[-1];
+        memset(op, b, len+3);
+        op += len+3;
+      }
+      else {
+        /* copy from reference */
+        ref--;
+        len += 3;
+        if (abs((int32_t)(ref-op)) <= (int32_t)len) {
+          /* src and dst do overlap: do a loop */
+          for(; len; --len)
+            *op++ = *ref++;
+          /* The memmove below does not work well (don't know why) */
+          /* memmove(op, ref, len);
+             op += len;
+             ref += len;
+             len = 0; */
+        }
+        else {
+          memcpy(op, ref, len);
+          op += len;
+          ref += len;
+        }
+      }
+    }
+    else {
+      ctrl++;
+#ifdef BLOSCLZ_SAFE
+      if (BLOSCLZ_UNEXPECT_CONDITIONAL(op + ctrl > op_limit)) {
+        return 0;
+      }
+      if (BLOSCLZ_UNEXPECT_CONDITIONAL(ip + ctrl > ip_limit)) {
+        return 0;
+      }
+#endif
+
+      memcpy(op, ip, ctrl);
+      ip += ctrl;
+      op += ctrl;
+
+      loop = (int32_t)BLOSCLZ_EXPECT_CONDITIONAL(ip < ip_limit);
+      if(loop)
+        ctrl = *ip++;
+    }
+  } while(BLOSCLZ_EXPECT_CONDITIONAL(loop));
+
+  return (int)(op - (uint8_t*)output);
+}
Index: thirdparty/blosc/blosclz.h
===================================================================
--- thirdparty/blosc/blosclz.h	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
+++ thirdparty/blosc/blosclz.h	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
@@ -0,0 +1,59 @@
+/*********************************************************************
+  Blosc - Blocked Suffling and Compression Library
+
+  Author: Francesc Alted <faltet@gmail.com>
+
+  See LICENSES/BLOSC.txt for details about copyright and rights to use.
+**********************************************************************/
+
+/*********************************************************************
+  The code in this file is heavily based on FastLZ, a lightning-fast
+  lossless compression library.  See LICENSES/FASTLZ.txt for details
+  about copyright and rights to use.
+**********************************************************************/
+
+
+#ifndef BLOSCLZ_H
+#define BLOSCLZ_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/**
+  Compress a block of data in the input buffer and returns the size of
+  compressed block. The size of input buffer is specified by
+  length. The minimum input buffer size is 16.
+
+  The output buffer must be at least 5% larger than the input buffer
+  and can not be smaller than 66 bytes.
+
+  If the input is not compressible, or output does not fit in maxout
+  bytes, the return value will be 0 and you will have to discard the
+  output buffer.
+
+  The input buffer and the output buffer can not overlap.
+*/
+
+int blosclz_compress(int opt_level, const void* input, int length,
+                     void* output, int maxout);
+
+/**
+  Decompress a block of compressed data and returns the size of the
+  decompressed block. If error occurs, e.g. the compressed data is
+  corrupted or the output buffer is not large enough, then 0 (zero)
+  will be returned instead.
+
+  The input buffer and the output buffer can not overlap.
+
+  Decompression is memory safe and guaranteed not to write the output buffer
+  more than what is specified in maxout.
+ */
+
+int blosclz_decompress(const void* input, int length, void* output, int maxout);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* BLOSCLZ_H */
Index: thirdparty/blosc/shuffle.c
===================================================================
--- thirdparty/blosc/shuffle.c	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
+++ thirdparty/blosc/shuffle.c	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
@@ -0,0 +1,502 @@
+/*********************************************************************
+  Blosc - Blocked Suffling and Compression Library
+
+  Author: Francesc Alted <faltet@gmail.com>
+  Creation date: 2009-05-20
+
+  See LICENSES/BLOSC.txt for details about copyright and rights to use.
+**********************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include "shuffle.h"
+
+#if defined(_WIN32) && !defined(__MINGW32__)
+  #include <windows.h>
+  #include "win32/stdint-windows.h"
+  #define __SSE2__          /* Windows does not define this by default */
+#else
+  #include <stdint.h>
+  #include <inttypes.h>
+#endif  /* _WIN32 */
+
+
+/* The non-SSE2 versions of shuffle and unshuffle */
+
+/* Shuffle a block.  This can never fail. */
+static void _shuffle(size_t bytesoftype, size_t blocksize,
+	                 uint8_t* _src, uint8_t* _dest)
+{
+  size_t i, j, neblock, leftover;
+
+  /* Non-optimized shuffle */
+  neblock = blocksize / bytesoftype;  /* Number of elements in a block */
+  for (j = 0; j < bytesoftype; j++) {
+    for (i = 0; i < neblock; i++) {
+      _dest[j*neblock+i] = _src[i*bytesoftype+j];
+    }
+  }
+  leftover = blocksize % bytesoftype;
+  memcpy(_dest + neblock*bytesoftype, _src + neblock*bytesoftype, leftover);
+}
+
+/* Unshuffle a block.  This can never fail. */
+static void _unshuffle(size_t bytesoftype, size_t blocksize,
+                       uint8_t* _src, uint8_t* _dest)
+{
+  size_t i, j, neblock, leftover;
+
+  /* Non-optimized unshuffle */
+  neblock = blocksize / bytesoftype;  /* Number of elements in a block */
+  for (i = 0; i < neblock; i++) {
+    for (j = 0; j < bytesoftype; j++) {
+      _dest[i*bytesoftype+j] = _src[j*neblock+i];
+    }
+  }
+  leftover = blocksize % bytesoftype;
+  memcpy(_dest+neblock*bytesoftype, _src+neblock*bytesoftype, leftover);
+}
+
+
+#ifdef __SSE2__
+
+/* The SSE2 versions of shuffle and unshuffle */
+
+#include <emmintrin.h>
+
+/* The next is useful for debugging purposes */
+#if 0
+static void printxmm(__m128i xmm0)
+{
+  uint8_t buf[16];
+
+  ((__m128i *)buf)[0] = xmm0;
+  printf("%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n",
+          buf[0], buf[1], buf[2], buf[3],
+          buf[4], buf[5], buf[6], buf[7],
+          buf[8], buf[9], buf[10], buf[11],
+          buf[12], buf[13], buf[14], buf[15]);
+}
+#endif
+
+
+/* Routine optimized for shuffling a buffer for a type size of 2 bytes. */
+static void
+shuffle2(uint8_t* dest, uint8_t* src, size_t size)
+{
+  size_t i, j, k;
+  size_t numof16belem;
+  __m128i xmm0[2], xmm1[2];
+
+  numof16belem = size / (16*2);
+  for (i = 0, j = 0; i < numof16belem; i++, j += 16*2) {
+    /* Fetch and transpose bytes, words and double words in groups of
+       32 bytes */
+    for (k = 0; k < 2; k++) {
+      xmm0[k] = _mm_loadu_si128((__m128i*)(src+j+k*16));
+      xmm0[k] = _mm_shufflelo_epi16(xmm0[k], 0xd8);
+      xmm0[k] = _mm_shufflehi_epi16(xmm0[k], 0xd8);
+      xmm0[k] = _mm_shuffle_epi32(xmm0[k], 0xd8);
+      xmm1[k] = _mm_shuffle_epi32(xmm0[k], 0x4e);
+      xmm0[k] = _mm_unpacklo_epi8(xmm0[k], xmm1[k]);
+      xmm0[k] = _mm_shuffle_epi32(xmm0[k], 0xd8);
+      xmm1[k] = _mm_shuffle_epi32(xmm0[k], 0x4e);
+      xmm0[k] = _mm_unpacklo_epi16(xmm0[k], xmm1[k]);
+      xmm0[k] = _mm_shuffle_epi32(xmm0[k], 0xd8);
+    }
+    /* Transpose quad words */
+    for (k = 0; k < 1; k++) {
+      xmm1[k*2] = _mm_unpacklo_epi64(xmm0[k], xmm0[k+1]);
+      xmm1[k*2+1] = _mm_unpackhi_epi64(xmm0[k], xmm0[k+1]);
+    }
+    /* Store the result vectors */
+    for (k = 0; k < 2; k++) {
+      ((__m128i *)dest)[k*numof16belem+i] = xmm1[k];
+    }
+  }
+}
+
+
+/* Routine optimized for shuffling a buffer for a type size of 4 bytes. */
+static void
+shuffle4(uint8_t* dest, uint8_t* src, size_t size)
+{
+  size_t i, j, k;
+  size_t numof16belem;
+  __m128i xmm0[4], xmm1[4];
+
+  numof16belem = size / (16*4);
+  for (i = 0, j = 0; i < numof16belem; i++, j += 16*4) {
+    /* Fetch and transpose bytes and words in groups of 64 bytes */
+    for (k = 0; k < 4; k++) {
+      xmm0[k] = _mm_loadu_si128((__m128i*)(src+j+k*16));
+      xmm1[k] = _mm_shuffle_epi32(xmm0[k], 0xd8);
+      xmm0[k] = _mm_shuffle_epi32(xmm0[k], 0x8d);
+      xmm0[k] = _mm_unpacklo_epi8(xmm1[k], xmm0[k]);
+      xmm1[k] = _mm_shuffle_epi32(xmm0[k], 0x04e);
+      xmm0[k] = _mm_unpacklo_epi16(xmm0[k], xmm1[k]);
+    }
+    /* Transpose double words */
+    for (k = 0; k < 2; k++) {
+      xmm1[k*2] = _mm_unpacklo_epi32(xmm0[k*2], xmm0[k*2+1]);
+      xmm1[k*2+1] = _mm_unpackhi_epi32(xmm0[k*2], xmm0[k*2+1]);
+    }
+    /* Transpose quad words */
+    for (k = 0; k < 2; k++) {
+      xmm0[k*2] = _mm_unpacklo_epi64(xmm1[k], xmm1[k+2]);
+      xmm0[k*2+1] = _mm_unpackhi_epi64(xmm1[k], xmm1[k+2]);
+    }
+    /* Store the result vectors */
+    for (k = 0; k < 4; k++) {
+      ((__m128i *)dest)[k*numof16belem+i] = xmm0[k];
+    }
+  }
+}
+
+
+/* Routine optimized for shuffling a buffer for a type size of 8 bytes. */
+static void
+shuffle8(uint8_t* dest, uint8_t* src, size_t size)
+{
+  size_t i, j, k, l;
+  size_t numof16belem;
+  __m128i xmm0[8], xmm1[8];
+
+  numof16belem = size / (16*8);
+  for (i = 0, j = 0; i < numof16belem; i++, j += 16*8) {
+    /* Fetch and transpose bytes in groups of 128 bytes */
+    for (k = 0; k < 8; k++) {
+      xmm0[k] = _mm_loadu_si128((__m128i*)(src+j+k*16));
+      xmm1[k] = _mm_shuffle_epi32(xmm0[k], 0x4e);
+      xmm1[k] = _mm_unpacklo_epi8(xmm0[k], xmm1[k]);
+    }
+    /* Transpose words */
+    for (k = 0, l = 0; k < 4; k++, l +=2) {
+      xmm0[k*2] = _mm_unpacklo_epi16(xmm1[l], xmm1[l+1]);
+      xmm0[k*2+1] = _mm_unpackhi_epi16(xmm1[l], xmm1[l+1]);
+    }
+    /* Transpose double words */
+    for (k = 0, l = 0; k < 4; k++, l++) {
+      if (k == 2) l += 2;
+      xmm1[k*2] = _mm_unpacklo_epi32(xmm0[l], xmm0[l+2]);
+      xmm1[k*2+1] = _mm_unpackhi_epi32(xmm0[l], xmm0[l+2]);
+    }
+    /* Transpose quad words */
+    for (k = 0; k < 4; k++) {
+      xmm0[k*2] = _mm_unpacklo_epi64(xmm1[k], xmm1[k+4]);
+      xmm0[k*2+1] = _mm_unpackhi_epi64(xmm1[k], xmm1[k+4]);
+    }
+    /* Store the result vectors */
+    for (k = 0; k < 8; k++) {
+      ((__m128i *)dest)[k*numof16belem+i] = xmm0[k];
+    }
+  }
+}
+
+
+/* Routine optimized for shuffling a buffer for a type size of 16 bytes. */
+static void
+shuffle16(uint8_t* dest, uint8_t* src, size_t size)
+{
+  size_t i, j, k, l;
+  size_t numof16belem;
+  __m128i xmm0[16], xmm1[16];
+
+  numof16belem = size / (16*16);
+  for (i = 0, j = 0; i < numof16belem; i++, j += 16*16) {
+    /* Fetch elements in groups of 256 bytes */
+    for (k = 0; k < 16; k++) {
+      xmm0[k] = _mm_loadu_si128((__m128i*)(src+j+k*16));
+    }
+    /* Transpose bytes */
+    for (k = 0, l = 0; k < 8; k++, l +=2) {
+      xmm1[k*2] = _mm_unpacklo_epi8(xmm0[l], xmm0[l+1]);
+      xmm1[k*2+1] = _mm_unpackhi_epi8(xmm0[l], xmm0[l+1]);
+    }
+    /* Transpose words */
+    for (k = 0, l = -2; k < 8; k++, l++) {
+      if ((k%2) == 0) l += 2;
+      xmm0[k*2] = _mm_unpacklo_epi16(xmm1[l], xmm1[l+2]);
+      xmm0[k*2+1] = _mm_unpackhi_epi16(xmm1[l], xmm1[l+2]);
+    }
+    /* Transpose double words */
+    for (k = 0, l = -4; k < 8; k++, l++) {
+      if ((k%4) == 0) l += 4;
+      xmm1[k*2] = _mm_unpacklo_epi32(xmm0[l], xmm0[l+4]);
+      xmm1[k*2+1] = _mm_unpackhi_epi32(xmm0[l], xmm0[l+4]);
+    }
+    /* Transpose quad words */
+    for (k = 0; k < 8; k++) {
+      xmm0[k*2] = _mm_unpacklo_epi64(xmm1[k], xmm1[k+8]);
+      xmm0[k*2+1] = _mm_unpackhi_epi64(xmm1[k], xmm1[k+8]);
+    }
+    /* Store the result vectors */
+    for (k = 0; k < 16; k++) {
+      ((__m128i *)dest)[k*numof16belem+i] = xmm0[k];
+    }
+  }
+}
+
+
+/* Shuffle a block.  This can never fail. */
+void shuffle(size_t bytesoftype, size_t blocksize,
+             uint8_t* _src, uint8_t* _dest) {
+  int unaligned_dest = (int)((uintptr_t)_dest % 16);
+  int power_of_two = (blocksize & (blocksize - 1)) == 0;
+  int too_small = (blocksize < 256);
+
+  if (unaligned_dest || !power_of_two || too_small) {
+    /* _dest buffer is not aligned, not a power of two or is too
+       small.  Call the non-sse2 version. */
+    _shuffle(bytesoftype, blocksize, _src, _dest);
+    return;
+  }
+
+  /* Optimized shuffle */
+  /* The buffer must be aligned on a 16 bytes boundary, have a power */
+  /* of 2 size and be larger or equal than 256 bytes. */
+  if (bytesoftype == 4) {
+    shuffle4(_dest, _src, blocksize);
+  }
+  else if (bytesoftype == 8) {
+    shuffle8(_dest, _src, blocksize);
+  }
+  else if (bytesoftype == 16) {
+    shuffle16(_dest, _src, blocksize);
+  }
+  else if (bytesoftype == 2) {
+    shuffle2(_dest, _src, blocksize);
+  }
+  else {
+    /* Non-optimized shuffle */
+    _shuffle(bytesoftype, blocksize, _src, _dest);
+  }
+}
+
+
+/* Routine optimized for unshuffling a buffer for a type size of 2 bytes. */
+static void
+unshuffle2(uint8_t* dest, uint8_t* orig, size_t size)
+{
+  size_t i, k;
+  size_t neblock, numof16belem;
+  __m128i xmm1[2], xmm2[2];
+
+  neblock = size / 2;
+  numof16belem = neblock / 16;
+  for (i = 0, k = 0; i < numof16belem; i++, k += 2) {
+    /* Load the first 32 bytes in 2 XMM registrers */
+    xmm1[0] = ((__m128i *)orig)[0*numof16belem+i];
+    xmm1[1] = ((__m128i *)orig)[1*numof16belem+i];
+    /* Shuffle bytes */
+    /* Compute the low 32 bytes */
+    xmm2[0] = _mm_unpacklo_epi8(xmm1[0], xmm1[1]);
+    /* Compute the hi 32 bytes */
+    xmm2[1] = _mm_unpackhi_epi8(xmm1[0], xmm1[1]);
+    /* Store the result vectors in proper order */
+    ((__m128i *)dest)[k+0] = xmm2[0];
+    ((__m128i *)dest)[k+1] = xmm2[1];
+  }
+}
+
+
+/* Routine optimized for unshuffling a buffer for a type size of 4 bytes. */
+static void
+unshuffle4(uint8_t* dest, uint8_t* orig, size_t size)
+{
+  size_t i, j, k;
+  size_t neblock, numof16belem;
+  __m128i xmm0[4], xmm1[4];
+
+  neblock = size / 4;
+  numof16belem = neblock / 16;
+  for (i = 0, k = 0; i < numof16belem; i++, k += 4) {
+    /* Load the first 64 bytes in 4 XMM registrers */
+    for (j = 0; j < 4; j++) {
+      xmm0[j] = ((__m128i *)orig)[j*numof16belem+i];
+    }
+    /* Shuffle bytes */
+    for (j = 0; j < 2; j++) {
+      /* Compute the low 32 bytes */
+      xmm1[j] = _mm_unpacklo_epi8(xmm0[j*2], xmm0[j*2+1]);
+      /* Compute the hi 32 bytes */
+      xmm1[2+j] = _mm_unpackhi_epi8(xmm0[j*2], xmm0[j*2+1]);
+    }
+    /* Shuffle 2-byte words */
+    for (j = 0; j < 2; j++) {
+      /* Compute the low 32 bytes */
+      xmm0[j] = _mm_unpacklo_epi16(xmm1[j*2], xmm1[j*2+1]);
+      /* Compute the hi 32 bytes */
+      xmm0[2+j] = _mm_unpackhi_epi16(xmm1[j*2], xmm1[j*2+1]);
+    }
+    /* Store the result vectors in proper order */
+    ((__m128i *)dest)[k+0] = xmm0[0];
+    ((__m128i *)dest)[k+1] = xmm0[2];
+    ((__m128i *)dest)[k+2] = xmm0[1];
+    ((__m128i *)dest)[k+3] = xmm0[3];
+  }
+}
+
+
+/* Routine optimized for unshuffling a buffer for a type size of 8 bytes. */
+static void
+unshuffle8(uint8_t* dest, uint8_t* orig, size_t size)
+{
+  size_t i, j, k;
+  size_t neblock, numof16belem;
+  __m128i xmm0[8], xmm1[8];
+
+  neblock = size / 8;
+  numof16belem = neblock / 16;
+  for (i = 0, k = 0; i < numof16belem; i++, k += 8) {
+    /* Load the first 64 bytes in 8 XMM registrers */
+    for (j = 0; j < 8; j++) {
+      xmm0[j] = ((__m128i *)orig)[j*numof16belem+i];
+    }
+    /* Shuffle bytes */
+    for (j = 0; j < 4; j++) {
+      /* Compute the low 32 bytes */
+      xmm1[j] = _mm_unpacklo_epi8(xmm0[j*2], xmm0[j*2+1]);
+      /* Compute the hi 32 bytes */
+      xmm1[4+j] = _mm_unpackhi_epi8(xmm0[j*2], xmm0[j*2+1]);
+    }
+    /* Shuffle 2-byte words */
+    for (j = 0; j < 4; j++) {
+      /* Compute the low 32 bytes */
+      xmm0[j] = _mm_unpacklo_epi16(xmm1[j*2], xmm1[j*2+1]);
+      /* Compute the hi 32 bytes */
+      xmm0[4+j] = _mm_unpackhi_epi16(xmm1[j*2], xmm1[j*2+1]);
+    }
+    /* Shuffle 4-byte dwords */
+    for (j = 0; j < 4; j++) {
+      /* Compute the low 32 bytes */
+      xmm1[j] = _mm_unpacklo_epi32(xmm0[j*2], xmm0[j*2+1]);
+      /* Compute the hi 32 bytes */
+      xmm1[4+j] = _mm_unpackhi_epi32(xmm0[j*2], xmm0[j*2+1]);
+    }
+    /* Store the result vectors in proper order */
+    ((__m128i *)dest)[k+0] = xmm1[0];
+    ((__m128i *)dest)[k+1] = xmm1[4];
+    ((__m128i *)dest)[k+2] = xmm1[2];
+    ((__m128i *)dest)[k+3] = xmm1[6];
+    ((__m128i *)dest)[k+4] = xmm1[1];
+    ((__m128i *)dest)[k+5] = xmm1[5];
+    ((__m128i *)dest)[k+6] = xmm1[3];
+    ((__m128i *)dest)[k+7] = xmm1[7];
+  }
+}
+
+
+/* Routine optimized for unshuffling a buffer for a type size of 16 bytes. */
+static void
+unshuffle16(uint8_t* dest, uint8_t* orig, size_t size)
+{
+  size_t i, j, k;
+  size_t neblock, numof16belem;
+  __m128i xmm1[16], xmm2[16];
+
+  neblock = size / 16;
+  numof16belem = neblock / 16;
+  for (i = 0, k = 0; i < numof16belem; i++, k += 16) {
+    /* Load the first 128 bytes in 16 XMM registrers */
+    for (j = 0; j < 16; j++) {
+      xmm1[j] = ((__m128i *)orig)[j*numof16belem+i];
+    }
+    /* Shuffle bytes */
+    for (j = 0; j < 8; j++) {
+      /* Compute the low 32 bytes */
+      xmm2[j] = _mm_unpacklo_epi8(xmm1[j*2], xmm1[j*2+1]);
+      /* Compute the hi 32 bytes */
+      xmm2[8+j] = _mm_unpackhi_epi8(xmm1[j*2], xmm1[j*2+1]);
+    }
+    /* Shuffle 2-byte words */
+    for (j = 0; j < 8; j++) {
+      /* Compute the low 32 bytes */
+      xmm1[j] = _mm_unpacklo_epi16(xmm2[j*2], xmm2[j*2+1]);
+      /* Compute the hi 32 bytes */
+      xmm1[8+j] = _mm_unpackhi_epi16(xmm2[j*2], xmm2[j*2+1]);
+    }
+    /* Shuffle 4-byte dwords */
+    for (j = 0; j < 8; j++) {
+      /* Compute the low 32 bytes */
+      xmm2[j] = _mm_unpacklo_epi32(xmm1[j*2], xmm1[j*2+1]);
+      /* Compute the hi 32 bytes */
+      xmm2[8+j] = _mm_unpackhi_epi32(xmm1[j*2], xmm1[j*2+1]);
+    }
+    /* Shuffle 8-byte qwords */
+    for (j = 0; j < 8; j++) {
+      /* Compute the low 32 bytes */
+      xmm1[j] = _mm_unpacklo_epi64(xmm2[j*2], xmm2[j*2+1]);
+      /* Compute the hi 32 bytes */
+      xmm1[8+j] = _mm_unpackhi_epi64(xmm2[j*2], xmm2[j*2+1]);
+    }
+    /* Store the result vectors in proper order */
+    ((__m128i *)dest)[k+0] = xmm1[0];
+    ((__m128i *)dest)[k+1] = xmm1[8];
+    ((__m128i *)dest)[k+2] = xmm1[4];
+    ((__m128i *)dest)[k+3] = xmm1[12];
+    ((__m128i *)dest)[k+4] = xmm1[2];
+    ((__m128i *)dest)[k+5] = xmm1[10];
+    ((__m128i *)dest)[k+6] = xmm1[6];
+    ((__m128i *)dest)[k+7] = xmm1[14];
+    ((__m128i *)dest)[k+8] = xmm1[1];
+    ((__m128i *)dest)[k+9] = xmm1[9];
+    ((__m128i *)dest)[k+10] = xmm1[5];
+    ((__m128i *)dest)[k+11] = xmm1[13];
+    ((__m128i *)dest)[k+12] = xmm1[3];
+    ((__m128i *)dest)[k+13] = xmm1[11];
+    ((__m128i *)dest)[k+14] = xmm1[7];
+    ((__m128i *)dest)[k+15] = xmm1[15];
+  }
+}
+
+
+/* Unshuffle a block.  This can never fail. */
+void unshuffle(size_t bytesoftype, size_t blocksize,
+               uint8_t* _src, uint8_t* _dest) {
+  int unaligned_src = (int)((uintptr_t)_src % 16);
+  int unaligned_dest = (int)((uintptr_t)_dest % 16);
+  int power_of_two = (blocksize & (blocksize - 1)) == 0;
+  int too_small = (blocksize < 256);
+
+  if (unaligned_src || unaligned_dest || !power_of_two || too_small) {
+    /* _src or _dest buffer is not aligned, not a power of two or is
+       too small.  Call the non-sse2 version. */
+    _unshuffle(bytesoftype, blocksize, _src, _dest);
+    return;
+  }
+
+  /* Optimized unshuffle */
+  /* The buffers must be aligned on a 16 bytes boundary, have a power */
+  /* of 2 size and be larger or equal than 256 bytes. */
+  if (bytesoftype == 4) {
+    unshuffle4(_dest, _src, blocksize);
+  }
+  else if (bytesoftype == 8) {
+    unshuffle8(_dest, _src, blocksize);
+  }
+  else if (bytesoftype == 16) {
+    unshuffle16(_dest, _src, blocksize);
+  }
+  else if (bytesoftype == 2) {
+    unshuffle2(_dest, _src, blocksize);
+  }
+  else {
+    /* Non-optimized unshuffle */
+    _unshuffle(bytesoftype, blocksize, _src, _dest);
+  }
+}
+
+#else   /* no __SSE2__ available */
+
+void shuffle(size_t bytesoftype, size_t blocksize,
+             uint8_t* _src, uint8_t* _dest) {
+  _shuffle(bytesoftype, blocksize, _src, _dest);
+}
+
+void unshuffle(size_t bytesoftype, size_t blocksize,
+               uint8_t* _src, uint8_t* _dest) {
+  _unshuffle(bytesoftype, blocksize, _src, _dest);
+}
+
+#endif  /* __SSE2__ */
Index: thirdparty/blosc/shuffle.h
===================================================================
--- thirdparty/blosc/shuffle.h	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
+++ thirdparty/blosc/shuffle.h	(revision 00587dc5492d37549f9181cc536aef5fcd190667)
@@ -0,0 +1,16 @@
+/*********************************************************************
+  Blosc - Blocked Suffling and Compression Library
+
+  Author: Francesc Alted <faltet@gmail.com>
+
+  See LICENSES/BLOSC.txt for details about copyright and rights to use.
+**********************************************************************/
+
+
+/* Shuffle/unshuffle routines */
+
+void shuffle(size_t bytesoftype, size_t blocksize,
+             unsigned char* _src, unsigned char* _dest);
+
+void unshuffle(size_t bytesoftype, size_t blocksize,
+               unsigned char* _src, unsigned char* _dest);
