<commit_before>// Copyright 2014 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <iostream>
#include <string>
#include <vector>
#include <exception>
#include <fstream>
#include <iomanip>
#include <limits>

#include <ArgumentList.hpp>
#include <Observation.hpp>
#include <InitializeOpenCL.hpp>
#include <Kernel.hpp>
#include <Shifts.hpp>
#include <Dedispersion.hpp>
#include <utils.hpp>
#include <Timer.hpp>
#include <Stats.hpp>

// Define the data types
typedef float inputDataType;
std::string inputTypeName("float");
std::string intermediateTypeName("float");
typedef float outputDataType;
std::string outputTypeName("float");

void initializeDeviceMemory(cl::Context & clContext, cl::CommandQueue * clQueue, std::vector< float > * shifts, cl::Buffer * shifts_d, cl::Buffer * dispersedData_d, const unsigned int dispersedData_size, cl::Buffer * dedispersedData_d, const unsigned int dedispersedData_size);

int main(int argc, char * argv[]) {
  bool reInit = false;
  uint8_t inputBits = 0;
  unsigned int splitSeconds = 0;
	unsigned int nrIterations = 0;
	unsigned int clPlatformID = 0;
	unsigned int clDeviceID = 0;
	unsigned int minThreads = 0;
  unsigned int maxThreads = 0;
	unsigned int maxRows = 0;
	unsigned int maxColumns = 0;
  unsigned int threadUnit = 0;
  unsigned int threadIncrement = 0;
  unsigned int maxItems = 0;
  unsigned int maxUnroll = 0;
  unsigned int maxLoopBodySize = 0;
  AstroData::Observation observation;
  PulsarSearch::DedispersionConf conf;
  cl::Event event;

	try {
    isa::utils::ArgumentList args(argc, argv);

		nrIterations = args.getSwitchArgument< unsigned int >("-iterations");
		clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
		clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
    conf.setSplitSeconds(args.getSwitch("-split_seconds"));
    conf.setLocalMem(args.getSwitch("-local"));
		observation.setPadding(args.getSwitchArgument< unsigned int >("-padding"));
    inputBits = args.getSwitchArgument< unsigned int >("-input_bits");
    threadUnit = args.getSwitchArgument< unsigned int >("-thread_unit");
		minThreads = args.getSwitchArgument< unsigned int >("-min_threads");
		maxThreads = args.getSwitchArgument< unsigned int >("-max_threads");
		maxRows = args.getSwitchArgument< unsigned int >("-max_rows");
		maxColumns = args.getSwitchArgument< unsigned int >("-max_columns");
    threadIncrement = args.getSwitchArgument< unsigned int >("-thread_increment");
		maxItems = args.getSwitchArgument< unsigned int >("-max_items");
    maxUnroll = args.getSwitchArgument< unsigned int >("-max_unroll");
    maxLoopBodySize = args.getSwitchArgument< unsigned int >("-max_loopsize");
    observation.setFrequencyRange(args.getSwitchArgument< unsigned int >("-channels"), args.getSwitchArgument< float >("-min_freq"), args.getSwitchArgument< float >("-channel_bandwidth"));
		observation.setNrSamplesPerSecond(args.getSwitchArgument< unsigned int >("-samples"));
    observation.setDMRange(args.getSwitchArgument< unsigned int >("-dms"), args.getSwitchArgument< float >("-dm_first"), args.getSwitchArgument< float >("-dm_step"));
	} catch ( isa::utils::EmptyCommandLine & err ) {
		std::cerr << argv[0] << " -iterations ... -opencl_platform ... -opencl_device ... [-split_seconds] [-local] -input_bits ... -padding ... -thread_unit ... -min_threads ... -max_threads ... -max_items ... -max_unroll ... -max_loopsize ... -max_columns ... -max_rows ... -thread_increment ... -min_freq ... -channel_bandwidth ... -samples ... -channels ... -dms ... -dm_first ... -dm_step ..." << std::endl;
		return 1;
	} catch ( std::exception & err ) {
		std::cerr << err.what() << std::endl;
		return 1;
	}

  // Allocate host memory
  std::vector< float > * shifts = PulsarSearch::getShifts(observation);
  if ( conf.getSplitSeconds() ) {
    if ( (observation.getNrSamplesPerSecond() + static_cast< unsigned int >(shifts->at(0) * (observation.getFirstDM() + ((observation.getNrDMs() - 1) * observation.getDMStep())))) % observation.getNrSamplesPerSecond() == 0 ) {
      splitSeconds = (observation.getNrSamplesPerSecond() + static_cast< unsigned int >(shifts->at(0) * (observation.getFirstDM() + ((observation.getNrDMs() - 1) * observation.getDMStep())))) / observation.getNrSamplesPerSecond();
    } else {
      splitSeconds = ((observation.getNrSamplesPerSecond() + static_cast< unsigned int >(shifts->at(0) * (observation.getFirstDM() + ((observation.getNrDMs() - 1) * observation.getDMStep())))) / observation.getNrSamplesPerSecond()) + 1;
    }
  } else {
    observation.setNrSamplesPerDispersedChannel(observation.getNrSamplesPerSecond() + static_cast< unsigned int >(shifts->at(0) * (observation.getFirstDM() + ((observation.getNrDMs() - 1) * observation.getDMStep()))));
  }

	// Initialize OpenCL
	cl::Context clContext;
	std::vector< cl::Platform > * clPlatforms = new std::vector< cl::Platform >();
	std::vector< cl::Device > * clDevices = new std::vector< cl::Device >();
	std::vector< std::vector< cl::CommandQueue > > * clQueues = new std::vector< std::vector < cl::CommandQueue > >();
  isa::OpenCL::initializeOpenCL(clPlatformID, 1, clPlatforms, &clContext, clDevices, clQueues);

	// Allocate device memory
  cl::Buffer shifts_d;
  cl::Buffer dispersedData_d;
  cl::Buffer dedispersedData_d;

  try {
    if ( conf.getSplitSeconds() ) {
      initializeDeviceMemory(clContext, &(clQueues->at(clDeviceID)[0]), shifts, &shifts_d, &dispersedData_d, splitSeconds * observation.getNrChannels() * observation.getNrSamplesPerPaddedSecond(), &dedispersedData_d, observation.getNrDMs() * observation.getNrSamplesPerPaddedSecond());
    } else {
      initializeDeviceMemory(clContext, &(clQueues->at(clDeviceID)[0]), shifts, &shifts_d, &dispersedData_d, observation.getNrChannels() * observation.getNrSamplesPerDispersedChannel(), &dedispersedData_d, observation.getNrDMs() * observation.getNrSamplesPerPaddedSecond());
    }
  } catch ( cl::Error & err ) {
    std::cerr << err.what() << std::endl;
    return -1;
  }

	// Find the parameters
	std::vector< unsigned int > samplesPerBlock;
	for ( unsigned int samples = minThreads; samples <= maxColumns; samples += threadIncrement ) {
		if ( (observation.getNrSamplesPerSecond() % samples) == 0 || (observation.getNrSamplesPerPaddedSecond() % samples) == 0 ) {
			samplesPerBlock.push_back(samples);
		}
	}
	std::vector< unsigned int > DMsPerBlock;
	for ( unsigned int DMs = 1; DMs <= maxRows; DMs++ ) {
		if ( (observation.getNrDMs() % DMs) == 0 ) {
			DMsPerBlock.push_back(DMs);
		}
	}

	std::cout << std::fixed << std::endl;
	std::cout << "# nrDMs nrChannels nrSamples splitSeconds local unroll samplesPerBlock DMsPerBlock samplesPerThread DMsPerThread GFLOP/s time stdDeviation COV" << std::endl << std::endl;

	for ( std::vector< unsigned int >::iterator samples = samplesPerBlock.begin(); samples != samplesPerBlock.end(); ++samples ) {
    conf.setNrSamplesPerBlock(*samples);

		for ( std::vector< unsigned int >::iterator DMs = DMsPerBlock.begin(); DMs != DMsPerBlock.end(); ++DMs ) {
      conf.setNrDMsPerBlock(*DMs);
			if ( conf.getNrSamplesPerBlock() * conf.getNrDMsPerBlock() > maxThreads ) {
				break;
			} else if ( (conf.getNrSamplesPerBlock() * conf.getNrDMsPerBlock()) % threadUnit != 0 ) {
        continue;
      }

			for ( unsigned int samplesPerThread = 1; samplesPerThread <= maxItems; samplesPerThread++ ) {
        conf.setNrSamplesPerThread(samplesPerThread);
				if ( (observation.getNrSamplesPerSecond() % (conf.getNrSamplesPerBlock() * conf.getNrSamplesPerThread())) != 0 && (observation.getNrSamplesPerPaddedSecond() % (conf.getNrSamplesPerBlock() * conf.getNrSamplesPerThread())) != 0 ) {
					continue;
				}

				for ( unsigned int DMsPerThread = 1; DMsPerThread <= maxItems; DMsPerThread++ ) {
          conf.setNrDMsPerThread(DMsPerThread);
					if ( (observation.getNrDMs() % (conf.getNrDMsPerBlock() * conf.getNrDMsPerThread())) != 0 ) {
						continue;
					} else if ( (conf.getNrSamplesPerThread() * conf.getNrDMsPerThread()) + conf.getNrDMsPerThread() > maxItems ) {
						break;
					}

          for ( unsigned int unroll = 1; unroll <= maxUnroll; unroll++ ) {
            conf.setUnroll(unroll);
            if ( (observation.getNrChannels() - 1) % conf.getUnroll() != 0 ) {
              continue;
            } else if ( (conf.getNrSamplesPerThread() * conf.getNrDMsPerThread() * conf.getUnroll()) > maxLoopBodySize ) {
              break;
            }
            // Generate kernel
            double gflops = isa::utils::giga(static_cast< long long unsigned int >(observation.getNrDMs()) * observation.getNrChannels() * observation.getNrSamplesPerSecond());
            isa::utils::Timer timer;
            cl::Kernel * kernel;
            std::string * code = PulsarSearch::getDedispersionOpenCL(conf, inputBits, inputTypeName, intermediateTypeName, outputTypeName, observation, *shifts);

            if ( reInit ) {
              delete clQueues;
              clQueues = new std::vector< std::vector < cl::CommandQueue > >();
              isa::OpenCL::initializeOpenCL(clPlatformID, 1, clPlatforms, &clContext, clDevices, clQueues);
              try {
                initializeDeviceMemory(clContext, &(clQueues->at(clDeviceID)[0]), shifts, &shifts_d, &dispersedData_d, observation.getNrChannels() * observation.getNrSamplesPerDispersedChannel(), &dedispersedData_d, observation.getNrDMs() * observation.getNrSamplesPerPaddedSecond());
              } catch ( cl::Error & err ) {
                return -1;
              }
              reInit = false;
            }
            try {
              kernel = isa::OpenCL::compile("dedispersion", *code, "-cl-mad-enable -Werror", clContext, clDevices->at(clDeviceID));
            } catch ( isa::OpenCL::OpenCLError & err ) {
              std::cerr << err.what() << std::endl;
              delete code;
              break;
            }
            delete code;

            unsigned int nrThreads = 0;
            if ( observation.getNrSamplesPerSecond() % (conf.getNrSamplesPerBlock() * conf.getNrSamplesPerThread()) == 0 ) {
              nrThreads = observation.getNrSamplesPerSecond() / conf.getNrSamplesPerThread();
            } else {
              nrThreads = observation.getNrSamplesPerPaddedSecond() / conf.getNrSamplesPerThread();
            }
            cl::NDRange global(nrThreads, observation.getNrDMs() / conf.getNrDMsPerThread());
            cl::NDRange local(conf.getNrSamplesPerBlock(), conf.getNrDMsPerBlock());

            kernel->setArg(0, dispersedData_d);
            kernel->setArg(1, dedispersedData_d);
            kernel->setArg(2, shifts_d);

            try {
              // Warm-up run
              clQueues->at(clDeviceID)[0].finish();
              clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &event);
              event.wait();
              // Tuning runs
              for ( unsigned int iteration = 0; iteration < nrIterations; iteration++ ) {
                timer.start();
                clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &event);
                event.wait();
                timer.stop();
              }
            } catch ( cl::Error & err ) {
              std::cerr << "OpenCL error kernel execution (";
              std::cerr << conf.print() << "): ";
              std::cerr << isa::utils::toString(err.err()) << "." << std::endl;
              delete kernel;
              if ( err.err() == -4 || err.err() == -61 ) {
                return -1;
              }
              reInit = true;
              break;
            }
            delete kernel;

            std::cout << observation.getNrDMs() << " " << observation.getNrChannels() << " " << observation.getNrSamplesPerSecond() << " ";
            std::cout << conf.print() << " ";
            std::cout << std::setprecision(3);
            std::cout << gflops / timer.getAverageTime() << " ";
            std::cout << std::setprecision(6);
            std::cout << timer.getAverageTime() << " " << timer.getStandardDeviation() << " ";
            std::cout << timer.getCoefficientOfVariation() <<  std::endl;
          }
				}
			}
		}
	}

	std::cout << std::endl;

	return 0;
}

