<commit_before>// ==========================================================================
//                 SeqAn - The Library for Sequence Analysis
// ==========================================================================
// Copyright (c) 2006-2011, Knut Reinert, FU Berlin
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of Knut Reinert or the FU Berlin nor the names of
//       its contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
//
// ==========================================================================
// Author: Enrico Siragusa <enrico.siragusa@fu-berlin.de>
// ==========================================================================
// This file contains the masai_mapper application.
// ==========================================================================

#include <seqan/basic.h>
#include <seqan/sequence.h>

#include "options.h"
#include "mapper.h"

using namespace seqan;

// ============================================================================
// Tags, Classes, Enums
// ============================================================================

// ----------------------------------------------------------------------------
// Class Options
// ----------------------------------------------------------------------------

struct Options : public MasaiOptions
{
    CharString  genomeFile;
    CharString  genomeIndexFile;
    IndexType   genomeIndexType;
    CharString  readsFile;

    CharString  mappedReadsFile;
    OutputFormat outputFormat;
    bool        outputCigar;

    MappingMode mappingMode;
    unsigned    errorsPerRead;
    unsigned    errorsLossy;
    unsigned    seedLength;
    bool        mismatchesOnly;

    bool        verifyHits;
    bool        dumpResults;
    bool        multipleBacktracking;

    Options() :
        MasaiOptions(),
        genomeIndexType(INDEX_SA),
        outputFormat(RAW),
        outputCigar(true),
        mappingMode(ANY_BEST),
        errorsPerRead(5),
        errorsLossy(0),
        seedLength(33),
        mismatchesOnly(false),
        verifyHits(true),
        dumpResults(true),
        multipleBacktracking(true)
    {}
};

// ============================================================================

void setupArgumentParser(ArgumentParser & parser, Options const & options)
{
    setAppName(parser, "masai_mapper");
    setShortDescription(parser, "Masai Mapper");
    setCategory(parser, "Read Mapping");

    setDateAndVersion(parser);
    setDescription(parser);

    addUsageLine(parser, "[\\fIOPTIONS\\fP] <\\fIGENOME FILE\\fP> <\\fIREADS FILE\\fP>");

    addArgument(parser, ArgParseArgument(ArgParseArgument::INPUTFILE));
    addArgument(parser, ArgParseArgument(ArgParseArgument::INPUTFILE));
    setValidValues(parser, 0, "fasta");
    setValidValues(parser, 1, "fastq");

    addSection(parser, "Mapping Options");

    addOption(parser, ArgParseOption("mm", "mapping-mode", "Select mapping mode.", ArgParseOption::STRING));
    setValidValues(parser, "mapping-mode", options.mappingModeList);
    setDefaultValue(parser, "mapping-mode", options.mappingModeList[options.mappingMode]);

    addOption(parser, ArgParseOption("e", "errors", "Maximum number of errors per read.", ArgParseOption::INTEGER));
    setMinValue(parser, "errors", "0");
    setMaxValue(parser, "errors", "32");
    setDefaultValue(parser, "errors", options.errorsPerRead);

//    addOption(parser, ArgParseOption("el", "errors-lossy",
//                                     "Maximum number of errors per read to report. For any-best mode only.",
//                                     ArgParseOption::INTEGER));
//    setMinValue(parser, "errors-lossy", "0");
//    setMaxValue(parser, "errors-lossy", "32");
//    setDefaultValue(parser, "errors-lossy", options.errorsLossy);

    addOption(parser, ArgParseOption("sl", "seed-length", "Minimum seed length.", ArgParseOption::INTEGER));
    setMinValue(parser, "seed-length", "10");
    setMaxValue(parser, "seed-length", "100");
    setDefaultValue(parser, "seed-length", options.seedLength);

    addOption(parser, ArgParseOption("ng", "no-gaps", "Do not align reads with gaps."));

    addSection(parser, "Genome Index Options");

    setIndexType(parser, options);
    setIndexPrefix(parser);

    addSection(parser, "Output Options");

    setOutputFile(parser);
    setOutputFormat(parser, options);

    addSection(parser, "Debug Options");

    addOption(parser, ArgParseOption("nv", "no-verify", "Do not verify seed hits."));
    addOption(parser, ArgParseOption("nd", "no-dump", "Do not dump results."));
    addOption(parser, ArgParseOption("nm", "no-multiple", "Disable multiple backtracking."));
}

ArgumentParser::ParseResult
parseCommandLine(Options & options, ArgumentParser & parser, int argc, char const ** argv)
{
    ArgumentParser::ParseResult res = parse(parser, argc, argv);

    if (res != seqan::ArgumentParser::PARSE_OK)
        return res;

    // Parse genome input file.
    getArgumentValue(options.genomeFile, parser, 0);

    // Parse reads input file.
    getArgumentValue(options.readsFile, parser, 1);

    // Parse mapping mode.
    getOptionValue(options.mappingMode, parser, "mapping-mode", options.mappingModeList);

    // Parse mapping options.
    getOptionValue(options.errorsPerRead, parser, "errors");
//    getOptionValue(options.errorsLossy, parser, "errors-lossy");
    options.errorsLossy = std::max(options.errorsLossy, options.errorsPerRead);
    getOptionValue(options.seedLength, parser, "seed-length");
    options.mismatchesOnly = isSet(parser, "no-gaps");

    // Parse genome index prefix.
    getIndexPrefix(options, parser);

    // Parse genome index type.
    getIndexType(options, parser);

    // Parse output format.
    getOutputFormat(options, parser);

    // Parse output format.
    getOutputFormat(options, parser);

    // Parse output file.
    getOutputFile(options.mappedReadsFile, options, parser, options.readsFile, "");

    // Parse debug options.
    options.verifyHits = !isSet(parser, "no-verify");
    options.dumpResults = !isSet(parser, "no-dump");
    options.multipleBacktracking = !isSet(parser, "no-multiple");

    return seqan::ArgumentParser::PARSE_OK;
}

// ============================================================================

template <typename TStrategy, typename TDistance, typename TFormat, typename TBacktracking, typename TIndex>
int runMapper(Options & options)
{
    // TODO(esiragusa): Use typename TGenomeIndex instead of TSpec.
    typedef Mapper<TIndex>    TMapper;

    // TODO(esiragusa): Remove writeCigar from Mapper members.
    TMapper mapper(options.seedLength, options.outputCigar, options.verifyHits, options.dumpResults);

    double start, finish;

    // Loading genome.
    std::cout << "Loading genome:\t\t\t" << std::flush;
    start = sysTime();
    if (!loadGenome(mapper.indexer, options.genomeFile))
    {
        std::cerr << "Error while loading genome" << std::endl;
        return 1;
    }
    finish = sysTime();
    std::cout << finish - start << " sec" << std::endl;
//	std::cout << "Contigs count:\t\t\t" << mapper.indexer.contigsCount << std::endl;

    // Loading genome index.
    std::cout << "Loading genome index:\t\t" << std::flush;
    start = sysTime();
    if (!loadGenomeIndex(mapper.indexer, options.genomeIndexFile))
    {
        std::cout << "Error while loading genome index" << std::endl;
        return 1;
    }
    finish = sysTime();
    std::cout << finish - start << " sec" << std::endl;

    // Loading reads.
    std::cout << "Loading reads:\t\t\t" << std::flush;
    start = sysTime();
    if (!loadReads(mapper, options.readsFile, TFormat()))
    {
        std::cerr << "Error while loading reads" << std::endl;
        return 1;
    }
    finish = sysTime();
    std::cout << finish - start << " sec" << std::endl;
    std::cout << "Reads count:\t\t\t" << mapper.readsCount << std::endl;

    // Mapping reads.
    start = sysTime();
    if (!mapReads(mapper, options.mappedReadsFile, options.errorsPerRead, options.errorsLossy,
                  TDistance(), TStrategy(), TBacktracking(), TFormat()))
    {
        std::cerr << "Error while writing results" << std::endl;
        return 1;
    }
    finish = sysTime();
    std::cout << "Mapping time:\t\t\t" << std::flush;
    std::cout << finish - start << " sec" << std::endl;

    return 0;
}

// ============================================================================

template <typename TStrategy, typename TDistance, typename TFormat, typename TBacktracking>
int configureGenomeIndex(Options & options)
{
    switch (options.genomeIndexType)
    {
    case Options::INDEX_ESA:
        return runMapper<TStrategy, TDistance, TFormat, TBacktracking, TGenomeEsa>(options);

    case Options::INDEX_SA:
        return runMapper<TStrategy, TDistance, TFormat, TBacktracking, TGenomeSa>(options);

    case Options::INDEX_QGRAM:
        return runMapper<TStrategy, TDistance, TFormat, TBacktracking, TGenomeQGram>(options);

        case Options::INDEX_FM:
            return runMapper<TStrategy, TDistance, TFormat, TBacktracking, TGenomeFM>(options);

    default:
        return 1;
    }
}

template <typename TStrategy, typename TDistance, typename TFormat>
int configureBacktracking(Options & options)
{
    if (options.multipleBacktracking)
        return configureGenomeIndex<TStrategy, TDistance, TFormat, MultipleBacktracking>(options);
    else
        return configureGenomeIndex<TStrategy, TDistance, TFormat, SingleBacktracking>(options);
}

template <typename TStrategy, typename TDistance>
int configureOutputFormat(Options & options)
{
    switch (options.outputFormat)
    {
    case Options::RAW:
        return configureBacktracking<TStrategy, TDistance, Raw>(options);

    case Options::SAM:
        return configureBacktracking<TStrategy, TDistance, Sam>(options);

    case Options::SAM_NO_CIGAR:
        options.outputCigar = false;
        return configureBacktracking<TStrategy, TDistance, Sam>(options);

    default:
        return 1;
    }
}

template <typename TStrategy>
int configureDistance(Options & options)
{
    if (options.mismatchesOnly)
        return configureOutputFormat<TStrategy, HammingDistance>(options);
    else
        return configureOutputFormat<TStrategy, EditDistance>(options);
}

int mainWithOptions(Options & options)
{
    switch (options.mappingMode)
    {
    case Options::ANY_BEST:
        return configureDistance<AnyBest>(options);

    case Options::ALL_BEST:
        return configureDistance<AllBest>(options);

    case Options::ALL:
        return configureDistance<All>(options);

    default:
        return 1;
    }
}

int main(int argc, char const ** argv)
{
    ArgumentParser parser;
    Options options;
    setupArgumentParser(parser, options);

    ArgumentParser::ParseResult res = parseCommandLine(options, parser, argc, argv);

    if (res == seqan::ArgumentParser::PARSE_OK)
        return mainWithOptions(options);
    else
        return res;
}
<commit_msg>[CLI] masai: disabling qgram index option again :|<commit_after>// ==========================================================================
//                 SeqAn - The Library for Sequence Analysis
// ==========================================================================
// Copyright (c) 2006-2011, Knut Reinert, FU Berlin
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of Knut Reinert or the FU Berlin nor the names of
//       its contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
//
// ==========================================================================
// Author: Enrico Siragusa <enrico.siragusa@fu-berlin.de>
// ==========================================================================
// This file contains the masai_mapper application.
// ==========================================================================

#include <seqan/basic.h>
#include <seqan/sequence.h>

#include "options.h"
#include "mapper.h"

using namespace seqan;

// ============================================================================
// Tags, Classes, Enums
// ============================================================================

// ----------------------------------------------------------------------------
// Class Options
// ----------------------------------------------------------------------------

struct Options : public MasaiOptions
{
    CharString  genomeFile;
    CharString  genomeIndexFile;
    IndexType   genomeIndexType;
    CharString  readsFile;

    CharString  mappedReadsFile;
    OutputFormat outputFormat;
    bool        outputCigar;

    MappingMode mappingMode;
    unsigned    errorsPerRead;
    unsigned    errorsLossy;
    unsigned    seedLength;
    bool        mismatchesOnly;

    bool        verifyHits;
    bool        dumpResults;
    bool        multipleBacktracking;

    Options() :
        MasaiOptions(),
        genomeIndexType(INDEX_SA),
        outputFormat(RAW),
        outputCigar(true),
        mappingMode(ANY_BEST),
        errorsPerRead(5),
        errorsLossy(0),
        seedLength(33),
        mismatchesOnly(false),
        verifyHits(true),
        dumpResults(true),
        multipleBacktracking(true)
    {}
};

// ============================================================================

