tweak

tweak

// Copyright Hugh Perkins 2014 hughperkins at gmail
//
// This Source Code Form is subject to the terms of the Mozilla Public License,
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
// obtain one at http://mozilla.org/MPL/2.0/.

// expected defines:
// BIASED (or not)

// globalId: [outPlane][inputPlane][filterRow][filterCol]
// per-thread iteration: [n][outputRow][outputCol]
void kernel backprop_floats( const float learningRateMultiplier,
        const int batchSize,
         global const float *errors, global const float *images,
        global float *weights
        #ifdef BIASED
            , global float *biasWeights
        #endif
 ) {
    int globalId = get_global_id(0);
    if( globalId >= gNumFilters * gInputPlanes * gFilterSize * gFilterSize ) {
        return;
    }

    int IntraFilterOffset = globalId % gFilterSizeSquared;
    int filterRow = IntraFilterOffset / gFilterSize;
    int filterCol = IntraFilterOffset % gFilterSize;

    int filter2Id = globalId / gFilterSizeSquared;
    int outPlane = filter2Id / gInputPlanes;
    int upstreamPlane = filter2Id % gInputPlanes;

    float thiswchange = 0;
    // weights:     [outPlane][upstreamPlane][filterRow][filterCol]
    //       aggregate over:  [outRow][outCol][n]
#ifdef BIASED
    float thisbiaschange = 0;
#endif
    for( int n = 0; n < batchSize; n++ ) {
        for( int outRow = 0; outRow < gOutputBoardSize; outRow++ ) {
            int upstreamRow = outRow - gMargin + filterRow;
            for( int outCol = 0; outCol < gOutputBoardSize; outCol++ ) {
                int upstreamCol = outCol - gMargin + filterCol;
                bool proceed = upstreamRow >= 0 && upstreamCol >= 0 && upstreamRow < gInputBoardSize
                    && upstreamCol < gInputBoardSize;
                if( proceed ) {
                    int resultIndex = ( ( n * gNumFilters
                              + outPlane ) * gOutputBoardSize
                              + outRow ) * gOutputBoardSize
                              + outCol;
                    float error = errors[resultIndex];
                    int upstreamDataIndex = ( ( n * gInputPlanes
                                     + upstreamPlane ) * gInputBoardSize
                                     + upstreamRow ) * gInputBoardSize
                                     + upstreamCol;
                    float upstreamResult = images[upstreamDataIndex];
                    float thisimagethiswchange = upstreamResult * error;
                    thiswchange += thisimagethiswchange;
    #ifdef BIASED
                    thisbiaschange += error;
    #endif
                }
            }
        }
    }
    // weights:     [outPlane][upstreamPlane][filterRow][filterCol]
    //       aggregate over:  [outRow][outCol][n]
    weights[ globalId ] += - learningRateMultiplier * thiswchange;
#ifdef BIASED
    bool writeBias = upstreamPlane == 0 && IntraFilterOffset == 0;
    if( writeBias ) {
        biasWeights[outPlane] += - learningRateMultiplier * thisbiaschange;
    }
#endif
}

// workgroupId: [outputPlane][inputPlane]
// localId: [filterRow][filterCol]
// per-thread iteration: [n][outputRow][outputCol]
// local: errorboard: outputBoardSize * outputBoardSize
//        imageboard: inputBoardSize * inputBoardSize
void kernel backprop_floats_withscratch_dobias(
        const float learningRateMultiplier, const int batchSize,
         global const float *errors, global const float *images,
        global float *weights,
        #ifdef BIASED
             global float *biasWeights,
        #endif
        local float *_errorBoard, local float *_imageBoard
 ) {
    const int globalId = get_global_id(0);
    const int localId = get_local_id(0);
    const int workgroupId = get_group_id(0);
    const int workgroupSize = get_local_size(0);

    const int filterRow = localId / gFilterSize;
    const int filterCol = localId % gFilterSize;

    const int outPlane = workgroupId / gInputPlanes;
    const int upstreamPlane = workgroupId % gInputPlanes;

    // weights:     [outPlane][upstreamPlane][filterRow][filterCol]
    //       aggregate over:  [outRow][outCol][n]
    float thiswchange = 0;
#ifdef BIASED
    float thisbiaschange = 0;
#endif
    for( int n = 0; n < batchSize; n++ ) {
        int upstreamBoardGlobalOffset = ( n * gInputPlanes + upstreamPlane ) * gInputBoardSizeSquared;
        // need to fetch the board, but it's bigger than us, so will need to loop...
        int numLoopsForUpstream = ( gInputBoardSizeSquared + workgroupSize - 1 ) / workgroupSize;
        barrier(CLK_LOCAL_MEM_FENCE);
        for( int i = 0; i < numLoopsForUpstream; i++ ) {
            int thisOffset = i * workgroupSize + localId;
            if( thisOffset < gInputBoardSizeSquared ) {
                _imageBoard[thisOffset] = images[ upstreamBoardGlobalOffset + thisOffset ];
            }
        }
        int resultBoardGlobalOffset = ( n * gNumFilters + outPlane ) * gOutputBoardSizeSquared;
        int numLoopsForResults = ( gOutputBoardSizeSquared + workgroupSize - 1 ) / workgroupSize;
        for( int i = 0; i < numLoopsForResults; i++ ) {
            int thisOffset = i * workgroupSize + localId;
            if( thisOffset < gOutputBoardSizeSquared ) {
                _errorBoard[thisOffset ] = errors[resultBoardGlobalOffset + thisOffset];
            }
        }
        barrier(CLK_LOCAL_MEM_FENCE);
        if( localId < gFilterSizeSquared ) {
            for( int outRow = 0; outRow < gOutputBoardSize; outRow++ ) {
                int upstreamRow = outRow - gMargin + filterRow;
                for( int outCol = 0; outCol < gOutputBoardSize; outCol++ ) {
                    int upstreamCol = outCol - gMargin + filterCol;
                    bool proceed = upstreamRow >= 0 && upstreamCol >= 0 && upstreamRow < gInputBoardSize
                        && upstreamCol < gInputBoardSize;
                    if( proceed ) {
                        int resultIndex = outRow * gOutputBoardSize + outCol;
                        float error = _errorBoard[resultIndex];
                        int upstreamDataIndex = upstreamRow * gInputBoardSize + upstreamCol;
                        float upstreamResult = _imageBoard[upstreamDataIndex];
                        thiswchange += upstreamResult * error;
    #ifdef BIASED
                        thisbiaschange += error;
    #endif
                    }
                }
            }
        }
    }
    if( localId < gFilterSizeSquared ) {
        weights[ workgroupId * gFilterSizeSquared + localId ] += - learningRateMultiplier * thiswchange;
//        weightChanges[ workgroupId * gFilterSizeSquared + localId ] = workgroupId;
    }
#ifdef BIASED
    bool writeBias = upstreamPlane == 0 && localId == 0;
    if( writeBias ) {
        biasWeights[outPlane] += - learningRateMultiplier * thisbiaschange;
    }
#endif
    // weights:     [outPlane][upstreamPlane][filterRow][filterCol]
    //       aggregate over:  [outRow][outCol][n]
}