void initializeDeviceMemory(cl::Context & clContext, cl::CommandQueue * clQueue, std::vector< float > * shifts, cl::Buffer * shifts_d, cl::Buffer * dispersedData_d, const unsigned int dispersedData_size, cl::Buffer * dedispersedData_d, const unsigned int dedispersedData_size) {
  try {
    *shifts_d = cl::Buffer(clContext, CL_MEM_READ_ONLY, shifts->size() * sizeof(float), 0, 0);
    *dispersedData_d = cl::Buffer(clContext, CL_MEM_READ_ONLY, dispersedData_size * sizeof(inputDataType), 0, 0);
    *dedispersedData_d = cl::Buffer(clContext, CL_MEM_READ_WRITE, dedispersedData_size * sizeof(outputDataType), 0, 0);
    clQueue->enqueueWriteBuffer(*shifts_d, CL_FALSE, 0, shifts->size() * sizeof(float), reinterpret_cast< void * >(shifts->data()));
    clQueue->finish();
  } catch ( cl::Error & err ) {
    std::cerr << "OpenCL error: " << isa::utils::toString(err.err()) << "." << std::endl;
    throw;
  }
}

<commit_msg>The version that uses split seconds needs a parameter more.<commit_after>// Copyright 2014 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <iostream>
#include <string>
#include <vector>
#include <exception>
#include <fstream>
#include <iomanip>
#include <limits>

#include <ArgumentList.hpp>
#include <Observation.hpp>
#include <InitializeOpenCL.hpp>
#include <Kernel.hpp>
#include <Shifts.hpp>
#include <Dedispersion.hpp>
#include <utils.hpp>
#include <Timer.hpp>
#include <Stats.hpp>

// Define the data types
typedef float inputDataType;
std::string inputTypeName("float");
std::string intermediateTypeName("float");
typedef float outputDataType;
std::string outputTypeName("float");

void initializeDeviceMemory(cl::Context & clContext, cl::CommandQueue * clQueue, std::vector< float > * shifts, cl::Buffer * shifts_d, cl::Buffer * dispersedData_d, const unsigned int dispersedData_size, cl::Buffer * dedispersedData_d, const unsigned int dedispersedData_size);

int main(int argc, char * argv[]) {
  bool reInit = false;
  uint8_t inputBits = 0;
  unsigned int splitSeconds = 0;
	unsigned int nrIterations = 0;
	unsigned int clPlatformID = 0;
	unsigned int clDeviceID = 0;
	unsigned int minThreads = 0;
  unsigned int maxThreads = 0;
	unsigned int maxRows = 0;
	unsigned int maxColumns = 0;
  unsigned int threadUnit = 0;
  unsigned int threadIncrement = 0;
  unsigned int maxItems = 0;
  unsigned int maxUnroll = 0;
  unsigned int maxLoopBodySize = 0;
  AstroData::Observation observation;
  PulsarSearch::DedispersionConf conf;
  cl::Event event;

	try {
    isa::utils::ArgumentList args(argc, argv);

		nrIterations = args.getSwitchArgument< unsigned int >("-iterations");
		clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
		clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
    conf.setSplitSeconds(args.getSwitch("-split_seconds"));
    conf.setLocalMem(args.getSwitch("-local"));
		observation.setPadding(args.getSwitchArgument< unsigned int >("-padding"));
    inputBits = args.getSwitchArgument< unsigned int >("-input_bits");
    threadUnit = args.getSwitchArgument< unsigned int >("-thread_unit");
		minThreads = args.getSwitchArgument< unsigned int >("-min_threads");
		maxThreads = args.getSwitchArgument< unsigned int >("-max_threads");
		maxRows = args.getSwitchArgument< unsigned int >("-max_rows");
		maxColumns = args.getSwitchArgument< unsigned int >("-max_columns");
    threadIncrement = args.getSwitchArgument< unsigned int >("-thread_increment");
		maxItems = args.getSwitchArgument< unsigned int >("-max_items");
    maxUnroll = args.getSwitchArgument< unsigned int >("-max_unroll");
    maxLoopBodySize = args.getSwitchArgument< unsigned int >("-max_loopsize");
    observation.setFrequencyRange(args.getSwitchArgument< unsigned int >("-channels"), args.getSwitchArgument< float >("-min_freq"), args.getSwitchArgument< float >("-channel_bandwidth"));
		observation.setNrSamplesPerSecond(args.getSwitchArgument< unsigned int >("-samples"));
    observation.setDMRange(args.getSwitchArgument< unsigned int >("-dms"), args.getSwitchArgument< float >("-dm_first"), args.getSwitchArgument< float >("-dm_step"));
	} catch ( isa::utils::EmptyCommandLine & err ) {
		std::cerr << argv[0] << " -iterations ... -opencl_platform ... -opencl_device ... [-split_seconds] [-local] -input_bits ... -padding ... -thread_unit ... -min_threads ... -max_threads ... -max_items ... -max_unroll ... -max_loopsize ... -max_columns ... -max_rows ... -thread_increment ... -min_freq ... -channel_bandwidth ... -samples ... -channels ... -dms ... -dm_first ... -dm_step ..." << std::endl;
		return 1;
	} catch ( std::exception & err ) {
		std::cerr << err.what() << std::endl;
		return 1;
	}

  // Allocate host memory
  std::vector< float > * shifts = PulsarSearch::getShifts(observation);
  if ( conf.getSplitSeconds() ) {
    if ( (observation.getNrSamplesPerSecond() + static_cast< unsigned int >(shifts->at(0) * (observation.getFirstDM() + ((observation.getNrDMs() - 1) * observation.getDMStep())))) % observation.getNrSamplesPerSecond() == 0 ) {
      splitSeconds = (observation.getNrSamplesPerSecond() + static_cast< unsigned int >(shifts->at(0) * (observation.getFirstDM() + ((observation.getNrDMs() - 1) * observation.getDMStep())))) / observation.getNrSamplesPerSecond();
    } else {
      splitSeconds = ((observation.getNrSamplesPerSecond() + static_cast< unsigned int >(shifts->at(0) * (observation.getFirstDM() + ((observation.getNrDMs() - 1) * observation.getDMStep())))) / observation.getNrSamplesPerSecond()) + 1;
    }
  } else {
    observation.setNrSamplesPerDispersedChannel(observation.getNrSamplesPerSecond() + static_cast< unsigned int >(shifts->at(0) * (observation.getFirstDM() + ((observation.getNrDMs() - 1) * observation.getDMStep()))));
  }

	// Initialize OpenCL
	cl::Context clContext;
	std::vector< cl::Platform > * clPlatforms = new std::vector< cl::Platform >();
	std::vector< cl::Device > * clDevices = new std::vector< cl::Device >();
	std::vector< std::vector< cl::CommandQueue > > * clQueues = new std::vector< std::vector < cl::CommandQueue > >();
  isa::OpenCL::initializeOpenCL(clPlatformID, 1, clPlatforms, &clContext, clDevices, clQueues);

	// Allocate device memory
  cl::Buffer shifts_d;
  cl::Buffer dispersedData_d;
  cl::Buffer dedispersedData_d;

  try {
    if ( conf.getSplitSeconds() ) {
      initializeDeviceMemory(clContext, &(clQueues->at(clDeviceID)[0]), shifts, &shifts_d, &dispersedData_d, splitSeconds * observation.getNrChannels() * observation.getNrSamplesPerPaddedSecond(), &dedispersedData_d, observation.getNrDMs() * observation.getNrSamplesPerPaddedSecond());
    } else {
      initializeDeviceMemory(clContext, &(clQueues->at(clDeviceID)[0]), shifts, &shifts_d, &dispersedData_d, observation.getNrChannels() * observation.getNrSamplesPerDispersedChannel(), &dedispersedData_d, observation.getNrDMs() * observation.getNrSamplesPerPaddedSecond());
    }
  } catch ( cl::Error & err ) {
    std::cerr << err.what() << std::endl;
    return -1;
  }

	// Find the parameters
	std::vector< unsigned int > samplesPerBlock;
	for ( unsigned int samples = minThreads; samples <= maxColumns; samples += threadIncrement ) {
		if ( (observation.getNrSamplesPerSecond() % samples) == 0 || (observation.getNrSamplesPerPaddedSecond() % samples) == 0 ) {
			samplesPerBlock.push_back(samples);
		}
	}
	std::vector< unsigned int > DMsPerBlock;
	for ( unsigned int DMs = 1; DMs <= maxRows; DMs++ ) {
		if ( (observation.getNrDMs() % DMs) == 0 ) {
			DMsPerBlock.push_back(DMs);
		}
	}

	std::cout << std::fixed << std::endl;
	std::cout << "# nrDMs nrChannels nrSamples splitSeconds local unroll samplesPerBlock DMsPerBlock samplesPerThread DMsPerThread GFLOP/s time stdDeviation COV" << std::endl << std::endl;

	for ( std::vector< unsigned int >::iterator samples = samplesPerBlock.begin(); samples != samplesPerBlock.end(); ++samples ) {
    conf.setNrSamplesPerBlock(*samples);

		for ( std::vector< unsigned int >::iterator DMs = DMsPerBlock.begin(); DMs != DMsPerBlock.end(); ++DMs ) {
      conf.setNrDMsPerBlock(*DMs);
			if ( conf.getNrSamplesPerBlock() * conf.getNrDMsPerBlock() > maxThreads ) {
				break;
			} else if ( (conf.getNrSamplesPerBlock() * conf.getNrDMsPerBlock()) % threadUnit != 0 ) {
        continue;
      }

			for ( unsigned int samplesPerThread = 1; samplesPerThread <= maxItems; samplesPerThread++ ) {
        conf.setNrSamplesPerThread(samplesPerThread);
				if ( (observation.getNrSamplesPerSecond() % (conf.getNrSamplesPerBlock() * conf.getNrSamplesPerThread())) != 0 && (observation.getNrSamplesPerPaddedSecond() % (conf.getNrSamplesPerBlock() * conf.getNrSamplesPerThread())) != 0 ) {
					continue;
				}

				for ( unsigned int DMsPerThread = 1; DMsPerThread <= maxItems; DMsPerThread++ ) {
          conf.setNrDMsPerThread(DMsPerThread);
					if ( (observation.getNrDMs() % (conf.getNrDMsPerBlock() * conf.getNrDMsPerThread())) != 0 ) {
						continue;
					} else if ( (conf.getNrSamplesPerThread() * conf.getNrDMsPerThread()) + conf.getNrDMsPerThread() > maxItems ) {
						break;
					}

          for ( unsigned int unroll = 1; unroll <= maxUnroll; unroll++ ) {
            conf.setUnroll(unroll);
            if ( (observation.getNrChannels() - 1) % conf.getUnroll() != 0 ) {
              continue;
            } else if ( (conf.getNrSamplesPerThread() * conf.getNrDMsPerThread() * conf.getUnroll()) > maxLoopBodySize ) {
              break;
            }
            // Generate kernel
            double gflops = isa::utils::giga(static_cast< long long unsigned int >(observation.getNrDMs()) * observation.getNrChannels() * observation.getNrSamplesPerSecond());
            isa::utils::Timer timer;
            cl::Kernel * kernel;
            std::string * code = PulsarSearch::getDedispersionOpenCL(conf, inputBits, inputTypeName, intermediateTypeName, outputTypeName, observation, *shifts);

            if ( reInit ) {
              delete clQueues;
              clQueues = new std::vector< std::vector < cl::CommandQueue > >();
              isa::OpenCL::initializeOpenCL(clPlatformID, 1, clPlatforms, &clContext, clDevices, clQueues);
              try {
                initializeDeviceMemory(clContext, &(clQueues->at(clDeviceID)[0]), shifts, &shifts_d, &dispersedData_d, observation.getNrChannels() * observation.getNrSamplesPerDispersedChannel(), &dedispersedData_d, observation.getNrDMs() * observation.getNrSamplesPerPaddedSecond());
              } catch ( cl::Error & err ) {
                return -1;
              }
              reInit = false;
            }
            try {
              kernel = isa::OpenCL::compile("dedispersion", *code, "-cl-mad-enable -Werror", clContext, clDevices->at(clDeviceID));
            } catch ( isa::OpenCL::OpenCLError & err ) {
              std::cerr << err.what() << std::endl;
              delete code;
              break;
            }
            delete code;

            unsigned int nrThreads = 0;
            if ( observation.getNrSamplesPerSecond() % (conf.getNrSamplesPerBlock() * conf.getNrSamplesPerThread()) == 0 ) {
              nrThreads = observation.getNrSamplesPerSecond() / conf.getNrSamplesPerThread();
            } else {
              nrThreads = observation.getNrSamplesPerPaddedSecond() / conf.getNrSamplesPerThread();
            }
            cl::NDRange global(nrThreads, observation.getNrDMs() / conf.getNrDMsPerThread());
            cl::NDRange local(conf.getNrSamplesPerBlock(), conf.getNrDMsPerBlock());

            if ( conf.getSplitSeconds() ) {
              kernel->setArg(0, 0);
              kernel->setArg(1, dispersedData_d);
              kernel->setArg(2, dedispersedData_d);
              kernel->setArg(3, shifts_d);
            } else {
              kernel->setArg(0, dispersedData_d);
              kernel->setArg(1, dedispersedData_d);
              kernel->setArg(2, shifts_d);
            }

            try {
              // Warm-up run
              clQueues->at(clDeviceID)[0].finish();
              clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &event);
              event.wait();
              // Tuning runs
              for ( unsigned int iteration = 0; iteration < nrIterations; iteration++ ) {
                timer.start();
                clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &event);
                event.wait();
                timer.stop();
              }
            } catch ( cl::Error & err ) {
              std::cerr << "OpenCL error kernel execution (";
              std::cerr << conf.print() << "): ";
              std::cerr << isa::utils::toString(err.err()) << "." << std::endl;
              delete kernel;
              if ( err.err() == -4 || err.err() == -61 ) {
                return -1;
              }
              reInit = true;
              break;
            }
            delete kernel;

            std::cout << observation.getNrDMs() << " " << observation.getNrChannels() << " " << observation.getNrSamplesPerSecond() << " ";
            std::cout << conf.print() << " ";
            std::cout << std::setprecision(3);
            std::cout << gflops / timer.getAverageTime() << " ";
            std::cout << std::setprecision(6);
            std::cout << timer.getAverageTime() << " " << timer.getStandardDeviation() << " ";
            std::cout << timer.getCoefficientOfVariation() <<  std::endl;
          }
				}
			}
		}
	}

	std::cout << std::endl;

	return 0;
}

