Blame IlmImf/dwaLookups.cpp

Packit 0d464f
///////////////////////////////////////////////////////////////////////////
Packit 0d464f
//
Packit 0d464f
// Copyright (c) 2009-2014 DreamWorks Animation LLC. 
Packit 0d464f
//
Packit 0d464f
// All rights reserved.
Packit 0d464f
//
Packit 0d464f
// Redistribution and use in source and binary forms, with or without
Packit 0d464f
// modification, are permitted provided that the following conditions are
Packit 0d464f
// met:
Packit 0d464f
// *       Redistributions of source code must retain the above copyright
Packit 0d464f
// notice, this list of conditions and the following disclaimer.
Packit 0d464f
// *       Redistributions in binary form must reproduce the above
Packit 0d464f
// copyright notice, this list of conditions and the following disclaimer
Packit 0d464f
// in the documentation and/or other materials provided with the
Packit 0d464f
// distribution.
Packit 0d464f
// *       Neither the name of DreamWorks Animation nor the names of
Packit 0d464f
// its contributors may be used to endorse or promote products derived
Packit 0d464f
// from this software without specific prior written permission.
Packit 0d464f
//
Packit 0d464f
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit 0d464f
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit 0d464f
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Packit 0d464f
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
Packit 0d464f
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Packit 0d464f
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Packit 0d464f
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit 0d464f
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit 0d464f
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit 0d464f
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit 0d464f
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 0d464f
//
Packit 0d464f
///////////////////////////////////////////////////////////////////////////
Packit 0d464f
Packit 0d464f
//
Packit 0d464f
// A program to generate various acceleration lookup tables 
Packit 0d464f
// for Imf::DwaCompressor
Packit 0d464f
//
Packit 0d464f
Packit 0d464f
#include <cstddef>
Packit 0d464f
#include <stdio.h>
Packit 0d464f
#include <stdlib.h>
Packit 0d464f
#include <math.h>
Packit 0d464f
#include <vector>
Packit 0d464f
Packit 0d464f
#include <OpenEXRConfig.h>
Packit 0d464f
Packit 0d464f
#ifdef OPENEXR_IMF_HAVE_SYSCONF_NPROCESSORS_ONLN
Packit 0d464f
#include <unistd.h>
Packit 0d464f
#endif
Packit 0d464f
Packit 0d464f
#include <half.h>
Packit 0d464f
#include <IlmThread.h>
Packit 0d464f
#include <IlmThreadSemaphore.h>
Packit 0d464f
#include <ImfIO.h>
Packit 0d464f
#include <ImfXdr.h>
Packit 0d464f
#include "ImfNamespace.h"
Packit 0d464f
Packit 0d464f
using namespace OPENEXR_IMF_NAMESPACE;
Packit 0d464f
Packit 0d464f
namespace {
Packit 0d464f
Packit 0d464f
    class LutHeaderWorker
Packit 0d464f
    {
Packit 0d464f
        public:
Packit 0d464f
            class Runner : public IlmThread::Thread
Packit 0d464f
            {
Packit 0d464f
                public:
Packit 0d464f
                    Runner(LutHeaderWorker &worker, bool output):
Packit 0d464f
                        IlmThread::Thread(),
Packit 0d464f
                        _worker(worker),
Packit 0d464f
                        _output(output)
Packit 0d464f
                    {
Packit 0d464f
                        start();
Packit 0d464f
                    }
Packit 0d464f
Packit 0d464f
                    virtual ~Runner()
Packit 0d464f
                    {
Packit 0d464f
                        _semaphore.wait();
Packit 0d464f
                    }
Packit 0d464f
Packit 0d464f
                    virtual void run()
Packit 0d464f
                    {
Packit 0d464f
                        _semaphore.post();
Packit 0d464f
                        _worker.run(_output);
Packit 0d464f
                    }
Packit 0d464f
Packit 0d464f
                private:
Packit 0d464f
                    LutHeaderWorker     &_worker;
Packit 0d464f
                    bool                 _output;
Packit 0d464f
                    IlmThread::Semaphore _semaphore;
Packit 0d464f
Packit 0d464f
            }; // class LutHeaderWorker::Runner
Packit 0d464f
Packit 0d464f
Packit 0d464f
            LutHeaderWorker(size_t startValue,
Packit 0d464f
                            size_t endValue):
Packit 0d464f
                _lastCandidateCount(0),
Packit 0d464f
                _startValue(startValue),
Packit 0d464f
                _endValue(endValue),
Packit 0d464f
                _numElements(0),
Packit 0d464f
                _offset(new size_t[numValues()]),
Packit 0d464f
                _elements(new unsigned short[1024*1024*2])
Packit 0d464f
            {
Packit 0d464f
            }
Packit 0d464f
Packit 0d464f
            ~LutHeaderWorker()
Packit 0d464f
            {
Packit 0d464f
                delete[] _offset;
Packit 0d464f
                delete[] _elements;
Packit 0d464f
            }
Packit 0d464f
Packit 0d464f
            size_t lastCandidateCount() const
Packit 0d464f
            {
Packit 0d464f
                return _lastCandidateCount;
Packit 0d464f
            }
Packit 0d464f
Packit 0d464f
            size_t numValues() const 
Packit 0d464f
            {
Packit 0d464f
                return _endValue - _startValue;
Packit 0d464f
            }
Packit 0d464f
Packit 0d464f
            size_t numElements() const
Packit 0d464f
            {
Packit 0d464f
                return _numElements;
Packit 0d464f
            }
Packit 0d464f
Packit 0d464f
            const size_t* offset() const
Packit 0d464f
            {
Packit 0d464f
                return _offset;
Packit 0d464f
            }
Packit 0d464f
Packit 0d464f
            const unsigned short* elements() const
Packit 0d464f
            {
Packit 0d464f
                return _elements;
Packit 0d464f
            }
Packit 0d464f
Packit 0d464f
            void run(bool outputProgress)
Packit 0d464f
            {
Packit 0d464f
                half candidate[16];
Packit 0d464f
                int  candidateCount = 0;
Packit 0d464f
Packit 0d464f
                for (size_t input=_startValue; input<_endValue; ++input) {
Packit 0d464f
Packit 0d464f
                    if (outputProgress) {
Packit 0d464f
#ifdef __GNUC__
Packit 0d464f
                        if (input % 100 == 0) {
Packit 0d464f
                            fprintf(stderr, 
Packit 0d464f
                            " Building acceleration for DwaCompressor, %.2f %%      %c",
Packit 0d464f
                                          100.*(float)input/(float)numValues(), 13);
Packit 0d464f
                        }
Packit 0d464f
#else
Packit 0d464f
                        if (input % 1000 == 0) {
Packit 0d464f
                            fprintf(stderr, 
Packit 0d464f
                            " Building acceleration for DwaCompressor, %.2f %%\n",
Packit 0d464f
                                          100.*(float)input/(float)numValues());
Packit 0d464f
                        }
Packit 0d464f
#endif
Packit 0d464f
                    } 
Packit 0d464f
Packit 0d464f
                    
Packit 0d464f
                    int  numSetBits = countSetBits(input);
Packit 0d464f
                    half inputHalf, closestHalf;
Packit 0d464f
Packit 0d464f
                    inputHalf.setBits(input);
Packit 0d464f
Packit 0d464f
                    _offset[input - _startValue] = _numElements;
Packit 0d464f
Packit 0d464f
                    // Gather candidates
Packit 0d464f
                    candidateCount = 0;
Packit 0d464f
                    for (int targetNumSetBits=numSetBits-1; targetNumSetBits>=0;
Packit 0d464f
                                                           --targetNumSetBits) {
Packit 0d464f
                        bool valueFound = false;
Packit 0d464f
Packit 0d464f
                        for (int i=0; i<65536; ++i) {
Packit 0d464f
                            if (countSetBits(i) != targetNumSetBits) continue;
Packit 0d464f
Packit 0d464f
                            if (!valueFound) {
Packit 0d464f
                                closestHalf.setBits(i);
Packit 0d464f
                                valueFound = true;
Packit 0d464f
                            } else {
Packit 0d464f
                                half tmpHalf;
Packit 0d464f
Packit 0d464f
                                tmpHalf.setBits(i);
Packit 0d464f
Packit 0d464f
                                if (fabs((float)inputHalf - (float)tmpHalf) < 
Packit 0d464f
                                    fabs((float)inputHalf - (float)closestHalf)) {
Packit 0d464f
                                    closestHalf = tmpHalf;
Packit 0d464f
                                }
Packit 0d464f
                            }
Packit 0d464f
                        }
Packit 0d464f
Packit 0d464f
                        if (valueFound == false) {
Packit 0d464f
                            fprintf(stderr, "bork bork bork!\n");
Packit 0d464f
                        }       
Packit 0d464f
Packit 0d464f
                        candidate[candidateCount] = closestHalf;
Packit 0d464f
                        candidateCount++;
Packit 0d464f
                    }
Packit 0d464f
Packit 0d464f
                    // Sort candidates by increasing number of bits set
Packit 0d464f
                    for (int i=0; i
Packit 0d464f
                        for (int j=i+1; j
Packit 0d464f
Packit 0d464f
                            int   iCnt = countSetBits(candidate[i].bits());
Packit 0d464f
                            int   jCnt = countSetBits(candidate[j].bits());
Packit 0d464f
Packit 0d464f
                            if (jCnt < iCnt) {
Packit 0d464f
                                half tmp     = candidate[i];
Packit 0d464f
                                candidate[i] = candidate[j];
Packit 0d464f
                                candidate[j] = tmp;
Packit 0d464f
                            }
Packit 0d464f
                        }
Packit 0d464f
                    }
Packit 0d464f
Packit 0d464f
                    // Copy candidates to the data buffer;
Packit 0d464f
                    for (int i=0; i
Packit 0d464f
                        _elements[_numElements] = candidate[i].bits();
Packit 0d464f
                        _numElements++;
Packit 0d464f
                    }
Packit 0d464f
Packit 0d464f
                    if (input == _endValue-1) {
Packit 0d464f
                        _lastCandidateCount = candidateCount;
Packit 0d464f
                    }
Packit 0d464f
                }
Packit 0d464f
            }
Packit 0d464f
            
Packit 0d464f
Packit 0d464f
        private:
Packit 0d464f
            size_t          _lastCandidateCount;
Packit 0d464f
            size_t          _startValue;
Packit 0d464f
            size_t          _endValue;
Packit 0d464f
            size_t          _numElements;
Packit 0d464f
            size_t         *_offset;
Packit 0d464f
            unsigned short *_elements;
Packit 0d464f
Packit 0d464f
            //
Packit 0d464f
            // Precomputing the bit count runs faster than using
Packit 0d464f
            // the builtin instruction, at least in one case..
Packit 0d464f
            //
Packit 0d464f
            // Precomputing 8-bits is no slower than 16-bits,
Packit 0d464f
            // and saves a fair bit of overhead..
Packit 0d464f
            //
Packit 0d464f
            int countSetBits(unsigned short src)
Packit 0d464f
            {
Packit 0d464f
                static const unsigned short numBitsSet[256] =
Packit 0d464f
                {
Packit 0d464f
                    0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
Packit 0d464f
                    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
Packit 0d464f
                    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
Packit 0d464f
                    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
Packit 0d464f
                    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
Packit 0d464f
                    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
Packit 0d464f
                    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
Packit 0d464f
                    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
Packit 0d464f
                    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
Packit 0d464f
                    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
Packit 0d464f
                    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
Packit 0d464f
                    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
Packit 0d464f
                    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
Packit 0d464f
                    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
Packit 0d464f
                    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
Packit 0d464f
                    4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
Packit 0d464f
                };
Packit 0d464f
Packit 0d464f
                return numBitsSet[src & 0xff] + numBitsSet[src >> 8];
Packit 0d464f
            }
Packit 0d464f
Packit 0d464f
    }; // class LutHeaderWorker
Packit 0d464f
Packit 0d464f
} // namespace
Packit 0d464f
Packit 0d464f
Packit 0d464f
//
Packit 0d464f
// Generate a no-op LUT, to cut down in conditional branches
Packit 0d464f
//
Packit 0d464f
void
Packit 0d464f
generateNoop()
Packit 0d464f
{
Packit 0d464f
    printf("const unsigned short dwaCompressorNoOp[] = \n");
Packit 0d464f
    printf("{");
Packit 0d464f
    for (int i=0; i<65536; ++i) {
Packit 0d464f
Packit 0d464f
        if (i % 8 == 0) {
Packit 0d464f
            printf("\n    ");
Packit 0d464f
        }
Packit 0d464f
Packit 0d464f
        unsigned short dst;
Packit 0d464f
        char *tmp = (char *)(&dst);
Packit 0d464f
Packit 0d464f
        unsigned short src = (unsigned short)i;
Packit 0d464f
        Xdr::write <CharPtrIO> (tmp,  src);
Packit 0d464f
Packit 0d464f
        printf("0x%04x, ", dst);
Packit 0d464f
    }
Packit 0d464f
    printf("\n};\n");
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
//
Packit 0d464f
// Nonlinearly encode luminance. For values below 1.0, we want
Packit 0d464f
// to use a gamma 2.2 function to match what is fairly common
Packit 0d464f
// for storing output referred. However, > 1, gamma functions blow up,
Packit 0d464f
// and log functions are much better behaved. We could use a log 
Packit 0d464f
// function everywhere, but it tends to over-sample dark 
Packit 0d464f
// regions and undersample the brighter regions, when 
Packit 0d464f
// compared to the way real devices reproduce values.
Packit 0d464f
//
Packit 0d464f
// So, above 1, use a log function which is a smooth blend
Packit 0d464f
// into the gamma function. 
Packit 0d464f
//
Packit 0d464f
//  Nonlinear(linear) = 
Packit 0d464f
//
Packit 0d464f
//    linear^(1./2.2)             / linear <= 1.0
Packit 0d464f
//                               |
Packit 0d464f
//    ln(linear)/ln(e^2.2) + 1    \ otherwise
Packit 0d464f
//
Packit 0d464f
//
Packit 0d464f
// toNonlinear[] needs to take in XDR format half float values,
Packit 0d464f
// and output NATIVE format float. 
Packit 0d464f
//
Packit 0d464f
// toLinear[] does the opposite - takes in NATIVE half and 
Packit 0d464f
// outputs XDR half values.
Packit 0d464f
//
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
generateToLinear()
Packit 0d464f
{
Packit 0d464f
    unsigned short toLinear[65536];
Packit 0d464f
Packit 0d464f
    toLinear[0] = 0;
Packit 0d464f
Packit 0d464f
    for (int i=1; i<65536; ++i) {
Packit 0d464f
        half  h;
Packit 0d464f
        float sign    = 1;
Packit 0d464f
        float logBase = pow(2.7182818, 2.2);
Packit 0d464f
Packit 0d464f
        // map  NaN and inf to 0
Packit 0d464f
        if ((i & 0x7c00) == 0x7c00) {
Packit 0d464f
            toLinear[i]    = 0;
Packit 0d464f
            continue;
Packit 0d464f
        }
Packit 0d464f
Packit 0d464f
        //
Packit 0d464f
        // _toLinear - assume i is NATIVE, but our output needs
Packit 0d464f
        //             to get flipped to XDR
Packit 0d464f
        //
Packit 0d464f
        h.setBits(i);
Packit 0d464f
        sign = 1;
Packit 0d464f
        if ((float)h < 0) {
Packit 0d464f
            sign = -1;
Packit 0d464f
        } 
Packit 0d464f
Packit 0d464f
        if ( fabs( (float)h) <= 1.0 ) {
Packit 0d464f
            h  = (half)(sign * pow((float)fabs((float)h), 2.2f));
Packit 0d464f
        } else {
Packit 0d464f
            h  = (half)(sign * pow(logBase, (float)(fabs((float)h) - 1.0)));
Packit 0d464f
        }
Packit 0d464f
Packit 0d464f
        {
Packit 0d464f
            char *tmp = (char *)(&toLinear[i]);
Packit 0d464f
Packit 0d464f
            Xdr::write <CharPtrIO> ( tmp,  h.bits());
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
    
Packit 0d464f
    printf("const unsigned short dwaCompressorToLinear[] = \n");
Packit 0d464f
    printf("{");
Packit 0d464f
    for (int i=0; i<65536; ++i) {
Packit 0d464f
        if (i % 8 == 0) {
Packit 0d464f
            printf("\n    ");
Packit 0d464f
        }
Packit 0d464f
        printf("0x%04x, ", toLinear[i]);
Packit 0d464f
    }
Packit 0d464f
    printf("\n};\n");
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
generateToNonlinear()
Packit 0d464f
{
Packit 0d464f
    unsigned short toNonlinear[65536];
Packit 0d464f
Packit 0d464f
    toNonlinear[0] = 0;
Packit 0d464f
Packit 0d464f
    for (int i=1; i<65536; ++i) {
Packit 0d464f
        unsigned short usNative, usXdr;
Packit 0d464f
        half  h;
Packit 0d464f
        float sign    = 1;
Packit 0d464f
        float logBase = pow(2.7182818, 2.2);
Packit 0d464f
Packit 0d464f
        usXdr           = i;
Packit 0d464f
Packit 0d464f
        {
Packit 0d464f
            const char *tmp = (char *)(&usXdr);
Packit 0d464f
Packit 0d464f
            Xdr::read<CharPtrIO>(tmp, usNative);
Packit 0d464f
        }
Packit 0d464f
Packit 0d464f
        // map  NaN and inf to 0
Packit 0d464f
        if ((usNative & 0x7c00) == 0x7c00) {
Packit 0d464f
            toNonlinear[i] = 0;
Packit 0d464f
            continue;
Packit 0d464f
        }
Packit 0d464f
Packit 0d464f
        //
Packit 0d464f
        // toNonlinear - assume i is XDR
Packit 0d464f
        //
Packit 0d464f
        h.setBits(usNative);
Packit 0d464f
        sign = 1;
Packit 0d464f
        if ((float)h < 0) {
Packit 0d464f
            sign = -1;
Packit 0d464f
        } 
Packit 0d464f
Packit 0d464f
        if ( fabs( (float)h ) <= 1.0) {
Packit 0d464f
            h = (half)(sign * pow(fabs((float)h), 1.f/2.2f));
Packit 0d464f
        } else {
Packit 0d464f
            h = (half)(sign * ( log(fabs((float)h)) / log(logBase) + 1.0) );
Packit 0d464f
        }
Packit 0d464f
        toNonlinear[i] = h.bits();
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    printf("const unsigned short dwaCompressorToNonlinear[] = \n");
Packit 0d464f
    printf("{");
Packit 0d464f
    for (int i=0; i<65536; ++i) {
Packit 0d464f
        if (i % 8 == 0) {
Packit 0d464f
            printf("\n    ");
Packit 0d464f
        }
Packit 0d464f
        printf("0x%04x, ", toNonlinear[i]);
Packit 0d464f
    }
Packit 0d464f
    printf("\n};\n");
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
//
Packit 0d464f
// Attempt to get available CPUs in a somewhat portable way. 
Packit 0d464f
//
Packit 0d464f
Packit 0d464f
int
Packit 0d464f
cpuCount()
Packit 0d464f
{
Packit 0d464f
    if (!IlmThread::supportsThreads()) return 1;
Packit 0d464f
Packit 0d464f
    int cpuCount = 1;
Packit 0d464f
Packit 0d464f
#if defined (OPENEXR_IMF_HAVE_SYSCONF_NPROCESSORS_ONLN)
Packit 0d464f
Packit 0d464f
    cpuCount = sysconf(_SC_NPROCESSORS_ONLN);
Packit 0d464f
Packit 0d464f
#elif defined (_WIN32)
Packit 0d464f
Packit 0d464f
    SYSTEM_INFO sysinfo;
Packit 0d464f
    GetSystemInfo( &sysinfo );
Packit 0d464f
    cpuCount = sysinfo.dwNumberOfProcessors;
Packit 0d464f
Packit 0d464f
#endif
Packit 0d464f
Packit 0d464f
    if (cpuCount < 1) cpuCount = 1;
Packit 0d464f
    return cpuCount;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
//
Packit 0d464f
// Generate acceleration luts for the quantization.
Packit 0d464f
//
Packit 0d464f
// For each possible input value, we want to find the closest numbers
Packit 0d464f
// which have one fewer bits set than before. 
Packit 0d464f
//
Packit 0d464f
// This gives us num_bits(input)-1 values per input. If we alloc
Packit 0d464f
// space for everything, that's like a 2MB table. We can do better
Packit 0d464f
// by compressing all the values to be contigious and using offset
Packit 0d464f
// pointers.
Packit 0d464f
//
Packit 0d464f
// After we've found the candidates with fewer bits set, sort them
Packit 0d464f
// based on increasing numbers of bits set. This way, on quantize(),
Packit 0d464f
// we can scan through the list and halt once we find the first
Packit 0d464f
// candidate within the error range. For small values that can 
Packit 0d464f
// be quantized to 0, 0 is the first value tested and the search
Packit 0d464f
// can exit fairly quickly.
Packit 0d464f
//
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
generateLutHeader()
Packit 0d464f
{
Packit 0d464f
    std::vector<LutHeaderWorker*> workers;
Packit 0d464f
Packit 0d464f
    size_t numWorkers     = cpuCount();
Packit 0d464f
    size_t workerInterval = 65536 / numWorkers;
Packit 0d464f
Packit 0d464f
    for (size_t i=0; i
Packit 0d464f
        if (i != numWorkers-1) {
Packit 0d464f
            workers.push_back( new LutHeaderWorker( i   *workerInterval, 
Packit 0d464f
                                                   (i+1)*workerInterval) );
Packit 0d464f
        } else {
Packit 0d464f
            workers.push_back( new LutHeaderWorker(i*workerInterval, 65536) );
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    if (IlmThread::supportsThreads()) {
Packit 0d464f
        std::vector<LutHeaderWorker::Runner*> runners;
Packit 0d464f
        for (size_t i=0; i
Packit 0d464f
            runners.push_back( new LutHeaderWorker::Runner(*workers[i], (i==0)) );
Packit 0d464f
        }
Packit 0d464f
Packit 0d464f
        for (size_t i=0; i
Packit 0d464f
            delete runners[i];
Packit 0d464f
        }
Packit 0d464f
    } else {
Packit 0d464f
        for (size_t i=0; i
Packit 0d464f
            workers[i]->run(i == 0);
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    printf("static unsigned int closestDataOffset[] = {\n");
Packit 0d464f
    int offsetIdx  = 0;
Packit 0d464f
    int offsetPrev = 0;
Packit 0d464f
    for (size_t i=0; i
Packit 0d464f
        for (size_t value=0; value<workers[i]->numValues(); ++value) {
Packit 0d464f
            if (offsetIdx % 8 == 0) {
Packit 0d464f
                printf("    ");
Packit 0d464f
            }
Packit 0d464f
            printf("%6lu, ", workers[i]->offset()[value] + offsetPrev);
Packit 0d464f
            if (offsetIdx % 8 == 7) {
Packit 0d464f
                printf("\n");
Packit 0d464f
            }
Packit 0d464f
            offsetIdx++;
Packit 0d464f
        }
Packit 0d464f
        offsetPrev += workers[i]->offset()[workers[i]->numValues()-1] + 
Packit 0d464f
                      workers[i]->lastCandidateCount();
Packit 0d464f
    }
Packit 0d464f
    printf("};\n\n\n");
Packit 0d464f
Packit 0d464f
Packit 0d464f
    printf("static unsigned short closestData[] = {\n");
Packit 0d464f
    int elementIdx = 0;
Packit 0d464f
    for (size_t i=0; i
Packit 0d464f
        for (size_t element=0; element<workers[i]->numElements(); ++element) {
Packit 0d464f
            if (elementIdx % 8 == 0) {
Packit 0d464f
                printf("    ");
Packit 0d464f
            }
Packit 0d464f
            printf("%5d, ", workers[i]->elements()[element]);
Packit 0d464f
            if (elementIdx % 8 == 7) {
Packit 0d464f
                printf("\n");
Packit 0d464f
            }
Packit 0d464f
            elementIdx++;
Packit 0d464f
        }    
Packit 0d464f
    }
Packit 0d464f
    printf("};\n\n\n");
Packit 0d464f
Packit 0d464f
    for (size_t i=0; i
Packit 0d464f
        delete workers[i];
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
int
Packit 0d464f
main(int argc, char **argv)
Packit 0d464f
{
Packit 0d464f
    printf("#include <cstddef>\n");
Packit 0d464f
    printf("\n\n\n");
Packit 0d464f
Packit 0d464f
    generateNoop();
Packit 0d464f
Packit 0d464f
    printf("\n\n\n");
Packit 0d464f
Packit 0d464f
    generateToLinear();
Packit 0d464f
Packit 0d464f
    printf("\n\n\n");
Packit 0d464f
Packit 0d464f
    generateToNonlinear();
Packit 0d464f
Packit 0d464f
    printf("\n\n\n");
Packit 0d464f
Packit 0d464f
    generateLutHeader();
Packit 0d464f
Packit 0d464f
    return 0;
Packit 0d464f
}