// workgroupId: [outputPlane][inputPlane]
// localId: [filterRow][filterCol]
// per-thread iteration: [n][outputRow][outputCol]
// local: errorboard: outputBoardSize * outputBoardSize
//        imageboard: inputBoardSize * inputBoardSize
// specific characteristic: load one stripe of each image at a time,
// so we dont run out of memory
// number of stripes set in: gNumStripes
// note that whilst we can stripe the errors simply,
// we actually need to add a half-filter widthed additional few rows
// onto the images stripe, otherwise we will be missing data
//   we will call the size of the non-overlapping image stripes: gInputStripeInnerSize
//      the outersize, including the two margins is: gInputStripeOuterSize
//      of course, the first and last stripes will be missing a bit off the top/bottom, where the
//      corresponding outer margin would be
void kernel backprop_floats_withscratch_dobias_striped(
        const float learningRateMultiplier, const int batchSize,
         global const float *errors, global const float *images,
        global float *weights,
        #ifdef BIASED
             global float *biasWeights,
        #endif
        local float *_errorStripe, local float *_imageStripe
 ) {
    // gHalfFilterSize
    // gInputBoardSize
    //
    // gInputStripeMarginRows => basically equal to gHalfFilterSize
    // gInputStripeInnerNumRows = gInputBoardSize / gNumStripes
    // gInputStripeOuterNumRows = gInputStripeInnerNumRows + 2 * gHalfFilterSize  (note: one row less than
    //                                                         if we just added gFilterSize)
    // gInputStripeInnerSize = gInputStripeInnerNumRows * gInputBoardSize
    // gInputStripeOuterSize = gInputStripeOuterNumRows * gInputBoardSize
    // gInputStripeMarginSize = gInputStripeMarginRows * gInputBoardSize
    //
    // gOutputStripeNumRows
    // gOutputStripeSize

    const int globalId = get_global_id(0);
    const int localId = get_local_id(0);
    const int workgroupId = get_group_id(0);
    const int workgroupSize = get_local_size(0);

    const int filterRow = localId / gFilterSize;
    const int filterCol = localId % gFilterSize;

    const int outPlane = workgroupId / gInputPlanes;
    const int upstreamPlane = workgroupId % gInputPlanes;

    // weights:     [outPlane][upstreamPlane][filterRow][filterCol]
    //       aggregate over:  [outRow][outCol][n]
    float thiswchange = 0;
#ifdef BIASED
    float thisbiaschange = 0;
#endif
    const int numLoopsForImageStripe = ( gInputStripeOuterSize + workgroupSize - 1 ) / workgroupSize;
    const int numLoopsForErrorStripe = ( gOutputBoardSizeSquared + workgroupSize - 1 ) / workgroupSize;
    for( int n = 0; n < batchSize; n++ ) {
        const int imageBoardGlobalOffset = ( n * gInputPlanes + upstreamPlane ) * gInputBoardSizeSquared;
        const int imageBoardGlobalOffsetAfter = imageBoardGlobalOffset + gInputBoardSizeSquared;
        const int errorBoardGlobalOffset = ( n * gNumFilters + outPlane ) * gOutputBoardSizeSquared;
        for( int stripe = 0; stripe < gNumStripes; stripe++ ) {
            int imageStripeOffset = imageBoardGlobalOffset + stripe * gInputStripeInnerSize
                               - gInputStripeMarginSize;
            // need to fetch the board, but it's bigger than us, so will need to loop...
            barrier(CLK_LOCAL_MEM_FENCE);
            for( int i = 0; i < numLoopsForImageStripe; i++ ) {
                int thisOffset = i * workgroupSize + localId;
                int thisGlobalOffset = imageStripeOffset + thisOffset;
                bool process = thisOffset < gInputStripeOuterSize
                    && thisGlobalOffset >= imageBoardGlobalOffset && thisGlobalOffset < imageBoardGlobalOffsetAfter;
                if( process ) {
                    _imageStripe[thisOffset] = images[ thisGlobalOffset ];
                }
            }
            int errorStripeOffset = errorBoardGlobalOffset + stripe * gOutputStripeSize;
            for( int i = 0; i < numLoopsForErrorStripe; i++ ) {
                int thisOffset = i * workgroupSize + localId;
                if( thisOffset < gOutputStripeSize ) {
                    _errorStripe[thisOffset ] = errors[errorStripeOffset + thisOffset];
                }
            }
            const int stripeOutRowStart = stripe * gOutputStripeNumRows;
            const int stripeOutRowEndExcl = stripeOutRowStart + gOutputStripeNumRows;
            barrier(CLK_LOCAL_MEM_FENCE);
            if( localId < gFilterSizeSquared ) {
                for( int outRow = stripeOutRowStart; outRow < stripeOutRowEndExcl; outRow++ ) {
                    int upstreamRow = outRow - gMargin + filterRow;
                    for( int outCol = 0; outCol < gOutputBoardSize; outCol++ ) {
                        int upstreamCol = outCol - gMargin + filterCol;
                        bool proceed = upstreamRow >= 0 && upstreamCol >= 0 && upstreamRow < gInputBoardSize
                            && upstreamCol < gInputBoardSize; // dont need to check more than this, since
                                                              // the inputstripe margin means we have
                        if( proceed ) {
                            int resultIndex = outRow * gOutputBoardSize + outCol;
                            float error = _errorStripe[resultIndex - stripe * gOutputStripeSize];
                            int upstreamDataIndex = upstreamRow * gInputBoardSize + upstreamCol;
                            // next line segfaults on nvidia, out of bounds
                            float upstreamResult = _imageStripe[upstreamDataIndex +  gInputStripeMarginSize
                                        - stripe * gInputStripeInnerSize ];
                            thiswchange += upstreamResult * error;
        #ifdef BIASED
                            thisbiaschange += error;
        #endif
                        }
                    }
                }
            }
        }
    }
    if( localId < gFilterSizeSquared ) {
        weights[ workgroupId * gFilterSizeSquared + localId ] += - learningRateMultiplier * thiswchange;
//        weightChanges[ workgroupId * gFilterSizeSquared + localId ] = workgroupId;
    }
#ifdef BIASED
    bool writeBias = upstreamPlane == 0 && localId == 0;
    if( writeBias ) {
        biasWeights[outPlane] += - learningRateMultiplier * thisbiaschange;
    }
#endif
    // weights:     [outPlane][upstreamPlane][filterRow][filterCol]
    //       aggregate over:  [outRow][outCol][n]
}

// Copyright Hugh Perkins 2014 hughperkins at gmail
//
// This Source Code Form is subject to the terms of the Mozilla Public License,
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
// obtain one at http://mozilla.org/MPL/2.0/.

// expected defines:
// BIASED (or not)

// globalId: [outPlane][inputPlane][filterRow][filterCol]
// per-thread iteration: [n][outputRow][outputCol]
void kernel backprop_floats( const float learningRateMultiplier,
        const int batchSize,
         global const float *errors, global const float *images,
        global float *weights
        #ifdef BIASED
            , global float *biasWeights
        #endif
 ) {
    int globalId = get_global_id(0);
    if( globalId >= gNumFilters * gInputPlanes * gFilterSize * gFilterSize ) {
        return;
    }

    int IntraFilterOffset = globalId % gFilterSizeSquared;
    int filterRow = IntraFilterOffset / gFilterSize;
    int filterCol = IntraFilterOffset % gFilterSize;

    int filter2Id = globalId / gFilterSizeSquared;
    int outPlane = filter2Id / gInputPlanes;
    int upstreamPlane = filter2Id % gInputPlanes;

    float thiswchange = 0;
    // weights:     [outPlane][upstreamPlane][filterRow][filterCol]
    //       aggregate over:  [outRow][outCol][n]
#ifdef BIASED
    float thisbiaschange = 0;
#endif
    for( int n = 0; n < batchSize; n++ ) {
        for( int outRow = 0; outRow < gOutputBoardSize; outRow++ ) {
            int upstreamRow = outRow - gMargin + filterRow;
            for( int outCol = 0; outCol < gOutputBoardSize; outCol++ ) {
                int upstreamCol = outCol - gMargin + filterCol;
                bool proceed = upstreamRow >= 0 && upstreamCol >= 0 && upstreamRow < gInputBoardSize
                    && upstreamCol < gInputBoardSize;
                if( proceed ) {
                    int resultIndex = ( ( n * gNumFilters
                              + outPlane ) * gOutputBoardSize
                              + outRow ) * gOutputBoardSize
                              + outCol;
                    float error = errors[resultIndex];
                    int upstreamDataIndex = ( ( n * gInputPlanes
                                     + upstreamPlane ) * gInputBoardSize
                                     + upstreamRow ) * gInputBoardSize
                                     + upstreamCol;
                    float upstreamResult = images[upstreamDataIndex];
                    float thisimagethiswchange = upstreamResult * error;
                    thiswchange += thisimagethiswchange;
    #ifdef BIASED
                    thisbiaschange += error;
    #endif
                }
            }
        }
    }
    // weights:     [outPlane][upstreamPlane][filterRow][filterCol]
    //       aggregate over:  [outRow][outCol][n]
    weights[ globalId ] += - learningRateMultiplier * thiswchange;
#ifdef BIASED
    bool writeBias = upstreamPlane == 0 && IntraFilterOffset == 0;
    if( writeBias ) {
        biasWeights[outPlane] += - learningRateMultiplier * thisbiaschange;
    }
#endif
}

// workgroupId: [outputPlane][inputPlane]
// localId: [filterRow][filterCol]
// per-thread iteration: [n][outputRow][outputCol]
// local: errorboard: outputBoardSize * outputBoardSize
//        imageboard: inputBoardSize * inputBoardSize
void kernel backprop_floats_withscratch_dobias(
        const float learningRateMultiplier, const int batchSize,
         global const float *errors, global const float *images,
        global float *weights,
        #ifdef BIASED
             global float *biasWeights,
        #endif
        local float *_errorBoard, local float *_imageBoard
 ) {
    const int globalId = get_global_id(0);
    const int localId = get_local_id(0);
    const int workgroupId = get_group_id(0);
    const int workgroupSize = get_local_size(0);

    const int filterRow = localId / gFilterSize;
    const int filterCol = localId % gFilterSize;

    const int outPlane = workgroupId / gInputPlanes;
    const int upstreamPlane = workgroupId % gInputPlanes;

    // weights:     [outPlane][upstreamPlane][filterRow][filterCol]
    //       aggregate over:  [outRow][outCol][n]
    float thiswchange = 0;
#ifdef BIASED
    float thisbiaschange = 0;
#endif
    for( int n = 0; n < batchSize; n++ ) {
        int upstreamBoardGlobalOffset = ( n * gInputPlanes + upstreamPlane ) * gInputBoardSizeSquared;
        // need to fetch the board, but it's bigger than us, so will need to loop...
        int numLoopsForUpstream = ( gInputBoardSizeSquared + workgroupSize - 1 ) / workgroupSize;
        barrier(CLK_LOCAL_MEM_FENCE);
        for( int i = 0; i < numLoopsForUpstream; i++ ) {
            int thisOffset = i * workgroupSize + localId;
            if( thisOffset < gInputBoardSizeSquared ) {
                _imageBoard[thisOffset] = images[ upstreamBoardGlobalOffset + thisOffset ];
            }
        }
        int resultBoardGlobalOffset = ( n * gNumFilters + outPlane ) * gOutputBoardSizeSquared;
        int numLoopsForResults = ( gOutputBoardSizeSquared + workgroupSize - 1 ) / workgroupSize;
        for( int i = 0; i < numLoopsForResults; i++ ) {
            int thisOffset = i * workgroupSize + localId;
            if( thisOffset < gOutputBoardSizeSquared ) {
                _errorBoard[thisOffset ] = errors[resultBoardGlobalOffset + thisOffset];
            }
        }
        barrier(CLK_LOCAL_MEM_FENCE);
        if( localId < gFilterSizeSquared ) {
            for( int outRow = 0; outRow < gOutputBoardSize; outRow++ ) {
                int upstreamRow = outRow - gMargin + filterRow;
                for( int outCol = 0; outCol < gOutputBoardSize; outCol++ ) {
                    int upstreamCol = outCol - gMargin + filterCol;
                    bool proceed = upstreamRow >= 0 && upstreamCol >= 0 && upstreamRow < gInputBoardSize
                        && upstreamCol < gInputBoardSize;
                    if( proceed ) {
                        int resultIndex = outRow * gOutputBoardSize + outCol;
                        float error = _errorBoard[resultIndex];
                        int upstreamDataIndex = upstreamRow * gInputBoardSize + upstreamCol;
                        float upstreamResult = _imageBoard[upstreamDataIndex];
                        thiswchange += upstreamResult * error;
    #ifdef BIASED
                        thisbiaschange += error;
    #endif
                    }
                }
            }
        }
    }
    if( localId < gFilterSizeSquared ) {
        weights[ workgroupId * gFilterSizeSquared + localId ] += - learningRateMultiplier * thiswchange;
//        weightChanges[ workgroupId * gFilterSizeSquared + localId ] = workgroupId;
    }
#ifdef BIASED
    bool writeBias = upstreamPlane == 0 && localId == 0;
    if( writeBias ) {
        biasWeights[outPlane] += - learningRateMultiplier * thisbiaschange;
    }
#endif
    // weights:     [outPlane][upstreamPlane][filterRow][filterCol]
    //       aggregate over:  [outRow][outCol][n]
}