void initializeDeviceMemory(cl::Context & clContext, cl::CommandQueue * clQueue, std::vector< float > * shifts, cl::Buffer * shifts_d, cl::Buffer * dispersedData_d, const unsigned int dispersedData_size, cl::Buffer * dedispersedData_d, const unsigned int dedispersedData_size) {
  try {
    *shifts_d = cl::Buffer(clContext, CL_MEM_READ_ONLY, shifts->size() * sizeof(float), 0, 0);
    *dispersedData_d = cl::Buffer(clContext, CL_MEM_READ_ONLY, dispersedData_size * sizeof(inputDataType), 0, 0);
    *dedispersedData_d = cl::Buffer(clContext, CL_MEM_READ_WRITE, dedispersedData_size * sizeof(outputDataType), 0, 0);
    clQueue->enqueueWriteBuffer(*shifts_d, CL_FALSE, 0, shifts->size() * sizeof(float), reinterpret_cast< void * >(shifts->data()));
    clQueue->finish();
  } catch ( cl::Error & err ) {
    std::cerr << "OpenCL error: " << isa::utils::toString(err.err()) << "." << std::endl;
    throw;
  }
}

<|endoftext|>


<commit_before>/*******************************
Copyright (C) 2013-2015 gregoire ANGERAND

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
**********************************/

#include "DeferredCommon.h"
#include "GLContext.h"
#include "VertexArrayFactory.h"

namespace n {
namespace graphics {

const VertexArrayObject<> &getSphere() {
	static VertexArrayObject<> *sphere = 0;
	if(!sphere) {
		sphere = new VertexArrayObject<>(GLContext::getContext()->getVertexArrayFactory()(TriangleBuffer<>::getSphere()));
	}
	return *sphere;
}

const VertexArrayObject<> &getBox() {
	static VertexArrayObject<> *box = 0;
	if(!box) {
		box = new VertexArrayObject<>(GLContext::getContext()->getVertexArrayFactory()(TriangleBuffer<>::getCube()));
	}
	return *box;
}

core::String getBRDFs() {
	return
			// [Walter et al. 2007, "Microfacet models for refraction through rough surfaces"]
			"float D_GGX(float NoH, float a2) {"
				"float d = (NoH * a2 - NoH) * NoH + 1.0;"
				"return a2 / (pi * d * d);"
			"}"

			// [Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering"]
			"float F_Schlick(float VoH, float F0) {"
				"float Fc = pow(1 - VoH, 5.0);"
				"return Fc + (1.0 - Fc) * F0;"
			"}"

			"vec3 F_Schlick(float VoH, vec3 F0) {"
				"float Fc = pow(1 - VoH, 5.0);"
				"return Fc + (1.0 - Fc) * F0;"
			"}"

			"float V_Schlick(float NoL, float NoV, float a) {"
				"float k = a * 0.5;"
				"float GV = NoV * (1.0 - k) + k;"
				"float GL = NoL * (1.0 - k) + k;"
				"return 0.25 / (GL * GV + epsilon);"
			"}"

			"float V_Smith(float NoL, float NoV, float a2) {"
				"float GV = NoV + sqrt(NoV * (NoV - NoV * a2) + a2);"
				"float GL = NoL + sqrt(NoL * (NoL - NoL * a2) + a2);"
				"return 1.0 / (GL * GV + epsilon);"
			"}"

			"float V_SmithApprox(float NoL, float NoV, float a) {"
				"float GV = NoL * (NoV * (1.0 - a) + a);"
				"float GL = NoV * (NoL * (1.0 - a) + a);"
				"return 0.5 / (GV + GL + epsilon);"
			"}"

			"float brdf_cook_torrance(vec3 L, vec3 V, vec3 N, vec4 M) {"
				"vec3 H = normalize(L + V);"

				"float NoL = saturate(dot(N, L));"
				"float NoV = max(dot(N, V), epsilon);"
				"float VoH = saturate(dot(V, H));"
				"float NoH = saturate(dot(N, H));"

				"float roughness = saturate(M.x + epsilon);"
				"float a = sqr(roughness);"
				"float a2 = sqr(a);"

				"return "
					"F_Schlick(VoH, M.z) * "
					"D_GGX(NoH, a) * "
					"V_Schlick(NoL, NoV, a);"
			"}"

			"float brdf_lambert(vec3 L, vec3 V, vec3 N, vec4 M) {"
				"return 1.0 / pi;"
			"}"

			//http://blog.selfshadow.com/publications/s2013-shading-course/#course_content
			"vec3 brdf_importance_sample(vec2 Xi, float a) {"
				"float phi = 2.0 * pi * Xi.x;"
				"float cosT = sqrt((1.0 - Xi.y) / (1.0 + (a * a - 1.0) * Xi.y));"
				"float sinT = sqrt(1.0 - cosT * cosT);"
				"return vec3(sinT * cos(phi), sinT * sin(phi), cosT);"
			"}";

}

}
}
<commit_msg>Fixed Schlick to match unreal roughness scale.<commit_after>/*******************************
Copyright (C) 2013-2015 gregoire ANGERAND

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
**********************************/

#include "DeferredCommon.h"
#include "GLContext.h"
#include "VertexArrayFactory.h"

namespace n {
namespace graphics {

const VertexArrayObject<> &getSphere() {
	static VertexArrayObject<> *sphere = 0;
	if(!sphere) {
		sphere = new VertexArrayObject<>(GLContext::getContext()->getVertexArrayFactory()(TriangleBuffer<>::getSphere()));
	}
	return *sphere;
}

const VertexArrayObject<> &getBox() {
	static VertexArrayObject<> *box = 0;
	if(!box) {
		box = new VertexArrayObject<>(GLContext::getContext()->getVertexArrayFactory()(TriangleBuffer<>::getCube()));
	}
	return *box;
}

core::String getBRDFs() {
	return
			// [Walter et al. 2007, "Microfacet models for refraction through rough surfaces"]
			"float D_GGX(float NoH, float a2) {"
				"float d = (NoH * a2 - NoH) * NoH + 1.0;"
				"return a2 / (pi * d * d);"
			"}"

			// [Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering"]
			"float F_Schlick(float VoH, float F0) {"
				"float Fc = pow(1 - VoH, 5.0);"
				"return Fc + (1.0 - Fc) * F0;"
			"}"

			"vec3 F_Schlick(float VoH, vec3 F0) {"
				"float Fc = pow(1 - VoH, 5.0);"
				"return Fc + (1.0 - Fc) * F0;"
			"}"

			"float V_Schlick(float NoL, float NoV, float roughness) {"
				"float k = sqr((roughness + 1.0) * 0.5);"
				"float GV = NoV * (1.0 - k) + k;"
				"float GL = NoL * (1.0 - k) + k;"
				"return 0.25 / (GL * GV + epsilon);"
			"}"

			"float V_Smith(float NoL, float NoV, float a2) {"
				"float GV = NoV + sqrt(NoV * (NoV - NoV * a2) + a2);"
				"float GL = NoL + sqrt(NoL * (NoL - NoL * a2) + a2);"
				"return 1.0 / (GL * GV + epsilon);"
			"}"

			"float V_SmithApprox(float NoL, float NoV, float a) {"
				"float GV = NoL * (NoV * (1.0 - a) + a);"
				"float GL = NoV * (NoL * (1.0 - a) + a);"
				"return 0.5 / (GV + GL + epsilon);"
			"}"

			"float brdf_cook_torrance(vec3 L, vec3 V, vec3 N, vec4 M) {"
				"vec3 H = normalize(L + V);"

				"float NoL = saturate(dot(N, L));"
				"float NoV = max(dot(N, V), epsilon);"
				"float VoH = saturate(dot(V, H));"
				"float NoH = saturate(dot(N, H));"

				"float roughness = saturate(M.x + epsilon);"
				"float a = sqr(roughness);"

				"return "
					"F_Schlick(VoH, M.z) * "
					"D_GGX(NoH, a) * "
					"V_Schlick(NoL, NoV, roughness);"
			"}"

			"float brdf_lambert(vec3 L, vec3 V, vec3 N, vec4 M) {"
				"return 1.0 / pi;"
			"}"

			//http://blog.selfshadow.com/publications/s2013-shading-course/#course_content
			"vec3 brdf_importance_sample(vec2 Xi, float a) {"
				"float phi = 2.0 * pi * Xi.x;"
				"float cosT = sqrt((1.0 - Xi.y) / (1.0 + (a * a - 1.0) * Xi.y));"
				"float sinT = sqrt(1.0 - cosT * cosT);"
				"return vec3(sinT * cos(phi), sinT * sin(phi), cosT);"
			"}";

}

}
}
<|endoftext|>