void setupArgumentParser(ArgumentParser & parser, Options const & options)
{
    setAppName(parser, "masai_mapper");
    setShortDescription(parser, "Masai Mapper");
    setCategory(parser, "Read Mapping");

    setDateAndVersion(parser);
    setDescription(parser);

    addUsageLine(parser, "[\\fIOPTIONS\\fP] <\\fIGENOME FILE\\fP> <\\fIREADS FILE\\fP>");

    addArgument(parser, ArgParseArgument(ArgParseArgument::INPUTFILE));
    addArgument(parser, ArgParseArgument(ArgParseArgument::INPUTFILE));
    setValidValues(parser, 0, "fasta");
    setValidValues(parser, 1, "fastq");

    addSection(parser, "Mapping Options");

    addOption(parser, ArgParseOption("mm", "mapping-mode", "Select mapping mode.", ArgParseOption::STRING));
    setValidValues(parser, "mapping-mode", options.mappingModeList);
    setDefaultValue(parser, "mapping-mode", options.mappingModeList[options.mappingMode]);

    addOption(parser, ArgParseOption("e", "errors", "Maximum number of errors per read.", ArgParseOption::INTEGER));
    setMinValue(parser, "errors", "0");
    setMaxValue(parser, "errors", "32");
    setDefaultValue(parser, "errors", options.errorsPerRead);

//    addOption(parser, ArgParseOption("el", "errors-lossy",
//                                     "Maximum number of errors per read to report. For any-best mode only.",
//                                     ArgParseOption::INTEGER));
//    setMinValue(parser, "errors-lossy", "0");
//    setMaxValue(parser, "errors-lossy", "32");
//    setDefaultValue(parser, "errors-lossy", options.errorsLossy);

    addOption(parser, ArgParseOption("sl", "seed-length", "Minimum seed length.", ArgParseOption::INTEGER));
    setMinValue(parser, "seed-length", "10");
    setMaxValue(parser, "seed-length", "100");
    setDefaultValue(parser, "seed-length", options.seedLength);

    addOption(parser, ArgParseOption("ng", "no-gaps", "Do not align reads with gaps."));

    addSection(parser, "Genome Index Options");

    setIndexType(parser, options);
    setIndexPrefix(parser);

    addSection(parser, "Output Options");

    setOutputFile(parser);
    setOutputFormat(parser, options);

    addSection(parser, "Debug Options");

    addOption(parser, ArgParseOption("nv", "no-verify", "Do not verify seed hits."));
    addOption(parser, ArgParseOption("nd", "no-dump", "Do not dump results."));
    addOption(parser, ArgParseOption("nm", "no-multiple", "Disable multiple backtracking."));
}

ArgumentParser::ParseResult
parseCommandLine(Options & options, ArgumentParser & parser, int argc, char const ** argv)
{
    ArgumentParser::ParseResult res = parse(parser, argc, argv);

    if (res != seqan::ArgumentParser::PARSE_OK)
        return res;

    // Parse genome input file.
    getArgumentValue(options.genomeFile, parser, 0);

    // Parse reads input file.
    getArgumentValue(options.readsFile, parser, 1);

    // Parse mapping mode.
    getOptionValue(options.mappingMode, parser, "mapping-mode", options.mappingModeList);

    // Parse mapping options.
    getOptionValue(options.errorsPerRead, parser, "errors");
//    getOptionValue(options.errorsLossy, parser, "errors-lossy");
    options.errorsLossy = std::max(options.errorsLossy, options.errorsPerRead);
    getOptionValue(options.seedLength, parser, "seed-length");
    options.mismatchesOnly = isSet(parser, "no-gaps");

    // Parse genome index prefix.
    getIndexPrefix(options, parser);

    // Parse genome index type.
    getIndexType(options, parser);

    // Parse output format.
    getOutputFormat(options, parser);

    // Parse output format.
    getOutputFormat(options, parser);

    // Parse output file.
    getOutputFile(options.mappedReadsFile, options, parser, options.readsFile, "");

    // Parse debug options.
    options.verifyHits = !isSet(parser, "no-verify");
    options.dumpResults = !isSet(parser, "no-dump");
    options.multipleBacktracking = !isSet(parser, "no-multiple");

    return seqan::ArgumentParser::PARSE_OK;
}

// ============================================================================

template <typename TStrategy, typename TDistance, typename TFormat, typename TBacktracking, typename TIndex>
int runMapper(Options & options)
{
    // TODO(esiragusa): Use typename TGenomeIndex instead of TSpec.
    typedef Mapper<TIndex>    TMapper;

    // TODO(esiragusa): Remove writeCigar from Mapper members.
    TMapper mapper(options.seedLength, options.outputCigar, options.verifyHits, options.dumpResults);

    double start, finish;

    // Loading genome.
    std::cout << "Loading genome:\t\t\t" << std::flush;
    start = sysTime();
    if (!loadGenome(mapper.indexer, options.genomeFile))
    {
        std::cerr << "Error while loading genome" << std::endl;
        return 1;
    }
    finish = sysTime();
    std::cout << finish - start << " sec" << std::endl;
//	std::cout << "Contigs count:\t\t\t" << mapper.indexer.contigsCount << std::endl;

    // Loading genome index.
    std::cout << "Loading genome index:\t\t" << std::flush;
    start = sysTime();
    if (!loadGenomeIndex(mapper.indexer, options.genomeIndexFile))
    {
        std::cout << "Error while loading genome index" << std::endl;
        return 1;
    }
    finish = sysTime();
    std::cout << finish - start << " sec" << std::endl;

    // Loading reads.
    std::cout << "Loading reads:\t\t\t" << std::flush;
    start = sysTime();
    if (!loadReads(mapper, options.readsFile, TFormat()))
    {
        std::cerr << "Error while loading reads" << std::endl;
        return 1;
    }
    finish = sysTime();
    std::cout << finish - start << " sec" << std::endl;
    std::cout << "Reads count:\t\t\t" << mapper.readsCount << std::endl;

    // Mapping reads.
    start = sysTime();
    if (!mapReads(mapper, options.mappedReadsFile, options.errorsPerRead, options.errorsLossy,
                  TDistance(), TStrategy(), TBacktracking(), TFormat()))
    {
        std::cerr << "Error while writing results" << std::endl;
        return 1;
    }
    finish = sysTime();
    std::cout << "Mapping time:\t\t\t" << std::flush;
    std::cout << finish - start << " sec" << std::endl;

    return 0;
}

// ============================================================================

template <typename TStrategy, typename TDistance, typename TFormat, typename TBacktracking>
int configureGenomeIndex(Options & options)
{
    switch (options.genomeIndexType)
    {
    case Options::INDEX_ESA:
        return runMapper<TStrategy, TDistance, TFormat, TBacktracking, TGenomeEsa>(options);

    case Options::INDEX_SA:
        return runMapper<TStrategy, TDistance, TFormat, TBacktracking, TGenomeSa>(options);

//    case Options::INDEX_QGRAM:
//        return runMapper<TStrategy, TDistance, TFormat, TBacktracking, TGenomeQGram>(options);

        case Options::INDEX_FM:
            return runMapper<TStrategy, TDistance, TFormat, TBacktracking, TGenomeFM>(options);

    default:
        return 1;
    }
}

template <typename TStrategy, typename TDistance, typename TFormat>
int configureBacktracking(Options & options)
{
    if (options.multipleBacktracking)
        return configureGenomeIndex<TStrategy, TDistance, TFormat, MultipleBacktracking>(options);
    else
        return configureGenomeIndex<TStrategy, TDistance, TFormat, SingleBacktracking>(options);
}

template <typename TStrategy, typename TDistance>
int configureOutputFormat(Options & options)
{
    switch (options.outputFormat)
    {
    case Options::RAW:
        return configureBacktracking<TStrategy, TDistance, Raw>(options);

    case Options::SAM:
        return configureBacktracking<TStrategy, TDistance, Sam>(options);

    case Options::SAM_NO_CIGAR:
        options.outputCigar = false;
        return configureBacktracking<TStrategy, TDistance, Sam>(options);

    default:
        return 1;
    }
}

template <typename TStrategy>
int configureDistance(Options & options)
{
    if (options.mismatchesOnly)
        return configureOutputFormat<TStrategy, HammingDistance>(options);
    else
        return configureOutputFormat<TStrategy, EditDistance>(options);
}

int mainWithOptions(Options & options)
{
    switch (options.mappingMode)
    {
    case Options::ANY_BEST:
        return configureDistance<AnyBest>(options);

    case Options::ALL_BEST:
        return configureDistance<AllBest>(options);

    case Options::ALL:
        return configureDistance<All>(options);

    default:
        return 1;
    }
}

int main(int argc, char const ** argv)
{
    ArgumentParser parser;
    Options options;
    setupArgumentParser(parser, options);

    ArgumentParser::ParseResult res = parseCommandLine(options, parser, argc, argv);

    if (res == seqan::ArgumentParser::PARSE_OK)
        return mainWithOptions(options);
    else
        return res;
}
<|endoftext|>


<commit_before>#pragma once

#include <port.hpp>

template <class USI_t, class CSn>
class CC1101 {
public:
	typedef USI_t USI;

	enum ConfReg {
		IOCFG2 = 0x00,
		IOCFG1 = 0x01,
		IOCFG0 = 0x02,
		FIFOTHR = 0x03,
		SYNC1 = 0x04,
		SYNC0 = 0x05,
		PKTLEN = 0x06,
		PKTCTRL1 = 0x07,
		PKTCTRL0 = 0x08,
		ADDR = 0x09,
		CHANNR = 0x0A,
		FSCTRL1 = 0x0B,
		FSCTRL0 = 0x0C,
		FREQ2 = 0x0D,
		FREQ1 = 0x0E,
		FREQ0 = 0x0F,
		MDMCFG4 = 0x10,
		MDMCFG3 = 0x11,
		MDMCFG2 = 0x12,
		MDMCFG1 = 0x13,
		MDMCFG0 = 0x14,
		DEVIATN = 0x15,
		MCSM2 = 0x16,
		MCSM1 = 0x17,
		MCSM0 = 0x18,
		FOCCFG = 0x19,
		BSCFG = 0x1A,
		AGCCTRL2 = 0x1B,
		AGCCTRL1 = 0x1C,
		AGCCTRL0 = 0x1D,
		WOREVT1 = 0x1E,
		WOREVT0 = 0x1F,
		WORCTRL = 0x20,
		FREND1 = 0x21,
		FREND0 = 0x22,
		FSCAL3 = 0x23,
		FSCAL2 = 0x24,
		FSCAL1 = 0x25,
		FSCAL0 = 0x26,
		RCCTRL1 = 0x27,
		RCCTRL0 = 0x28,
		FSTEST = 0x29,
		PTEST = 0x2A,
		AGCTEST = 0x2B,
		TEST2 = 0x2C,
		TEST1 = 0x2D,
		TEST0 = 0x2E,
		PATABLE = 0x3E,
	};

	enum CommandStrobe {
		SRES = 0x30,
		SFSTXON = 0x31,
		SXOFF = 0x32,
		SCAL = 0x33,
		SRX = 0x34,
		STX = 0x35,
		SIDLE = 0x36,
		SWOR = 0x38,
		SPWD = 0x39,
		SFRX = 0x3A,
		SFTX = 0x3B,
		SWORRST = 0x3C,
		SNOP = 0x3D,
	};

	enum StatusReg {
		PARTNUM = 0x30,
		VERSION = 0x31,
		FREQEST = 0x32,
		LQI = 0x33,
		RSSI = 0x34,
		MARCSTATE = 0x35,
		WORTIME1 = 0x36,
		WORTIME0 = 0x37,
		PKTSTATUS = 0x38,
		VCO_VC_DAC = 0x39,
		TXBYTES = 0x3A,
		RXBYTES = 0x3B,
		RCCTRL1_STATUS = 0x3C,
		RCCTRL0_STATUS = 0x3D,
	};

	static void setup() {
		USI::setup();
		CSn::mode(OUTPUT);
		CSn::set();
	}

	template <ConfReg Reg>
	static void set(unsigned char value) {
		USI::xmit(Reg);
		USI::xmit(value);
	}

	template <ConfReg Reg>
	static unsigned char get() {
		USI::xmit(Reg | 0x80);
		return USI::xmit(0);
	}

	template <CommandStrobe Cmd>
	static unsigned char rcmd() {
		return USI::xmit(Cmd | 0x80);
	}

	template <CommandStrobe Cmd>
	static unsigned char wcmd() {
		return USI::xmit(Cmd);
	}

	template <StatusReg Reg>
	static unsigned char status() {
		USI::xmit(Reg | 0xc0);
		return USI::xmit(0);
	}

	static bool select()
	{
		CSn::clear();
		return USI::DI::loop_until_clear(200);
	}

	static void release()
	{
		CSn::set();
	}

	static void write_txfifo(unsigned char* values, int len) {
		USI::xmit(0x7f);
		while(len-- > 0) {
			USI::xmit(*values++);
		}
		release();
	}