// workgroupId: [outputPlane][inputPlane]
// localId: [filterRow][filterCol]
// per-thread iteration: [n][outputRow][outputCol]
// local: errorboard: outputBoardSize * outputBoardSize
//        imageboard: inputBoardSize * inputBoardSize
// specific characteristic: load one stripe of each image at a time,
// so we dont run out of memory
// number of stripes set in: gNumStripes
// note that whilst we can stripe the errors simply,
// we actually need to add a half-filter widthed additional few rows
// onto the images stripe, otherwise we will be missing data
//   we will call the size of the non-overlapping image stripes: gInputStripeInnerSize
//      the outersize, including the two margins is: gInputStripeOuterSize
//      of course, the first and last stripes will be missing a bit off the top/bottom, where the
//      corresponding outer margin would be
void kernel backprop_floats_withscratch_dobias_striped(
        const float learningRateMultiplier, const int batchSize,
         global const float *errors, global const float *images,
        global float *weights,
        #ifdef BIASED
             global float *biasWeights,
        #endif
        local float *_errorStripe, local float *_imageStripe
 ) {
    // gHalfFilterSize
    // gInputBoardSize
    //
    // gInputStripeMarginRows => basically equal to gHalfFilterSize
    // gInputStripeInnerNumRows = gInputBoardSize / gNumStripes
    // gInputStripeOuterNumRows = gInputStripeInnerNumRows + 2 * gHalfFilterSize  (note: one row less than
    //                                                         if we just added gFilterSize)
    // gInputStripeInnerSize = gInputStripeInnerNumRows * gInputBoardSize
    // gInputStripeOuterSize = gInputStripeOuterNumRows * gInputBoardSize
    // gInputStripeMarginSize = gInputStripeMarginRows * gInputBoardSize
    //
    // gOutputStripeNumRows
    // gOutputStripeSize

    const int globalId = get_global_id(0);
    const int localId = get_local_id(0);
    const int workgroupId = get_group_id(0);
    const int workgroupSize = get_local_size(0);

    const int filterRow = localId / gFilterSize;
    const int filterCol = localId % gFilterSize;

    const int outPlane = workgroupId / gInputPlanes;
    const int upstreamPlane = workgroupId % gInputPlanes;

    // weights:     [outPlane][upstreamPlane][filterRow][filterCol]
    //       aggregate over:  [outRow][outCol][n]
    float thiswchange = 0;
#ifdef BIASED
    float thisbiaschange = 0;
#endif
    const int numLoopsForImageStripe = ( gInputStripeOuterSize + workgroupSize - 1 ) / workgroupSize;
    const int numLoopsForErrorStripe = ( gOutputBoardSizeSquared + workgroupSize - 1 ) / workgroupSize;
    for( int n = 0; n < batchSize; n++ ) {
        const int imageBoardGlobalOffset = ( n * gInputPlanes + upstreamPlane ) * gInputBoardSizeSquared;
        const int imageBoardGlobalOffsetAfter = imageBoardGlobalOffset + gInputBoardSizeSquared;
        const int errorBoardGlobalOffset = ( n * gNumFilters + outPlane ) * gOutputBoardSizeSquared;
        for( int stripe = 0; stripe < gNumStripes; stripe++ ) {
            int imageStripeOffset = imageBoardGlobalOffset + stripe * gInputStripeInnerSize
                               - gInputStripeMarginSize;
            // need to fetch the board, but it's bigger than us, so will need to loop...
            barrier(CLK_LOCAL_MEM_FENCE);
            for( int i = 0; i < numLoopsForImageStripe; i++ ) {
                int thisLocalOffset = i * workgroupSize + localId;
                int thisGlobalOffset = imageStripeOffset + thisOffset;
                bool process = thisOffset < gInputStripeOuterSize
                    && thisGlobalOffset >= imageBoardGlobalOffset && thisGlobalOffset < imageBoardGlobalOffsetAfter;
                if( process ) {
                    _imageStripe[thisLocalOffset] = images[ thisGlobalOffset ];
                }
            }
            int errorStripeOffset = errorBoardGlobalOffset + stripe * gOutputStripeSize;
            for( int i = 0; i < numLoopsForErrorStripe; i++ ) {
                int thisOffset = i * workgroupSize + localId;
                if( thisOffset < gOutputStripeSize ) {
                    _errorStripe[thisOffset ] = errors[errorStripeOffset + thisOffset];
                }
            }
            const int stripeOutRowStart = stripe * gOutputStripeNumRows;
            const int stripeOutRowEndExcl = stripeOutRowStart + gOutputStripeNumRows;
            barrier(CLK_LOCAL_MEM_FENCE);
            if( localId < gFilterSizeSquared ) {
                for( int outRow = stripeOutRowStart; outRow < stripeOutRowEndExcl; outRow++ ) {
                    int upstreamRow = outRow - gMargin + filterRow;
                    for( int outCol = 0; outCol < gOutputBoardSize; outCol++ ) {
                        int upstreamCol = outCol - gMargin + filterCol;
                        bool proceed = upstreamRow >= 0 && upstreamCol >= 0 && upstreamRow < gInputBoardSize
                            && upstreamCol < gInputBoardSize; // dont need to check more than this, since
                                                              // the inputstripe margin means we have
                        if( proceed ) {
                            int resultIndex = outRow * gOutputBoardSize + outCol;
                            float error = _errorStripe[resultIndex - stripe * gOutputStripeSize];
                            int upstreamDataIndex = upstreamRow * gInputBoardSize + upstreamCol;
                            // next line segfaults on nvidia, out of bounds
                            float upstreamResult = _imageStripe[upstreamDataIndex +  gInputStripeMarginSize
                                        - stripe * gInputStripeInnerSize ];
                            thiswchange += upstreamResult * error;
        #ifdef BIASED
                            thisbiaschange += error;
        #endif
                        }
                    }
                }
            }
        }
    }
    if( localId < gFilterSizeSquared ) {
        weights[ workgroupId * gFilterSizeSquared + localId ] += - learningRateMultiplier * thiswchange;
//        weightChanges[ workgroupId * gFilterSizeSquared + localId ] = workgroupId;
    }
#ifdef BIASED
    bool writeBias = upstreamPlane == 0 && localId == 0;
    if( writeBias ) {
        biasWeights[outPlane] += - learningRateMultiplier * thisbiaschange;
    }
#endif
    // weights:     [outPlane][upstreamPlane][filterRow][filterCol]
    //       aggregate over:  [outRow][outCol][n]
}


Add series: World's Craziest Fools

Add series: World's Craziest Fools

'cause I'm a programmin' fool.

(in-package :user)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Feed and other options

(setq *log-rss* (merge-pathnames "rss.log" *tget-data-directory*))
(setq *log-file* (merge-pathnames "ep.log" *tget-data-directory*))

;; Wait 6 hours before downloading (most) episodes, to wait for repacks and
;; propers.
(defvar *tvt-delay* 6)

(defun tvt-rss-feed (days)
  (format nil "~a&interval=~d+days" (sys:getenv "TGET_TVT_RSS_BASE") days))