<commit_before>#include "Plater/Plate2D.hpp"

// libslic3r includes
#include "Geometry.hpp"
#include "Log.hpp"

// wx includes
#include <wx/colour.h>
#include <wx/dcbuffer.h>

namespace Slic3r { namespace GUI {

Plate2D::Plate2D(wxWindow* parent, const wxSize& size, std::vector<Plater2DObject>& _objects, std::shared_ptr<Model> _model, std::shared_ptr<Config> _config, std::shared_ptr<Settings> _settings) :
    wxPanel(parent, wxID_ANY, wxDefaultPosition, size, wxTAB_TRAVERSAL), objects(_objects), model(_model), config(_config), settings(_settings)
{

    this->Bind(wxEVT_PAINT, [=](wxPaintEvent &e) { this->repaint(e); });
    this->Bind(wxEVT_MOTION, [=](wxMouseEvent &e) { this->mouse_drag(e); });
    if (user_drawn_background) {
        this->Bind(wxEVT_ERASE_BACKGROUND, [=](wxEraseEvent& e){ });
    }

    this->Bind(wxEVT_SIZE, [=](wxSizeEvent &e) { this->update_bed_size(); this->Refresh(); });

    // Bind the varying mouse events

    // Set the brushes
    set_colors();
}

void Plate2D::repaint(wxPaintEvent& e) {

    // Need focus to catch keyboard events.
    this->SetFocus();

    auto dc {new wxAutoBufferedPaintDC(this)};
    const auto& size = this->GetSize();

    if (this->user_drawn_background) {
        // On all systems the AutoBufferedPaintDC() achieves double buffering.
        // On MacOS the background is erased, on Windows the background is not erased
        // and on Linux/GTK the background is erased to gray color.
        // Fill DC with the background on Windows & Linux/GTK.
        const auto& brush_background {wxBrush(this->settings->color->BACKGROUND255(), wxBRUSHSTYLE_SOLID)};
        const auto& pen_background {wxPen(this->settings->color->BACKGROUND255(), 1, wxPENSTYLE_SOLID)};
        dc->SetPen(pen_background);
        dc->SetBrush(brush_background);
        const auto& rect {this->GetUpdateRegion().GetBox()};
        dc->DrawRectangle(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight());
    }

    // Draw bed
    {
        dc->SetPen(this->print_center_pen);
        dc->SetBrush(this->bed_brush);

        dc->DrawPolygon(scaled_points_to_pixel(this->bed_polygon, true), 0, 0);
    }

}

void Plate2D::mouse_drag(wxMouseEvent& e) {
    if (e.Dragging()) {
        Slic3r::Log::info(LogChannel, L"Mouse dragging");
    } else {
        Slic3r::Log::info(LogChannel, L"Mouse moving");
    }
}

void Plate2D::set_colors() {

    this->SetBackgroundColour(settings->color->BACKGROUND255());

    this->objects_brush.SetColour(settings->color->BED_OBJECTS());
    this->objects_brush.SetStyle(wxBRUSHSTYLE_SOLID);
    this->instance_brush.SetColour(settings->color->BED_INSTANCE());
    this->instance_brush.SetStyle(wxBRUSHSTYLE_SOLID);
    this->selected_brush.SetColour(settings->color->BED_SELECTED());
    this->selected_brush.SetStyle(wxBRUSHSTYLE_SOLID);
    this->dragged_brush.SetColour(settings->color->BED_DRAGGED());
    this->dragged_brush.SetStyle(wxBRUSHSTYLE_SOLID);
    this->bed_brush.SetColour(settings->color->BED_COLOR());
    this->bed_brush.SetStyle(wxBRUSHSTYLE_SOLID);
    this->transparent_brush.SetColour(wxColour(0,0,0));
    this->transparent_brush.SetStyle(wxBRUSHSTYLE_TRANSPARENT);

    this->grid_pen.SetColour(settings->color->BED_GRID());
    this->grid_pen.SetWidth(1);
    this->grid_pen.SetStyle(wxPENSTYLE_SOLID);
    this->print_center_pen.SetColour(settings->color->BED_CENTER());
    this->print_center_pen.SetWidth(1);
    this->print_center_pen.SetStyle(wxPENSTYLE_SOLID);
    this->clearance_pen.SetColour(settings->color->BED_CLEARANCE());
    this->clearance_pen.SetWidth(1);
    this->clearance_pen.SetStyle(wxPENSTYLE_SOLID);
    this->skirt_pen.SetColour(settings->color->BED_SKIRT());
    this->skirt_pen.SetWidth(1);
    this->skirt_pen.SetStyle(wxPENSTYLE_SOLID);
    this->dark_pen.SetColour(settings->color->BED_DARK());
    this->dark_pen.SetWidth(1);
    this->dark_pen.SetStyle(wxPENSTYLE_SOLID);

}

void Plate2D::nudge_key(wxKeyEvent& e) {
    const auto key = e.GetKeyCode();

    switch( key ) {
        case WXK_LEFT:
            this->nudge(MoveDirection::Left);
        case WXK_RIGHT:
            this->nudge(MoveDirection::Right);
        case WXK_DOWN:
            this->nudge(MoveDirection::Down);
        case WXK_UP:
            this->nudge(MoveDirection::Up);
        default:
            break; // do nothing
    }

}

void Plate2D::nudge(MoveDirection dir) {
    if (this->selected_instance < this->objects.size()) {
        auto i = 0U;
        for (auto& obj : this->objects) {
            if (obj.selected()) {
                if (obj.selected_instance != -1) {
                }
            }
            i++;
        }
    }
    if (selected_instance >= this->objects.size()) {
        Slic3r::Log::warn(LogChannel, L"Nudge failed because there is no selected instance.");
        return; // Abort
    }
}

void Plate2D::update_bed_size() {
    const auto& canvas_size {this->GetSize()};
    const auto& canvas_w {canvas_size.GetWidth()};
    const auto& canvas_h {canvas_size.GetHeight()};
    if (canvas_w == 0) return; // Abort early if we haven't drawn canvas yet.

    this->bed_polygon = Slic3r::Polygon();
    const auto& polygon = bed_polygon;

    const auto& bb = bed_polygon.bounding_box();
    const auto& size = bb.size();

    this->scaling_factor = std::min(static_cast<double>(canvas_w) / unscale(size.x),
    static_cast<double>(canvas_h) / unscale(size.y));

    assert(this->scaling_factor != 0);

std::vector<wxPoint> Plate2D::scaled_points_to_pixel(const Slic3r::Polygon& poly, bool unscale) {
    return this->scaled_points_to_pixel(Polyline(poly),  unscale);
}

std::vector<wxPoint> Plate2D::scaled_points_to_pixel(const Slic3r::Polyline& poly, bool unscale) {
    std::vector<wxPoint> result;
    for (const auto& pt : poly.points) {
        const auto tmp {wxPoint(pt.x, pt.y)};
        result.push_back( (unscale ? unscaled_point_to_pixel(tmp) : tmp) );
    }
    return result;
}
} } // Namespace Slic3r::GUI
<commit_msg>Set BackgroundStyle because wxWidgets wants us to.<commit_after>#include "Plater/Plate2D.hpp"

// libslic3r includes
#include "Geometry.hpp"
#include "Log.hpp"

// wx includes
#include <wx/colour.h>
#include <wx/dcbuffer.h>

namespace Slic3r { namespace GUI {

Plate2D::Plate2D(wxWindow* parent, const wxSize& size, std::vector<Plater2DObject>& _objects, std::shared_ptr<Model> _model, std::shared_ptr<Config> _config, std::shared_ptr<Settings> _settings) :
    wxPanel(parent, wxID_ANY, wxDefaultPosition, size, wxTAB_TRAVERSAL), objects(_objects), model(_model), config(_config), settings(_settings)
{

    this->Bind(wxEVT_PAINT, [=](wxPaintEvent &e) { this->repaint(e); });
    this->Bind(wxEVT_MOTION, [=](wxMouseEvent &e) { this->mouse_drag(e); });
    if (user_drawn_background) {
        this->Bind(wxEVT_ERASE_BACKGROUND, [=](wxEraseEvent& e){ });
    }

    this->Bind(wxEVT_SIZE, [=](wxSizeEvent &e) { this->update_bed_size(); this->Refresh(); });

    // Bind the varying mouse events

    // Set the brushes
    set_colors();
    this->SetBackgroundStyle(wxBG_STYLE_PAINT);
}

void Plate2D::repaint(wxPaintEvent& e) {

    // Need focus to catch keyboard events.
    this->SetFocus();

    auto dc {new wxAutoBufferedPaintDC(this)};
    const auto& size = this->GetSize();

    if (this->user_drawn_background) {
        // On all systems the AutoBufferedPaintDC() achieves double buffering.
        // On MacOS the background is erased, on Windows the background is not erased
        // and on Linux/GTK the background is erased to gray color.
        // Fill DC with the background on Windows & Linux/GTK.
        const auto& brush_background {wxBrush(this->settings->color->BACKGROUND255(), wxBRUSHSTYLE_SOLID)};
        const auto& pen_background {wxPen(this->settings->color->BACKGROUND255(), 1, wxPENSTYLE_SOLID)};
        dc->SetPen(pen_background);
        dc->SetBrush(brush_background);
        const auto& rect {this->GetUpdateRegion().GetBox()};
        dc->DrawRectangle(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight());
    }

    // Draw bed
    {
        dc->SetPen(this->print_center_pen);
        dc->SetBrush(this->bed_brush);

        dc->DrawPolygon(scaled_points_to_pixel(this->bed_polygon, true), 0, 0);
    }

}

void Plate2D::mouse_drag(wxMouseEvent& e) {
    if (e.Dragging()) {
        Slic3r::Log::info(LogChannel, L"Mouse dragging");
    } else {
        Slic3r::Log::info(LogChannel, L"Mouse moving");
    }
}

void Plate2D::set_colors() {

    this->SetBackgroundColour(settings->color->BACKGROUND255());

    this->objects_brush.SetColour(settings->color->BED_OBJECTS());
    this->objects_brush.SetStyle(wxBRUSHSTYLE_SOLID);
    this->instance_brush.SetColour(settings->color->BED_INSTANCE());
    this->instance_brush.SetStyle(wxBRUSHSTYLE_SOLID);
    this->selected_brush.SetColour(settings->color->BED_SELECTED());
    this->selected_brush.SetStyle(wxBRUSHSTYLE_SOLID);
    this->dragged_brush.SetColour(settings->color->BED_DRAGGED());
    this->dragged_brush.SetStyle(wxBRUSHSTYLE_SOLID);
    this->bed_brush.SetColour(settings->color->BED_COLOR());
    this->bed_brush.SetStyle(wxBRUSHSTYLE_SOLID);
    this->transparent_brush.SetColour(wxColour(0,0,0));
    this->transparent_brush.SetStyle(wxBRUSHSTYLE_TRANSPARENT);

    this->grid_pen.SetColour(settings->color->BED_GRID());
    this->grid_pen.SetWidth(1);
    this->grid_pen.SetStyle(wxPENSTYLE_SOLID);
    this->print_center_pen.SetColour(settings->color->BED_CENTER());
    this->print_center_pen.SetWidth(1);
    this->print_center_pen.SetStyle(wxPENSTYLE_SOLID);
    this->clearance_pen.SetColour(settings->color->BED_CLEARANCE());
    this->clearance_pen.SetWidth(1);
    this->clearance_pen.SetStyle(wxPENSTYLE_SOLID);
    this->skirt_pen.SetColour(settings->color->BED_SKIRT());
    this->skirt_pen.SetWidth(1);
    this->skirt_pen.SetStyle(wxPENSTYLE_SOLID);
    this->dark_pen.SetColour(settings->color->BED_DARK());
    this->dark_pen.SetWidth(1);
    this->dark_pen.SetStyle(wxPENSTYLE_SOLID);

}

void Plate2D::nudge_key(wxKeyEvent& e) {
    const auto key = e.GetKeyCode();

    switch( key ) {
        case WXK_LEFT:
            this->nudge(MoveDirection::Left);
        case WXK_RIGHT:
            this->nudge(MoveDirection::Right);
        case WXK_DOWN:
            this->nudge(MoveDirection::Down);
        case WXK_UP:
            this->nudge(MoveDirection::Up);
        default:
            break; // do nothing
    }

}

void Plate2D::nudge(MoveDirection dir) {
    if (this->selected_instance < this->objects.size()) {
        auto i = 0U;
        for (auto& obj : this->objects) {
            if (obj.selected()) {
                if (obj.selected_instance != -1) {
                }
            }
            i++;
        }
    }
    if (selected_instance >= this->objects.size()) {
        Slic3r::Log::warn(LogChannel, L"Nudge failed because there is no selected instance.");
        return; // Abort
    }
}

void Plate2D::update_bed_size() {
    const auto& canvas_size {this->GetSize()};
    const auto& canvas_w {canvas_size.GetWidth()};
    const auto& canvas_h {canvas_size.GetHeight()};
    if (canvas_w == 0) return; // Abort early if we haven't drawn canvas yet.

    this->bed_polygon = Slic3r::Polygon();
    const auto& polygon = bed_polygon;

    const auto& bb = bed_polygon.bounding_box();
    const auto& size = bb.size();

    this->scaling_factor = std::min(static_cast<double>(canvas_w) / unscale(size.x),
    static_cast<double>(canvas_h) / unscale(size.y));

    assert(this->scaling_factor != 0);

std::vector<wxPoint> Plate2D::scaled_points_to_pixel(const Slic3r::Polygon& poly, bool unscale) {
    return this->scaled_points_to_pixel(Polyline(poly),  unscale);
}

std::vector<wxPoint> Plate2D::scaled_points_to_pixel(const Slic3r::Polyline& poly, bool unscale) {
    std::vector<wxPoint> result;
    for (const auto& pt : poly.points) {
        const auto tmp {wxPoint(pt.x, pt.y)};
        result.push_back( (unscale ? unscaled_point_to_pixel(tmp) : tmp) );
    }
    return result;
}
} } // Namespace Slic3r::GUI
<|endoftext|>


<commit_before>#ifndef INC_MUSPELHEIM_HPP
#define INC_MUSPELHEIM_HPP

#include <iostream>

#include <functional>
#include <random>
#include <vector>

#include <boost/gil/extension/io/png_dynamic_io.hpp>
#include <boost/gil/image.hpp>
#include <boost/gil/typedefs.hpp>

// Make sure that multiplying points by floating-point values works correctly.
namespace boost { namespace gil {