	static void read_rxfifo(unsigned char* values, int len) {
		USI::xmit(0xff);
		while(len-- > 0) {
			*values++ = USI::xmit(0);
		}
		release();
	}

	static void reset() {
		// reset
		select();
		wcmd<SRES>();
		release();

		select();

		// disable GDOx pins
		set<IOCFG2>(0x2f);
		set<IOCFG1>(0x2f);
		set<IOCFG0>(0x2f);

		// max packet length
		set<PKTLEN>(32);

		// packet automation
		set<PKTCTRL1>(0x0c);
		set<PKTCTRL0>(0x45);

		// frequency configuration
		set<FREQ2>(0x10);
		set<FREQ1>(0xa7);
		set<FREQ0>(0x63);

		// modem configuration
		set<MDMCFG2>(0x1e);

		// main radio control state machine configuration
		set<MCSM1>(0x3c);
		set<MCSM0>(0x34);

		// AGC control
		set<AGCCTRL1>(0x60);

		// patable
		set<PATABLE>(0xc0);

		wcmd<SCAL>();

		release();
	}
};
<commit_msg>cc1101: variables applied from rf studio<commit_after>#pragma once

#include <port.hpp>

template <class USI_t, class CSn>
class CC1101 {
public:
	typedef USI_t USI;

	enum ConfReg {
		IOCFG2 = 0x00,
		IOCFG1 = 0x01,
		IOCFG0 = 0x02,
		FIFOTHR = 0x03,
		SYNC1 = 0x04,
		SYNC0 = 0x05,
		PKTLEN = 0x06,
		PKTCTRL1 = 0x07,
		PKTCTRL0 = 0x08,
		ADDR = 0x09,
		CHANNR = 0x0A,
		FSCTRL1 = 0x0B,
		FSCTRL0 = 0x0C,
		FREQ2 = 0x0D,
		FREQ1 = 0x0E,
		FREQ0 = 0x0F,
		MDMCFG4 = 0x10,
		MDMCFG3 = 0x11,
		MDMCFG2 = 0x12,
		MDMCFG1 = 0x13,
		MDMCFG0 = 0x14,
		DEVIATN = 0x15,
		MCSM2 = 0x16,
		MCSM1 = 0x17,
		MCSM0 = 0x18,
		FOCCFG = 0x19,
		BSCFG = 0x1A,
		AGCCTRL2 = 0x1B,
		AGCCTRL1 = 0x1C,
		AGCCTRL0 = 0x1D,
		WOREVT1 = 0x1E,
		WOREVT0 = 0x1F,
		WORCTRL = 0x20,
		FREND1 = 0x21,
		FREND0 = 0x22,
		FSCAL3 = 0x23,
		FSCAL2 = 0x24,
		FSCAL1 = 0x25,
		FSCAL0 = 0x26,
		RCCTRL1 = 0x27,
		RCCTRL0 = 0x28,
		FSTEST = 0x29,
		PTEST = 0x2A,
		AGCTEST = 0x2B,
		TEST2 = 0x2C,
		TEST1 = 0x2D,
		TEST0 = 0x2E,
		PATABLE = 0x3E,
	};

	enum CommandStrobe {
		SRES = 0x30,
		SFSTXON = 0x31,
		SXOFF = 0x32,
		SCAL = 0x33,
		SRX = 0x34,
		STX = 0x35,
		SIDLE = 0x36,
		SWOR = 0x38,
		SPWD = 0x39,
		SFRX = 0x3A,
		SFTX = 0x3B,
		SWORRST = 0x3C,
		SNOP = 0x3D,
	};

	enum StatusReg {
		PARTNUM = 0x30,
		VERSION = 0x31,
		FREQEST = 0x32,
		LQI = 0x33,
		RSSI = 0x34,
		MARCSTATE = 0x35,
		WORTIME1 = 0x36,
		WORTIME0 = 0x37,
		PKTSTATUS = 0x38,
		VCO_VC_DAC = 0x39,
		TXBYTES = 0x3A,
		RXBYTES = 0x3B,
		RCCTRL1_STATUS = 0x3C,
		RCCTRL0_STATUS = 0x3D,
	};

	static void setup() {
		USI::setup();
		CSn::mode(OUTPUT);
		CSn::set();
	}

	template <ConfReg Reg>
	static void set(unsigned char value) {
		USI::xmit(Reg);
		USI::xmit(value);
	}

	template <ConfReg Reg>
	static unsigned char get() {
		USI::xmit(Reg | 0x80);
		return USI::xmit(0);
	}

	template <CommandStrobe Cmd>
	static unsigned char rcmd() {
		return USI::xmit(Cmd | 0x80);
	}

	template <CommandStrobe Cmd>
	static unsigned char wcmd() {
		return USI::xmit(Cmd);
	}

	template <StatusReg Reg>
	static unsigned char status() {
		USI::xmit(Reg | 0xc0);
		return USI::xmit(0);
	}

	static bool select()
	{
		CSn::clear();
		return USI::DI::loop_until_clear(200);
	}

	static void release()
	{
		CSn::set();
	}

	static void write_txfifo(unsigned char* values, int len) {
		USI::xmit(0x7f);
		while(len-- > 0) {
			USI::xmit(*values++);
		}
		release();
	}

	static void read_rxfifo(unsigned char* values, int len) {
		USI::xmit(0xff);
		while(len-- > 0) {
			*values++ = USI::xmit(0);
		}
		release();
	}

	static void reset() {
		// reset
		select();
		wcmd<SRES>();
		release();

		select();

		// disable GDOx pins
		set<IOCFG2>(0x2f);
		set<IOCFG1>(0x2f);
		set<IOCFG0>(0x2f);

		// max packet length
		set<PKTLEN>(32);

		// packet automation
		set<PKTCTRL1>(0x0c);
		set<PKTCTRL0>(0x45);

		// frequency configuration
		set<FREQ2>(0x10);
		set<FREQ1>(0xa7);
		set<FREQ0>(0x63);

		// modem configuration
		set<MDMCFG2>(0x1a);

		// main radio control state machine configuration
		set<MCSM1>(0x3c);
		set<MCSM0>(0x34);

		// frequency synthesizer calibration
		set<FSCAL3>(0xea);
		set<FSCAL2>(0x2a);
		set<FSCAL1>(0x00);
		set<FSCAL0>(0x1f);

		// Various test settings
		set<TEST2>(0x81);
		set<TEST1>(0x35);
		set<TEST0>(0x09);

		wcmd<SCAL>();

		release();
	}
};
<|endoftext|>


<commit_before>/*
 *   CrissCross
 *   A multi-purpose cross-platform library.
 *
 *   A product of Uplink Laboratories.
 *
 *   (c) 2006-2008 Steven Noonan.
 *   Licensed under the New BSD License.
 *
 */

#ifndef __included_cc_darray_h
#error "This file shouldn't be compiled directly."
#endif

#include <crisscross/debug.h>

#include <crisscross/darray.h>
#include <crisscross/dstack.h>

namespace CrissCross
{
	namespace Data
	{
		template <class T>
		DArray <T>::DArray()
		{
			m_stepSize = -1;
			m_numUsed = m_arraySize = 0;
			m_shadow = NULL;
			m_array = NULL;
			m_emptyNodes = new DStack<size_t>;
			m_emptyNodes->push((size_t)-1);
			m_encapsulated = true;
		}

		template <class T>
		DArray <T>::DArray(T *_array, size_t _indices, bool _encapsulate)
		{
			m_encapsulated = _encapsulate;
			if ( _encapsulate )
			{
				m_array = new T[_indices];
				memcpy(m_array, _array, _indices * sizeof(T));
			} else {
				m_array = _array;
			}
			m_shadow = new char[_indices];
			memset(m_shadow, 0, _indices * sizeof(char));
			m_numUsed = 0;
			for (size_t i = 0; i < _indices; i++)
			{
				m_shadow[i] = m_array[i] != NULL ? 1 : 0;
				if ( m_shadow[i] )
				{
					m_numUsed++;
				}
			}
			m_numUsed = m_numUsed;
			m_arraySize = _indices;
			m_stepSize = -1;
			m_emptyNodes = new DStack<size_t>;
			rebuildStack();
		}

		template <class T>
		DArray <T>::DArray(DArray const &_array, bool _encapsulate)
		{
			m_encapsulated = _encapsulate;
			if ( _encapsulate )
			{
				m_array = new T[_array.m_arraySize];
				memcpy(m_array, _array.m_array, _array.m_arraySize * sizeof(T));
			} else {
				m_array = _array.m_array;
			}
			m_shadow = new char[_array.m_arraySize];
			memset(m_shadow, 0, _array.m_arraySize * sizeof(char));
			m_numUsed = 0;
			for (size_t i = 0; i < _array.m_arraySize; i++)
			{
				m_shadow[i] = m_array[i] != NULL ? 1 : 0;
				if ( m_shadow[i] )
				{
					m_numUsed++;
				}
			}
			m_arraySize = _array.m_arraySize;
			m_stepSize = _array.m_stepSize;
			m_emptyNodes = new DStack<size_t>;
			rebuildStack();
		}

		template <class T>
		DArray <T>::DArray(int _newStepSize)
		{
			if (_newStepSize < 1)
				m_stepSize = -1;
			else
				m_stepSize = _newStepSize;

			m_numUsed = m_arraySize = 0;
			m_shadow = NULL;
			m_array = NULL;
			m_emptyNodes = new DStack<size_t> (_newStepSize + 1);
			m_emptyNodes->push((size_t)-1);
			m_encapsulated = true;
		}

		template <class T>
		DArray <T>::~DArray()
		{
			empty();
			delete m_emptyNodes;
			m_emptyNodes = NULL;
		}

		template <class T>
		size_t DArray <T>::pop()
		{
			CoreAssert ( m_encapsulated );

			size_t freeslot = getNextFree();

			if (m_shadow[freeslot] == 0) m_numUsed++;

			m_shadow[freeslot] = 1;
			return freeslot;
		}

		template <class T>
		void DArray <T>::rebuildStack()
		{
			if ( !m_encapsulated ) return;

			/*  Reset free list */

			m_emptyNodes->empty();
			m_emptyNodes->push((size_t)-1);

			/* Step through, rebuilding */

			for (size_t i = m_arraySize - 1; (int)i >= 0; i--)
				if (m_shadow[i] == 0)
					m_emptyNodes->push(i);
		}

		template <class T>
		void DArray <T>::recount()
		{
			if ( !m_encapsulated ) return;

			m_numUsed = 0;
			for (size_t i = 0; i < m_arraySize; i++)
				if (m_shadow[i] == 1)
					m_numUsed++;
		}

		template <class T>
		void DArray <T>::setSize(size_t newsize)
		{
			if ( !m_encapsulated ) return;

			if (newsize > m_arraySize) {
				size_t oldarraysize = m_arraySize;

				m_arraySize = newsize;
				T     *temparray = new T[m_arraySize];
				char  *tempshadow = new char[m_arraySize];

				if (m_array && m_shadow) {
					memcpy(&temparray[0], &m_array[0], sizeof(temparray[0]) * oldarraysize);
					memcpy(&tempshadow[0], &m_shadow[0], sizeof(tempshadow[0]) * oldarraysize);
				}

				memset(&temparray[oldarraysize], 0, sizeof(temparray[0]) * (m_arraySize - oldarraysize));
				memset(&tempshadow[oldarraysize], 0, sizeof(tempshadow[0]) * (m_arraySize - oldarraysize));

				for (size_t a = m_arraySize - 1; (int)a >= (int)oldarraysize; a--) {
					m_emptyNodes->push(a);
				}

				delete [] m_array;
				delete [] m_shadow;

				m_array = temparray;
				m_shadow = tempshadow;
			} else if (newsize < m_arraySize) {
				m_arraySize = newsize;
				T    *temparray = new T[m_arraySize];
				char *tempshadow = new char[m_arraySize];

				if (m_array && m_shadow) {
					memcpy(&temparray[0], &m_array[0], sizeof(temparray[0]) * m_arraySize);
					memcpy(&tempshadow[0], &m_shadow[0], sizeof(tempshadow[0]) * m_arraySize);
				}

				/* We may have lost more than one node. It's worth rebuilding over. */
				rebuildStack();
				recount();

				delete [] m_array;
				delete [] m_shadow;

				m_array = temparray;
				m_shadow = tempshadow;
			} else if (newsize == m_arraySize) {
				/* Do nothing */
			}
		}

		template <class T>
		void DArray <T>::grow()
		{
			CoreAssert ( m_encapsulated );

			if (m_stepSize == -1) {
				/* Double array size */
				if (m_arraySize == 0) {
					setSize(64);
				} else {
					setSize(m_arraySize * 2);
				}
			} else {
				/* Increase array size by fixed amount */
				setSize(m_arraySize + m_stepSize);
			}
		}