(defvar *tvt-rss* 'tvt-rss-feed)

;; custom rss feed with these options:
;; - feed name: RegularShow
;; - series: Regular Show
;; - category: Episode
;; - resolutions: 720p (less than this quality are crap)
(defvar *btn-regular-show-rss* (sys:getenv "TGET_BTN_RSS_REGULARSHOW"))

;; custom rss feed with these options:
;; - feed name: Spongebob
;; - series: Spongebob Squarepants
;; - category: Episode
;; - resolutions: 720p (less than this quality are crap)
(defvar *btn-spongebob-rss* (sys:getenv "TGET_BTN_RSS_SPONGEBOB"))

#+not-yet
(deftransmission ()
    :host (sys:getenv "TRANSMISSION_HOST")
    :port 9091
    :username (sys:getenv "TRANSMISSION_USER")
    :password (sys:getenv "TRANSMISSION_PASS")
    :add-paused nil
    :ratio "1.04"
    ;; Don't enable this because I like to see what's there before it's
    ;; removed.
    :remove-when-done nil)

(setq *download-root* "/me/layer/videos/")

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Quality settings

(defquality :normal
    :source :hdtv
    :codec :x264
    :resolution :<720p)

(defquality :high
    :source :hdtv
    :codec :x264
    :resolution :720p)

(defquality :low
    :source :hdtv
    :codec :xvid
    :resolution :<720p)

(defun my-quality (episode)
  ;; Download :normal quality immediately.
  ;; If that's not available, then download :high quality after 12 hours
  ;; and :low quality after 2 days.  There are still some shows that never
  ;; get anything but :low, for some episodes.
  (if* (and (null
	     ;; See if there is an episode with :normal quality.  The
	     ;; :transient keyword is important, since it restricts the
	     ;; search to episodes we have *not* downloaded yet.
	     (query-episode :episode episode :quality :normal :transient t))
	    (eq :high (episode-quality episode))
	    (>= (hours-available episode) 12))
     then ;; :normal quality is not available and the :high quality episode
	  ;; has been available for 12 hours, then return...
	  :high
   elseif (and (null
		;; See if there is an episode with :normal or :high
		;; quality.
		(or
		 (query-episode :episode episode :quality :normal :transient t)
		 (query-episode :episode episode :quality :high :transient t)))
	       (eq :low (episode-quality episode))
	       (>= (hours-available episode) 48))
     then :low
     else :normal))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defgroup :adrian
    :rss-url *tvt-rss*
    :delay *tvt-delay*
    :client :transmission-rpc
    :quality 'my-quality
    :download-path (merge-pathnames "adrian/" *download-root*))

(defseries "Phineas and Furb" :adrian)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defgroup :anh
    :rss-url *tvt-rss*
    :delay *tvt-delay*
    :client :transmission-rpc
    :quality 'my-quality
    :download-path (merge-pathnames "anh/" *download-root*))

(defseries "Downton Abbey" :anh)
(defseries "Midsomer Murders" :anh)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defgroup :kevin
    :rss-url *tvt-rss*
    :delay *tvt-delay*
    :client :transmission-rpc
    :quality 'my-quality
    :download-path (merge-pathnames "kevin/" *download-root*))

(defseries "8 Out of 10 Cats" :kevin)
(defseries "Boardwalk Empire" :kevin)
(defseries "Breaking Bad" :kevin :delay 0) ;; immediate download
(defseries "Childrens Hospital (US)" :kevin)
(defseries "Come Fly with Me (2010)" :kevin)
(defseries "Dexter" :kevin)
(defseries "Dragons Den" :kevin)
(defseries "Elementary" :kevin)
(defseries "Falling Skies" :kevin)
(defseries "Frontline" :kevin)
(defseries "Game of Thrones" :kevin :delay 0) ;; immediate download
(defseries "Homeland" :kevin)
(defseries "Justified" :kevin :delay 0) ;; immediate download
(defseries "Longmire" :kevin)
(defseries "Louis Theroux Documentaries" :kevin)
(defseries "Louis" :kevin)
(defseries "Luther" :kevin)
(defseries "Mad Men" :kevin)
(defseries "Misfits" :kevin)
(defseries "Motive" :kevin)
(defseries "Orphan Black" :kevin)
(defseries "Person of Interest" :kevin)
(defseries "Shameless (US)" :kevin)
(defseries "Sherlock" :kevin)
(defseries "Southland" :kevin)
(defseries "Strike Back" :kevin)
(defseries "The Americans (2013)" :kevin)
(defseries "The Colbert Report" :kevin)
(defseries "The Daily Show with Jon Stewart" :kevin)
(defseries "The Graham Norton Show" :kevin)
(defseries "The IT Crowd" :kevin)
(defseries "The Jeselnik Offensive" :kevin)
(defseries "The Newsroom (2012)" :kevin)
(defseries "The Ultimate Fighter" :kevin)
(defseries "The Walking Dead" :kevin :delay 0) ;; immediate download
(defseries "Tosh.0" :kevin)
(defseries "Vikings" :kevin)
(defseries "Witness (2012)" :kevin)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defgroup :adrian+kevin
    :rss-url *tvt-rss*
    :delay *tvt-delay*
    :client :transmission-rpc
    :quality 'my-quality
    :download-path (merge-pathnames "adrian+kevin/" *download-root*))

(defseries "An Idiot Abroad" :adrian+kevin)
(defseries "Community" :adrian+kevin)
(defseries "Eagleheart" :adrian+kevin)
(defseries "Futurama" :adrian+kevin)
(defseries "James May's Man Lab" :adrian+kevin)
(defseries "Modern Family" :adrian+kevin)
(defseries "Mythbusters" :adrian+kevin)
(defseries "Nathan for You" :adrian+kevin)
(defseries "NCIS" :adrian+kevin)
(defseries "Nova" :adrian+kevin)
(defseries "Parks and Recreation" :adrian+kevin)
(defseries "Ridiculousness" :adrian+kevin)
(defseries "Shark Tank" :adrian+kevin)
(defseries "The Mentalist" :adrian+kevin)
(defseries "The Neighbors (2012)" :adrian+kevin)
(defseries "The Simpsons" :adrian+kevin)
(defseries "Top Gear" :adrian+kevin :quality :high)
(defseries "Top Gear (US)" :adrian+kevin :quality :high)
(defseries "World's Craziest Fools" :adrian+kevin)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defgroup :btn-regular-show
    :rss-url *btn-regular-show-rss*
    :ratio "-1"
    :client :transmission-rpc
    :quality t ;; built into the feed
    :download-path (merge-pathnames "adrian+kevin/" *download-root*))

(defseries "Regular Show" :btn-regular-show)

(defgroup :btn-spongebob
    :rss-url *btn-spongebob-rss*
    :ratio "-1"
    :client :transmission-rpc
    :quality t ;; built into the feed
    :download-path (merge-pathnames "adrian+kevin/" *download-root*))

(defseries "Spongebob Squarepants" :btn-spongebob)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defgroup :anh+kevin
    :rss-url *tvt-rss*
    :delay *tvt-delay*
    :client :transmission-rpc
    :quality 'my-quality
    :download-path (merge-pathnames "anh+kevin/" *download-root*))

(defseries "Bates Motel" :anh+kevin)
(defseries "Curb your Enthusiasm" :anh+kevin)
(defseries "Doc Martin" :anh+kevin)
(defseries "The Following" :anh+kevin)
(defseries "The Good Wife" :anh+kevin)
(defseries "The Killing" :anh+kevin)
(defseries "Wallander" :anh+kevin)
(defseries "White Collar" :anh+kevin)

(in-package :user)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Feed and other options

(setq *log-rss* (merge-pathnames "rss.log" *tget-data-directory*))
(setq *log-file* (merge-pathnames "ep.log" *tget-data-directory*))

;; Wait 6 hours before downloading (most) episodes, to wait for repacks and
;; propers.
(defvar *tvt-delay* 6)

(defun tvt-rss-feed (days)
  (format nil "~a&interval=~d+days" (sys:getenv "TGET_TVT_RSS_BASE") days))

(defvar *tvt-rss* 'tvt-rss-feed)

;; custom rss feed with these options:
;; - feed name: RegularShow
;; - series: Regular Show
;; - category: Episode
;; - resolutions: 720p (less than this quality are crap)
(defvar *btn-regular-show-rss* (sys:getenv "TGET_BTN_RSS_REGULARSHOW"))

;; custom rss feed with these options:
;; - feed name: Spongebob
;; - series: Spongebob Squarepants
;; - category: Episode
;; - resolutions: 720p (less than this quality are crap)
(defvar *btn-spongebob-rss* (sys:getenv "TGET_BTN_RSS_SPONGEBOB"))

#+not-yet
(deftransmission ()
    :host (sys:getenv "TRANSMISSION_HOST")
    :port 9091
    :username (sys:getenv "TRANSMISSION_USER")
    :password (sys:getenv "TRANSMISSION_PASS")
    :add-paused nil
    :ratio "1.04"
    ;; Don't enable this because I like to see what's there before it's
    ;; removed.
    :remove-when-done nil)

(setq *download-root* "/me/layer/videos/")

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Quality settings

(defquality :normal
    :source :hdtv
    :codec :x264
    :resolution :<720p)

(defquality :high
    :source :hdtv
    :codec :x264
    :resolution :720p)

(defquality :low
    :source :hdtv
    :codec :xvid
    :resolution :<720p)

(defun my-quality (episode)
  ;; Download :normal quality immediately.
  ;; If that's not available, then download :high quality after 12 hours
  ;; and :low quality after 2 days.  There are still some shows that never
  ;; get anything but :low, for some episodes.
  (if* (and (null
	     ;; See if there is an episode with :normal quality.  The
	     ;; :transient keyword is important, since it restricts the
	     ;; search to episodes we have *not* downloaded yet.
	     (query-episode :episode episode :quality :normal :transient t))
	    (eq :high (episode-quality episode))
	    (>= (hours-available episode) 12))
     then ;; :normal quality is not available and the :high quality episode
	  ;; has been available for 12 hours, then return...
	  :high
   elseif (and (null
		;; See if there is an episode with :normal or :high
		;; quality.
		(or
		 (query-episode :episode episode :quality :normal :transient t)
		 (query-episode :episode episode :quality :high :transient t)))
	       (eq :low (episode-quality episode))
	       (>= (hours-available episode) 48))
     then :low
     else :normal))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defgroup :adrian
    :rss-url *tvt-rss*
    :delay *tvt-delay*
    :client :transmission-rpc
    :quality 'my-quality
    :download-path (merge-pathnames "adrian/" *download-root*))