  template <typename T, typename U>
  point2<T> operator *(const point2<T> &p, U t) {
    return point2<T>(p.x*t, p.y*t);
  }
  template <typename T, typename U>
  point2<U> operator *(T t, const point2<U> &p) {
    return point2<U>(t*p.x, t*p.y);
  }

} }

namespace muspelheim {

template<typename Pixel, typename T = double>
class flame_function {
public:
  using point_type = boost::gil::point2<T>;
  using pixel_type = Pixel;
  using function_type = std::function<
    point_type(const point_type &, const affine_transform<T> &)
  >;
  using value_type = std::pair<function_type, T>;

  flame_function(const function_type &f,
                 const affine_transform<T> &transform,
                 const Pixel &color,
                 const affine_transform<T> &post = {1, 0, 0, 0, 1, 0})
    : f_({{f, 1}}), transform_(transform), color_(color), post_(post) {}

  flame_function(const std::initializer_list<value_type> &f,
                 const affine_transform<T> &transform,
                 const Pixel &color,
                 const affine_transform<T> &post = {1, 0, 0, 0, 1, 0})
    : f_(f), transform_(transform), color_(color), post_(post) {}

  inline point_type operator ()(const point_type &p) const {
    point_type value = {0, 0};
    const auto &transformed = transform_(p);
    for(const auto &i : f_)
      value += i.second * i.first(transformed, transform_);
    return post_(value);
  }

  inline pixel_type color() const {
    return color_;
  }
private:
  std::vector<value_type> f_;
  affine_transform<T> transform_;
  Pixel color_;
  affine_transform<T> post_;
};

template<typename Pixel, typename T = double>
using flame_function_set = std::vector<flame_function<Pixel, T>>;

template<typename ChannelValue, typename Layout>
boost::gil::pixel<ChannelValue, Layout>
blend(const boost::gil::pixel<ChannelValue, Layout> &a,
      const boost::gil::pixel<ChannelValue, Layout> &b, double ratio) {
  boost::gil::pixel<ChannelValue, Layout> p;
  constexpr size_t channels = boost::mpl::size<
    typename Layout::color_space_t
  >::value;

  for(int i = 0; i < channels; i++)
    p[i] = a[i] * ratio + b[i] * (1 - ratio);
  return p;
}

template<typename View, typename Pixel, typename T>
void chaos_game(const View &dst, const flame_function_set<Pixel, T> &funcs,
                size_t num_iterations = 10000000) {
  using namespace boost::gil;
  using biunit_pt = point2<T>;
  using image_pt = point2<ptrdiff_t>;
  using color_image_t = image<Pixel, false>;

  std::mt19937 engine;
  std::uniform_int_distribution<size_t> random_func(0, funcs.size() - 1);
  std::uniform_real_distribution<T> random_biunit(-1, 1);

  gray32_image_t alpha_img(dst.dimensions(), gray32_pixel_t(0), 0);
  gray32_image_t::view_t alpha = view(alpha_img);
  bits32 max_alpha = 0;

  color_image_t color_img(dst.dimensions(), Pixel(0), 0);
  typename color_image_t::view_t color = view(color_img);

  biunit_pt point(random_biunit(engine), random_biunit(engine));

  for(size_t i = 0; i < 20; i++)
    point = funcs[random_func(engine)](point);

  for(size_t i = 0; i < num_iterations; i++) {
    auto &f = funcs[random_func(engine)];
    point = f(point);
    if(point.x >= -1 && point.x < 1 && point.y >= -1 && point.y < 1) {
      image_pt pt(
        static_cast<ptrdiff_t>((point.x + 1) / 2 * alpha.width()),
        static_cast<ptrdiff_t>((point.y + 1) / 2 * alpha.height())
      );
      if(!alpha(pt)[0])
        color(pt) = f.color();
      else
        color(pt) = blend(color(pt), f.color(), 0.9);

      alpha(pt)[0]++;
      if(alpha(pt)[0] > max_alpha)
        max_alpha = alpha(pt)[0];
    }
  }

  auto logmax = std::log(static_cast<T>(max_alpha));
  for(size_t x = 0; x < dst.width(); x++) {
    for(size_t y = 0; y < dst.height(); y++) {
      auto a = std::log(static_cast<T>(alpha(x, y)[0])) / logmax;
      auto &c = color(x, y);
      dst(x, y) = typename View::value_type(c[0] * a, c[1] * a, c[2] * a);
    }
  }
}

} // namespace muspelheim

#endif
<commit_msg>Simplify flame_function's constructors<commit_after>#ifndef INC_MUSPELHEIM_HPP
#define INC_MUSPELHEIM_HPP

#include <iostream>

#include <functional>
#include <random>
#include <vector>

#include <boost/gil/extension/io/png_dynamic_io.hpp>
#include <boost/gil/image.hpp>
#include <boost/gil/typedefs.hpp>

// Make sure that multiplying points by floating-point values works correctly.
namespace boost { namespace gil {

  template <typename T, typename U>
  point2<T> operator *(const point2<T> &p, U t) {
    return point2<T>(p.x*t, p.y*t);
  }
  template <typename T, typename U>
  point2<U> operator *(T t, const point2<U> &p) {
    return point2<U>(t*p.x, t*p.y);
  }

} }

namespace muspelheim {

template<typename Pixel, typename T = double>
class flame_function {
public:
  using point_type = boost::gil::point2<T>;
  using pixel_type = Pixel;
  using function_type = std::function<
    point_type(const point_type &, const affine_transform<T> &)
  >;
  using value_type = std::pair<function_type, T>;

  flame_function(const function_type &f,
                 const affine_transform<T> &transform,
                 const Pixel &color,
                 const affine_transform<T> &post = {1, 0, 0, 0, 1, 0})
    : flame_function({{f, 1}}, transform, color, post) {}

  flame_function(const std::initializer_list<value_type> &f,
                 const affine_transform<T> &transform,
                 const Pixel &color,
                 const affine_transform<T> &post = {1, 0, 0, 0, 1, 0})
    : f_(f), transform_(transform), color_(color), post_(post) {}

  inline point_type operator ()(const point_type &p) const {
    point_type value = {0, 0};
    const auto &transformed = transform_(p);
    for(const auto &i : f_)
      value += i.second * i.first(transformed, transform_);
    return post_(value);
  }