		template <class T>
		void DArray <T>::setStepSize(int _stepSize)
		{
			m_stepSize = _stepSize;
		}

		template <class T>
		void DArray <T>::setStepDouble()
		{
			m_stepSize = -1;
		}

		template <class T>
		size_t DArray <T>::insert(T const & newdata)
		{
			CoreAssert ( m_encapsulated );

			size_t freeslot = getNextFree();

			m_array[freeslot] = newdata;
			if (m_shadow[freeslot] == 0) m_numUsed++;

			m_shadow[freeslot] = 1;
			return freeslot;
		}

		template <class T>
		void DArray <T>::insert(T const & newdata, size_t index)
		{
			CoreAssert ( m_encapsulated );

			while (index >= m_arraySize) grow();

			m_array[index] = newdata;
			if (m_shadow[index] == 0) m_numUsed++;

			m_shadow[index] = 1;
		}

		template <class T>
		void DArray <T>::empty()
		{
			if ( m_encapsulated ) {
				delete [] m_array;
				m_array = NULL;
			}
			m_array = NULL;
			delete [] m_shadow;
			m_shadow = NULL;

			m_emptyNodes->empty();
			m_emptyNodes->push((size_t)-1);

			m_arraySize = 0;
			m_numUsed = 0;
			m_encapsulated = true;
		}

		template <class T>
		size_t DArray <T>::getNextFree()
		{
			if ( !m_encapsulated ) return -1;

			/* WARNING: This function assumes the node returned */
			/*          will be used by the calling function. */

			if (!m_shadow)
				grow();

			size_t freeslot = (size_t)-2;

			while ((freeslot = m_emptyNodes->pop()) != (size_t)-1) {
				if (m_shadow[freeslot] == 0)
					break;
			}

			if (freeslot == (size_t)-1) {
				m_emptyNodes->push((size_t)-1);
				freeslot = m_arraySize;
				grow();
			}

			if (m_shadow[freeslot] == 0)
				m_numUsed++;

			m_shadow[freeslot] = 1;

			return freeslot;
		}

		template <class T>
		T DArray <T>::get(size_t index) const
		{
			CoreAssert(m_shadow[index]);
			CoreAssert(index < m_arraySize);

			return m_array[index];
		}

		template <class T>
		T & DArray <T>::operator [](size_t index)
		{
			/* Ugh. Messy. Don't run into this. >.< */
			if ( !m_encapsulated ) throw;

			CoreAssert(m_shadow[index]);
			CoreAssert(index < m_arraySize);

			return m_array[index];
		}

		template <class T>
		const T &DArray <T>::operator [](size_t index) const
		{
			/* Ugh. Messy. Don't run into this. >.< */
			if ( !m_encapsulated ) throw;

			CoreAssert(m_shadow[index]);
			CoreAssert(index < m_arraySize);

			return m_array[index];
		}

		template <class T>
		size_t DArray<T>::mem_usage() const
		{
			size_t ret = sizeof(*this);
			ret += m_arraySize * sizeof(T);
			ret += m_arraySize * sizeof(char);
			return ret;
		}

		template <class T>
		void DArray <T>::remove(size_t index)
		{
			if ( !m_encapsulated ) return;
			CoreAssert(m_shadow[index] != 0);
			CoreAssert(index < m_arraySize);

			m_emptyNodes->push(index);

			if (m_shadow[index] == 1) m_numUsed--;

			m_shadow[index] = 0;
		}

		template <class T>
		size_t DArray <T>::find(T const & newdata)
		{
			for (size_t a = 0; a < m_arraySize; ++a)
				if (m_shadow[a])
					if (Compare(m_array[a], newdata) == 0)
						return a;

			return -1;
		}

#ifdef ENABLE_SORTS
		template <class T>
		int DArray <T>::sort(Sorter<T> *_sortMethod)
		{
			if ( !m_encapsulated ) return -1;

			int ret;

			T  *temp_array = new T[m_numUsed];
			T  *temp_ptr = temp_array;

			memset(temp_array, 0, m_numUsed * sizeof(T));

			for (size_t i = 0; i < m_arraySize; i++) {
				if (valid(i)) {
					*temp_ptr = m_array[i];
					temp_ptr++;
				}
			}

			ret = _sortMethod->Sort(temp_array, m_numUsed);

			delete [] m_shadow;
			m_shadow = new char[m_numUsed];
			memset(m_shadow, 1, m_numUsed);

			delete [] m_array;
			m_array = temp_array;

			m_arraySize = m_numUsed;

			rebuildStack();
			recount();

			return ret;
		}

		template <class T>
		int DArray <T>::sort(Sorter<T> &_sortMethod)
		{
			if ( !m_encapsulated ) return -1;

			return sort(&_sortMethod);
		}
#endif

		template <class T>
		void DArray<T>::flush()
		{
			if ( m_encapsulated )
			{
				for (size_t i = 0; i < m_arraySize; ++i) {
					if (valid(i)) {
						delete m_array[i];
					}
				}
			}
			empty();
		}

		template <class T>
		void DArray<T>::flushArray()
		{
			if ( m_encapsulated )
			{
				for (size_t i = 0; i < m_arraySize; ++i) {
					if (valid(i)) {
						delete [] m_array[i];
					}
				}
			}
			empty();
		}

		/* BELOW ARE DEPRECATED FUNCTIONS */

#if !defined(DISABLE_DEPRECATED_CODE)
		template <class T>
		void DArray<T>::EmptyAndDelete()
		{
			if ( m_encapsulated )
			{
				for (size_t i = 0; i < m_arraySize; ++i) {
					if (valid(i)) {
						delete m_array[i];
					}
				}
			}

			empty();
		}

		template <class T>
		void DArray<T>::EmptyAndDeleteArray()
		{
			if ( m_encapsulated )
			{
				for (size_t i = 0; i < m_arraySize; ++i) {
					if (valid(i)) {
						delete [] m_array[i];
					}
				}
			}
			empty();
		}

		template <class T>
		void DArray<T>::ChangeData(T const & _rec, size_t index)
		{
			if ( !m_encapsulated ) return;
			CoreAssert(m_shadow[index] == 1);
			m_array[index] = _rec;
		}
#endif
	}
}
<commit_msg>darray: no throw because we don't have C++ exceptions by policy<commit_after>/*
 *   CrissCross
 *   A multi-purpose cross-platform library.
 *
 *   A product of Uplink Laboratories.
 *
 *   (c) 2006-2008 Steven Noonan.
 *   Licensed under the New BSD License.
 *
 */

#ifndef __included_cc_darray_h
#error "This file shouldn't be compiled directly."
#endif

#include <crisscross/debug.h>

#include <crisscross/darray.h>
#include <crisscross/dstack.h>

namespace CrissCross
{
	namespace Data
	{
		template <class T>
		DArray <T>::DArray()
		{
			m_stepSize = -1;
			m_numUsed = m_arraySize = 0;
			m_shadow = NULL;
			m_array = NULL;
			m_emptyNodes = new DStack<size_t>;
			m_emptyNodes->push((size_t)-1);
			m_encapsulated = true;
		}

		template <class T>
		DArray <T>::DArray(T *_array, size_t _indices, bool _encapsulate)
		{
			m_encapsulated = _encapsulate;
			if ( _encapsulate )
			{
				m_array = new T[_indices];
				memcpy(m_array, _array, _indices * sizeof(T));
			} else {
				m_array = _array;
			}
			m_shadow = new char[_indices];
			memset(m_shadow, 0, _indices * sizeof(char));
			m_numUsed = 0;
			for (size_t i = 0; i < _indices; i++)
			{
				m_shadow[i] = m_array[i] != NULL ? 1 : 0;
				if ( m_shadow[i] )
				{
					m_numUsed++;
				}
			}
			m_numUsed = m_numUsed;
			m_arraySize = _indices;
			m_stepSize = -1;
			m_emptyNodes = new DStack<size_t>;
			rebuildStack();
		}

		template <class T>
		DArray <T>::DArray(DArray const &_array, bool _encapsulate)
		{
			m_encapsulated = _encapsulate;
			if ( _encapsulate )
			{
				m_array = new T[_array.m_arraySize];
				memcpy(m_array, _array.m_array, _array.m_arraySize * sizeof(T));
			} else {
				m_array = _array.m_array;
			}
			m_shadow = new char[_array.m_arraySize];
			memset(m_shadow, 0, _array.m_arraySize * sizeof(char));
			m_numUsed = 0;
			for (size_t i = 0; i < _array.m_arraySize; i++)
			{
				m_shadow[i] = m_array[i] != NULL ? 1 : 0;
				if ( m_shadow[i] )
				{
					m_numUsed++;
				}
			}
			m_arraySize = _array.m_arraySize;
			m_stepSize = _array.m_stepSize;
			m_emptyNodes = new DStack<size_t>;
			rebuildStack();
		}

		template <class T>
		DArray <T>::DArray(int _newStepSize)
		{
			if (_newStepSize < 1)
				m_stepSize = -1;
			else
				m_stepSize = _newStepSize;

			m_numUsed = m_arraySize = 0;
			m_shadow = NULL;
			m_array = NULL;
			m_emptyNodes = new DStack<size_t> (_newStepSize + 1);
			m_emptyNodes->push((size_t)-1);
			m_encapsulated = true;
		}

		template <class T>
		DArray <T>::~DArray()
		{
			empty();
			delete m_emptyNodes;
			m_emptyNodes = NULL;
		}

		template <class T>
		size_t DArray <T>::pop()
		{
			CoreAssert ( m_encapsulated );

			size_t freeslot = getNextFree();

			if (m_shadow[freeslot] == 0) m_numUsed++;

			m_shadow[freeslot] = 1;
			return freeslot;
		}

		template <class T>
		void DArray <T>::rebuildStack()
		{
			if ( !m_encapsulated ) return;

			/*  Reset free list */

			m_emptyNodes->empty();
			m_emptyNodes->push((size_t)-1);

			/* Step through, rebuilding */

			for (size_t i = m_arraySize - 1; (int)i >= 0; i--)
				if (m_shadow[i] == 0)
					m_emptyNodes->push(i);
		}

		template <class T>
		void DArray <T>::recount()
		{
			if ( !m_encapsulated ) return;

			m_numUsed = 0;
			for (size_t i = 0; i < m_arraySize; i++)
				if (m_shadow[i] == 1)
					m_numUsed++;
		}

		template <class T>
		void DArray <T>::setSize(size_t newsize)
		{
			if ( !m_encapsulated ) return;

			if (newsize > m_arraySize) {
				size_t oldarraysize = m_arraySize;

				m_arraySize = newsize;
				T     *temparray = new T[m_arraySize];
				char  *tempshadow = new char[m_arraySize];

				if (m_array && m_shadow) {
					memcpy(&temparray[0], &m_array[0], sizeof(temparray[0]) * oldarraysize);
					memcpy(&tempshadow[0], &m_shadow[0], sizeof(tempshadow[0]) * oldarraysize);
				}

				memset(&temparray[oldarraysize], 0, sizeof(temparray[0]) * (m_arraySize - oldarraysize));
				memset(&tempshadow[oldarraysize], 0, sizeof(tempshadow[0]) * (m_arraySize - oldarraysize));

				for (size_t a = m_arraySize - 1; (int)a >= (int)oldarraysize; a--) {
					m_emptyNodes->push(a);
				}

				delete [] m_array;
				delete [] m_shadow;

				m_array = temparray;
				m_shadow = tempshadow;
			} else if (newsize < m_arraySize) {
				m_arraySize = newsize;
				T    *temparray = new T[m_arraySize];
				char *tempshadow = new char[m_arraySize];

				if (m_array && m_shadow) {
					memcpy(&temparray[0], &m_array[0], sizeof(temparray[0]) * m_arraySize);
					memcpy(&tempshadow[0], &m_shadow[0], sizeof(tempshadow[0]) * m_arraySize);
				}

				/* We may have lost more than one node. It's worth rebuilding over. */
				rebuildStack();
				recount();

				delete [] m_array;
				delete [] m_shadow;

				m_array = temparray;
				m_shadow = tempshadow;
			} else if (newsize == m_arraySize) {
				/* Do nothing */
			}
		}

		template <class T>
		void DArray <T>::grow()
		{
			CoreAssert ( m_encapsulated );

			if (m_stepSize == -1) {
				/* Double array size */
				if (m_arraySize == 0) {
					setSize(64);
				} else {
					setSize(m_arraySize * 2);
				}
			} else {
				/* Increase array size by fixed amount */
				setSize(m_arraySize + m_stepSize);
			}
		}