(defseries "Phineas and Furb" :adrian)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defgroup :anh
    :rss-url *tvt-rss*
    :delay *tvt-delay*
    :client :transmission-rpc
    :quality 'my-quality
    :download-path (merge-pathnames "anh/" *download-root*))

(defseries "Downton Abbey" :anh)
(defseries "Midsomer Murders" :anh)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defgroup :kevin
    :rss-url *tvt-rss*
    :delay *tvt-delay*
    :client :transmission-rpc
    :quality 'my-quality
    :download-path (merge-pathnames "kevin/" *download-root*))

(defseries "8 Out of 10 Cats" :kevin)
(defseries "Boardwalk Empire" :kevin)
(defseries "Breaking Bad" :kevin :delay 0) ;; immediate download
(defseries "Childrens Hospital (US)" :kevin)
(defseries "Come Fly with Me (2010)" :kevin)
(defseries "Dexter" :kevin)
(defseries "Dragons Den" :kevin)
(defseries "Elementary" :kevin)
(defseries "Falling Skies" :kevin)
(defseries "Frontline" :kevin)
(defseries "Game of Thrones" :kevin :delay 0) ;; immediate download
(defseries "Homeland" :kevin)
(defseries "Justified" :kevin :delay 0) ;; immediate download
(defseries "Longmire" :kevin)
(defseries "Louis Theroux Documentaries" :kevin)
(defseries "Louis" :kevin)
(defseries "Luther" :kevin)
(defseries "Mad Men" :kevin)
(defseries "Misfits" :kevin)
(defseries "Motive" :kevin)
(defseries "Orphan Black" :kevin)
(defseries "Person of Interest" :kevin)
(defseries "Shameless (US)" :kevin)
(defseries "Sherlock" :kevin)
(defseries "Southland" :kevin)
(defseries "Strike Back" :kevin)
(defseries "The Americans (2013)" :kevin)
(defseries "The Colbert Report" :kevin)
(defseries "The Daily Show with Jon Stewart" :kevin)
(defseries "The Graham Norton Show" :kevin)
(defseries "The IT Crowd" :kevin)
(defseries "The Jeselnik Offensive" :kevin)
(defseries "The Newsroom (2012)" :kevin)
(defseries "The Ultimate Fighter" :kevin)
(defseries "The Walking Dead" :kevin :delay 0) ;; immediate download
(defseries "Tosh.0" :kevin)
(defseries "Vikings" :kevin)
(defseries "Witness (2012)" :kevin)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defgroup :adrian+kevin
    :rss-url *tvt-rss*
    :delay *tvt-delay*
    :client :transmission-rpc
    :quality 'my-quality
    :download-path (merge-pathnames "adrian+kevin/" *download-root*))

(defseries "An Idiot Abroad" :adrian+kevin)
(defseries "Community" :adrian+kevin)
(defseries "Eagleheart" :adrian+kevin)
(defseries "Futurama" :adrian+kevin)
(defseries "James May's Man Lab" :adrian+kevin)
(defseries "Modern Family" :adrian+kevin)
(defseries "Mythbusters" :adrian+kevin)
(defseries "Nathan for You" :adrian+kevin)
(defseries "NCIS" :adrian+kevin)
(defseries "Nova" :adrian+kevin)
(defseries "Parks and Recreation" :adrian+kevin)
(defseries "Ridiculousness" :adrian+kevin)
(defseries "Shark Tank" :adrian+kevin)
(defseries "The Mentalist" :adrian+kevin)
(defseries "The Neighbors (2012)" :adrian+kevin)
(defseries "The Simpsons" :adrian+kevin)
(defseries "Top Gear" :adrian+kevin :quality :high)
(defseries "Top Gear (US)" :adrian+kevin :quality :high)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defgroup :btn-regular-show
    :rss-url *btn-regular-show-rss*
    :ratio "-1"
    :client :transmission-rpc
    :quality t ;; built into the feed
    :download-path (merge-pathnames "adrian+kevin/" *download-root*))

(defseries "Regular Show" :btn-regular-show)

(defgroup :btn-spongebob
    :rss-url *btn-spongebob-rss*
    :ratio "-1"
    :client :transmission-rpc
    :quality t ;; built into the feed
    :download-path (merge-pathnames "adrian+kevin/" *download-root*))

(defseries "Spongebob Squarepants" :btn-spongebob)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defgroup :anh+kevin
    :rss-url *tvt-rss*
    :delay *tvt-delay*
    :client :transmission-rpc
    :quality 'my-quality
    :download-path (merge-pathnames "anh+kevin/" *download-root*))

(defseries "Bates Motel" :anh+kevin)
(defseries "Curb your Enthusiasm" :anh+kevin)
(defseries "Doc Martin" :anh+kevin)
(defseries "The Following" :anh+kevin)
(defseries "The Good Wife" :anh+kevin)
(defseries "The Killing" :anh+kevin)
(defseries "Wallander" :anh+kevin)
(defseries "White Collar" :anh+kevin)


Update for the new Declt API.

Update for the new Declt API.

2016-04-21  Didier Verna  <didier@didierverna.net>

	* generate.cl: Update keywords in DECLT call.

;;; generate.cl --- Declt reference manual generation script

;; Copyright (C) 2010-2013, 2015 Didier Verna

;; Author: Didier Verna <didier@didierverna.net>

;; This file is part of FoCus.

;; Permission to use, copy, modify, and distribute this software for any
;; purpose with or without fee is hereby granted, provided that the above
;; copyright notice and this permission notice appear in all copies.

;; THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
;; WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
;; MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
;; ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
;; WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
;; ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
;; OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

;;; Commentary:

;;; Code:

(require "asdf")