  inline pixel_type color() const {
    return color_;
  }
private:
  std::vector<value_type> f_;
  affine_transform<T> transform_;
  Pixel color_;
  affine_transform<T> post_;
};

template<typename Pixel, typename T = double>
using flame_function_set = std::vector<flame_function<Pixel, T>>;

template<typename ChannelValue, typename Layout>
boost::gil::pixel<ChannelValue, Layout>
blend(const boost::gil::pixel<ChannelValue, Layout> &a,
      const boost::gil::pixel<ChannelValue, Layout> &b, double ratio) {
  boost::gil::pixel<ChannelValue, Layout> p;
  constexpr size_t channels = boost::mpl::size<
    typename Layout::color_space_t
  >::value;

  for(int i = 0; i < channels; i++)
    p[i] = a[i] * ratio + b[i] * (1 - ratio);
  return p;
}

template<typename View, typename Pixel, typename T>
void chaos_game(const View &dst, const flame_function_set<Pixel, T> &funcs,
                size_t num_iterations = 10000000) {
  using namespace boost::gil;
  using biunit_pt = point2<T>;
  using image_pt = point2<ptrdiff_t>;
  using color_image_t = image<Pixel, false>;

  std::mt19937 engine;
  std::uniform_int_distribution<size_t> random_func(0, funcs.size() - 1);
  std::uniform_real_distribution<T> random_biunit(-1, 1);

  gray32_image_t alpha_img(dst.dimensions(), gray32_pixel_t(0), 0);
  gray32_image_t::view_t alpha = view(alpha_img);
  bits32 max_alpha = 0;

  color_image_t color_img(dst.dimensions(), Pixel(0), 0);
  typename color_image_t::view_t color = view(color_img);

  biunit_pt point(random_biunit(engine), random_biunit(engine));

  for(size_t i = 0; i < 20; i++)
    point = funcs[random_func(engine)](point);

  for(size_t i = 0; i < num_iterations; i++) {
    auto &f = funcs[random_func(engine)];
    point = f(point);
    if(point.x >= -1 && point.x < 1 && point.y >= -1 && point.y < 1) {
      image_pt pt(
        static_cast<ptrdiff_t>((point.x + 1) / 2 * alpha.width()),
        static_cast<ptrdiff_t>((point.y + 1) / 2 * alpha.height())
      );
      if(!alpha(pt)[0])
        color(pt) = f.color();
      else
        color(pt) = blend(color(pt), f.color(), 0.9);

      alpha(pt)[0]++;
      if(alpha(pt)[0] > max_alpha)
        max_alpha = alpha(pt)[0];
    }
  }

  auto logmax = std::log(static_cast<T>(max_alpha));
  for(size_t x = 0; x < dst.width(); x++) {
    for(size_t y = 0; y < dst.height(); y++) {
      auto a = std::log(static_cast<T>(alpha(x, y)[0])) / logmax;
      auto &c = color(x, y);
      dst(x, y) = typename View::value_type(c[0] * a, c[1] * a, c[2] * a);
    }
  }
}

} // namespace muspelheim

#endif
<|endoftext|>


<commit_before>/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/lite/delegates/gpu/cl/kernels/mean_stddev_normalization.h"

#include <string>

#include "tensorflow/lite/delegates/gpu/cl/cl_program.h"
#include "tensorflow/lite/delegates/gpu/cl/device_info.h"
#include "tensorflow/lite/delegates/gpu/cl/kernels/util.h"
#include "tensorflow/lite/delegates/gpu/cl/kernels/work_group_picking.h"
#include "tensorflow/lite/delegates/gpu/cl/precision.h"

namespace tflite {
namespace gpu {
namespace cl {
namespace {

std::string GetVectorReduceCode() {
  return R"(static inline float reduce_vector(float4 v) {
  return dot(v, (float4)(1.0f));
})";
}

std::string GetReduceCode() {
  // If it is supported, use the built-in work_group_reduce_add function.
  // Otherwise, implement a reduction using __local memory. Note this only works
  // with power-of-two work group sizes.
  return R"(
#if (__OPENCL_C_VERSION__ >= 200) && (__OPENCL_C_VERSION__ < 300) && \
  !defined(__opencl_c_work_group_collective_functions)
  #define __opencl_c_work_group_collective_functions 1
#endif

#ifdef __opencl_c_work_group_collective_functions
#define local_reduce(input, tmp) work_group_reduce_add(input)
#else  // !defined(__opencl_c_work_group_collective_functions)
static inline float local_reduce(float input, __local float* tmp) {
  const int local_id = get_local_id(0);
  tmp[local_id] = input;
  barrier(CLK_LOCAL_MEM_FENCE);
  int reduction_size = get_local_size(0) / 2;
  while (reduction_size > 0) {
    if (local_id < reduction_size) {
      tmp[local_id] += tmp[local_id + reduction_size];
    }
    barrier(CLK_LOCAL_MEM_FENCE);
    reduction_size /=  2;
  }
  return tmp[0];
}
#endif  // defined(__opencl_c_work_group_collective_functions)
)";
}

std::string GetFilterCode() {
  return R"(
static inline float4 filter_outside_tensor(float4 x, int num_channels, int slice) {
  return select(x, (float4)(0.0f), slice * 4 + (int4)(0, 1, 2, 3) >= num_channels);
}
)";
}
}  // namespace

MeanStdDevNormalization::MeanStdDevNormalization(const OperationDef& definition,
                                                 const DeviceInfo& device_info)
    : GPUOperation(definition) {
  // The kernel code does not inherently need a fixed size, but in order to not
  // hardcode the __local array's size for the reductions, we would need to pass
  // that size to the kernel at runtime, and that is currently not supported.
  // For now, fix workgroup size to 128 threads.
  work_group_size_.x = 128;
  work_group_size_.y = 1;  // Required
  work_group_size_.z = 1;  // Required
  code_ = GetNormalizationCode();
  if (device_info.cl_version >= OpenCLVersion::CL_3_0) {
    compiler_options_.push_back(CompilerOptions::CL_3_0);
  } else if (device_info.cl_version >= OpenCLVersion::CL_2_0) {
    compiler_options_.push_back(CompilerOptions::CL_2_0);
  }
}

std::string MeanStdDevNormalization::GetNormalizationCode() {
  AddSrcTensor("src_tensor", definition_.src_tensors[0]);
  AddDstTensor("dst_tensor", definition_.dst_tensors[0]);

  std::string c = GetCommonDefines(definition_.precision);
  c += GetVectorReduceCode();
  c += GetReduceCode();
  c += GetFilterCode();
  c += "__attribute__((reqd_work_group_size(" +
       std::to_string(work_group_size_.x) + ", 1, 1)))\n";
  c += R"(__kernel void main_function($0) {
#ifndef __opencl_c_work_group_collective_functions
  __local float tmp[)" +
       std::to_string(work_group_size_.x) + R"(];
#endif
  const int B = get_global_id(1);
  if (get_global_id(2) > 0) { return; }
  if (B >= args.src_tensor.Batch()) { return; }
  // Calculate the total sum of the input tensor.
  // First, get a local sum of input[local_id_x + N*local_size_x] for all N.
  float4 private_sum4 = (float4)(0.0f);
  for (int S = get_local_id(0); S < args.src_tensor.Slices(); S += get_local_size(0)) {
    const float4 t = args.src_tensor.Read<float>(0, 0, S, B);
    private_sum4 += filter_outside_tensor(t, args.src_tensor.Channels(), S);
  }
  // Reduce the vector to a single float and do a workgroup reduce.
  const float private_sum = reduce_vector(private_sum4);
  const float sum = local_reduce(private_sum, tmp);
  // Calculate the mean
  const float mean = sum / args.src_tensor.Channels();
  // Calculate the squared sum of the difference from the mean.
  float4 private_sum_diff_sq4 = (float4)(0.0f);
  for (int S = get_local_id(0); S < args.src_tensor.Slices(); S += get_local_size(0)) {
    const float4 t = args.src_tensor.Read<float>(0, 0, S, B);
    const float4 diff = filter_outside_tensor(t - mean, args.src_tensor.Channels(), S);
    // sum_diff_sq += diff²
    private_sum_diff_sq4 = mad(diff, diff, private_sum_diff_sq4);
  }
  // Reduce
  const float private_sum_diff_sq = reduce_vector(private_sum_diff_sq4);
  const float sum_diff_sq = local_reduce(private_sum_diff_sq, tmp);
  // Calculate 1/stddev (with the 'regulazing constant' as in tensor_utils.cc)
  const float variance = sum_diff_sq / args.src_tensor.Channels();
  const float stddev_inv =  rsqrt(variance + 1.0e-8f);
  // Calculate (t-mean)/stddev for each element
  for (int S = get_local_id(0); S < args.src_tensor.Slices(); S += get_local_size(0)) {
    const float4 t = args.src_tensor.Read<float>(0, 0, S, B);
    FLT4 result = TO_FLT4((t - mean) * stddev_inv);
    args.dst_tensor.Write(result, 0, 0, S, B);
  }
})";
  return c;
}

int3 MeanStdDevNormalization::GetGridSize() const {
  // To avoid dealing with global reductions, we restrict the grid size to the
  // work group size in the first dimension.
  const int grid_x = work_group_size_.x;
  const int grid_y = src_[0]->Batch();
  const int grid_z = 1;
  return int3(grid_x, grid_y, grid_z);
}

MeanStdDevNormalization CreateMeanStdDevNormalization(
    const OperationDef& definition, const DeviceInfo& device_info) {
  return MeanStdDevNormalization(definition, device_info);
}

}  // namespace cl
}  // namespace gpu
}  // namespace tflite
<commit_msg>Use native_rsqrt in MeanStdDevNormalization. It seems to have enough precision on tested hardware.<commit_after>/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/lite/delegates/gpu/cl/kernels/mean_stddev_normalization.h"

#include <string>

#include "tensorflow/lite/delegates/gpu/cl/cl_program.h"
#include "tensorflow/lite/delegates/gpu/cl/device_info.h"
#include "tensorflow/lite/delegates/gpu/cl/kernels/util.h"
#include "tensorflow/lite/delegates/gpu/cl/kernels/work_group_picking.h"
#include "tensorflow/lite/delegates/gpu/cl/precision.h"

namespace tflite {
namespace gpu {
namespace cl {
namespace {

std::string GetVectorReduceCode() {
  return R"(static inline float reduce_vector(float4 v) {
  return dot(v, (float4)(1.0f));
})";
}

std::string GetReduceCode() {
  // If it is supported, use the built-in work_group_reduce_add function.
  // Otherwise, implement a reduction using __local memory. Note this only works
  // with power-of-two work group sizes.
  return R"(
#if (__OPENCL_C_VERSION__ >= 200) && (__OPENCL_C_VERSION__ < 300) && \
  !defined(__opencl_c_work_group_collective_functions)
  #define __opencl_c_work_group_collective_functions 1
#endif

#ifdef __opencl_c_work_group_collective_functions
#define local_reduce(input, tmp) work_group_reduce_add(input)
#else  // !defined(__opencl_c_work_group_collective_functions)
static inline float local_reduce(float input, __local float* tmp) {
  const int local_id = get_local_id(0);
  tmp[local_id] = input;
  barrier(CLK_LOCAL_MEM_FENCE);
  int reduction_size = get_local_size(0) / 2;
  while (reduction_size > 0) {
    if (local_id < reduction_size) {
      tmp[local_id] += tmp[local_id + reduction_size];
    }
    barrier(CLK_LOCAL_MEM_FENCE);
    reduction_size /=  2;
  }
  return tmp[0];
}
#endif  // defined(__opencl_c_work_group_collective_functions)
)";
}

std::string GetFilterCode() {
  return R"(
static inline float4 filter_outside_tensor(float4 x, int num_channels, int slice) {
  return select(x, (float4)(0.0f), slice * 4 + (int4)(0, 1, 2, 3) >= num_channels);
}
)";
}
}  // namespace

MeanStdDevNormalization::MeanStdDevNormalization(const OperationDef& definition,
                                                 const DeviceInfo& device_info)
    : GPUOperation(definition) {
  // The kernel code does not inherently need a fixed size, but in order to not
  // hardcode the __local array's size for the reductions, we would need to pass
  // that size to the kernel at runtime, and that is currently not supported.
  // For now, fix workgroup size to 128 threads.
  work_group_size_.x = 128;
  work_group_size_.y = 1;  // Required
  work_group_size_.z = 1;  // Required
  code_ = GetNormalizationCode();
  if (device_info.cl_version >= OpenCLVersion::CL_3_0) {
    compiler_options_.push_back(CompilerOptions::CL_3_0);
  } else if (device_info.cl_version >= OpenCLVersion::CL_2_0) {
    compiler_options_.push_back(CompilerOptions::CL_2_0);
  }
}