		template <class T>
		void DArray <T>::setStepSize(int _stepSize)
		{
			m_stepSize = _stepSize;
		}

		template <class T>
		void DArray <T>::setStepDouble()
		{
			m_stepSize = -1;
		}

		template <class T>
		size_t DArray <T>::insert(T const & newdata)
		{
			CoreAssert ( m_encapsulated );

			size_t freeslot = getNextFree();

			m_array[freeslot] = newdata;
			if (m_shadow[freeslot] == 0) m_numUsed++;

			m_shadow[freeslot] = 1;
			return freeslot;
		}

		template <class T>
		void DArray <T>::insert(T const & newdata, size_t index)
		{
			CoreAssert ( m_encapsulated );

			while (index >= m_arraySize) grow();

			m_array[index] = newdata;
			if (m_shadow[index] == 0) m_numUsed++;

			m_shadow[index] = 1;
		}

		template <class T>
		void DArray <T>::empty()
		{
			if ( m_encapsulated ) {
				delete [] m_array;
				m_array = NULL;
			}
			m_array = NULL;
			delete [] m_shadow;
			m_shadow = NULL;

			m_emptyNodes->empty();
			m_emptyNodes->push((size_t)-1);

			m_arraySize = 0;
			m_numUsed = 0;
			m_encapsulated = true;
		}

		template <class T>
		size_t DArray <T>::getNextFree()
		{
			if ( !m_encapsulated ) return -1;

			/* WARNING: This function assumes the node returned */
			/*          will be used by the calling function. */

			if (!m_shadow)
				grow();

			size_t freeslot = (size_t)-2;

			while ((freeslot = m_emptyNodes->pop()) != (size_t)-1) {
				if (m_shadow[freeslot] == 0)
					break;
			}

			if (freeslot == (size_t)-1) {
				m_emptyNodes->push((size_t)-1);
				freeslot = m_arraySize;
				grow();
			}

			if (m_shadow[freeslot] == 0)
				m_numUsed++;

			m_shadow[freeslot] = 1;

			return freeslot;
		}

		template <class T>
		T DArray <T>::get(size_t index) const
		{
			CoreAssert(m_shadow[index]);
			CoreAssert(index < m_arraySize);

			return m_array[index];
		}

		template <class T>
		T & DArray <T>::operator [](size_t index)
		{
			/* Ugh. Messy. Don't run into this. >.< */
			CoreAssert ( m_encapsulated );

			CoreAssert(m_shadow[index]);
			CoreAssert(index < m_arraySize);

			return m_array[index];
		}

		template <class T>
		const T &DArray <T>::operator [](size_t index) const
		{
			/* Ugh. Messy. Don't run into this. >.< */
			CoreAssert ( m_encapsulated );

			CoreAssert(m_shadow[index]);
			CoreAssert(index < m_arraySize);

			return m_array[index];
		}

		template <class T>
		size_t DArray<T>::mem_usage() const
		{
			size_t ret = sizeof(*this);
			ret += m_arraySize * sizeof(T);
			ret += m_arraySize * sizeof(char);
			return ret;
		}

		template <class T>
		void DArray <T>::remove(size_t index)
		{
			if ( !m_encapsulated ) return;
			CoreAssert(m_shadow[index] != 0);
			CoreAssert(index < m_arraySize);

			m_emptyNodes->push(index);

			if (m_shadow[index] == 1) m_numUsed--;

			m_shadow[index] = 0;
		}

		template <class T>
		size_t DArray <T>::find(T const & newdata)
		{
			for (size_t a = 0; a < m_arraySize; ++a)
				if (m_shadow[a])
					if (Compare(m_array[a], newdata) == 0)
						return a;

			return -1;
		}

#ifdef ENABLE_SORTS
		template <class T>
		int DArray <T>::sort(Sorter<T> *_sortMethod)
		{
			if ( !m_encapsulated ) return -1;

			int ret;

			T  *temp_array = new T[m_numUsed];
			T  *temp_ptr = temp_array;

			memset(temp_array, 0, m_numUsed * sizeof(T));

			for (size_t i = 0; i < m_arraySize; i++) {
				if (valid(i)) {
					*temp_ptr = m_array[i];
					temp_ptr++;
				}
			}

			ret = _sortMethod->Sort(temp_array, m_numUsed);

			delete [] m_shadow;
			m_shadow = new char[m_numUsed];
			memset(m_shadow, 1, m_numUsed);

			delete [] m_array;
			m_array = temp_array;

			m_arraySize = m_numUsed;

			rebuildStack();
			recount();

			return ret;
		}

		template <class T>
		int DArray <T>::sort(Sorter<T> &_sortMethod)
		{
			if ( !m_encapsulated ) return -1;

			return sort(&_sortMethod);
		}
#endif

		template <class T>
		void DArray<T>::flush()
		{
			if ( m_encapsulated )
			{
				for (size_t i = 0; i < m_arraySize; ++i) {
					if (valid(i)) {
						delete m_array[i];
					}
				}
			}
			empty();
		}

		template <class T>
		void DArray<T>::flushArray()
		{
			if ( m_encapsulated )
			{
				for (size_t i = 0; i < m_arraySize; ++i) {
					if (valid(i)) {
						delete [] m_array[i];
					}
				}
			}
			empty();
		}

		/* BELOW ARE DEPRECATED FUNCTIONS */

#if !defined(DISABLE_DEPRECATED_CODE)
		template <class T>
		void DArray<T>::EmptyAndDelete()
		{
			if ( m_encapsulated )
			{
				for (size_t i = 0; i < m_arraySize; ++i) {
					if (valid(i)) {
						delete m_array[i];
					}
				}
			}

			empty();
		}

		template <class T>
		void DArray<T>::EmptyAndDeleteArray()
		{
			if ( m_encapsulated )
			{
				for (size_t i = 0; i < m_arraySize; ++i) {
					if (valid(i)) {
						delete [] m_array[i];
					}
				}
			}
			empty();
		}

		template <class T>
		void DArray<T>::ChangeData(T const & _rec, size_t index)
		{
			if ( !m_encapsulated ) return;
			CoreAssert(m_shadow[index] == 1);
			m_array[index] = _rec;
		}
#endif
	}
}
<|endoftext|>


<commit_before>/**********************************************************************
 * $Id$
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.refractions.net
 *
 * Copyright (C) 2001-2002 Vivid Solutions Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************/

#include <geos/geomgraph.h>

namespace geos {

NodeMap::NodeMap(NodeFactory *newNodeFact)
{
	nodeFact=newNodeFact;
	nodeMap=new map<Coordinate,Node*,CoordLT>();
}

NodeMap::~NodeMap()
{
	map<Coordinate,Node*,CoordLT>::iterator	it=nodeMap->begin();
	for (;it!=nodeMap->end();it++) {
		Node *node=it->second;
		delete node;
	}
	delete nodeMap;
	delete nodeFact;
}

Node*
NodeMap::addNode(const Coordinate& coord)
{
	Node *node=find(coord);
	if (node==NULL) {
		node=nodeFact->createNode(coord);
		(*nodeMap)[coord]=node;
	}
	return node;
}

// first arg cannot be const because
// it is liable to label-merging ... --strk;
Node*
NodeMap::addNode(Node *n)
{
	Node *node=find(n->getCoordinate());
	if (node==NULL) {
		(*nodeMap)[n->getCoordinate()]=n;
		return n;
	}
	node->mergeLabel(n);
	return node;
}

void
NodeMap::add(EdgeEnd *e)
{
	Coordinate& p=e->getCoordinate();
	Node *n=addNode(p);
	n->add(e);
}

/*
 * @return the node if found; null otherwise
 */
Node*
NodeMap::find(const Coordinate& coord) const
{
	map<Coordinate,Node*,CoordLT>::iterator found=nodeMap->find(coord);
	if (found==nodeMap->end())
		return NULL;
	else
		return found->second;
}

map<Coordinate,Node*,CoordLT>::iterator
NodeMap::iterator() const
{
	return nodeMap->begin();
}

//Doesn't work yet. Use iterator.
//public Collection NodeMap::values(){
//	return nodeMap.values();
//}

vector<Node*>*
NodeMap::getBoundaryNodes(int geomIndex) const
{
	vector<Node*>* bdyNodes=new vector<Node*>();
	map<Coordinate,Node*,CoordLT>::iterator	it=nodeMap->begin();
	for (;it!=nodeMap->end();it++) {
		Node *node=it->second;
		if (node->getLabel()->getLocation(geomIndex)==Location::BOUNDARY)
			bdyNodes->push_back(node);
	}
	return bdyNodes;
}

string
NodeMap::print() const
{
	string out="";
	map<Coordinate,Node*,CoordLT>::iterator	it=nodeMap->begin();
	for (;it!=nodeMap->end();it++) {
		Node *node=it->second;
		out+=node->print();
	}
	return out;
}

}

/**********************************************************************
 * $Log$
 * Revision 1.3  2004/10/21 22:29:54  strk
 * Indentation changes and some more COMPUTE_Z rules
 *
 * Revision 1.2  2004/07/02 13:28:26  strk
 * Fixed all #include lines to reflect headers layout change.
 * Added client application build tips in README.
 *
 * Revision 1.1  2004/03/19 09:48:45  ybychkov
 * "geomgraph" and "geomgraph/indexl" upgraded to JTS 1.4
 *
 * Revision 1.12  2003/11/07 01:23:42  pramsey
 * Add standard CVS headers licence notices and copyrights to all cpp and h
 * files.
 *
 *
 **********************************************************************/

<commit_msg>Added Z merging in ::addNode<commit_after>/**********************************************************************
 * $Id$
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.refractions.net
 *
 * Copyright (C) 2001-2002 Vivid Solutions Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************/

#include <geos/geomgraph.h>

#define DEBUG 0

namespace geos {

NodeMap::NodeMap(NodeFactory *newNodeFact)
{
#if DEBUG
	cerr<<"["<<this<<"] NodeMap::NodeMap"<<endl;
#endif
	nodeFact=newNodeFact;
	nodeMap=new map<Coordinate,Node*,CoordLT>();
}

NodeMap::~NodeMap()
{
	map<Coordinate,Node*,CoordLT>::iterator	it=nodeMap->begin();
	for (;it!=nodeMap->end();it++) {
		Node *node=it->second;
		delete node;
	}
	delete nodeMap;
	delete nodeFact;
}

Node*
NodeMap::addNode(const Coordinate& coord)
{
#if DEBUG
	cerr<<"["<<this<<"] NodeMap::addNode("<<coord.toString()<<")";
#endif
	Node *node=find(coord);
	if (node==NULL) {
#if DEBUG
		cerr<<" is new"<<endl;
#endif
		node=nodeFact->createNode(coord);
		(*nodeMap)[coord]=node;
	}
	else
	{
#if DEBUG
		cerr<<" already found ("<<node->getCoordinate().toString()<<") - adding Z"<<endl;
#endif
		node->addZ(coord.z);
	}
	return node;
}

// first arg cannot be const because
// it is liable to label-merging ... --strk;
Node*
NodeMap::addNode(Node *n)
{
#if DEBUG
	cerr<<"["<<this<<"] NodeMap::addNode("<<n->print()<<")";
#endif
	Node *node=find(n->getCoordinate());
	if (node==NULL) {
#if DEBUG
		cerr<<" is new"<<endl;
#endif
		(*nodeMap)[n->getCoordinate()]=n;
		return n;
	}
#if DEBUG
	else
	{
		cerr<<" found already, merging label"<<endl;
	}
#endif // DEBUG
	node->mergeLabel(n);
	return node;
}

void
NodeMap::add(EdgeEnd *e)
{
	Coordinate& p=e->getCoordinate();
	Node *n=addNode(p);
	n->add(e);
}

/*
 * @return the node if found; null otherwise
 */
Node*
NodeMap::find(const Coordinate& coord) const
{
	map<Coordinate,Node*,CoordLT>::iterator found=nodeMap->find(coord);
	if (found==nodeMap->end())
		return NULL;
	else
		return found->second;
}

map<Coordinate,Node*,CoordLT>::iterator
NodeMap::iterator() const
{
	return nodeMap->begin();
}

//Doesn't work yet. Use iterator.
//public Collection NodeMap::values(){
//	return nodeMap.values();
//}

vector<Node*>*
NodeMap::getBoundaryNodes(int geomIndex) const
{
	vector<Node*>* bdyNodes=new vector<Node*>();
	map<Coordinate,Node*,CoordLT>::iterator	it=nodeMap->begin();
	for (;it!=nodeMap->end();it++) {
		Node *node=it->second;
		if (node->getLabel()->getLocation(geomIndex)==Location::BOUNDARY)
			bdyNodes->push_back(node);
	}
	return bdyNodes;
}

string
NodeMap::print() const
{
	string out="";
	map<Coordinate,Node*,CoordLT>::iterator	it=nodeMap->begin();
	for (;it!=nodeMap->end();it++) {
		Node *node=it->second;
		out+=node->print();
	}
	return out;
}

}