(defconstant +introduction+
  "@macro focus
@t{FoCus}
@end macro

@macro Fmt
@code{Format}
@end macro

@macro fmt
@code{format}
@end macro

@macro cl
Common-Lisp
@end macro

@macro etc
@i{etc.}
@end macro

@Fmt{} is a powerful utility in the @cl{} standard. Format strings are
written in what can be considered as a printing DSL (Domain Specific
Language). However powerful that language is though, it suffers from two
important limitations.

@enumerate
@item
It is not modifiable: only a predefined set of standard directive
characters can be used and it is not possible to alter their semantics.
@item
It is hardly extensible. The only embryonic extension mechanism
available, the @code{~/} directive, is extremely cumbersome to use. The
called function must either reside in the @code{cl-user} package, or you
must always use its fully qualified name in the format string, even if
the corresponding code lies in the appropriate package. For instance,
consider that there is a function called @code{my-format-function} in
the package named @code{:my.long.package.name}. Every time you want to
use this function, you need to write something like
@verbatim
(format t \"~/my.long.package.name:my-format-function/\" ...)
@end verbatim
which essentially makes the @code{/} directive unusable.
@end enumerate

@focus{} is a library designed to circumvent those limitations. It
allows you to customize the @fmt{} DSL by adding new directive
characters or modifying the standard ones. The semantics of these
directive characters is specified in a so-called @dfn{format table}, a
concept very close to that of readtables. @focus{} ultimately translates
into regular @fmt{} calls.

This is the @focus{} reference manual, and as such, it is not meant to be
read. It may help you find sleep in case of insomnia though.
@ifinfo
See @xref{Top, , The FoCus User Manual, focus-user},
@end ifinfo
@ifhtml
See @xref{Top, , The FoCus User Manual, user},
@end ifhtml
@ifnotinfo
@ifnothtml
@xref{Top, , , user, The FoCus User Manual},
@end ifnothtml
@end ifnotinfo
for a more human-readable guide to using @focus{}."
  "The reference manual's introductory text.")

(asdf:load-system :net.didierverna.declt)
(net.didierverna.declt:nickname-package)

;; ASDF doesn't understand my version numnbering scheme. That will change
;; soon, but in the meantime, I have to provide my version number explicitly
;; here (and so I need to load the system in order to get the VERSION
;; function).
(asdf:load-system :net.didierverna.focus)

(if (and (second sb-ext:*posix-argv*)
	 (string= (second sb-ext:*posix-argv*) "--web"))
    (declt:declt :net.didierverna.focus
		 :library "FoCus"
		 :texi-file "webreference.texi"
		 :info-file "focus-webreference" ; but we don't care
		 :introduction +introduction+
		 :version (net.didierverna.focus:version :long)
		 :license :bsd
		 :copyright "2015")
    (declt:declt :net.didierverna.focus
		 :library "FoCus"
		 :texi-file "reference.texi"
		 :info-file "focus-reference"
		 :introduction +introduction+
		 :version (net.didierverna.focus:version :long)
		 :license :bsd
		 :copyright "2015"
		 :hyperlinks t))

(uiop:quit)

;;; generate.cl ends here

;;; generate.cl --- Declt reference manual generation script

;; Copyright (C) 2010-2013, 2015 Didier Verna

;; Author: Didier Verna <didier@didierverna.net>

;; This file is part of FoCus.

;; Permission to use, copy, modify, and distribute this software for any
;; purpose with or without fee is hereby granted, provided that the above
;; copyright notice and this permission notice appear in all copies.

;; THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
;; WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
;; MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
;; ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
;; WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
;; ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
;; OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

;;; Commentary:

;;; Code:

(require "asdf")

(defconstant +introduction+
  "@macro focus
@t{FoCus}
@end macro

@macro Fmt
@code{Format}
@end macro

@macro fmt
@code{format}
@end macro

@macro cl
Common-Lisp
@end macro

@macro etc
@i{etc.}
@end macro

@Fmt{} is a powerful utility in the @cl{} standard. Format strings are
written in what can be considered as a printing DSL (Domain Specific
Language). However powerful that language is though, it suffers from two
important limitations.

@enumerate
@item
It is not modifiable: only a predefined set of standard directive
characters can be used and it is not possible to alter their semantics.
@item
It is hardly extensible. The only embryonic extension mechanism
available, the @code{~/} directive, is extremely cumbersome to use. The
called function must either reside in the @code{cl-user} package, or you
must always use its fully qualified name in the format string, even if
the corresponding code lies in the appropriate package. For instance,
consider that there is a function called @code{my-format-function} in
the package named @code{:my.long.package.name}. Every time you want to
use this function, you need to write something like
@verbatim
(format t \"~/my.long.package.name:my-format-function/\" ...)
@end verbatim
which essentially makes the @code{/} directive unusable.
@end enumerate

@focus{} is a library designed to circumvent those limitations. It
allows you to customize the @fmt{} DSL by adding new directive
characters or modifying the standard ones. The semantics of these
directive characters is specified in a so-called @dfn{format table}, a
concept very close to that of readtables. @focus{} ultimately translates
into regular @fmt{} calls.

This is the @focus{} reference manual, and as such, it is not meant to be
read. It may help you find sleep in case of insomnia though.
@ifinfo
See @xref{Top, , The FoCus User Manual, focus-user},
@end ifinfo
@ifhtml
See @xref{Top, , The FoCus User Manual, user},
@end ifhtml
@ifnotinfo
@ifnothtml
@xref{Top, , , user, The FoCus User Manual},
@end ifnothtml
@end ifnotinfo
for a more human-readable guide to using @focus{}."
  "The reference manual's introductory text.")

(asdf:load-system :net.didierverna.declt)
(net.didierverna.declt:nickname-package)

;; ASDF doesn't understand my version numnbering scheme. That will change
;; soon, but in the meantime, I have to provide my version number explicitly
;; here (and so I need to load the system in order to get the VERSION
;; function).
(asdf:load-system :net.didierverna.focus)

(if (and (second sb-ext:*posix-argv*)
	 (string= (second sb-ext:*posix-argv*) "--web"))
    (declt:declt :net.didierverna.focus
		 :library-name "FoCus"
		 :texi-file "webreference.texi"
		 :info-file "focus-webreference" ; but we don't care
		 :introduction +introduction+
		 :version (net.didierverna.focus:version :long)
		 :license :bsd
		 :copyright-date "2015")
    (declt:declt :net.didierverna.focus
		 :library-name "FoCus"
		 :texi-file "reference.texi"
		 :info-file "focus-reference"
		 :introduction +introduction+
		 :version (net.didierverna.focus:version :long)
		 :license :bsd
		 :copyright-date "2015"
		 :hyperlinks t))

(uiop:quit)

;;; generate.cl ends here


r2876: *** empty log message ***

r2876: *** empty log message ***

;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*-
;;;; *************************************************************************
;;;; FILE IDENTIFICATION
;;;;
;;;; Name:          db-interface.cl
;;;; Purpose:       Generic function definitions for DB interfaces
;;;; Programmers:   Kevin M. Rosenberg based on
;;;;                Original code by Pierre R. Mai. Additions from
;;;;                onShoreD to support UncommonSQL front-end
;;;; Date Started:  Feb 2002
;;;;
;;;; $Id: db-interface.cl,v 1.6 2002/09/27 15:08:13 kevin Exp $
;;;;
;;;; This file, part of CLSQL, is Copyright (c) 2002 by Kevin M. Rosenberg
;;;; and Copyright (c) 1999-2001 by Pierre R. Mai, and onShoreD
;;;;
;;;; CLSQL users are granted the rights to distribute and use this software
;;;; as governed by the terms of the Lisp Lesser GNU Public License
;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL.
;;;; *************************************************************************

(declaim (optimize (debug 3) (speed 3) (safety 1) (compilation-speed 0)))
(in-package :clsql-base-sys)

(defgeneric database-type-load-foreign (database-type)
  (:documentation
   "The internal generic implementation of reload-database-types."))

(defgeneric database-type-library-loaded (database-type)
  (:documentation
   "The internal generic implementation for checking if
database type library loaded successfully."))

(defgeneric database-type (database)
  (:documentation
   "Returns database type")
  (:method (database)
	   (signal-nodb-error database)))

(defgeneric database-initialize-database-type (database-type)
  (:documentation
   "The internal generic implementation of initialize-database-type."))

(defgeneric database-name-from-spec (connection-spec database-type)
  (:documentation
   "Returns the name of the database that would be created if connect
was called with the connection-spec."))

(defgeneric database-connect (connection-spec database-type)
  (:documentation "Internal generic implementation of connect."))

(defgeneric database-disconnect (database)
  (:method ((database closed-database))
	   (signal-closed-database-error database))
  (:method ((database t))
	   (signal-nodb-error database))
  (:documentation "Internal generic implementation of disconnect."))

(defgeneric database-query (query-expression database types)
  (:method (query-expression (database closed-database) types)
	   (declare (ignore query-expression types))
	   (signal-closed-database-error database))
  (:method (query-expression (database t) types)
	   (declare (ignore query-expression types))
	   (signal-nodb-error database))
  (:documentation "Internal generic implementation of query."))

(defgeneric database-execute-command (sql-expression database)
  (:method (sql-expression (database closed-database))
	   (declare (ignore sql-expression))
	   (signal-closed-database-error database))
  (:method (sql-expression (database t))
	   (declare (ignore sql-expression))
	   (signal-nodb-error database))
  (:documentation "Internal generic implementation of execute-command."))

;;; Mapping and iteration
(defgeneric database-query-result-set
    (query-expression database &key full-set types)
  (:method (query-expression (database closed-database) &key full-set types)
	   (declare (ignore query-expression full-set types))
	   (signal-closed-database-error database)
	   (values nil nil nil))
  (:method (query-expression (database t) &key full-set types)
	   (declare (ignore query-expression full-set types))
	   (signal-nodb-error database)
	   (values nil nil nil))
  (:documentation
   "Internal generic implementation of query mapping.  Starts the
query specified by query-expression on the given database and returns
a result-set to be used with database-store-next-row and
database-dump-result-set to access the returned data.  The second
value is the number of columns in the result-set, if there are any.
If full-set is true, the number of rows in the result-set is returned
as a third value, if this is possible (otherwise nil is returned for
the third value).  This might have memory and resource usage
implications, since many databases will require the query to be
executed in full to answer this question.  If the query produced no
results then nil is returned for all values that would have been
returned otherwise.  If an error occurs during query execution, the
function should signal a clsql-sql-error."))

(defgeneric database-dump-result-set (result-set database)
  (:method (result-set (database closed-database))
	   (declare (ignore result-set))
	   (signal-closed-database-error database))
  (:method (result-set (database t))
	   (declare (ignore result-set))
	   (signal-nodb-error database))
  (:documentation "Dumps the received result-set."))

(defgeneric database-store-next-row (result-set database list)
  (:method (result-set (database closed-database) list)
	   (declare (ignore result-set list))
	   (signal-closed-database-error database))
  (:method (result-set (database t) list)
	   (declare (ignore result-set list))
	   (signal-nodb-error database))
  (:documentation
   "Returns t and stores the next row in the result set in list or
returns nil when result-set is finished."))

;; Interfaces to support UncommonSQL

(defgeneric database-create-sequence (name database)
  (:documentation "Create a sequence in DATABASE."))

(defgeneric database-drop-sequence (name database)
  (:documentation "Drop a sequence from DATABASE."))

(defgeneric database-sequence-next (name database)
  (:documentation "Increment a sequence in DATABASE."))

(defgeneric database-start-transaction (database)
  (:documentation "Start a transaction in DATABASE."))

(defgeneric database-commit-transaction (database)
  (:documentation "Commit current transaction in DATABASE."))

(defgeneric database-abort-transaction (database)
  (:documentation "Abort current transaction in DATABASE."))

(defgeneric database-get-type-specifier (type args database)
  (:documentation "Return the type SQL type specifier as a string, for
the given lisp type and parameters."))

(defgeneric database-list-tables (database &key system-tables)
  (:documentation "List all tables in the given database"))

(defgeneric database-list-attributes (table database)
  (:documentation "List all attributes in TABLE."))

(defgeneric database-attribute-type (attribute table database)
  (:documentation "Return the type of ATTRIBUTE in TABLE."))

(defgeneric database-add-attribute (table attribute database)
  (:documentation "Add the attribute to the table."))

(defgeneric database-rename-attribute (table oldatt newname database)
  (:documentation "Rename the attribute in the table to NEWNAME."))

(defgeneric oid (object)
  (:documentation "Return the unique ID of a database object."))

;;; Large objects support (Marc Battyani)

(defgeneric database-create-large-object (database)
  (:documentation "Creates a new large object in the database and returns the object identifier"))

(defgeneric database-write-large-object (object-id data database)
  (:documentation "Writes data to the large object"))

(defgeneric database-read-large-object (object-id database)
  (:documentation "Reads the large object content"))

(defgeneric database-delete-large-object (object-id database)
  (:documentation "Deletes the large object in the database"))

;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*-
;;;; *************************************************************************
;;;; FILE IDENTIFICATION
;;;;
;;;; Name:          db-interface.cl
;;;; Purpose:       Generic function definitions for DB interfaces
;;;; Programmers:   Kevin M. Rosenberg based on
;;;;                Original code by Pierre R. Mai. Additions from
;;;;                onShoreD to support UncommonSQL front-end
;;;; Date Started:  Feb 2002
;;;;
;;;; $Id: db-interface.cl,v 1.5 2002/09/27 14:55:37 kevin Exp $
;;;;
;;;; This file, part of CLSQL, is Copyright (c) 2002 by Kevin M. Rosenberg
;;;; and Copyright (c) 1999-2001 by Pierre R. Mai, and onShoreD
;;;;
;;;; CLSQL users are granted the rights to distribute and use this software
;;;; as governed by the terms of the Lisp Lesser GNU Public License
;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL.
;;;; *************************************************************************

(declaim (optimize (debug 3) (speed 3) (safety 1) (compilation-speed 0)))
(in-package :clsql-base-sys)

(defgeneric database-type-load-foreign (database-type)
  (:documentation
   "The internal generic implementation of reload-database-types."))

(defgeneric database-type-library-loaded (database-type)
  (:documentation
   "The internal generic implementation for checking if
database type library loaded successfully."))

(defgeneric database-type (database)
  (:documentation
   "Returns database type")
  (:method (database)
	   (signal-nodb-error database)))

(defgeneric database-initialize-database-type (database-type)
  (:documentation
   "The internal generic implementation of initialize-database-type."))

(defgeneric database-name-from-spec (connection-spec database-type)
  (:documentation
   "Returns the name of the database that would be created if connect
was called with the connection-spec."))

(defgeneric database-connect (connection-spec database-type)
  (:documentation "Internal generic implementation of connect."))

(defgeneric database-disconnect (database)
  (:method ((database closed-database))
	   (signal-closed-database-error database))
  (:method ((database t))
	   (signal-nodb-error database))
  (:documentation "Internal generic implementation of disconnect."))

(defgeneric database-query (query-expression database types)
  (:method (query-expression (database closed-database) types)
	   (declare (ignore query-expression types))
	   (signal-closed-database-error database))
  (:method (query-expression (database t) types)
	   (declare (ignore query-expression types))
	   (signal-nodb-error database))
  (:documentation "Internal generic implementation of query."))

(defgeneric database-execute-command (sql-expression database)
  (:method (sql-expression (database closed-database))
	   (declare (ignore sql-expression))
	   (signal-closed-database-error database))
  (:method (sql-expression (database t))
	   (declare (ignore sql-expression))
	   (signal-nodb-error database))
  (:documentation "Internal generic implementation of execute-command."))

;;; Mapping and iteration
(defgeneric database-query-result-set
    (query-expression database &key full-set types)
  (:method (query-expression (database closed-database) &key full-set types)
	   (declare (ignore query-expression full-set types))
	   (signal-closed-database-error database)
	   (values nil nil nil))
  (:method (query-expression (database t) &key full-set types)
	   (declare (ignore query-expression full-set types))
	   (signal-nodb-error database)
	   (values nil nil nil))
  (:documentation
   "Internal generic implementation of query mapping.  Starts the
query specified by query-expression on the given database and returns
a result-set to be used with database-store-next-row and
database-dump-result-set to access the returned data.  The second
value is the number of columns in the result-set, if there are any.
If full-set is true, the number of rows in the result-set is returned
as a third value, if this is possible (otherwise nil is returned for
the third value).  This might have memory and resource usage
implications, since many databases will require the query to be
executed in full to answer this question.  If the query produced no
results then nil is returned for all values that would have been
returned otherwise.  If an error occurs during query execution, the
function should signal a clsql-sql-error."))

(defgeneric database-dump-result-set (result-set database)
  (:method (result-set (database closed-database))
	   (declare (ignore result-set))
	   (signal-closed-database-error database))
  (:method (result-set (database t))
	   (declare (ignore result-set))
	   (signal-nodb-error database))
  (:documentation "Dumps the received result-set."))

(defgeneric database-store-next-row (result-set database list)
  (:method (result-set (database closed-database) list)
	   (declare (ignore result-set list))
	   (signal-closed-database-error database))
  (:method (result-set (database t) list)
	   (declare (ignore result-set list))
	   (signal-nodb-error database))
  (:documentation
   "Returns t and stores the next row in the result set in list or
returns nil when result-set is finished."))

;; Interfaces to support UncommonSQL

(defgeneric database-create-sequence (name database)
  (:documentation "Create a sequence in DATABASE."))

(defgeneric database-drop-sequence (name database)
  (:documentation "Drop a sequence from DATABASE."))

(defgeneric database-sequence-next (name database)
  (:documentation "Increment a sequence in DATABASE."))

(defgeneric database-start-transaction (database)
  (:documentation "Start a transaction in DATABASE."))

(defgeneric database-commit-transaction (database)
  (:documentation "Commit current transaction in DATABASE."))

(defgeneric database-abort-transaction (database)
  (:documentation "Abort current transaction in DATABASE."))

(defgeneric database-get-type-specifier (type args database)
  (:documentation "Return the type SQL type specifier as a string, for
the given lisp type and parameters."))

(defgeneric database-list-tables (database &key system-tables)
  (:documentation "List all tables in the given database"))

(defgeneric database-list-attributes (table database)
  (:documentation "List all attributes in TABLE."))

(defgeneric database-attribute-type (attribute table database)
  (:documentation "Return the type of ATTRIBUTE in TABLE."))

(defgeneric database-add-attribute (table attribute database)
  (:documentation "Add the attribute to the table."))

(defgeneric database-rename-attribute (table oldatt newname database)
  (:documentation "Rename the attribute in the table to NEWNAME."))

(defgeneric oid (object)
  (:documentation "Return the unique ID of a database object."))

;;; Large objects support (Marc Battyani)

(defgeneric database-create-large-object (database)
  (:documentation "Creates a new large object in the database and returns the object identifier"))

(defgeneric database-write-large-object (object-id (data string) database)
  (:documentation "Writes data to the large object"))

(defgeneric database-read-large-object (object-id database)
  (:documentation "Reads the large object content"))

(defgeneric database-delete-large-object (object-id database)
  (:documentation "Deletes the large object in the database"))


Update

Update

__kernel
void rotate_image3d(sampler_t sampler,
                    read_only image3d_t image,
                    float16 rotmat,
                   __global float *out,
                   float4 center,
                   int4 shape)
{
    int id = get_global_id(0);
    int stride = get_global_size(0);

    int x, y, z, slice;
    float xrot, yrot, zrot;
    float4 coordinate, weight;

    slice = shape.s2*shape.s1;

    int i;
    for (i = id; i < shape.s3; i += stride) {

        z = i/slice;
        y = (i - z*slice)/shape.s2;
        x = i - z*slice - y*shape.s2;

        if (x >= 0.5*shape.s2)
            x -= shape.s2;
        if (y >= 0.5*shape.s1)
            y -= shape.s1;
        if (z >= 0.5*shape.s0)
            z -= shape.s0;

        xrot = rotmat.s0*x + rotmat.s1*y + rotmat.s2*z;
        yrot = rotmat.s3*x + rotmat.s4*y + rotmat.s5*z;
        zrot = rotmat.s6*x + rotmat.s7*y + rotmat.s8*z;

        xrot += 0.5f + center.s0;
        yrot += 0.5f + center.s1;
        zrot += 0.5f + center.s2;

        coordinate = (float4) (xrot, yrot, zrot, 0);
        weight = read_imagef(image, sampler, coordinate);

        out[i] = weight.s0;
    }
}
__kernel
void count(__global int *interspace,
           __global int *access_interspace,
           float weight,
           __global float *counts,
           int size)
{
    int id = get_global_id(0);
    int stride = get_global_size(0);
    int i, n;

    for (i = id; i < size; i += stride){
        if (interspace[i] > 0)
            counts[i] += weight;

        n = access_interspace[i];
        if (n > 0)
            counts[n*size + i] += weight;
    }
}

__kernel
void blur_points(__global float4 *points,
                 __global float *weights,
                 float sigma,
                 __global float *out,
                 int4 shape, int npoints)
{
    const int zid = get_global_id(0);
    const int yid = get_global_id(1);
    const int xid = get_global_id(2);

    const int zstride = get_global_size(0);
    const int ystride = get_global_size(1);
    const int xstride = get_global_size(2);

    const float sigma2 = pown(sigma, 2);
    const float extend2 = pown(4*sigma, 2);
    const int slice = shape.s2 * shape.s1;
    const float hx = 0.5 * shape.s2;
    const float hy = 0.5 * shape.s1;
    const float hz = 0.5 * shape.s0;

    unsigned int i, iz, iy, ix, z_ind, yz_ind;
    float z, y, x, z2, y2z2, x2y2z2;

    for (i = 0; i < npoints; i ++){

        for (iz = zid; iz < shape.s0; iz += zstride){

            z = iz;
            if (z > hz)
                z -= shape.s0;

            z2 = pown(z - points[i].s0, 2);

            if (z2 > extend2)
                continue;

            z_ind = iz*slice;

            for (iy = yid; iy < shape.s1; iy += ystride){
                y = iy;
                if (y > hy)
                    y -= shape.s1;

                y2z2 = pown(y - points[i].s1, 2) + z2;

                if (y2z2 > extend2)
                    continue;

                yz_ind = iy*shape.s2 + z_ind;

                for (ix = xid; ix < shape.s2; ix += xstride){
                    x = ix;
                    if (x > hx)
                        x -= shape.s2;

                    x2y2z2 = pown(x - points[i].s2, 2) + y2z2;

                    if (x2y2z2 > extend2)
                        continue;

                    out[yz_ind + ix] += weights[i]*exp(-x2y2z2/sigma2);
                }
            }
        }
    }
}

__kernel
void dilate_points_add(__global float8 *constraints,
                       float16 rotmat,
                       __global int *restspace, int4 shape, int nrestraints)
{

    int zid = get_global_id(0);
    int yid = get_global_id(1);
    int xid = get_global_id(2);

    int zstride = get_global_size(0);
    int ystride = get_global_size(1);
    int xstride = get_global_size(2);

    int i, ix, iy, iz;
    int z_ind, yz_ind, xyz_ind, slice;
    float xligand, yligand, zligand;
    float xcenter, ycenter, zcenter, distance2, z_dis2, yz_dis2, xyz_dis2;

    slice = shape.s2 * shape.s1;

    for (i = 0; i < nrestraints; i++){

         // determine the center of the point that will be dilated
         xligand = rotmat.s0 * constraints[i].s3 + rotmat.s1 * constraints[i].s4 + rotmat.s2 * constraints[i].s5;
         yligand = rotmat.s3 * constraints[i].s3 + rotmat.s4 * constraints[i].s4 + rotmat.s5 * constraints[i].s5;
         zligand = rotmat.s6 * constraints[i].s3 + rotmat.s7 * constraints[i].s4 + rotmat.s8 * constraints[i].s5;

         xcenter = constraints[i].s0 - xligand;
         ycenter = constraints[i].s1 - yligand;
         zcenter = constraints[i].s2 - zligand;

         distance2 = pown(constraints[i].s6, 2);

         // calculate the distance of every voxel to the determined center
         for (iz = zid; iz < shape.s0; iz += zstride){

             z_dis2 = pown(iz - zcenter, 2);

             z_ind = iz * slice;

             for (iy = yid; iy < shape.s1; iy += ystride){
                 yz_dis2 = pown(iy - ycenter, 2) + z_dis2;

                 yz_ind = z_ind + iy*shape.s2;

                 for (ix = xid; ix < shape.s2; ix += xstride){

                     xyz_dis2 = pown(ix - xcenter, 2) + yz_dis2;

                     if (xyz_dis2 <= distance2){
                         xyz_ind = ix + yz_ind;
                         restspace[xyz_ind] += 1;
                     }
                 }
             }
         }
    }
}

__kernel
void rotate_image3d(sampler_t sampler,
                    read_only image3d_t image,
                    float16 rotmat,
                   __global float *out,
                   float4 center,
                   int4 shape)
{
    int id = get_global_id(0);
    int stride = get_global_size(0);

    int x, y, z, slice;
    float xrot, yrot, zrot;
    float4 coordinate, weight;

    slice = shape.s2*shape.s1;

    int i;
    for (i = id; i < shape.s3; i += stride) {

        z = i/slice;
        y = (i - z*slice)/shape.s2;
        x = i - z*slice - y*shape.s2;

        if (x >= 0.5*shape.s2)
            x -= shape.s2;
        if (y >= 0.5*shape.s1)
            y -= shape.s1;
        if (z >= 0.5*shape.s0)
            z -= shape.s0;

        xrot = rotmat.s0*x + rotmat.s1*y + rotmat.s2*z;
        yrot = rotmat.s3*x + rotmat.s4*y + rotmat.s5*z;
        zrot = rotmat.s6*x + rotmat.s7*y + rotmat.s8*z;

        xrot += 0.5f + center.s0;
        yrot += 0.5f + center.s1;
        zrot += 0.5f + center.s2;

        coordinate = (float4) (xrot, yrot, zrot, 0);
        weight = read_imagef(image, sampler, coordinate);

        out[i] = weight.s0;
    }
}
__kernel
void count(__global int *interspace,
           __global int *access_interspace,
           float weight,
           __global float *counts,
           int size)
{
    int id = get_global_id(0);
    int stride = get_global_size(0);
    int i, n;

    for (i = id; i < size; i += stride){
        if (interspace[i] > 0)
            counts[i] += weight;

        n = access_interspace[i];
        if (n > 0)
            counts[n*size + i] += weight;
    }
}

__kernel
void blur_points(__global float4 points,
                 __global float weights,
                 float sigma,
                 __global float out,
                 int4 shape, int npoints)
{
    const int zid = get_global_id(0);
    const int yid = get_global_id(1);
    const int xid = get_global_id(2);

    const int zstride = get_global_size(0);
    const int ystride = get_global_size(1);
    const int xstride = get_global_size(2);

    const float sigma2 = pown(sigma, 2)
    const float extend2 = pown(4*sigma, 2);
    const int slice = shape.s2 * shape.s1;
    const float hx = 0.5 * shape.s2;
    const float hy = 0.5 * shape.s1;
    const float hz = 0.5 * shape.s0;

    unsigned int i, iz, iy, ix, z_ind, yz_ind;
    float z, y, x, z2, y2z2, x2y2z2;

    for (i = 0; i < npoints; i ++){

        for (iz = zid; iz < shape.s0; iz += zstride){

            z = iz;
            if (z > hz)
                z -= shape.s0;

            z2 = pown(z - points[i].s0, 2);

            if (z2 > extend2)
                continue

            z_ind = iz*slice;

            for (iy = yid; iy < shape.s1; iy += ystride){
                y = iy;
                if (y > hy)
                    y -= shape.s1;

                y2z2 = pown(y - points[i].s1, 2) + z2;

                if (y2z2 > extend2)
                    continue

                yz_ind = iy*shape.s2 + z_ind;

                for (ix = xid; ix < shape.s2; ix += xstride){
                    x = ix;
                    if (x > hx)
                        x -= shape.s2;

                    x2y2z2 = pown(x - points[i].s2, 2) + y2z2;

                    if (x2y2z2 > extend2)
                        continue

                    out[yz_ind + ix] += weights[i]*exp(-x2y2z2/sigma2);
                }
            }
        }
    }
}

__kernel
void dilate_points_add(__global float8 *constraints,
                       float16 rotmat,
                       __global int *restspace, int4 shape, int nrestraints)
{

    int zid = get_global_id(0);
    int yid = get_global_id(1);
    int xid = get_global_id(2);

    int zstride = get_global_size(0);
    int ystride = get_global_size(1);
    int xstride = get_global_size(2);

    int i, ix, iy, iz;
    int z_ind, yz_ind, xyz_ind, slice;
    float xligand, yligand, zligand;
    float xcenter, ycenter, zcenter, distance2, z_dis2, yz_dis2, xyz_dis2;

    slice = shape.s2 * shape.s1;

    for (i = 0; i < nrestraints; i++){

         // determine the center of the point that will be dilated
         xligand = rotmat.s0 * constraints[i].s3 + rotmat.s1 * constraints[i].s4 + rotmat.s2 * constraints[i].s5;
         yligand = rotmat.s3 * constraints[i].s3 + rotmat.s4 * constraints[i].s4 + rotmat.s5 * constraints[i].s5;
         zligand = rotmat.s6 * constraints[i].s3 + rotmat.s7 * constraints[i].s4 + rotmat.s8 * constraints[i].s5;

         xcenter = constraints[i].s0 - xligand;
         ycenter = constraints[i].s1 - yligand;
         zcenter = constraints[i].s2 - zligand;

         distance2 = pown(constraints[i].s6, 2);

         // calculate the distance of every voxel to the determined center
         for (iz = zid; iz < shape.s0; iz += zstride){

             z_dis2 = pown(iz - zcenter, 2);

             z_ind = iz * slice;

             for (iy = yid; iy < shape.s1; iy += ystride){
                 yz_dis2 = pown(iy - ycenter, 2) + z_dis2;

                 yz_ind = z_ind + iy*shape.s2;

                 for (ix = xid; ix < shape.s2; ix += xstride){

                     xyz_dis2 = pown(ix - xcenter, 2) + yz_dis2;

                     if (xyz_dis2 <= distance2){
                         xyz_ind = ix + yz_ind;
                         restspace[xyz_ind] += 1;
                     }
                 }
             }
         }
    }
}


Updates to simple add to support vectors of dimensions > workgroup size

git-svn-id: 807bbae5e1e1e6af950d5bf3f1690f093529d808@61 319ae97b-01e6-675e-e8e9-a1b9ca5b6390

// Need to define a simplified iteration id:
inline int get_index(int nelems, int index ) {
  if (index == -1)  {
    index = get_global_id(0);
  } else {
    index += get_global_size(0);
  }

  if (index >= nelems) index = -1;

  return index;
}

__kernel void add(__global const float *x, __global const float *y, __global float *z, int N) {

  int id = get_index(N, -1);
  while(id >= 0) {
     z[id] = x[id] + y[id];
     id = get_index(N, id);
  }

}

__kernel void add(__global const float *x, __global const float *y, __global float *z, int N) {
  int id = get_global_id(0);
  if (id >= N) return;
  z[id] = x[id] + y[id];
}