std::string MeanStdDevNormalization::GetNormalizationCode() {
  AddSrcTensor("src_tensor", definition_.src_tensors[0]);
  AddDstTensor("dst_tensor", definition_.dst_tensors[0]);

  std::string c = GetCommonDefines(definition_.precision);
  c += GetVectorReduceCode();
  c += GetReduceCode();
  c += GetFilterCode();
  c += "__attribute__((reqd_work_group_size(" +
       std::to_string(work_group_size_.x) + ", 1, 1)))\n";
  c += R"(__kernel void main_function($0) {
#ifndef __opencl_c_work_group_collective_functions
  __local float tmp[)" +
       std::to_string(work_group_size_.x) + R"(];
#endif
  const int B = get_global_id(1);
  if (get_global_id(2) > 0) { return; }
  if (B >= args.src_tensor.Batch()) { return; }
  // Calculate the total sum of the input tensor.
  // First, get a local sum of input[local_id_x + N*local_size_x] for all N.
  float4 private_sum4 = (float4)(0.0f);
  for (int S = get_local_id(0); S < args.src_tensor.Slices(); S += get_local_size(0)) {
    const float4 t = args.src_tensor.Read<float>(0, 0, S, B);
    private_sum4 += filter_outside_tensor(t, args.src_tensor.Channels(), S);
  }
  // Reduce the vector to a single float and do a workgroup reduce.
  const float private_sum = reduce_vector(private_sum4);
  const float sum = local_reduce(private_sum, tmp);
  // Calculate the mean
  const float mean = sum / args.src_tensor.Channels();
  // Calculate the squared sum of the difference from the mean.
  float4 private_sum_diff_sq4 = (float4)(0.0f);
  for (int S = get_local_id(0); S < args.src_tensor.Slices(); S += get_local_size(0)) {
    const float4 t = args.src_tensor.Read<float>(0, 0, S, B);
    const float4 diff = filter_outside_tensor(t - mean, args.src_tensor.Channels(), S);
    // sum_diff_sq += diff²
    private_sum_diff_sq4 = mad(diff, diff, private_sum_diff_sq4);
  }
  // Reduce
  const float private_sum_diff_sq = reduce_vector(private_sum_diff_sq4);
  const float sum_diff_sq = local_reduce(private_sum_diff_sq, tmp);
  // Calculate 1/stddev (with the 'regulazing constant' as in tensor_utils.cc)
  const float variance = sum_diff_sq / args.src_tensor.Channels();
  const float stddev_inv = native_rsqrt(variance + 1.0e-8f);
  // Calculate (t-mean)/stddev for each element
  for (int S = get_local_id(0); S < args.src_tensor.Slices(); S += get_local_size(0)) {
    const float4 t = args.src_tensor.Read<float>(0, 0, S, B);
    FLT4 result = TO_FLT4((t - mean) * stddev_inv);
    args.dst_tensor.Write(result, 0, 0, S, B);
  }
})";
  return c;
}

int3 MeanStdDevNormalization::GetGridSize() const {
  // To avoid dealing with global reductions, we restrict the grid size to the
  // work group size in the first dimension.
  const int grid_x = work_group_size_.x;
  const int grid_y = src_[0]->Batch();
  const int grid_z = 1;
  return int3(grid_x, grid_y, grid_z);
}

MeanStdDevNormalization CreateMeanStdDevNormalization(
    const OperationDef& definition, const DeviceInfo& device_info) {
  return MeanStdDevNormalization(definition, device_info);
}

}  // namespace cl
}  // namespace gpu
}  // namespace tflite
<|endoftext|>


<commit_before>/*    Copyright (c) 2010-2019, Delft University of Technology
 *    All rigths reserved
 *
 *    This file is part of the Tudat. Redistribution and use in source and
 *    binary forms, with or without modification, are permitted exclusively
 *    under the terms of the Modified BSD license. You should have received
 *    a copy of the license with this file. If not, please or visit:
 *    http://tudat.tudelft.nl/LICENSE.
 *
 */

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN

#include <boost/test/unit_test.hpp>

#include <Eigen/Core>

#include <vector>

#include "tudat/basics/testMacros.h"
#include "tudat/basics/utilities.h"
#include "tudat/io/matrixTextFileReader.h"

#include "tudat/math/interpolators/createInterpolator.h"
#include "tudat/io/basicInputOutput.h"

#include "tudat/interface/spice/spiceInterface.h"

namespace tudat
{
namespace unit_tests
{

using namespace interpolators;

BOOST_AUTO_TEST_SUITE( test_interpolator_vector_conversion )

BOOST_AUTO_TEST_CASE( testInterpolatorVectorConversion )
{
    spice_interface::loadStandardSpiceKernels( );

    std::map< double, Eigen::Vector6d > vector6dInterpolatorInput;
    std::map< double, Eigen::VectorXd > vectorXdInterpolatorInput;
    std::map< double, Eigen::MatrixXd > matrixXdInterpolatorInput;
    for( int i = 0; i < 30; i++ )
    {
        double time = static_cast< double >( i ) * 86400.0;
        vector6dInterpolatorInput[ time ] = spice_interface::getBodyCartesianStateAtEpoch(
                    "Moon", "Earth", "J2000", "None", time );
        vectorXdInterpolatorInput[ time ] = vector6dInterpolatorInput[ time ];
        matrixXdInterpolatorInput[ time ] = vector6dInterpolatorInput[ time ];
    }

    std::vector< double > interpolationTimes = { 1.0, 5.0 * 86400.0, 12.43 * 86400.0 };

    for( int i = 0; i < 4; i++ )
    {
        std::shared_ptr< InterpolatorSettings > interpolatorSettings;
        switch( i )
        {
        case 0:
            interpolatorSettings =
                    std::make_shared< InterpolatorSettings >( linear_interpolator );
            break;
        case 1:
            interpolatorSettings =
                    std::make_shared< InterpolatorSettings >( cubic_spline_interpolator );
            break;
        case 2:
            interpolatorSettings =
                    std::make_shared< LagrangeInterpolatorSettings >( 8 );
            break;
//        case 3:
//            interpolatorSettings =
//                    std::make_shared< InterpolatorSettings >( hermite_spline_interpolator );
//            break;
        case 3:
            interpolatorSettings =
                    std::make_shared< InterpolatorSettings >( piecewise_constant_interpolator );
            break;
        }
        std::shared_ptr< OneDimensionalInterpolator< double, Eigen::Vector6d > > direct6dInterpolator =
                createOneDimensionalInterpolator( vector6dInterpolatorInput, interpolatorSettings );
        std::shared_ptr< OneDimensionalInterpolator< double, Eigen::VectorXd > > directXdInterpolator =
                createOneDimensionalInterpolator( vectorXdInterpolatorInput, interpolatorSettings );
        std::shared_ptr< OneDimensionalInterpolator< double, Eigen::MatrixXd > > directXdMatrixInterpolator =
                createOneDimensionalInterpolator( matrixXdInterpolatorInput, interpolatorSettings );

        std::shared_ptr< OneDimensionalInterpolator< double, Eigen::Vector6d > > converted6dInterpolator =
                convertBetweenStaticDynamicEigenTypeInterpolators<  double, double, -1, 1, 6, 1 >( directXdInterpolator );
        std::shared_ptr< OneDimensionalInterpolator< double, Eigen::Vector6d > > converted6dInterpolator2 =
                convertBetweenStaticDynamicEigenTypeInterpolators<  double, double, -1, -1, 6, 1 >( directXdMatrixInterpolator );

        std::shared_ptr< OneDimensionalInterpolator< double, Eigen::VectorXd > > convertedXdInterpolator =
                convertBetweenStaticDynamicEigenTypeInterpolators<  double, double, 6, 1, -1, 1 >( direct6dInterpolator );
        std::shared_ptr< OneDimensionalInterpolator< double, Eigen::VectorXd > > convertedXdInterpolator2 =
                convertBetweenStaticDynamicEigenTypeInterpolators<  double, double, -1, -1, -1, 1 >( directXdMatrixInterpolator );

        std::shared_ptr< OneDimensionalInterpolator< double, Eigen::MatrixXd > > convertedXdMatrixInterpolator =
                convertBetweenStaticDynamicEigenTypeInterpolators<  double, double, 6, 1, -1, -1 >( direct6dInterpolator );
        std::shared_ptr< OneDimensionalInterpolator< double, Eigen::MatrixXd > > convertedXdMatrixInterpolator2 =
                convertBetweenStaticDynamicEigenTypeInterpolators<  double, double, -1, 1, -1, -1 >( directXdInterpolator );

        for( unsigned int j = 0; j < interpolationTimes.size( ); j++ )
        {
            std::vector< Eigen::MatrixXd > testMatrices;
            testMatrices.push_back( direct6dInterpolator->interpolate( interpolationTimes.at( j ) ) );
            testMatrices.push_back( directXdInterpolator->interpolate( interpolationTimes.at( j ) ) );
            testMatrices.push_back( directXdMatrixInterpolator->interpolate( interpolationTimes.at( j ) ) );

            testMatrices.push_back( converted6dInterpolator->interpolate( interpolationTimes.at( j ) ) );
            testMatrices.push_back( converted6dInterpolator2->interpolate( interpolationTimes.at( j ) ) );

            testMatrices.push_back( convertedXdInterpolator->interpolate( interpolationTimes.at( j ) ) );
            testMatrices.push_back( convertedXdInterpolator2->interpolate( interpolationTimes.at( j ) ) );

            testMatrices.push_back( convertedXdMatrixInterpolator->interpolate( interpolationTimes.at( j ) ) );
            testMatrices.push_back( convertedXdMatrixInterpolator2->interpolate( interpolationTimes.at( j ) ) );

            for( unsigned int k = 1; k < testMatrices.size( ); k++ )
            {
                TUDAT_CHECK_MATRIX_CLOSE_FRACTION(
                            ( testMatrices.at( 0 ) ), ( testMatrices.at( k ) ), std::numeric_limits< double >::epsilon( ) );
            }

        }
    }
}

BOOST_AUTO_TEST_SUITE_END( )

} // namespace unit_tests
} // namespace tudat
<commit_msg>Finalized tests of interpolator eigen type conversion<commit_after>/*    Copyright (c) 2010-2019, Delft University of Technology
 *    All rigths reserved
 *
 *    This file is part of the Tudat. Redistribution and use in source and
 *    binary forms, with or without modification, are permitted exclusively
 *    under the terms of the Modified BSD license. You should have received
 *    a copy of the license with this file. If not, please or visit:
 *    http://tudat.tudelft.nl/LICENSE.
 *
 */

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN

#include <boost/test/unit_test.hpp>

#include <Eigen/Core>

#include <vector>

#include "tudat/math/basic/numericalDerivative.h"
#include "tudat/basics/testMacros.h"
#include "tudat/basics/utilities.h"
#include "tudat/io/matrixTextFileReader.h"

#include "tudat/math/interpolators/createInterpolator.h"
#include "tudat/io/basicInputOutput.h"

#include "tudat/interface/spice/spiceInterface.h"