/**********************************************************************
 * $Log$
 * Revision 1.4  2004/11/20 15:41:41  strk
 * Added Z merging in ::addNode
 *
 * Revision 1.3  2004/10/21 22:29:54  strk
 * Indentation changes and some more COMPUTE_Z rules
 *
 * Revision 1.2  2004/07/02 13:28:26  strk
 * Fixed all #include lines to reflect headers layout change.
 * Added client application build tips in README.
 *
 * Revision 1.1  2004/03/19 09:48:45  ybychkov
 * "geomgraph" and "geomgraph/indexl" upgraded to JTS 1.4
 *
 * Revision 1.12  2003/11/07 01:23:42  pramsey
 * Add standard CVS headers licence notices and copyrights to all cpp and h
 * files.
 *
 *
 **********************************************************************/

<|endoftext|>


<commit_before>/**
    The Opensource Compiler CKX -- for my honey ChenKX
    Copyright (C) 2017  CousinZe

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero 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
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

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

#ifndef CKX_AST_NODE_HPP
#define CKX_AST_NODE_HPP

#include "defs.hpp"

#include "memory.hpp"
#include "string.hpp"
#include "vector.hpp"
#include "list.hpp"

#include "ckx_type.hpp"
#include "ckx_env_table.hpp"

#include "ckx_token.hpp"

#include "ckx_ast_node_fwd.hpp"

namespace ckx
{

using saber::saber_ptr;

class ckx_ast_node
{
public:
    explicit ckx_ast_node(saber_ptr<ckx_token> _at_token);
    ~ckx_ast_node() = default;

    saber_ptr<ckx_token> get_at_token();

private:
    saber_ptr<ckx_token> at_token;
};

class ckx_ast_translation_unit make_use_of ckx_ast_node
{
public:
    explicit ckx_ast_translation_unit(saber_ptr<ckx_token> _at_token);
    ~ckx_ast_translation_unit();

    void add_new_stmt(ckx_ast_stmt *_stmt);

private:
    explicit saber::vector<ckx_ast_stmt*> stmts;
    ckx_env_table *global_table;
};

interface ckx_ast_stmt make_use_of ckx_ast_node
{
public:
    explicit ckx_ast_stmt(saber_ptr<ckx_token> _at_token);
    virtual ~ckx_ast_stmt() = 0;

    // SKTT1Faker
    // This function will be finished after we get a proper intermediate
    // representation and start to write syntax-directed translation
    Q_ON_HOLD(virtual void translate(saber::list<ckx_ir_instance>& ret) = 0;)
};

class ckx_ast_compound_stmt final implements ckx_ast_stmt
{
public:
    ckx_ast_compound_stmt(saber_ptr<ckx_token> _at_token,
                          ckx_env_table *_parent_scope_table);
    ~ckx_ast_compound_stmt() override final;

    void add_new_stmt(ckx_ast_stmt *_stmt);

private:
    saber::vector<ckx_ast_stmt*> stmts;
    ckx_env_table *local_table;
};

class ckx_ast_if_stmt final implements ckx_ast_stmt
{
public:
    ckx_ast_if_stmt(saber_ptr<ckx_token> _at_token,
                    ckx_ast_expr* _condition,
                    ckx_ast_stmt* _then_clause,
                    ckx_ast_stmt* _else_clause);
    ~ckx_ast_if_stmt() override final;

private:
    ckx_ast_expr *condition;
    ckx_ast_stmt *then_clause;
    ckx_ast_stmt *else_clause;
};

class ckx_ast_while_stmt final implements ckx_ast_stmt
{
public:
    ckx_ast_while_stmt(saber_ptr<ckx_token> _at_token,
                       ckx_ast_expr *_condition,
                       ckx_ast_stmt *_clause);
    ~ckx_ast_while_stmt() override final;

private:
    ckx_ast_expr *condition;
    ckx_ast_stmt *clause;
};

class ckx_ast_do_while_stmt final implements ckx_ast_stmt
{
public:
    ckx_ast_do_while_stmt(saber_ptr<ckx_token> _at_token,
                          ckx_ast_expr *_condition,
                          ckx_ast_stmt *_clause);
    ~ckx_ast_do_while_stmt() override final;

private:
    ckx_ast_expr *condition;
    ckx_ast_stmt *clause;
};

class ckx_ast_break_stmt final implements ckx_ast_stmt
{
public:
    explicit ckx_ast_break_stmt(saber_ptr<ckx_token> _at_token);
    ~ckx_ast_break_stmt() override final = default;
};

class ckx_ast_continue_stmt final implements ckx_ast_stmt
{
public:
    explicit ckx_ast_continue_stmt(saber_ptr<ckx_token> _at_token);
    ~ckx_ast_continue_stmt() override final = default;
};

class ckx_ast_return_stmt final implements ckx_ast_stmt
{
public:
    ckx_ast_return_stmt(saber_ptr<ckx_token> _at_token,
                        ckx_ast_expr* _return_expr);
    ~ckx_ast_return_stmt() override final = default;

private:
    ckx_ast_expr *return_expr;
};

class ckx_ast_decl_stmt final implements ckx_ast_stmt
{
public:
    explicit ckx_ast_decl_stmt(saber_ptr<ckx_token> _at_token);
    ~ckx_ast_decl_stmt() override final;

    void add_decl(ckx_ast_init_decl* _decl);

private:
    saber::vector<ckx_ast_init_decl*> decls;
};

class ckx_ast_expr_stmt final implements ckx_ast_stmt
{
public:
    ckx_ast_expr_stmt(saber_ptr<ckx_token> _at_token, ckx_ast_expr* _expr);
    ~ckx_ast_expr_stmt() override final;

private:
    ckx_ast_expr *expr;
};

class ckx_ast_expr make_use_of ckx_ast_node
{
    Q_ON_HOLD(...)
};

class ckx_ast_func_stmt make_use_of ckx_ast_node
{
public:
    ckx_ast_func_stmt(saber_ptr<ckx_token> _at_token,
                      ckx_func_entry *_entry,
                      ckx_env_table *_param_env_table);
    ~ckx_ast_func_stmt();

    bool is_defined() const;

    ckx_env_table* get_param_env_table();
    void define(ckx_ast_compound_stmt* _fnbody) const;

private:
    ckx_func_entry *entry;
    ckx_env_table *param_env_table;
};

class ckx_ast_init_decl make_use_of ckx_ast_node
{
public:
    ckx_ast_init_decl(saber_ptr<ckx_token> _at_token,
                      ckx_var_entry* _entry,
                      ckx_ast_expr* _init);
    ~ckx_ast_init_decl();

private:
    ckx_var_entry *entry;
    ckx_ast_expr *init;
};

class ckx_ast_param_decl make_use_of ckx_ast_node
{
public:
    ckx_ast_param_decl(saber_ptr<ckx_token> _at_token,
                       ckx_var_entry* _entry);
    ~ckx_ast_param_decl() = default;

private:
    ckx_var_entry *entry;
};

class ckx_ast_struct_stmt make_use_of ckx_ast_node
{
public:
    ckx_ast_struct_stmt(saber_ptr<ckx_token> _at_token,
                   ckx_type_entry* _entry);
    ~ckx_ast_struct_stmt();

private:
    ckx_type_entry *entry;
};

class ckx_ast_variant_stmt make_use_of ckx_ast_node
{
public:
    ckx_ast_variant_stmt(saber_ptr<ckx_token> _at_token,
                    ckx_type_entry* _entry);
    ~ckx_ast_variant_stmt();

private:
    ckx_type_entry *entry;
};

class ckx_ast_enum_stmt make_use_of ckx_ast_node
{
public:
    ckx_ast_enum_stmt(saber_ptr<ckx_token> _at_token,
                      ckx_type_entry* _entry);
    ~ckx_ast_enum_stmt();

private:
    ckx_type_entry *entry;
};

} // namespace ckx

#endif // CKX_AST_NODE_HPP
<commit_msg>[(UTF +8:00) 2017-9-1 22:46] Small bugfix.<commit_after>/**
    The Opensource Compiler CKX -- for my honey ChenKX
    Copyright (C) 2017  CousinZe

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero 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
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

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

#ifndef CKX_AST_NODE_HPP
#define CKX_AST_NODE_HPP

#include "defs.hpp"

#include "memory.hpp"
#include "string.hpp"
#include "vector.hpp"
#include "list.hpp"

#include "ckx_type.hpp"
#include "ckx_env_table.hpp"

#include "ckx_token.hpp"

#include "ckx_ast_node_fwd.hpp"

namespace ckx
{

using saber::saber_ptr;

class ckx_ast_node
{
public:
    explicit ckx_ast_node(saber_ptr<ckx_token> _at_token);
    ~ckx_ast_node() = default;

    saber_ptr<ckx_token> get_at_token();

private:
    saber_ptr<ckx_token> at_token;
};

class ckx_ast_translation_unit make_use_of ckx_ast_node
{
public:
    explicit ckx_ast_translation_unit(saber_ptr<ckx_token> _at_token);
    ~ckx_ast_translation_unit();

    void add_new_stmt(ckx_ast_stmt *_stmt);

private:
    saber::vector<ckx_ast_stmt*> stmts;
    ckx_env_table *global_table;
};

interface ckx_ast_stmt make_use_of ckx_ast_node
{
public:
    explicit ckx_ast_stmt(saber_ptr<ckx_token> _at_token);
    virtual ~ckx_ast_stmt() = 0;

    // SKTT1Faker
    // This function will be finished after we get a proper intermediate
    // representation and start to write syntax-directed translation
    Q_ON_HOLD(virtual void translate(saber::list<ckx_ir_instance>& ret) = 0;)
};

class ckx_ast_compound_stmt final implements ckx_ast_stmt
{
public:
    ckx_ast_compound_stmt(saber_ptr<ckx_token> _at_token,
                          ckx_env_table *_parent_scope_table);
    ~ckx_ast_compound_stmt() override final;

    void add_new_stmt(ckx_ast_stmt *_stmt);

private:
    saber::vector<ckx_ast_stmt*> stmts;
    ckx_env_table *local_table;
};

class ckx_ast_if_stmt final implements ckx_ast_stmt
{
public:
    ckx_ast_if_stmt(saber_ptr<ckx_token> _at_token,
                    ckx_ast_expr* _condition,
                    ckx_ast_stmt* _then_clause,
                    ckx_ast_stmt* _else_clause);
    ~ckx_ast_if_stmt() override final;

private:
    ckx_ast_expr *condition;
    ckx_ast_stmt *then_clause;
    ckx_ast_stmt *else_clause;
};

class ckx_ast_while_stmt final implements ckx_ast_stmt
{
public:
    ckx_ast_while_stmt(saber_ptr<ckx_token> _at_token,
                       ckx_ast_expr *_condition,
                       ckx_ast_stmt *_clause);
    ~ckx_ast_while_stmt() override final;

private:
    ckx_ast_expr *condition;
    ckx_ast_stmt *clause;
};

class ckx_ast_do_while_stmt final implements ckx_ast_stmt
{
public:
    ckx_ast_do_while_stmt(saber_ptr<ckx_token> _at_token,
                          ckx_ast_expr *_condition,
                          ckx_ast_stmt *_clause);
    ~ckx_ast_do_while_stmt() override final;

private:
    ckx_ast_expr *condition;
    ckx_ast_stmt *clause;
};

class ckx_ast_break_stmt final implements ckx_ast_stmt
{
public:
    explicit ckx_ast_break_stmt(saber_ptr<ckx_token> _at_token);
    ~ckx_ast_break_stmt() override final = default;
};

class ckx_ast_continue_stmt final implements ckx_ast_stmt
{
public:
    explicit ckx_ast_continue_stmt(saber_ptr<ckx_token> _at_token);
    ~ckx_ast_continue_stmt() override final = default;
};

class ckx_ast_return_stmt final implements ckx_ast_stmt
{
public:
    ckx_ast_return_stmt(saber_ptr<ckx_token> _at_token,
                        ckx_ast_expr* _return_expr);
    ~ckx_ast_return_stmt() override final = default;

private:
    ckx_ast_expr *return_expr;
};

class ckx_ast_decl_stmt final implements ckx_ast_stmt
{
public:
    explicit ckx_ast_decl_stmt(saber_ptr<ckx_token> _at_token);
    ~ckx_ast_decl_stmt() override final;

    void add_decl(ckx_ast_init_decl* _decl);

private:
    saber::vector<ckx_ast_init_decl*> decls;
};

class ckx_ast_expr_stmt final implements ckx_ast_stmt
{
public:
    ckx_ast_expr_stmt(saber_ptr<ckx_token> _at_token, ckx_ast_expr* _expr);
    ~ckx_ast_expr_stmt() override final;

private:
    ckx_ast_expr *expr;
};

class ckx_ast_expr make_use_of ckx_ast_node
{
    Q_ON_HOLD(...)
};

class ckx_ast_func_stmt make_use_of ckx_ast_node
{
public:
    ckx_ast_func_stmt(saber_ptr<ckx_token> _at_token,
                      ckx_func_entry *_entry,
                      ckx_env_table *_param_env_table);
    ~ckx_ast_func_stmt();

    bool is_defined() const;

    ckx_env_table* get_param_env_table();
    void define(ckx_ast_compound_stmt* _fnbody) const;

private:
    ckx_func_entry *entry;
    ckx_env_table *param_env_table;
};

class ckx_ast_init_decl make_use_of ckx_ast_node
{
public:
    ckx_ast_init_decl(saber_ptr<ckx_token> _at_token,
                      ckx_var_entry* _entry,
                      ckx_ast_expr* _init);
    ~ckx_ast_init_decl();

private:
    ckx_var_entry *entry;
    ckx_ast_expr *init;
};

class ckx_ast_param_decl make_use_of ckx_ast_node
{
public:
    ckx_ast_param_decl(saber_ptr<ckx_token> _at_token,
                       ckx_var_entry* _entry);
    ~ckx_ast_param_decl() = default;

private:
    ckx_var_entry *entry;
};

class ckx_ast_struct_stmt make_use_of ckx_ast_node
{
public:
    ckx_ast_struct_stmt(saber_ptr<ckx_token> _at_token,
                   ckx_type_entry* _entry);
    ~ckx_ast_struct_stmt();

private:
    ckx_type_entry *entry;
};

class ckx_ast_variant_stmt make_use_of ckx_ast_node
{
public:
    ckx_ast_variant_stmt(saber_ptr<ckx_token> _at_token,
                    ckx_type_entry* _entry);
    ~ckx_ast_variant_stmt();

private:
    ckx_type_entry *entry;
};

class ckx_ast_enum_stmt make_use_of ckx_ast_node
{
public:
    ckx_ast_enum_stmt(saber_ptr<ckx_token> _at_token,
                      ckx_type_entry* _entry);
    ~ckx_ast_enum_stmt();

private:
    ckx_type_entry *entry;
};

} // namespace ckx

#endif // CKX_AST_NODE_HPP
<|endoftext|>


<commit_before>#include "xchainer/array.h"

#include <initializer_list>

#ifdef XCHAINER_ENABLE_CUDA
#include <cuda_runtime.h>
#endif  // XCHAINER_ENABLE_CUDA
#include <gtest/gtest.h>
#include <nonstd/optional.hpp>

#include "xchainer/array.h"
#include "xchainer/backend.h"
#include "xchainer/context.h"
#ifdef XCHAINER_ENABLE_CUDA
#include "xchainer/cuda/cuda_backend.h"
#include "xchainer/cuda/cuda_device.h"
#include "xchainer/cuda/cuda_runtime.h"
#endif  // XCHAINER_ENABLE_CUDA
#include "xchainer/device.h"
#include "xchainer/memory.h"
#include "xchainer/native_backend.h"
#include "xchainer/native_device.h"
#include "xchainer/testing/context_session.h"

namespace xchainer {
namespace {

class ArrayDeviceTest : public ::testing::Test {
protected:
    void SetUp() override { context_session_.emplace(); }

    void TearDown() override { context_session_.reset(); }

private:
    nonstd::optional<testing::ContextSession> context_session_;
};

// Check that Array data exists on the specified device
void ExpectDataExistsOnDevice(const Device& expected_device, const Array& array) {
    // Check device member of the Array
    EXPECT_EQ(&expected_device, &array.device());

    // Check device of data pointee
    if (expected_device.backend().GetName() == "native") {
        EXPECT_FALSE(internal::IsPointerCudaMemory(array.data().get()));
    } else if (expected_device.backend().GetName() == "cuda") {
        EXPECT_TRUE(internal::IsPointerCudaMemory(array.data().get()));
    } else {
        FAIL() << "invalid device";
    }
}

// Check that Arrays are created on the default device if no other devices are specified
void CheckDeviceFallback(const std::function<Array()>& create_array_func) {
    // Fallback to default device which is CPU
    {
        Context& ctx = GetDefaultContext();
        NativeBackend native_backend{ctx};
        NativeDevice cpu_device{native_backend, 0};
        auto scope = std::make_unique<DeviceScope>(cpu_device);
        Array array = create_array_func();
        ExpectDataExistsOnDevice(cpu_device, array);
    }
#ifdef XCHAINER_ENABLE_CUDA
    // Fallback to default device which is GPU
    {
        Context& ctx = GetDefaultContext();
        cuda::CudaBackend cuda_backend{ctx};
        cuda::CudaDevice cuda_device{cuda_backend, 0};
        auto scope = std::make_unique<DeviceScope>(cuda_device);
        Array array = create_array_func();
        ExpectDataExistsOnDevice(cuda_device, array);
    }
#endif
}

// Check that Arrays are created on the specified device, if specified, without taking into account the default device
void CheckDeviceExplicit(const std::function<Array(Device& device)>& create_array_func) {
    Context& ctx = GetDefaultContext();
    NativeBackend native_backend{ctx};
    NativeDevice cpu_device{native_backend, 0};

    // Explicitly create on CPU
    {
        Array array = create_array_func(cpu_device);
        ExpectDataExistsOnDevice(cpu_device, array);
    }
    {
        auto scope = std::make_unique<DeviceScope>(cpu_device);
        Array array = create_array_func(cpu_device);
        ExpectDataExistsOnDevice(cpu_device, array);
    }
#ifdef XCHAINER_ENABLE_CUDA
    cuda::CudaBackend cuda_backend{ctx};
    cuda::CudaDevice cuda_device{cuda_backend, 0};

    {
        auto scope = std::make_unique<DeviceScope>(cuda_device);
        Array array = create_array_func(cpu_device);
        ExpectDataExistsOnDevice(cpu_device, array);
    }
    // Explicitly create on GPU
    {
        Array array = create_array_func(cuda_device);
        ExpectDataExistsOnDevice(cuda_device, array);
    }
    {
        auto scope = std::make_unique<DeviceScope>(cpu_device);
        Array array = create_array_func(cuda_device);
        ExpectDataExistsOnDevice(cuda_device, array);
    }
    {
        auto scope = std::make_unique<DeviceScope>(cuda_device);
        Array array = create_array_func(cuda_device);
        ExpectDataExistsOnDevice(cuda_device, array);
    }
#endif  // XCHAINER_ENABLE_CUDA
}

TEST_F(ArrayDeviceTest, FromBuffer) {
    Shape shape({2, 3});
    Dtype dtype = Dtype::kFloat32;
    float raw_data[] = {0.f, 1.f, 2.f, 3.f, 4.f, 5.f};
    std::shared_ptr<void> data(raw_data, [](float* ptr) {
        (void)ptr;  // unused
    });
    CheckDeviceFallback([&]() { return Array::FromBuffer(shape, dtype, data); });
    CheckDeviceExplicit([&](Device& device) { return Array::FromBuffer(shape, dtype, data, device); });
}

TEST_F(ArrayDeviceTest, Empty) {
    Shape shape({2, 3});
    Dtype dtype = Dtype::kFloat32;
    CheckDeviceFallback([&]() { return Array::Empty(shape, dtype); });
    CheckDeviceExplicit([&](Device& device) { return Array::Empty(shape, dtype, device); });
}

TEST_F(ArrayDeviceTest, Full) {
    Shape shape({2, 3});
    Scalar scalar{2.f};
    Dtype dtype = Dtype::kFloat32;
    CheckDeviceFallback([&]() { return Array::Full(shape, scalar, dtype); });
    CheckDeviceFallback([&]() { return Array::Full(shape, scalar); });
    CheckDeviceExplicit([&](Device& device) { return Array::Full(shape, scalar, dtype, device); });
    CheckDeviceExplicit([&](Device& device) { return Array::Full(shape, scalar, device); });
}

TEST_F(ArrayDeviceTest, Zeros) {
    Shape shape({2, 3});
    Dtype dtype = Dtype::kFloat32;
    CheckDeviceFallback([&]() { return Array::Zeros(shape, dtype); });
    CheckDeviceExplicit([&](Device& device) { return Array::Zeros(shape, dtype, device); });
}

TEST_F(ArrayDeviceTest, Ones) {
    Shape shape({2, 3});
    Dtype dtype = Dtype::kFloat32;
    CheckDeviceFallback([&]() { return Array::Ones(shape, dtype); });
    CheckDeviceExplicit([&](Device& device) { return Array::Ones(shape, dtype, device); });
}

TEST_F(ArrayDeviceTest, EmptyLike) {
    Shape shape({2, 3});
    Dtype dtype = Dtype::kFloat32;

    CheckDeviceFallback([&]() {
        Array array_orig = Array::Empty(shape, dtype);
        return Array::EmptyLike(array_orig);
    });
    CheckDeviceExplicit([&](Device& device) {
        NativeBackend native_backend{device.context()};
        NativeDevice cpu_device{native_backend, 0};
        Array array_orig = Array::Empty(shape, dtype, cpu_device);
        return Array::EmptyLike(array_orig, device);
    });
}

TEST_F(ArrayDeviceTest, FullLike) {
    Shape shape({2, 3});
    Scalar scalar{2.f};
    Dtype dtype = Dtype::kFloat32;

    CheckDeviceFallback([&]() {
        Array array_orig = Array::Empty(shape, dtype);
        return Array::FullLike(array_orig, scalar);
    });
    CheckDeviceExplicit([&](Device& device) {
        NativeBackend native_backend{device.context()};
        NativeDevice cpu_device{native_backend, 0};
        Array array_orig = Array::Empty(shape, dtype, cpu_device);
        return Array::FullLike(array_orig, scalar, device);
    });
}

TEST_F(ArrayDeviceTest, ZerosLike) {
    Shape shape({2, 3});
    Dtype dtype = Dtype::kFloat32;

    CheckDeviceFallback([&]() {
        Array array_orig = Array::Empty(shape, dtype);
        return Array::ZerosLike(array_orig);
    });
    CheckDeviceExplicit([&](Device& device) {
        NativeBackend native_backend{device.context()};
        NativeDevice cpu_device{native_backend, 0};
        Array array_orig = Array::Empty(shape, dtype, cpu_device);
        return Array::ZerosLike(array_orig, device);
    });
}

TEST_F(ArrayDeviceTest, OnesLike) {
    Shape shape({2, 3});
    Dtype dtype = Dtype::kFloat32;

    CheckDeviceFallback([&]() {
        Array array_orig = Array::Empty(shape, dtype);
        return Array::OnesLike(array_orig);
    });
    CheckDeviceExplicit([&](Device& device) {
        NativeBackend native_backend{device.context()};
        NativeDevice cpu_device{native_backend, 0};
        Array array_orig = Array::Empty(shape, dtype, cpu_device);
        return Array::OnesLike(array_orig, device);
    });
}

TEST_F(ArrayDeviceTest, CheckDevicesCompatibleInvalidArguments) { EXPECT_THROW(CheckDevicesCompatible({}), DeviceError); }

TEST_F(ArrayDeviceTest, CheckDevicesCompatibleMultipleDevices) {
    Shape shape({2, 3});
    Dtype dtype = Dtype::kFloat32;

    Context& ctx = GetDefaultContext();
    NativeBackend native_backend{ctx};
    NativeDevice cpu_device_0{native_backend, 0};
    NativeDevice cpu_device_1{native_backend, 1};
    auto scope = std::make_unique<DeviceScope>(cpu_device_0);

    Array a = Array::Empty(shape, dtype, cpu_device_0);
    Array b = Array::Empty(shape, dtype, cpu_device_0);
    Array c = Array::Empty(shape, dtype, cpu_device_1);

    EXPECT_NO_THROW(CheckDevicesCompatible({a}));
    EXPECT_NO_THROW(CheckDevicesCompatible({a, b}));
    EXPECT_THROW(CheckDevicesCompatible({a, c}), DeviceError);
}

TEST_F(ArrayDeviceTest, CheckDevicesCompatibleBasicArithmetics) {
    Shape shape({2, 3});
    Dtype dtype = Dtype::kFloat32;

    Context& ctx = GetDefaultContext();
    NativeBackend native_backend{ctx};
    NativeDevice cpu_device_0{native_backend, 0};
    NativeDevice cpu_device_1{native_backend, 1};
    auto scope = std::make_unique<DeviceScope>(cpu_device_0);

    Array a = Array::Empty(shape, dtype, cpu_device_0);
    Array b = Array::Empty(shape, dtype, cpu_device_0);
    Array c = Array::Empty(shape, dtype, cpu_device_1);

    {
        // Asserts no throw, and similarly for the following three cases
        Array d = a + b;
        EXPECT_EQ(&cpu_device_0, &d.device());
    }
    {
        Array d = a * b;
        EXPECT_EQ(&cpu_device_0, &d.device());
    }
    {
        a += b;
        EXPECT_EQ(&cpu_device_0, &a.device());
    }
    {
        a *= b;
        EXPECT_EQ(&cpu_device_0, &a.device());
    }
    { EXPECT_THROW(a + c, DeviceError); }
    { EXPECT_THROW(a += c, DeviceError); }
    { EXPECT_THROW(a * c, DeviceError); }
    { EXPECT_THROW(a *= c, DeviceError); }
}

}  // namespace
}  // namespace xchainer
<commit_msg>Better test variable names<commit_after>#include "xchainer/array.h"

#include <initializer_list>

#ifdef XCHAINER_ENABLE_CUDA
#include <cuda_runtime.h>
#endif  // XCHAINER_ENABLE_CUDA
#include <gtest/gtest.h>
#include <nonstd/optional.hpp>

#include "xchainer/array.h"
#include "xchainer/backend.h"
#include "xchainer/context.h"
#ifdef XCHAINER_ENABLE_CUDA
#include "xchainer/cuda/cuda_backend.h"
#include "xchainer/cuda/cuda_device.h"
#include "xchainer/cuda/cuda_runtime.h"
#endif  // XCHAINER_ENABLE_CUDA
#include "xchainer/device.h"
#include "xchainer/memory.h"
#include "xchainer/native_backend.h"
#include "xchainer/native_device.h"
#include "xchainer/testing/context_session.h"

namespace xchainer {
namespace {

class ArrayDeviceTest : public ::testing::Test {
protected:
    void SetUp() override { context_session_.emplace(); }

    void TearDown() override { context_session_.reset(); }

private:
    nonstd::optional<testing::ContextSession> context_session_;
};

// Check that Array data exists on the specified device
void ExpectDataExistsOnDevice(const Device& expected_device, const Array& array) {
    // Check device member of the Array
    EXPECT_EQ(&expected_device, &array.device());

    // Check device of data pointee
    if (expected_device.backend().GetName() == "native") {
        EXPECT_FALSE(internal::IsPointerCudaMemory(array.data().get()));
    } else if (expected_device.backend().GetName() == "cuda") {
        EXPECT_TRUE(internal::IsPointerCudaMemory(array.data().get()));
    } else {
        FAIL() << "invalid device";
    }
}

// Check that Arrays are created on the default device if no other devices are specified
void CheckDeviceFallback(const std::function<Array()>& create_array_func) {
    // Fallback to default device which is CPU
    {
        Context& ctx = GetDefaultContext();
        NativeBackend native_backend{ctx};
        NativeDevice cpu_device{native_backend, 0};
        auto scope = std::make_unique<DeviceScope>(cpu_device);
        Array array = create_array_func();
        ExpectDataExistsOnDevice(cpu_device, array);
    }
#ifdef XCHAINER_ENABLE_CUDA
    // Fallback to default device which is GPU
    {
        Context& ctx = GetDefaultContext();
        cuda::CudaBackend cuda_backend{ctx};
        cuda::CudaDevice cuda_device{cuda_backend, 0};
        auto scope = std::make_unique<DeviceScope>(cuda_device);
        Array array = create_array_func();
        ExpectDataExistsOnDevice(cuda_device, array);
    }
#endif
}

// Check that Arrays are created on the specified device, if specified, without taking into account the default device
void CheckDeviceExplicit(const std::function<Array(Device& device)>& create_array_func) {
    Context& ctx = GetDefaultContext();
    NativeBackend native_backend{ctx};
    NativeDevice cpu_device{native_backend, 0};

    // Explicitly create on CPU
    {
        Array array = create_array_func(cpu_device);
        ExpectDataExistsOnDevice(cpu_device, array);
    }
    {
        auto scope = std::make_unique<DeviceScope>(cpu_device);
        Array array = create_array_func(cpu_device);
        ExpectDataExistsOnDevice(cpu_device, array);
    }
#ifdef XCHAINER_ENABLE_CUDA
    cuda::CudaBackend cuda_backend{ctx};
    cuda::CudaDevice cuda_device{cuda_backend, 0};

    {
        auto scope = std::make_unique<DeviceScope>(cuda_device);
        Array array = create_array_func(cpu_device);
        ExpectDataExistsOnDevice(cpu_device, array);
    }
    // Explicitly create on GPU
    {
        Array array = create_array_func(cuda_device);
        ExpectDataExistsOnDevice(cuda_device, array);
    }
    {
        auto scope = std::make_unique<DeviceScope>(cpu_device);
        Array array = create_array_func(cuda_device);
        ExpectDataExistsOnDevice(cuda_device, array);
    }
    {
        auto scope = std::make_unique<DeviceScope>(cuda_device);
        Array array = create_array_func(cuda_device);
        ExpectDataExistsOnDevice(cuda_device, array);
    }
#endif  // XCHAINER_ENABLE_CUDA
}

TEST_F(ArrayDeviceTest, FromBuffer) {
    Shape shape({2, 3});
    Dtype dtype = Dtype::kFloat32;
    float raw_data[] = {0.f, 1.f, 2.f, 3.f, 4.f, 5.f};
    std::shared_ptr<void> data(raw_data, [](float* ptr) {
        (void)ptr;  // unused
    });
    CheckDeviceFallback([&]() { return Array::FromBuffer(shape, dtype, data); });
    CheckDeviceExplicit([&](Device& device) { return Array::FromBuffer(shape, dtype, data, device); });
}

TEST_F(ArrayDeviceTest, Empty) {
    Shape shape({2, 3});
    Dtype dtype = Dtype::kFloat32;
    CheckDeviceFallback([&]() { return Array::Empty(shape, dtype); });
    CheckDeviceExplicit([&](Device& device) { return Array::Empty(shape, dtype, device); });
}

TEST_F(ArrayDeviceTest, Full) {
    Shape shape({2, 3});
    Scalar scalar{2.f};
    Dtype dtype = Dtype::kFloat32;
    CheckDeviceFallback([&]() { return Array::Full(shape, scalar, dtype); });
    CheckDeviceFallback([&]() { return Array::Full(shape, scalar); });
    CheckDeviceExplicit([&](Device& device) { return Array::Full(shape, scalar, dtype, device); });
    CheckDeviceExplicit([&](Device& device) { return Array::Full(shape, scalar, device); });
}

TEST_F(ArrayDeviceTest, Zeros) {
    Shape shape({2, 3});
    Dtype dtype = Dtype::kFloat32;
    CheckDeviceFallback([&]() { return Array::Zeros(shape, dtype); });
    CheckDeviceExplicit([&](Device& device) { return Array::Zeros(shape, dtype, device); });
}

TEST_F(ArrayDeviceTest, Ones) {
    Shape shape({2, 3});
    Dtype dtype = Dtype::kFloat32;
    CheckDeviceFallback([&]() { return Array::Ones(shape, dtype); });
    CheckDeviceExplicit([&](Device& device) { return Array::Ones(shape, dtype, device); });
}

TEST_F(ArrayDeviceTest, EmptyLike) {
    Shape shape({2, 3});
    Dtype dtype = Dtype::kFloat32;

    CheckDeviceFallback([&]() {
        Array array_orig = Array::Empty(shape, dtype);
        return Array::EmptyLike(array_orig);
    });
    CheckDeviceExplicit([&](Device& device) {
        NativeBackend native_backend{device.context()};
        NativeDevice cpu_device{native_backend, 0};
        Array array_orig = Array::Empty(shape, dtype, cpu_device);
        return Array::EmptyLike(array_orig, device);
    });
}

TEST_F(ArrayDeviceTest, FullLike) {
    Shape shape({2, 3});
    Scalar scalar{2.f};
    Dtype dtype = Dtype::kFloat32;

    CheckDeviceFallback([&]() {
        Array array_orig = Array::Empty(shape, dtype);
        return Array::FullLike(array_orig, scalar);
    });
    CheckDeviceExplicit([&](Device& device) {
        NativeBackend native_backend{device.context()};
        NativeDevice cpu_device{native_backend, 0};
        Array array_orig = Array::Empty(shape, dtype, cpu_device);
        return Array::FullLike(array_orig, scalar, device);
    });
}

TEST_F(ArrayDeviceTest, ZerosLike) {
    Shape shape({2, 3});
    Dtype dtype = Dtype::kFloat32;

    CheckDeviceFallback([&]() {
        Array array_orig = Array::Empty(shape, dtype);
        return Array::ZerosLike(array_orig);
    });
    CheckDeviceExplicit([&](Device& device) {
        NativeBackend native_backend{device.context()};
        NativeDevice cpu_device{native_backend, 0};
        Array array_orig = Array::Empty(shape, dtype, cpu_device);
        return Array::ZerosLike(array_orig, device);
    });
}

TEST_F(ArrayDeviceTest, OnesLike) {
    Shape shape({2, 3});
    Dtype dtype = Dtype::kFloat32;

    CheckDeviceFallback([&]() {
        Array array_orig = Array::Empty(shape, dtype);
        return Array::OnesLike(array_orig);
    });
    CheckDeviceExplicit([&](Device& device) {
        NativeBackend native_backend{device.context()};
        NativeDevice cpu_device{native_backend, 0};
        Array array_orig = Array::Empty(shape, dtype, cpu_device);
        return Array::OnesLike(array_orig, device);
    });
}

TEST_F(ArrayDeviceTest, CheckDevicesCompatibleInvalidArguments) { EXPECT_THROW(CheckDevicesCompatible({}), DeviceError); }

TEST_F(ArrayDeviceTest, CheckDevicesCompatibleMultipleDevices) {
    Shape shape({2, 3});
    Dtype dtype = Dtype::kFloat32;

    Context& ctx = GetDefaultContext();
    NativeBackend native_backend{ctx};
    NativeDevice cpu_device_0{native_backend, 0};
    NativeDevice cpu_device_1{native_backend, 1};
    auto scope = std::make_unique<DeviceScope>(cpu_device_0);

    Array a_device_0 = Array::Empty(shape, dtype, cpu_device_0);
    Array b_device_0 = Array::Empty(shape, dtype, cpu_device_0);
    Array c_device_1 = Array::Empty(shape, dtype, cpu_device_1);

    EXPECT_NO_THROW(CheckDevicesCompatible({a_device_0}));
    EXPECT_NO_THROW(CheckDevicesCompatible({a_device_0, b_device_0}));
    EXPECT_THROW(CheckDevicesCompatible({a_device_0, c_device_1}), DeviceError);
}

TEST_F(ArrayDeviceTest, CheckDevicesCompatibleBasicArithmetics) {
    Shape shape({2, 3});
    Dtype dtype = Dtype::kFloat32;

    Context& ctx = GetDefaultContext();
    NativeBackend native_backend{ctx};
    NativeDevice cpu_device_0{native_backend, 0};
    NativeDevice cpu_device_1{native_backend, 1};
    auto scope = std::make_unique<DeviceScope>(cpu_device_0);

    Array a_device_0 = Array::Empty(shape, dtype, cpu_device_0);
    Array b_device_0 = Array::Empty(shape, dtype, cpu_device_0);
    Array c_device_1 = Array::Empty(shape, dtype, cpu_device_1);

    {
        // Asserts no throw, and similarly for the following three cases
        Array d_device_0 = a_device_0 + b_device_0;
        EXPECT_EQ(&cpu_device_0, &d_device_0.device());
    }
    {
        Array d_device_0 = a_device_0 * b_device_0;
        EXPECT_EQ(&cpu_device_0, &d_device_0.device());
    }
    {
        a_device_0 += b_device_0;
        EXPECT_EQ(&cpu_device_0, &a_device_0.device());
    }
    {
        a_device_0 *= b_device_0;
        EXPECT_EQ(&cpu_device_0, &a_device_0.device());
    }
    { EXPECT_THROW(a_device_0 + c_device_1, DeviceError); }
    { EXPECT_THROW(a_device_0 += c_device_1, DeviceError); }
    { EXPECT_THROW(a_device_0 * c_device_1, DeviceError); }
    { EXPECT_THROW(a_device_0 *= c_device_1, DeviceError); }
}

}  // namespace
}  // namespace xchainer
<|endoftext|>