namespace tudat
{
namespace unit_tests
{

template< typename TimeType, typename StateScalarType >
std::vector< Eigen::Matrix< StateScalarType, 6, 1 > > computeSecondOrderCentralDifferenceCartesianStateDerivative(
        const std::map< TimeType, Eigen::Matrix< StateScalarType, 6, 1 > >& cartesianStateMap )
{
    std::vector< Eigen::Matrix< StateScalarType, 6, 1 > > cartesianStateDerivativeMap;

    auto lowerIterator = cartesianStateMap.begin( );
    auto centralIterator = cartesianStateMap.begin( );
    std::advance( centralIterator, 1 );
    auto upperIterator = cartesianStateMap.begin( );
    std::advance( upperIterator, 2 );

    Eigen::Matrix< StateScalarType, 6, 1 > currentStateDerivative;
    while( upperIterator != cartesianStateMap.end( ) )
    {
        if( lowerIterator == cartesianStateMap.begin( ) )
        {
            currentStateDerivative.segment( 0, 3 ) = lowerIterator->second.segment( 3, 3 );
            currentStateDerivative.segment( 3, 3 ) =
                    ( upperIterator->second.segment( 3, 3 ) - centralIterator->second.segment( 3, 3 ) ) /
                    ( upperIterator->first - centralIterator->first );
            cartesianStateDerivativeMap.push_back( currentStateDerivative );

        }

        currentStateDerivative.segment( 0, 3 ) = centralIterator->second.segment( 3, 3 );
        currentStateDerivative.segment( 3, 3 ) =
                ( upperIterator->second.segment( 3, 3 ) - lowerIterator->second.segment( 3, 3 ) ) /
                ( upperIterator->first - lowerIterator->first );
        cartesianStateDerivativeMap.push_back( currentStateDerivative );

        lowerIterator++;
        centralIterator++;
        upperIterator++;

        if( upperIterator == cartesianStateMap.end( ) )
        {
            currentStateDerivative.segment( 0, 3 ) = upperIterator->second.segment( 3, 3 );
            currentStateDerivative.segment( 3, 3 ) =
                    ( centralIterator->second.segment( 3, 3 ) - lowerIterator->second.segment( 3, 3 ) ) /
                    ( centralIterator->first - lowerIterator->first );
            cartesianStateDerivativeMap.push_back( currentStateDerivative );

        }

    }

    return cartesianStateDerivativeMap;
}

using namespace interpolators;

BOOST_AUTO_TEST_SUITE( test_interpolator_vector_conversion )

BOOST_AUTO_TEST_CASE( testInterpolatorVectorConversion )
{
    spice_interface::loadStandardSpiceKernels( );

    std::map< double, Eigen::Vector6d > vector6dInterpolatorInput;
    std::map< double, Eigen::VectorXd > vectorXdInterpolatorInput;
    std::map< double, Eigen::MatrixXd > matrixXdInterpolatorInput;
    for( int i = 0; i < 30; i++ )
    {
        double time = static_cast< double >( i ) * 86400.0;
        vector6dInterpolatorInput[ time ] = spice_interface::getBodyCartesianStateAtEpoch(
                    "Moon", "Earth", "J2000", "None", time );
        vectorXdInterpolatorInput[ time ] = vector6dInterpolatorInput[ time ];
        matrixXdInterpolatorInput[ time ] = vector6dInterpolatorInput[ time ];
    }

    std::vector< Eigen::Vector6d > vector6dDerivativeInput =
            computeSecondOrderCentralDifferenceCartesianStateDerivative(
                vector6dInterpolatorInput );
    std::vector< Eigen::VectorXd > vectorXdDerivativeInput;
    std::vector< Eigen::MatrixXd > matrixXdDerivativeInput;

    for( unsigned int i = 0; i < vector6dDerivativeInput.size( ); i++ )
    {
        vectorXdDerivativeInput.push_back( vector6dDerivativeInput.at( i ) );
        matrixXdDerivativeInput.push_back( vector6dDerivativeInput.at( i ) );

    }

    std::vector< double > interpolationTimes = { 1.0, 5.0 * 86400.0, 12.43 * 86400.0 };

    for( int i = 0; i < 5; i++ )
    {
        std::shared_ptr< InterpolatorSettings > interpolatorSettings;
        switch( i )
        {
        case 0:
            interpolatorSettings =
                    std::make_shared< InterpolatorSettings >( linear_interpolator );
            break;
        case 1:
            interpolatorSettings =
                    std::make_shared< InterpolatorSettings >( cubic_spline_interpolator );
            break;
        case 2:
            interpolatorSettings =
                    std::make_shared< LagrangeInterpolatorSettings >( 8 );
            break;
        case 3:
            interpolatorSettings =
                    std::make_shared< InterpolatorSettings >( hermite_spline_interpolator );
            break;
        case 4:
            interpolatorSettings =
                    std::make_shared< InterpolatorSettings >( piecewise_constant_interpolator );
            break;
        }
        std::shared_ptr< OneDimensionalInterpolator< double, Eigen::Vector6d > > direct6dInterpolator =
                createOneDimensionalInterpolator(
                    vector6dInterpolatorInput, interpolatorSettings,
                    std::make_pair( IdentityElement::getAdditionIdentity< Eigen::Vector6d >( ),
                                    IdentityElement::getAdditionIdentity< Eigen::Vector6d >( ) ),
                    vector6dDerivativeInput );
        std::shared_ptr< OneDimensionalInterpolator< double, Eigen::VectorXd > > directXdInterpolator =
                createOneDimensionalInterpolator(
                    vectorXdInterpolatorInput, interpolatorSettings,
                    std::make_pair( IdentityElement::getAdditionIdentity< Eigen::VectorXd >( ),
                                    IdentityElement::getAdditionIdentity< Eigen::VectorXd >( ) ),
                    vectorXdDerivativeInput );
        std::shared_ptr< OneDimensionalInterpolator< double, Eigen::MatrixXd > > directXdMatrixInterpolator =
                createOneDimensionalInterpolator(
                    matrixXdInterpolatorInput, interpolatorSettings,
                    std::make_pair( IdentityElement::getAdditionIdentity< Eigen::MatrixXd >( ),
                                    IdentityElement::getAdditionIdentity< Eigen::MatrixXd >( ) ),
                    matrixXdDerivativeInput);

        std::shared_ptr< OneDimensionalInterpolator< double, Eigen::Vector6d > > converted6dInterpolator =
                convertBetweenStaticDynamicEigenTypeInterpolators<  double, double, -1, 1, 6, 1 >( directXdInterpolator );
        std::shared_ptr< OneDimensionalInterpolator< double, Eigen::Vector6d > > converted6dInterpolator2 =
                convertBetweenStaticDynamicEigenTypeInterpolators<  double, double, -1, -1, 6, 1 >( directXdMatrixInterpolator );

        std::shared_ptr< OneDimensionalInterpolator< double, Eigen::VectorXd > > convertedXdInterpolator =
                convertBetweenStaticDynamicEigenTypeInterpolators<  double, double, 6, 1, -1, 1 >( direct6dInterpolator );
        std::shared_ptr< OneDimensionalInterpolator< double, Eigen::VectorXd > > convertedXdInterpolator2 =
                convertBetweenStaticDynamicEigenTypeInterpolators<  double, double, -1, -1, -1, 1 >( directXdMatrixInterpolator );

        std::shared_ptr< OneDimensionalInterpolator< double, Eigen::MatrixXd > > convertedXdMatrixInterpolator =
                convertBetweenStaticDynamicEigenTypeInterpolators<  double, double, 6, 1, -1, -1 >( direct6dInterpolator );
        std::shared_ptr< OneDimensionalInterpolator< double, Eigen::MatrixXd > > convertedXdMatrixInterpolator2 =
                convertBetweenStaticDynamicEigenTypeInterpolators<  double, double, -1, 1, -1, -1 >( directXdInterpolator );

        for( unsigned int j = 0; j < interpolationTimes.size( ); j++ )
        {
            std::vector< Eigen::MatrixXd > testMatrices;
            testMatrices.push_back( direct6dInterpolator->interpolate( interpolationTimes.at( j ) ) );
            testMatrices.push_back( directXdInterpolator->interpolate( interpolationTimes.at( j ) ) );
            testMatrices.push_back( directXdMatrixInterpolator->interpolate( interpolationTimes.at( j ) ) );

            testMatrices.push_back( converted6dInterpolator->interpolate( interpolationTimes.at( j ) ) );
            testMatrices.push_back( converted6dInterpolator2->interpolate( interpolationTimes.at( j ) ) );

            testMatrices.push_back( convertedXdInterpolator->interpolate( interpolationTimes.at( j ) ) );
            testMatrices.push_back( convertedXdInterpolator2->interpolate( interpolationTimes.at( j ) ) );

            testMatrices.push_back( convertedXdMatrixInterpolator->interpolate( interpolationTimes.at( j ) ) );
            testMatrices.push_back( convertedXdMatrixInterpolator2->interpolate( interpolationTimes.at( j ) ) );

            for( unsigned int k = 1; k < testMatrices.size( ); k++ )
            {
                TUDAT_CHECK_MATRIX_CLOSE_FRACTION(
                            ( testMatrices.at( 0 ) ), ( testMatrices.at( k ) ), std::numeric_limits< double >::epsilon( ) );
            }

        }
    }
}

BOOST_AUTO_TEST_SUITE_END( )

} // namespace unit_tests
} // namespace tudat
<|endoftext|>


<commit_before>/*

@Copyright Barrett Adair 2015-2017

Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)

*/

#ifndef BOOST_CLBL_TRTS_REMOVE_MEMBER_CV_HPP
#define BOOST_CLBL_TRTS_REMOVE_MEMBER_CV_HPP

#include <boost/callable_traits/detail/core.hpp>

namespace boost { namespace callable_traits {

//[ remove_member_cv_hpp
/*`
[section:ref_remove_member_cv remove_member_cv]
[heading Header]
``#include <boost/callable_traits/remove_member_cv.hpp>``
[heading Definition]
*/

template<typename T>
using remove_member_cv_t = //see below
//<-
    detail::try_but_fail_if_invalid<
        typename detail::traits<T>::remove_member_cv,
        member_qualifiers_are_illegal_for_this_type>;

namespace detail {

    template<typename T, typename = std::false_type>
    struct remove_member_cv_impl {};

    template<typename T>
    struct remove_member_cv_impl <T, typename std::is_same<
        remove_member_cv_t<T>, detail::dummy>::type>
    {
        using type = remove_member_cv_t<T>;
    };
}

//->

template<typename T>
struct remove_member_cv : detail::remove_member_cv_impl<T> {};

//<-
}} // namespace boost::callable_traits
//->

/*`
[heading Constraints]
* `T` must be a function type or a member function pointer type
* If `T` is a pointer, it may not be cv/ref qualified

[heading Behavior]
* A substitution failure occurs if the constraints are violated.
* Removes member `const` and/or `volatile` qualifiers from `T`, if present.

[heading Input/Output Examples]
[table
    [[`T`]                              [`remove_member_cv_t<T>`]]
    [[`int() const volatile`]           [`int()`]]
    [[`int(foo::*)() const volatile`]   [`int(foo::*)()`]]
    [[`int(foo::*)() volatile`]         [`int(foo::*)()`]]
    [[`int(foo::*)() const`]            [`int(foo::*)()`]]
    [[`int(foo::*)() const &`]          [`int(foo::*)() &`]]
    [[`int(foo::*)() const &&`]         [`int(foo::*)() &&`]]
    [[`int(foo::*)() const`]            [`int(foo::*)()`]]
    [[`int`]                            [(substitution failure)]]
    [[`int (&)()`]                      [(substitution failure)]]
    [[`int (*)()`]                      [(substitution failure)]]
    [[`int foo::*`]                     [(substitution failure)]]
    [[`int (foo::* const)()`]           [(substitution failure)]]
]

[heading Example Program]
[import ../example/remove_member_cv.cpp]
[remove_member_cv]
[endsect]
*/
//]

#endif // #ifndef BOOST_CLBL_TRTS_REMOVE_MEMBER_CV_HPP
<commit_msg>Delete remove_member_cv.hpp<commit_after><|endoftext|>