<commit_before>#include "AudioPluginUtil.h"
#include "FFTConvolver/FFTConvolver.h"
#include "FFTConvolver/TwoStageFFTConvolver.h"

#include <utility>

#include <mysofa.h>

//#include <ATK/Special/ConvolutionFilter.h>

// Our plugin will be encapsulated within a namespace
// This namespace is later used to indicate that we
// want to include this plugin in the build with PluginList.h
namespace Plugin_SofaSpatializer {

    /////////////////////////////////////////
    /// Utilities
    ///////////////////////////////////////

    const unsigned MAX_SOFA_FILES = 1;
    const unsigned CONVOLVERS = 2;

    class SofaContainer {
    public:
        MYSOFA_HRTF* hrtfs[MAX_SOFA_FILES];
        fftconvolver::FFTConvolver* convolver[CONVOLVERS];
        unsigned buffersize;
        bool is_initialized = false;
        float last;

        void init(unsigned samplerate, unsigned buffersize) {
            if (!is_initialized) {
                this->buffersize = buffersize;

                int err;

                // load sofa files
                hrtfs[0] = mysofa_load("WIEb_S00_R01.sofa", &err);
                //if (samplerate != hrtfs[0]->DataSamplingRate.values[0]) { mysofa_resample(hrtfs[0], (float)samplerate); }

                // init convolver
                this->setIr(0);

                this->is_initialized = true;
            }
        }

        void setIr(unsigned ir) {
            for (int i = 0; i < CONVOLVERS; ++i) {
                convolver[i] = new fftconvolver::FFTConvolver();
                convolver[i]->init(buffersize,
                                   &this->hrtfs[0]->DataIR.values[this->hrtfs[0]->N * (ir + i)],
                                   this->hrtfs[0]->N);
            }
        }

        void free() {
            if (is_initialized) {
                for (int i = 0; i < sizeof(this->hrtfs)/sizeof(*this->hrtfs); ++i) {
                    mysofa_free(hrtfs[i]);
                }
                this->is_initialized = false;
            }
        }
    };

    static SofaContainer sofaContainer;

    static void deinterleaveData(float* in, float* out, int len, int num_ch) {
        for (int ch = 0; ch < num_ch; ++ch) {
            int offset = ch * len;
            for (int i = 0; i < len; ++i) {
                out[offset + i] = in[ch + i*2];
            }
        }
    }

    static void interleaveData(float* in, float* out, int len, int num_ch) {
        for (int ch = 0; ch < num_ch; ++ch) {
            int offset = ch * len;
            for (int i = 0; i < len; ++i) {
                out[ch + i*2] = in[offset + i];
            }
        }
    }

    /////////////////////////////////////////
    /// plugin logic
    ///////////////////////////////////////

    // Use an enum for the plugin parameters
    // we want Unity to have access to
    // By default, Unity manipulates exposed
    // parameters with a slider in the editor
    enum Param
    {
        P_GAIN,
        P_NUM
        // Since enum values start at 0, the last value
        // gives us the total number of parameters in the enum
        // However, we don't use it as an actual parameter
    };

    // This is a callback we'll have the SDK invoke when initializing parameters
    // Instantiate the parameter details here
    int InternalRegisterEffectDefinition(UnityAudioEffectDefinition& definition)
    {
        definition.paramdefs = new UnityAudioParameterDefinition [P_NUM];
        RegisterParameter(definition,        // EffectDefinition object passed to us
                          "Gain Multiplier", // The parameter label shown in the Unity editor
                          "",                // The units (ex. dB, Hz, cm, s, etc)
                          0.0f,              // Minimum parameter value
                          10.0f,             // Maximum parameter value
                          1.0f,              // Default parameter value
                          1.0f,              // Display scale, Unity editor shows actualValue*displayScale
                          1.0f,              // Display exponent, in case you want a slider operating on an exponential scale in the editor
                          P_GAIN);           // The index of the parameter in question; use the enum value
        definition.flags |= UnityAudioEffectDefinitionFlags_IsSpatializer;
        return P_NUM;
    }

    // Define a struct that will hold the plugin's state
    // Our noise plugin is very simple, so we're only interested
    // in keeping track of the single parameter we have: gain
    struct EffectData
    {
        float p[P_NUM]; // Parameters
    };

    // UNITY_AUDIODSP_RESULT is defined as `int`
    // UNITY_AUDIODSP_CALLBACK is defined as nothing
    // So behind the scenes, the function signature is really `int CreateCallback(UnityAudioEffectState* state)`
    // This callback is invoked by Unity when the plugin is loaded
    UNITY_AUDIODSP_RESULT UNITY_AUDIODSP_CALLBACK CreateCallback(UnityAudioEffectState* state)
    {
        EffectData* data = new EffectData;    // Create a new pointer to the struct defined earlier
        memset(data, 0, sizeof(EffectData));  // Quickly fill memory location with zeros
        data->p[P_GAIN] = 1.0;                // Initialize effectdata with default parameter value(s)
        InitParametersFromDefinitions(InternalRegisterEffectDefinition, data->p);

        // Add our effectdata pointer to the state so we can reach it in other callbacks
        state->effectdata = data;

        sofaContainer.init(state->samplerate, state->dspbuffersize);
        return UNITY_AUDIODSP_OK;
    }

    // This callback is invoked by Unity when the plugin is unloaded
    UNITY_AUDIODSP_RESULT UNITY_AUDIODSP_CALLBACK ReleaseCallback(UnityAudioEffectState* state)
    {
        //sofaContainer.free();

        // Grab the EffectData pointer we added earlier in CreateCallback
        EffectData *data = state->GetEffectData<EffectData>();
        delete data; // Cleanup
        return UNITY_AUDIODSP_OK;
    }

    /////////////////////////////////////////
    /// Soundprocessing
    ///////////////////////////////////////

    // ProcessCallback gets called as long as the plugin is loaded
    // This includes when the editor is not in play mode!
    UNITY_AUDIODSP_RESULT UNITY_AUDIODSP_CALLBACK ProcessCallback(
            UnityAudioEffectState* state, // The state gets passed into all callbacks
            float* inbuffer,              // Plugins can be chained together; inbuffer holds the signal incoming from another plugin, or an AudioSource
            float* outbuffer,             // We fill outbuffer with the signal Unity should send to the speakers
            unsigned int length,          // The number of samples the buffers hold
            int inchannels,               // The number of channels the incoming signal uses
            int outchannels)              // The number of channels the outgoing signal uses
    {
        if (!sofaContainer.is_initialized) {
            memcpy(outbuffer, inbuffer, length * outchannels * sizeof(float));
            return UNITY_AUDIODSP_OK;
        }

        auto data = state->GetEffectData<EffectData>();
        if (sofaContainer.last != data->p[P_GAIN]) {
            unsigned i = rand() % sofaContainer.hrtfs[0]->R;
            sofaContainer.setIr(i);

            sofaContainer.last = i;
            data->p[P_GAIN] = i;
        };

        float in_deinterleaved[length * inchannels];
        float out_deinterleaved[length * inchannels];
        deinterleaveData(inbuffer, in_deinterleaved, length, inchannels);
        (*sofaContainer.convolver[0]).process(&in_deinterleaved[0], &out_deinterleaved[0], length); // left channel
        (*sofaContainer.convolver[1]).process(&in_deinterleaved[length], &out_deinterleaved[length], length); // right channel
        interleaveData(out_deinterleaved, outbuffer, length, outchannels);

        return UNITY_AUDIODSP_OK;
    }

    /////////////////////////////////////////
    /// editor parameter manipulation
    ///////////////////////////////////////

    // Called whenever a parameter is changed from the editor
    UNITY_AUDIODSP_RESULT UNITY_AUDIODSP_CALLBACK SetFloatParameterCallback(UnityAudioEffectState* state, int index, float value)
    {
        EffectData *data = state->GetEffectData<EffectData>(); // Grab EffectData
        // index should never point to a parameter that we haven't defined
        if (index >= P_NUM) {
            return UNITY_AUDIODSP_ERR_UNSUPPORTED;
        }
        data->p[index] = value; // Set the parameter to the value the editor gave us

        return UNITY_AUDIODSP_OK;
    }

    // Internally used by the SDK to query parameter values, not sure when this is called...
    UNITY_AUDIODSP_RESULT UNITY_AUDIODSP_CALLBACK GetFloatParameterCallback(UnityAudioEffectState* state, int index, float* value, char *valuestr)
    {
        EffectData *data = state->GetEffectData<EffectData>();
        if (index >= P_NUM) {
            return UNITY_AUDIODSP_ERR_UNSUPPORTED;
        }
        if (value != NULL) {
            *value = data->p[index];
        }
        if (valuestr != NULL) {
            valuestr[0] = 0;
        }
        return UNITY_AUDIODSP_OK;
    }

    // Also unsure where this is used, but it's required to be defined, so just return from the function as soon as it's called
    int UNITY_AUDIODSP_CALLBACK GetFloatBufferCallback(UnityAudioEffectState* state, const char* name, float* buffer, int numsamples)
    {
        return UNITY_AUDIODSP_OK;
    }
}<commit_msg>fix memory leak<commit_after>#include "AudioPluginUtil.h"
#include "FFTConvolver/FFTConvolver.h"
#include "FFTConvolver/TwoStageFFTConvolver.h"

#include <utility>

#include <mysofa.h>

//#include <ATK/Special/ConvolutionFilter.h>

// Our plugin will be encapsulated within a namespace
// This namespace is later used to indicate that we
// want to include this plugin in the build with PluginList.h
namespace Plugin_SofaSpatializer {

    /////////////////////////////////////////
    /// Utilities
    ///////////////////////////////////////

    const unsigned MAX_SOFA_FILES = 1;
    const unsigned CONVOLVERS = 2;

    class SofaContainer {
    public:
        MYSOFA_HRTF* hrtfs[MAX_SOFA_FILES];
        bool is_initialized = false;

        void init(unsigned samplerate) {
            if (!is_initialized) {
                int err;

                // load sofa files
                hrtfs[0] = mysofa_load("WIEb_S00_R01.sofa", &err);

                // resample if samplerates doesent match (Warning: long coputationtime!)
                //if (samplerate != hrtfs[0]->DataSamplingRate.values[0]) { mysofa_resample(hrtfs[0], (float)samplerate); }

                this->is_initialized = true;
            }
        }

        void free() {
            if (is_initialized) {
                for (int i = 0; i < sizeof(this->hrtfs)/sizeof(*this->hrtfs); ++i) {
                    mysofa_free(hrtfs[i]);
                }
                this->is_initialized = false;
            }
        }
    };

    static SofaContainer sofaContainer;

    static void deinterleaveData(float* in, float* out, int len, int num_ch) {
        for (int ch = 0; ch < num_ch; ++ch) {
            int offset = ch * len;
            for (int i = 0; i < len; ++i) {
                out[offset + i] = in[ch + i*2];
            }
        }
    }

    static void interleaveData(float* in, float* out, int len, int num_ch) {
        for (int ch = 0; ch < num_ch; ++ch) {
            int offset = ch * len;
            for (int i = 0; i < len; ++i) {
                out[ch + i*2] = in[offset + i];
            }
        }
    }

    /////////////////////////////////////////
    /// plugin logic
    ///////////////////////////////////////

    // Use an enum for the plugin parameters
    // we want Unity to have access to
    // By default, Unity manipulates exposed
    // parameters with a slider in the editor
    enum Param
    {
        P_GAIN,
        P_NUM
        // Since enum values start at 0, the last value
        // gives us the total number of parameters in the enum
        // However, we don't use it as an actual parameter
    };

    // Define a struct that will hold the plugin's state
    // Our noise plugin is very simple, so we're only interested
    // in keeping track of the single parameter we have: gain
    struct EffectData
    {
        float p[P_NUM]; // Parameters
        fftconvolver::FFTConvolver* convolver[CONVOLVERS];
        float last;
    };

    // This is a callback we'll have the SDK invoke when initializing parameters
    // Instantiate the parameter details here
    int InternalRegisterEffectDefinition(UnityAudioEffectDefinition& definition)
    {
        definition.paramdefs = new UnityAudioParameterDefinition [P_NUM];
        RegisterParameter(definition,        // EffectDefinition object passed to us
                          "Gain Multiplier", // The parameter label shown in the Unity editor
                          "",                // The units (ex. dB, Hz, cm, s, etc)
                          0.0f,              // Minimum parameter value
                          10.0f,             // Maximum parameter value
                          1.0f,              // Default parameter value
                          1.0f,              // Display scale, Unity editor shows actualValue*displayScale
                          1.0f,              // Display exponent, in case you want a slider operating on an exponential scale in the editor
                          P_GAIN);           // The index of the parameter in question; use the enum value
        definition.flags |= UnityAudioEffectDefinitionFlags_IsSpatializer;
        return P_NUM;
    }

    // UNITY_AUDIODSP_RESULT is defined as `int`
    // UNITY_AUDIODSP_CALLBACK is defined as nothing
    // So behind the scenes, the function signature is really `int CreateCallback(UnityAudioEffectState* state)`
    // This callback is invoked by Unity when the plugin is loaded
    UNITY_AUDIODSP_RESULT UNITY_AUDIODSP_CALLBACK CreateCallback(UnityAudioEffectState* state)
    {
        EffectData* data = new EffectData;    // Create a new pointer to the struct defined earlier
        memset(data, 0, sizeof(EffectData));  // Quickly fill memory location with zeros
        data->p[P_GAIN] = 1.0;                // Initialize effectdata with default parameter value(s)
        InitParametersFromDefinitions(InternalRegisterEffectDefinition, data->p);

        sofaContainer.init(state->samplerate);
        auto const len = sofaContainer.hrtfs[0]->N;
        for (int i = 0; i < CONVOLVERS; ++i) {
            data->convolver[i] = new fftconvolver::FFTConvolver();
            data->convolver[i]->init(state->dspbuffersize, &sofaContainer.hrtfs[0]->DataIR.values[len * i], len);
        }

        // Add our effectdata pointer to the state so we can reach it in other callbacks
        state->effectdata = data;

        return UNITY_AUDIODSP_OK;
    }

    // This callback is invoked by Unity when the plugin is unloaded
    UNITY_AUDIODSP_RESULT UNITY_AUDIODSP_CALLBACK ReleaseCallback(UnityAudioEffectState* state)
    {
        //sofaContainer.free();

        // Grab the EffectData pointer we added earlier in CreateCallback
        EffectData *data = state->GetEffectData<EffectData>();
        delete data; // Cleanup
        return UNITY_AUDIODSP_OK;
    }

    /////////////////////////////////////////
    /// Soundprocessing
    ///////////////////////////////////////

    // ProcessCallback gets called as long as the plugin is loaded
    // This includes when the editor is not in play mode!
    UNITY_AUDIODSP_RESULT UNITY_AUDIODSP_CALLBACK ProcessCallback(
            UnityAudioEffectState* state, // The state gets passed into all callbacks
            float* inbuffer,              // Plugins can be chained together; inbuffer holds the signal incoming from another plugin, or an AudioSource
            float* outbuffer,             // We fill outbuffer with the signal Unity should send to the speakers
            unsigned int length,          // The number of samples the buffers hold
            int inchannels,               // The number of channels the incoming signal uses
            int outchannels)              // The number of channels the outgoing signal uses
    {
        if (!sofaContainer.is_initialized) {
            memcpy(outbuffer, inbuffer, length * outchannels * sizeof(float));
            return UNITY_AUDIODSP_OK;
        }

        auto data = state->GetEffectData<EffectData>();
        if (data->last != data->p[P_GAIN]) {
            unsigned rnd = rand() % sofaContainer.hrtfs[0]->R;
            auto const len = sofaContainer.hrtfs[0]->N;
            for (int i = 0; rnd < CONVOLVERS; ++rnd) {
                data->convolver[rnd]->init(state->dspbuffersize, &sofaContainer.hrtfs[0]->DataIR.values[len * rnd], len);
            }
            data->last = rnd;
            data->p[P_GAIN] = rnd;
        };

        float in_deinterleaved[length * inchannels];
        float out_deinterleaved[length * inchannels];
        deinterleaveData(inbuffer, in_deinterleaved, length, inchannels);
        // left channel
        (*data->convolver[0]).process(&in_deinterleaved[0], &out_deinterleaved[0], length);
        // right channel
        (*data->convolver[1]).process(&in_deinterleaved[length], &out_deinterleaved[length], length);
        interleaveData(out_deinterleaved, outbuffer, length, outchannels);

        return UNITY_AUDIODSP_OK;
    }

    /////////////////////////////////////////
    /// editor parameter manipulation
    ///////////////////////////////////////

    // Called whenever a parameter is changed from the editor
    UNITY_AUDIODSP_RESULT UNITY_AUDIODSP_CALLBACK SetFloatParameterCallback(UnityAudioEffectState* state, int index, float value)
    {
        EffectData *data = state->GetEffectData<EffectData>(); // Grab EffectData
        // index should never point to a parameter that we haven't defined
        if (index >= P_NUM) {
            return UNITY_AUDIODSP_ERR_UNSUPPORTED;
        }
        data->p[index] = value; // Set the parameter to the value the editor gave us

        return UNITY_AUDIODSP_OK;
    }

    // Internally used by the SDK to query parameter values, not sure when this is called...
    UNITY_AUDIODSP_RESULT UNITY_AUDIODSP_CALLBACK GetFloatParameterCallback(UnityAudioEffectState* state, int index, float* value, char *valuestr)
    {
        EffectData *data = state->GetEffectData<EffectData>();
        if (index >= P_NUM) {
            return UNITY_AUDIODSP_ERR_UNSUPPORTED;
        }
        if (value != NULL) {
            *value = data->p[index];
        }
        if (valuestr != NULL) {
            valuestr[0] = 0;
        }
        return UNITY_AUDIODSP_OK;
    }

    // Also unsure where this is used, but it's required to be defined, so just return from the function as soon as it's called
    int UNITY_AUDIODSP_CALLBACK GetFloatBufferCallback(UnityAudioEffectState* state, const char* name, float* buffer, int numsamples)
    {
        return UNITY_AUDIODSP_OK;
    }
}<|endoftext|>


<commit_before>#include "ghost/config.h"
#include "ghost/types.h"
#include "ghost/densemat.h"
#include "ghost/util.h"
#include "ghost/math.h"
#include "ghost/tsmttsm.h"
#include "ghost/tsmttsm_gen.h"
#include "ghost/tsmttsm_avx_gen.h"

#include <map>

using namespace std;

static bool operator<(const ghost_tsmttsm_parameters_t &a, const ghost_tsmttsm_parameters_t &b)
{
    return ghost_hash(a.dt,a.wcols,ghost_hash(a.vcols,a.impl,0)) < ghost_hash(b.dt,b.wcols,ghost_hash(b.vcols,b.impl,0));
}

static map<ghost_tsmttsm_parameters_t, ghost_tsmttsm_kernel_t> ghost_tsmttsm_kernels;

ghost_error_t ghost_tsmttsm_valid(ghost_densemat_t *x, ghost_densemat_t *v, const char * transv,
ghost_densemat_t *w, const char *transw, void *alpha, void *beta, int reduce, int printerror)
{
    if (w->traits.storage != GHOST_DENSEMAT_ROWMAJOR) {
        if (printerror) {
            ERROR_LOG("w must be stored row-major!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (v->traits.storage != GHOST_DENSEMAT_ROWMAJOR) {
        if (printerror) {
            ERROR_LOG("v must be stored row-major!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (x->traits.storage != GHOST_DENSEMAT_COLMAJOR) {
        if (printerror) {
            ERROR_LOG("x must be stored col-major!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (v->traits.datatype != w->traits.datatype || v->traits.datatype != x->traits.datatype) {
        if (printerror) {
            ERROR_LOG("Different data types!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (v->traits.flags & GHOST_DENSEMAT_SCATTERED || w->traits.flags & GHOST_DENSEMAT_SCATTERED || x->traits.flags & GHOST_DENSEMAT_SCATTERED) {
        if (printerror) {
            ERROR_LOG("Scattered densemats not supported!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (reduce != GHOST_GEMM_ALL_REDUCE) {
        if (printerror) {
            ERROR_LOG("Only Allreduce supported currently!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (!strncasecmp(transv,"N",1)) {
        if (printerror) {
            ERROR_LOG("v must be transposed!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (strncasecmp(transw,"N",1)) {
        if (printerror) {
            ERROR_LOG("w must not be transposed!");
        }
        return GHOST_ERR_INVALID_ARG;
    }

    UNUSED(alpha);
    UNUSED(beta);

    return GHOST_SUCCESS;
}

ghost_error_t ghost_tsmttsm(ghost_densemat_t *x, ghost_densemat_t *v, ghost_densemat_t *w, void *alpha, void *beta,int reduce,int conjv)
{
    GHOST_FUNC_ENTER(GHOST_FUNCTYPE_MATH);
    ghost_error_t ret;

    if ((ret = ghost_tsmttsm_valid(x,v,"T",w,"N",alpha,beta,reduce,1)) != GHOST_SUCCESS) {
        return ret;
    }

    if (ghost_tsmttsm_kernels.empty()) {
#include "tsmttsm.def"
#include "tsmttsm_avx.def"
    }

    ghost_tsmttsm_parameters_t p;
    ghost_tsmttsm_kernel_t kernel = NULL;

#ifdef GHOST_HAVE_MIC
    p.impl = GHOST_IMPLEMENTATION_MIC;
#elif defined(GHOST_HAVE_AVX)
    p.impl = GHOST_IMPLEMENTATION_AVX;
#elif defined(GHOST_HAVE_SSE)
    p.impl = GHOST_IMPLEMENTATION_SSE;
#else
    p.impl = GHOST_IMPLEMENTATION_PLAIN;
#endif

    /*if (x->traits.ncolspadded < 4 || x->traits.flags & GHOST_DENSEMAT_VIEW) {
        p.impl = GHOST_IMPLEMENTATION_PLAIN;
    }*/

    p.dt = x->traits.datatype;

    p.vcols = v->traits.ncols;
    p.wcols = w->traits.ncols;

    if (p.vcols % 4 || p.wcols % 4) {
        PERFWARNING_LOG("Use plain for non-multiple of four");
        p.impl = GHOST_IMPLEMENTATION_PLAIN;
    }

    kernel = ghost_tsmttsm_kernels[p];

    if (!kernel) {
        PERFWARNING_LOG("Try kernel with arbitrary wcols");
        p.wcols = -1;
        p.vcols = v->traits.ncols;
        kernel = ghost_tsmttsm_kernels[p];
    }

    if (!kernel) {
        PERFWARNING_LOG("Try kernel with arbitrary vcols");
        p.wcols = w->traits.ncols;
        p.vcols = -1;
        kernel = ghost_tsmttsm_kernels[p];
    }

    if (!kernel) {
        PERFWARNING_LOG("Try kernel with arbitrary block sizes");
        p.wcols = -1;
        p.vcols = -1;
        kernel = ghost_tsmttsm_kernels[p];
    }

    if (!kernel) {
        PERFWARNING_LOG("Try plain implementation");
        p.impl = GHOST_IMPLEMENTATION_PLAIN;
    }
    kernel = ghost_tsmttsm_kernels[p];

    if (!kernel) {
        INFO_LOG("Could not find TSMTTSM kernel with %d %d %d. Fallback to GEMM",p.dt,p.wcols,p.vcols);
        return GHOST_ERR_INVALID_ARG;

            //return ghost_gemm(x,v,"T",w,"N",alpha,beta,GHOST_GEMM_ALL_REDUCE,GHOST_GEMM_NOT_SPECIAL);
    }

    ret = kernel(x,v,w,alpha,beta,conjv);

#ifdef GHOST_HAVE_INSTR_TIMING
    ghost_gemm_perf_args_t tsmttsm_perfargs;
    tsmttsm_perfargs.xcols = p.wcols;
    tsmttsm_perfargs.vcols = p.vcols;
    if (v->context) {
        tsmttsm_perfargs.vrows = v->context->gnrows;
    } else {
        tsmttsm_perfargs.vrows = v->traits.nrows;
    }
    tsmttsm_perfargs.dt = x->traits.datatype;
    ghost_timing_set_perfFunc(__ghost_functag,ghost_gemm_perf_GFs,(void *)&tsmttsm_perfargs,sizeof(tsmttsm_perfargs),"GF/s");
#endif

    GHOST_FUNC_EXIT(GHOST_FUNCTYPE_MATH);

    return ret;
}

<commit_msg>try fixed block sizes again after fallback to plain implementation<commit_after>#include "ghost/config.h"
#include "ghost/types.h"
#include "ghost/densemat.h"
#include "ghost/util.h"
#include "ghost/math.h"
#include "ghost/tsmttsm.h"
#include "ghost/tsmttsm_gen.h"
#include "ghost/tsmttsm_avx_gen.h"

#include <map>

using namespace std;

static bool operator<(const ghost_tsmttsm_parameters_t &a, const ghost_tsmttsm_parameters_t &b)
{
    return ghost_hash(a.dt,a.wcols,ghost_hash(a.vcols,a.impl,0)) < ghost_hash(b.dt,b.wcols,ghost_hash(b.vcols,b.impl,0));
}

static map<ghost_tsmttsm_parameters_t, ghost_tsmttsm_kernel_t> ghost_tsmttsm_kernels;

ghost_error_t ghost_tsmttsm_valid(ghost_densemat_t *x, ghost_densemat_t *v, const char * transv,
ghost_densemat_t *w, const char *transw, void *alpha, void *beta, int reduce, int printerror)
{
    if (w->traits.storage != GHOST_DENSEMAT_ROWMAJOR) {
        if (printerror) {
            ERROR_LOG("w must be stored row-major!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (v->traits.storage != GHOST_DENSEMAT_ROWMAJOR) {
        if (printerror) {
            ERROR_LOG("v must be stored row-major!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (x->traits.storage != GHOST_DENSEMAT_COLMAJOR) {
        if (printerror) {
            ERROR_LOG("x must be stored col-major!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (v->traits.datatype != w->traits.datatype || v->traits.datatype != x->traits.datatype) {
        if (printerror) {
            ERROR_LOG("Different data types!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (v->traits.flags & GHOST_DENSEMAT_SCATTERED || w->traits.flags & GHOST_DENSEMAT_SCATTERED || x->traits.flags & GHOST_DENSEMAT_SCATTERED) {
        if (printerror) {
            ERROR_LOG("Scattered densemats not supported!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (reduce != GHOST_GEMM_ALL_REDUCE) {
        if (printerror) {
            ERROR_LOG("Only Allreduce supported currently!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (!strncasecmp(transv,"N",1)) {
        if (printerror) {
            ERROR_LOG("v must be transposed!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (strncasecmp(transw,"N",1)) {
        if (printerror) {
            ERROR_LOG("w must not be transposed!");
        }
        return GHOST_ERR_INVALID_ARG;
    }

    UNUSED(alpha);
    UNUSED(beta);

    return GHOST_SUCCESS;
}

ghost_error_t ghost_tsmttsm(ghost_densemat_t *x, ghost_densemat_t *v, ghost_densemat_t *w, void *alpha, void *beta,int reduce,int conjv)
{
    GHOST_FUNC_ENTER(GHOST_FUNCTYPE_MATH);
    ghost_error_t ret;

    if ((ret = ghost_tsmttsm_valid(x,v,"T",w,"N",alpha,beta,reduce,1)) != GHOST_SUCCESS) {
        return ret;
    }

    if (ghost_tsmttsm_kernels.empty()) {
#include "tsmttsm.def"
#include "tsmttsm_avx.def"
    }

    ghost_tsmttsm_parameters_t p;
    ghost_tsmttsm_kernel_t kernel = NULL;

#ifdef GHOST_HAVE_MIC
    p.impl = GHOST_IMPLEMENTATION_MIC;
#elif defined(GHOST_HAVE_AVX)
    p.impl = GHOST_IMPLEMENTATION_AVX;
#elif defined(GHOST_HAVE_SSE)
    p.impl = GHOST_IMPLEMENTATION_SSE;
#else
    p.impl = GHOST_IMPLEMENTATION_PLAIN;
#endif

    /*if (x->traits.ncolspadded < 4 || x->traits.flags & GHOST_DENSEMAT_VIEW) {
        p.impl = GHOST_IMPLEMENTATION_PLAIN;
    }*/

    p.dt = x->traits.datatype;

    p.vcols = v->traits.ncols;
    p.wcols = w->traits.ncols;

    if (p.vcols % 4 || p.wcols % 4) {
        PERFWARNING_LOG("Use plain for non-multiple of four");
        p.impl = GHOST_IMPLEMENTATION_PLAIN;
    }

    kernel = ghost_tsmttsm_kernels[p];

    if (!kernel) {
        PERFWARNING_LOG("Try kernel with arbitrary wcols");
        p.wcols = -1;
        p.vcols = v->traits.ncols;
        kernel = ghost_tsmttsm_kernels[p];
    }

    if (!kernel) {
        PERFWARNING_LOG("Try kernel with arbitrary vcols");
        p.wcols = w->traits.ncols;
        p.vcols = -1;
        kernel = ghost_tsmttsm_kernels[p];
    }

    if (!kernel) {
        PERFWARNING_LOG("Try kernel with arbitrary block sizes");
        p.wcols = -1;
        p.vcols = -1;
        kernel = ghost_tsmttsm_kernels[p];
    }

    if (!kernel) {
        PERFWARNING_LOG("Try plain implementation");
        p.impl = GHOST_IMPLEMENTATION_PLAIN;
        p.vcols = v->traits.ncols;
        p.wcols = w->traits.ncols;
        kernel = ghost_tsmttsm_kernels[p];
    }

    if (!kernel) {
        PERFWARNING_LOG("Try kernel with arbitrary wcols");
        p.wcols = -1;
        p.vcols = v->traits.ncols;
        kernel = ghost_tsmttsm_kernels[p];
    }

    if (!kernel) {
        PERFWARNING_LOG("Try kernel with arbitrary vcols");
        p.wcols = w->traits.ncols;
        p.vcols = -1;
        kernel = ghost_tsmttsm_kernels[p];
    }

    if (!kernel) {
        PERFWARNING_LOG("Try kernel with arbitrary block sizes");
        p.wcols = -1;
        p.vcols = -1;
        kernel = ghost_tsmttsm_kernels[p];
    }

    if (!kernel) {
        INFO_LOG("Could not find TSMTTSM kernel with %d %d %d. Fallback to GEMM",p.dt,p.wcols,p.vcols);
        return GHOST_ERR_INVALID_ARG;

            //return ghost_gemm(x,v,"T",w,"N",alpha,beta,GHOST_GEMM_ALL_REDUCE,GHOST_GEMM_NOT_SPECIAL);
    }

    ret = kernel(x,v,w,alpha,beta,conjv);

#ifdef GHOST_HAVE_INSTR_TIMING
    ghost_gemm_perf_args_t tsmttsm_perfargs;
    tsmttsm_perfargs.xcols = p.wcols;
    tsmttsm_perfargs.vcols = p.vcols;
    if (v->context) {
        tsmttsm_perfargs.vrows = v->context->gnrows;
    } else {
        tsmttsm_perfargs.vrows = v->traits.nrows;
    }
    tsmttsm_perfargs.dt = x->traits.datatype;
    ghost_timing_set_perfFunc(__ghost_functag,ghost_gemm_perf_GFs,(void *)&tsmttsm_perfargs,sizeof(tsmttsm_perfargs),"GF/s");
#endif

    GHOST_FUNC_EXIT(GHOST_FUNCTYPE_MATH);

    return ret;
}

<|endoftext|>


<commit_before>// -*-c++-*-

#include <osgProducer/Viewer>

#include <osgDB/ReadFile>

#include <osg/Geode>
#include <osg/Geometry>
#include <osg/StateSet>
#include <osg/Material>
#include <osg/Texture2D>
#include <osg/TextureRectangle>
#include <osg/TexMat>
#include <osg/CullFace>

#include <osgGA/TrackballManipulator>

osg::Geometry* createTexturedQuadGeometry(const osg::Vec3& pos,float width,float height, osg::Image* image)
{
    bool useTextureRectangle = true;
    if (useTextureRectangle)
    {
        osg::Geometry* pictureQuad = osg::createTexturedQuadGeometry(pos,
                                           osg::Vec3(width,0.0f,0.0f),
                                           osg::Vec3(0.0f,0.0f,height),
                                           image->s(),image->t());

        pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0,
                    new osg::TextureRectangle(image),
                    osg::StateAttribute::ON);

        return pictureQuad;
    }
    else
    {
        osg::Geometry* pictureQuad = osg::createTexturedQuadGeometry(pos,
                                           osg::Vec3(width,0.0f,0.0f),
                                           osg::Vec3(0.0f,0.0f,height),
                                           1.0f,1.0f);

        pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0,
                    new osg::Texture2D(image),
                    osg::StateAttribute::ON);

        return pictureQuad;
    }
}

int main(int argc, char** argv)
{
    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    // set up the usage document, in case we need to print out how to use this program.
    arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the standard OpenSceneGraph example which loads and visualises 3d models.");
    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");

    // construct the viewer.
    osgProducer::Viewer viewer(arguments);

    // set up the value with sensible default event handlers.
    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);

    // get details on keyboard and mouse bindings used by the viewer.
    viewer.getUsage(*arguments.getApplicationUsage());

    // if user request help write it out to cout.
    if (arguments.read("-h") || arguments.read("--help"))
    {
        arguments.getApplicationUsage()->write(std::cout);
        return 1;
    }

    osg::Geode* geode = new osg::Geode;
    osg::Vec3 pos(0.0f,0.0f,0.0f);

    for(int i=1;i<arguments.argc();++i)
    {
        if (arguments.isString(i))
        {
            osg::Image* image = osgDB::readImageFile(arguments[i]);
            geode->addDrawable(createTexturedQuadGeometry(pos,image->s(),image->t(),image));
        }

    }

    // report any errors if they have occured when parsing the program aguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
        return 1;
    }

    if (arguments.argc()<=1)
    {
        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
        return 1;
    }

    // any option left unread are converted into errors to write out later.
    arguments.reportRemainingOptionsAsUnrecognized();

    // report any errors if they have occured when parsing the program aguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
    }

    // set the scene to render
    viewer.setSceneData(geode);

    // create the windows and run the threads.
    viewer.realize();

    while( !viewer.done() )
    {
        // wait for all cull and draw threads to complete.
        viewer.sync();

        // update the scene by traversing it with the the update visitor which will
        // call all node update callbacks and animations.
        viewer.update();

        // fire off the cull and draw traversals of the scene.
        viewer.frame();

    }

    // wait for all cull and draw threads to complete before exit.
    viewer.sync();

    return 0;

}
<commit_msg>Added some basic event handler.<commit_after>// -*-c++-*-

#include <osgProducer/Viewer>

#include <osgDB/ReadFile>

#include <osg/Geode>
#include <osg/Geometry>
#include <osg/StateSet>
#include <osg/Material>
#include <osg/Texture2D>
#include <osg/TextureRectangle>
#include <osg/TexMat>
#include <osg/CullFace>
#include <osg/ImageStream>

#include <osgGA/TrackballManipulator>

class MovieEventHandler : public osgGA::GUIEventHandler
{
public:

    MovieEventHandler() {}

    void set(osg::Node* node);

    virtual void accept(osgGA::GUIEventHandlerVisitor& v) { v.visit(*this); }

    virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&);

    virtual void getUsage(osg::ApplicationUsage& usage) const;

    typedef std::vector< osg::ref_ptr<osg::ImageStream> > ImageStreamList;

protected:

    virtual ~MovieEventHandler() {}

    class FindImageStreamsVisitor : public osg::NodeVisitor
    {
    public:
        FindImageStreamsVisitor(ImageStreamList& imageStreamList):
            _imageStreamList(imageStreamList) {}

        virtual void apply(osg::Geode& geode)
        {
            apply(geode.getStateSet());

            for(unsigned int i=0;i<geode.getNumDrawables();++i)
            {
                apply(geode.getDrawable(i)->getStateSet());
            }

            traverse(geode);
        }

        virtual void apply(osg::Node& node)
        {
            apply(node.getStateSet());
            traverse(node);
        }

        inline void apply(osg::StateSet* stateset)
        {
            if (!stateset) return;

            osg::StateAttribute* attr = stateset->getTextureAttribute(0,osg::StateAttribute::TEXTURE);
            if (attr)
            {
                osg::Texture2D* texture2D = dynamic_cast<osg::Texture2D*>(attr);
                if (texture2D) apply(dynamic_cast<osg::ImageStream*>(texture2D->getImage()));

                osg::TextureRectangle* textureRec = dynamic_cast<osg::TextureRectangle*>(attr);
                if (textureRec) apply(dynamic_cast<osg::ImageStream*>(textureRec->getImage()));
            }
        }

        inline void apply(osg::ImageStream* imagestream)
        {
            if (imagestream) _imageStreamList.push_back(imagestream);
        }

        ImageStreamList& _imageStreamList;
    };

    ImageStreamList _imageStreamList;

};

void MovieEventHandler::set(osg::Node* node)
{
    _imageStreamList.clear();
    if (node)
    {
        FindImageStreamsVisitor fisv(_imageStreamList);
        node->accept(fisv);
    }
}

bool MovieEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&)
{
    switch(ea.getEventType())
    {
        case(osgGA::GUIEventAdapter::KEYDOWN):
        {
            if (ea.getKey()=='s')
            {
                for(ImageStreamList::iterator itr=_imageStreamList.begin();
                    itr!=_imageStreamList.end();
                    ++itr)
                {
                    std::cout<<"Play"<<std::endl;
                     (*itr)->play();
                }
                return true;
            }
            else if (ea.getKey()=='p')
            {
                for(ImageStreamList::iterator itr=_imageStreamList.begin();
                    itr!=_imageStreamList.end();
                    ++itr)
                {
                    std::cout<<"Pause"<<std::endl;
                    (*itr)->pause();
                }
                return true;
            }
            else if (ea.getKey()=='r')
            {
                return true;
            }
            else if (ea.getKey()=='l')
            {
                return true;
            }
            return false;
        }

        default:
            return false;
    }
}

void MovieEventHandler::getUsage(osg::ApplicationUsage& usage) const
{
    usage.addKeyboardMouseBinding("p","Pause movie");
    usage.addKeyboardMouseBinding("s","Play movie");
    usage.addKeyboardMouseBinding("r","Start movie");
    usage.addKeyboardMouseBinding("l","Toggle looping of movie");
}

osg::Geometry* createTexturedQuadGeometry(const osg::Vec3& pos,float width,float height, osg::Image* image)
{
    bool useTextureRectangle = true;
    if (useTextureRectangle)
    {
        osg::Geometry* pictureQuad = osg::createTexturedQuadGeometry(pos,
                                           osg::Vec3(width,0.0f,0.0f),
                                           osg::Vec3(0.0f,0.0f,height),
                                           image->s(),image->t());

        pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0,
                    new osg::TextureRectangle(image),
                    osg::StateAttribute::ON);

        return pictureQuad;
    }
    else
    {
        osg::Geometry* pictureQuad = osg::createTexturedQuadGeometry(pos,
                                           osg::Vec3(width,0.0f,0.0f),
                                           osg::Vec3(0.0f,0.0f,height),
                                           1.0f,1.0f);

        pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0,
                    new osg::Texture2D(image),
                    osg::StateAttribute::ON);

        return pictureQuad;
    }
}

int main(int argc, char** argv)
{
    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    // set up the usage document, in case we need to print out how to use this program.
    arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the standard OpenSceneGraph example which loads and visualises 3d models.");
    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");

    // construct the viewer.
    osgProducer::Viewer viewer(arguments);

    // set up the value with sensible default event handlers.
    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);

    // register the handler to add keyboard and mosue handling.
    MovieEventHandler* meh = new MovieEventHandler();
    viewer.getEventHandlerList().push_front(meh);

    // get details on keyboard and mouse bindings used by the viewer.
    viewer.getUsage(*arguments.getApplicationUsage());

    // if user request help write it out to cout.
    if (arguments.read("-h") || arguments.read("--help"))
    {
        arguments.getApplicationUsage()->write(std::cout);
        return 1;
    }

    osg::Geode* geode = new osg::Geode;
    osg::Vec3 pos(0.0f,0.0f,0.0f);

    for(int i=1;i<arguments.argc();++i)
    {
        if (arguments.isString(i))
        {
            osg::Image* image = osgDB::readImageFile(arguments[i]);
            geode->addDrawable(createTexturedQuadGeometry(pos,image->s(),image->t(),image));
        }

    }

    // pass the model to the MovieEventHandler so it can pick out ImageStream's to manipulate.
    meh->set(geode);

    // report any errors if they have occured when parsing the program aguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
        return 1;
    }

    if (arguments.argc()<=1)
    {
        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
        return 1;
    }

    // any option left unread are converted into errors to write out later.
    arguments.reportRemainingOptionsAsUnrecognized();

    // report any errors if they have occured when parsing the program aguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
    }

    // set the scene to render
    viewer.setSceneData(geode);

    // create the windows and run the threads.
    viewer.realize();

    while( !viewer.done() )
    {
        // wait for all cull and draw threads to complete.
        viewer.sync();

        // update the scene by traversing it with the the update visitor which will
        // call all node update callbacks and animations.
        viewer.update();

        // fire off the cull and draw traversals of the scene.
        viewer.frame();

    }

    // wait for all cull and draw threads to complete before exit.
    viewer.sync();

    return 0;

}
<|endoftext|>


<commit_before>#include<stdio.h>
#include<malloc.h>
#define ERROR 0
#define OK 1
#define ElemType int

typedef int Status;
typedef struct LNode
{
 int data;
 struct LNode *next;
}LNode,*LinkList;

int CreateLink_L(LinkList &L,int n){
// 创建含有n个元素的单链表
  LinkList p,q;
  int i;
  ElemType e;
  L = (LinkList)malloc(sizeof(LNode));
  L->next = NULL;              // 先建立一个带头结点的单链表
  q = (LinkList)malloc(sizeof(LNode));
  q = L;
  for (i=0; i<n; i++) {
   scanf("%d", &e);
    p = (LinkList)malloc(sizeof(LNode));
    p->next=NULL;  // 生成新结点
    q->next=p;
    p->data=e;
    q=p;

  }
  return OK;
}

int LoadLink_L(LinkList &L,char * name){
// 单链表遍历
 LinkList p = L->next;
 if(p==NULL)printf("The List is empty!"); // 请填空
 else
 {
   printf("List %s:",name);
   while(p)    // 请填空
   {
    printf("%d ",p->data);
    p=p->next;   // 请填空
   }
 }
 printf("\n");
 return OK;
}

Status ListInsert_L(LinkList &L, int i, ElemType e) {  // 算法2.9
  // 在带头结点的单链线性表L的第i个元素之前插入元素e
  LinkList p,s;
  p = L;
  int j = 0;
  while (p && j < i-1) {  // 寻找第i-1个结点
    p = p->next;
    ++j;
  }
  if (!p || j > i-1) return ERROR;      // i小于1或者大于表长
  s = (LinkList)malloc(sizeof(LNode));  // 生成新结点
  s->data = e;  s->next = p->next;      // 插入L中
  p->next = s;
  return OK;
} // LinstInsert_L

Status ListDelete_L(LinkList &L, int i, ElemType &e) {  // 算法2.10
  // 在带头结点的单链线性表L中，删除第i个元素，并由e返回其值
  LinkList p,q;
  p = L;
  int j = 0;
  while (p->next && j < i-1) {  // 寻找第i个结点，并令p指向其前趋
    p = p->next;
    ++j;
  }
  if (!(p->next) || j > i-1) return ERROR;  // 删除位置不合理
  q = p->next;
  p->next = q->next;           // 删除并释放结点
  e = q->data;
  free(q);
  return OK;
} // ListDelete_L

Status Linkunion_L(LinkList a,LinkList b,LinkList c){

  LinkList pa,pb,pc;

  pa=a->next,pb=b->next;
  pc=c;
  int i=1;
  while(pa||pb){

    if(pa==NULL)
      {pc->next=pb;return OK;}
    if(pb==NULL)
      {pc->next=pa;return OK;}

    if((pa->data)<(pb->data)){

      pc->next=pa;
      pc=pa;
      pa=pa->next;
    }else
    {
      pc->next=pb;
      pc=pb;
      pb=pb->next;
    }
  }

}

Status Linkturn(LinkList &L){

    LNode * end=NULL,*p,*q,*c;

    p=L->next;

    while(1){
        while(1){
            if(p->next->next==NULL){
                q=p->next;
                p->next=NULL;
                break;
            }

            p=p->next;
        }

        if(end==NULL){
        end=q;
        c=q;
        }else{
        c->next=q;
        c=q;
        }

        if (p==L){
            c->next=p;
            break;}

        p=L;
    }

    L=end;

}
int main(int argc, char const *argv[])
{
   int n,m;

   scanf("%d",&n);
   LinkList A;
   CreateLink_L(A,n);
   LoadLink_L(A,"A");
   Linkturn(A);

  return 0;
}<commit_msg>update uoj8581<commit_after>#include<stdio.h>
#include<malloc.h>
#define ERROR 0
#define OK 1
#define ElemType int

typedef int Status;
typedef struct LNode
{
 int data;
 struct LNode *next;
}LNode,*LinkList;

int CreateLink_L(LinkList &L,int n){
// 创建含有n个元素的单链表
  LinkList p,q;
  int i;
  ElemType e;
  L = (LinkList)malloc(sizeof(LNode));
  L->next = NULL;
  L->data=n;             // 先建立一个带头结点的单链表
  q = (LinkList)malloc(sizeof(LNode));
  q = L;
  for (i=0; i<n; i++) {
   scanf("%d", &e);
    p = (LinkList)malloc(sizeof(LNode));
    p->next=NULL;  // 生成新结点
    q->next=p;
    p->data=e;
    q=p;

  }
  return OK;
}

int LoadLink_L(LinkList &L,char * name){
// 单链表遍历
 LinkList p = L->next;
 if(p==NULL)printf("The List is empty!"); // 请填空
 else
 {
   printf("List %s:",name);
   while(p)    // 请填空
   {
    printf("%d ",p->data);
    p=p->next;   // 请填空
   }
 }
 printf("\n");
 return OK;
}

Status ListInsert_L(LinkList &L, int i, ElemType e) {  // 算法2.9
  // 在带头结点的单链线性表L的第i个元素之前插入元素e
  LinkList p,s;
  p = L;
  int j = 0;
  while (p && j < i-1) {  // 寻找第i-1个结点
    p = p->next;
    ++j;
  }
  if (!p || j > i-1) return ERROR;      // i小于1或者大于表长
  s = (LinkList)malloc(sizeof(LNode));  // 生成新结点
  s->data = e;  s->next = p->next;      // 插入L中
  p->next = s;
  L->data++;
  return OK;
} // LinstInsert_L

Status ListDelete_L(LinkList &L, int i, ElemType &e) {  // 算法2.10
  // 在带头结点的单链线性表L中，删除第i个元素，并由e返回其值
  LinkList p,q;
  p = L;
  int j = 0;
  while (p->next && j < i-1) {  // 寻找第i个结点，并令p指向其前趋
    p = p->next;
    ++j;
  }
  if (!(p->next) || j > i-1) return ERROR;  // 删除位置不合理
  q = p->next;
  p->next = q->next;           // 删除并释放结点
  e = q->data;
  free(q);
  L->data--;
  return OK;
} // ListDelete_L

Status Linkunion_L(LinkList a,LinkList b,LinkList c){

  LinkList pa,pb,pc;

  pa=a->next,pb=b->next;
  pc=c;
  int i=1;
  while(pa||pb){

    if(pa==NULL)
      {pc->next=pb;return OK;}
    if(pb==NULL)
      {pc->next=pa;return OK;}

    if((pa->data)<(pb->data)){

      pc->next=pa;
      pc=pa;
      pa=pa->next;
    }else
    {
      pc->next=pb;
      pc=pb;
      pb=pb->next;
    }
  }

}

Status Linkturn(LinkList &L){

    LinkList out;

    ElemType e;
    while(L->data>0){
    ListDelete_L(L,L->data, ElemType &e) ;

    printf("%d",e);
  }

    for
}
int main(int argc, char const *argv[])
{
   int n,m;

   scanf("%d",&n);
   LinkList A;
   CreateLink_L(A,n);
   LoadLink_L(A,"A");
   Linkturn(A);

  return 0;
}<|endoftext|>


<commit_before>/*
    vcflib C++ library for parsing and manipulating VCF files

    Copyright © 2010-2022 Erik Garrison
    Copyright © 2020-2022 Pjotr Prins

    This software is published under the MIT License. See the LICENSE file.
*/

#include <algorithm>
#include <string>
#include <ranges>
#include <set>
#include <utility>
#include <vector>

#include <getopt.h>
#include <omp.h>

#include "Variant.h"
#include "convert.h"
#include "join.h"
#include "split.h"

using namespace std;
using namespace vcflib;

#define ALLELE_NULL -1
#define ALLELE_NULL2 -200 // large number brings out issues

double convertStrDbl(const string& s) {
    double r;
    convert(s, r);
    return r;
}

void printSummary(char** argv) {
    std::string text = R"(
usage: vcfwave [options] [file]

Realign reference and alternate alleles with WFA, parsing out the primitive alleles
into multiple VCF records. New records have IDs that reference the source record ID.
Genotypes are handled. Deletions generate haploid/missing genotypes at overlapping sites.

options:
    -p, --wf-params PARAMS  use the given BiWFA params (default: 0,19,39,3,81,1)
                            format=match,mismatch,gap1-open,gap1-ext,gap2-open,gap2-ext
    -f, --tag-parsed FLAG   Annotate decomposed records with the source record position
                            (default: ORIGIN).
    -L, --max-length LEN    Do not manipulate records in which either the ALT or
                            REF is longer than LEN (default: unlimited).
    -K, --inv-kmer K        Length of k-mer to use for inversion detection sketching (default: 17).
    -I, --inv-min LEN       Minimum allele length to consider for inverted alignment (default: 64).
    -k, --keep-info         Maintain site and allele-level annotations when decomposing.
                            Note that in many cases, such as multisample VCFs, these won't
                            be valid post-decomposition.  For biallelic loci in single-sample
                            VCFs, they should be usable with caution.
    -t, --threads N         use this many threads for variant decomposition
    -n, --nextgen           next gen mode.
    -d, --debug             debug mode.

Type: transformation
)";

    cerr << text;

    exit(0);
}

int main(int argc, char** argv) {

    bool includePreviousBaseForIndels = true;
    bool useMNPs = true;
    string parseFlag = "ORIGIN";
    string algorithm = "WF";
    string paramString = "0,19,39,3,81,1";
    int maxLength = 0;
    bool keepInfo = false;
    bool keepGeno = false;
    bool useWaveFront = true;
    bool nextGen  = false;
    bool debug    = false;

    int thread_count = 1;
    int inv_sketch_kmer = 17;
    int min_inv_len = 64;

    VariantCallFile variantFile;

    int c;
    while (true) {
        static struct option long_options[] =
            {
                /* These options set a flag. */
                //{"verbose", no_argument,       &verbose_flag, 1},
                {"help", no_argument, 0, 'h'},
                {"wf-params", required_argument, 0, 'p'},
                {"max-length", required_argument, 0, 'L'},
                {"inv-kmer", required_argument, 0, 'K'},
                {"inv-min", required_argument, 0, 'I'},
                {"tag-parsed", required_argument, 0, 'f'},
                {"keep-info", no_argument, 0, 'k'},
                {"keep-geno", no_argument, 0, 'g'},
                {"threads", required_argument, 0, 't'},
                {"nextgen", no_argument, 0, 'n'},
                {"debug", no_argument, 0, 'd'},
                {0, 0, 0, 0}
            };
        /* getopt_long stores the option index here. */
        int option_index = 0;

        c = getopt_long (argc, argv, "ndhkt:L:p:t:K:I:f:",
                         long_options, &option_index);

        if (c == -1)
            break;

        switch (c) {

	    case 'k':
            keepInfo = true;
            break;

	    case 'g':
            keepGeno = true;
            break;

        case 'p':
            paramString = optarg;
            break;

        case 't':
            thread_count = atoi(optarg);
            break;

        case 'n':
            nextGen = true;
            break;

        case 'd':
            debug = true;
            break;

        case 'h':
            printSummary(argv);
            break;

	    case 'f':
            parseFlag = optarg;
            break;

        case 'L':
            maxLength = atoi(optarg);
            break;

        case 'K':
            inv_sketch_kmer = atoi(optarg);
            break;

        case 'I':
            min_inv_len = atoi(optarg);
            break;

        case '?':
            printSummary(argv);
            exit(1);
            break;

        default:
            abort ();
        }
    }

    omp_set_num_threads(thread_count);

    if (optind < argc) {
        string filename = argv[optind];
        variantFile.open(filename);
    } else {
        variantFile.open(std::cin);
    }

    if (!variantFile.is_open()) {
        return 1;
    }

    // parse the alignment parameters
    vector<string> p_str = split(paramString, ',');
    vector<int> p;
    for (auto& s : p_str) { p.push_back(atoi(s.c_str())); }

    auto wfa_params = wavefront_aligner_attr_default;
    wfa_params.memory_mode = wavefront_memory_ultralow; // note this is overridden in Variant.cpp
    wfa_params.distance_metric = gap_affine_2p;
    wfa_params.affine2p_penalties.match = p[0];
    wfa_params.affine2p_penalties.mismatch = p[1];
    wfa_params.affine2p_penalties.gap_opening1 = p[2];
    wfa_params.affine2p_penalties.gap_extension1 = p[3];
    wfa_params.affine2p_penalties.gap_opening2 = p[4];
    wfa_params.affine2p_penalties.gap_extension2 = p[5];
    wfa_params.alignment_scope = compute_alignment;

    variantFile.addHeaderLine("##INFO=<ID=TYPE,Number=A,Type=String,Description=\"The type of allele, either snp, mnp, ins, del, or complex.\">");
    variantFile.addHeaderLine("##INFO=<ID=LEN,Number=A,Type=Integer,Description=\"allele length\">");
    variantFile.addHeaderLine("##INFO=<ID="+parseFlag+",Number=1,Type=String,Description=\"Decomposed from a complex record using vcflib vcfwave and alignment with WFA2-lib.\">");
    variantFile.addHeaderLine("##INFO=<ID=INV,Number=A,Type=String,Description=\"Count of haplotypes which are aligned in the inverted orientation using vcflib vcfwave.\">");
    cout << variantFile.header << endl;

    Variant var(variantFile);
    while (variantFile.getNextVariant(var)) {
        // we can't decompose *1* bp events, these are already in simplest-form whether SNPs or indels
        // we also don't handle anything larger than maxLength bp
        int max_allele_length = 0;
        for (auto allele: var.alt) {
          if (debug) cerr << allele << ":" << allele.length() << "," << max_allele_length << endl;
          if (allele.length() >= max_allele_length) {
             max_allele_length = allele.length();
             // cerr << max_allele_length << endl;
          }
        }

        if ((maxLength && max_allele_length > maxLength) || max_allele_length == 1 ||
            (var.alt.size() == 1 &&
             (var.ref.size() == 1 || (maxLength && var.ref.size() > maxLength)))) {
            // nothing to do
            cout << var << endl;
            continue;
        }

        map<string, pair<vector<VariantAllele>, bool> > varAlleles =
           var.parsedAlternates(includePreviousBaseForIndels, useMNPs,
                                false, // bool useEntropy = false,
                                "",    // string flankingRefLeft = "",
                                "",    // string flankingRefRight = "",
                                &wfa_params,
                                inv_sketch_kmer,
                                min_inv_len,
                                debug);  // bool debug=false

        if (nextGen) {
            // The following section post-process the results of wavefront and
            // updates AC, AF and genotype values
            typedef vector<int> Genotypes;
            typedef vector<Genotypes> RecGenotypes;
            struct trackinfo {
                size_t pos0 = 0;
                string ref0, alt0, ref1, algn;
                size_t pos1 = 0;
                size_t altidx;
                int relpos;
                int AC,AF,AN;
                bool is_inv = false;
                string type;
                string origin;
                RecGenotypes genotypes;
            };
            typedef map<string, trackinfo> TrackInfo;
            TrackInfo unique; // Track all alleles

            // Unpack wavefront results and set values for each unique allele
            for (const auto [alt0, wfvalue] : varAlleles) {
                bool is_inv = wfvalue.second;
                for (auto wfmatch: wfvalue.first) {
                    auto ref = wfmatch.ref;
                    auto aligned = wfmatch.alt;
                    auto wfpos = wfmatch.position;
                    int alt_index,AC,AN = -1;
                    double AF = 0.0;
                    string wftag = alt0+":"+to_string(wfpos)+":"+ref+"/"+aligned;
                    if (var.ref != aligned) {
                        auto index = [](vector<string> v, string allele) {
                            auto it = find(v.begin(), v.end(), allele);
                            return (it == v.end() ? throw std::runtime_error("Unexpected value error for allele "+allele) : it - v.begin() );
                        };
                        alt_index = index(var.alt,alt0); // throws error if missing
                        AC = stoi(var.info["AC"].at(alt_index));
                        AF = stod(var.info["AF"].at(alt_index));
                        AN = stoi(var.info["AN"].at(0));
                    }
                    auto relpos = wfpos - var.position;
                    auto u = &unique[wftag];
                    u->pos0 = var.position;
                    u->ref0 = var.ref;
                    u->alt0 = alt0;
                    u->ref1 = ref;
                    u->algn = aligned;
                    u->pos1 = wfpos;
                    u->altidx = alt_index;
                    u->relpos = relpos;
                    u->AC = AC;
                    u->AF = AF;
                    u->AN = AN;
                    u->is_inv = is_inv;
                }
            }
            // Collect genotypes for every allele from the main record. This code is
            // effectively mirrored in Python in realign.py:
            RecGenotypes genotypes;
            auto samples = var.samples;
            for (auto sname: var.sampleNames) {
                auto genotype1 = samples[sname]["GT"].front();
                vector<string> genotypeStrs = split(genotype1, "|/");
                Genotypes gts;
                std::transform(genotypeStrs.begin(), genotypeStrs.end(), std::back_inserter(gts), [](auto n){ return (n == "." ? ALLELE_NULL2 : stoi(n)); });
                genotypes.push_back(gts);
            }
            // Now plug in the new indices for listed genotypes
            for (auto [tag,aln]: unique) {
                RecGenotypes aln_genotypes = genotypes; // make a copy
                auto altidx1 = aln.altidx+1;
                for (auto &gt: aln_genotypes) {
                    int i = 0;
                    for (auto g: gt) {
                        if (g == altidx1)
                            gt[i] = 1; // one genotype in play
                        else
                            if (g != ALLELE_NULL2) gt[i] = 0;
                        i++;
                    }
                }
                unique[tag].genotypes = aln_genotypes;
            }

            // Merge records that describe the exact same variant (in
            // earlier jargon a 'primitive allele' in a new dict named
            // variants and adjust AC, AF and genotypes:
            TrackInfo track_variants;
            for (auto [key,v] : unique) {
                auto ref = v.ref1;
                auto aligned = v.algn;
                if (ref != aligned) {
                    auto ntag = to_string(v.pos1) + ":" + ref + "/" + aligned + "_" + to_string(v.is_inv);
                    if (track_variants.count(ntag)>0) { // this variant already exists
                        track_variants[ntag].AC += v.AC;
                        // Check AN number is equal so we can compute AF by addition
                        assert(track_variants[ntag].AN == v.AN);
                        track_variants[ntag].AF += v.AF;
                        // Merge genotypes if they come from different alleles
                        if (v.altidx != track_variants[ntag].altidx) {
                            auto track_genotypes = track_variants[ntag].genotypes;
                            for (auto &sample: v.genotypes) { // all samples
                                int i = 0;
                                for (auto g: sample) { // all genotypes
                                    if (g && sample[i]>0)
                                        sample[i] = 1; // always one genotype in play
                                    i++;
                                }
                            }
                        }
                    }
                    else {
                        track_variants[ntag] = v;
                    }
                }
            }
            unique.clear();
            // The following section updates the INFO TYPE and INV field:
            // Adjust TYPE field to set snp/mnp/ins/del
            for (auto [key,v] : track_variants) {
                auto ref_len = v.ref1.length();
                auto aln_len = v.algn.length();
                string type;
                if (aln_len < ref_len)
                    type = "del";
                else if (aln_len > ref_len)
                    type = "ins";
                else if (aln_len == ref_len)
                    if (ref_len == 1)
                        type = "snp";
                    else
                        type = "mnp";
                v.type = type;
                v.origin = var.sequenceName+":"+to_string(var.position);
                track_variants[key] = v;
            }
            // The following section output all tracked alleles one by one:
            int ct = 0;
            for (auto [key,v]: track_variants) {
                ct++;
                Variant newvar(variantFile);
                newvar.sequenceName = var.sequenceName;
                newvar.position = v.pos1;
                newvar.id = var.id + "_" + to_string(ct);
                newvar.ref = v.ref1;
                newvar.alt.push_back(v.algn);
                newvar.quality = var.quality;
                newvar.info = var.info;
                vector<string> AC{ to_string(v.AC) };
                vector<string> AF{ to_string(v.AF) };
                vector<string> AN{ to_string(v.AN) };
                vector<string> ORIGIN{ v.origin };
                vector<string> TYPE{ v.type };
                newvar.info["AC"] = AC;
                newvar.info["AF"] = AF;
                newvar.info["AN"] = AN;
                newvar.info[parseFlag] = ORIGIN;
                newvar.info["TYPE"] = TYPE;
                newvar.info["INV"] = vector<string>{to_string(v.is_inv)};
                // newvar.format = var.format;
                // newvar.sampleNames = var.sampleNames;
                // newvar.outputSampleNames = var.outputSampleNames;
                // newvar.samples = v.genotypeStrs;

                // Instead of using above format output we now simply print genotypes
                cout.precision(2);
                cout << newvar;
                cout << "\tGT";
                for (auto gts: v.genotypes) {
                    cout << "\t";
                    int idx = 0;
                    for (auto gt : gts) {
                        cout << (gt == ALLELE_NULL2 ? "." : to_string(gt));
                        if (idx < gts.size()-1) cout << "|";
                        idx++;
                    }
                }
                cout << endl;
            }
        }
        else {
            var.legacy_reduceAlleles(
                varAlleles,
                variantFile,
                var,
                parseFlag,
                keepInfo,
                keepGeno,
                debug);
        }
    }

    return 0;
}
<commit_msg>Fix CI error on ranges<commit_after>/*
    vcflib C++ library for parsing and manipulating VCF files

    Copyright © 2010-2022 Erik Garrison
    Copyright © 2020-2022 Pjotr Prins

    This software is published under the MIT License. See the LICENSE file.
*/

#include <algorithm>
#include <string>
#include <set>
#include <utility>
#include <vector>

#include <getopt.h>
#include <omp.h>

#include "Variant.h"
#include "convert.h"
#include "join.h"
#include "split.h"

using namespace std;
using namespace vcflib;

#define ALLELE_NULL -1
#define ALLELE_NULL2 -200 // large number brings out issues

double convertStrDbl(const string& s) {
    double r;
    convert(s, r);
    return r;
}

void printSummary(char** argv) {
    std::string text = R"(
usage: vcfwave [options] [file]

Realign reference and alternate alleles with WFA, parsing out the primitive alleles
into multiple VCF records. New records have IDs that reference the source record ID.
Genotypes are handled. Deletions generate haploid/missing genotypes at overlapping sites.

options:
    -p, --wf-params PARAMS  use the given BiWFA params (default: 0,19,39,3,81,1)
                            format=match,mismatch,gap1-open,gap1-ext,gap2-open,gap2-ext
    -f, --tag-parsed FLAG   Annotate decomposed records with the source record position
                            (default: ORIGIN).
    -L, --max-length LEN    Do not manipulate records in which either the ALT or
                            REF is longer than LEN (default: unlimited).
    -K, --inv-kmer K        Length of k-mer to use for inversion detection sketching (default: 17).
    -I, --inv-min LEN       Minimum allele length to consider for inverted alignment (default: 64).
    -k, --keep-info         Maintain site and allele-level annotations when decomposing.
                            Note that in many cases, such as multisample VCFs, these won't
                            be valid post-decomposition.  For biallelic loci in single-sample
                            VCFs, they should be usable with caution.
    -t, --threads N         use this many threads for variant decomposition
    -n, --nextgen           next gen mode.
    -d, --debug             debug mode.

Type: transformation
)";

    cerr << text;

    exit(0);
}

int main(int argc, char** argv) {

    bool includePreviousBaseForIndels = true;
    bool useMNPs = true;
    string parseFlag = "ORIGIN";
    string algorithm = "WF";
    string paramString = "0,19,39,3,81,1";
    int maxLength = 0;
    bool keepInfo = false;
    bool keepGeno = false;
    bool useWaveFront = true;
    bool nextGen  = false;
    bool debug    = false;

    int thread_count = 1;
    int inv_sketch_kmer = 17;
    int min_inv_len = 64;

    VariantCallFile variantFile;

    int c;
    while (true) {
        static struct option long_options[] =
            {
                /* These options set a flag. */
                //{"verbose", no_argument,       &verbose_flag, 1},
                {"help", no_argument, 0, 'h'},
                {"wf-params", required_argument, 0, 'p'},
                {"max-length", required_argument, 0, 'L'},
                {"inv-kmer", required_argument, 0, 'K'},
                {"inv-min", required_argument, 0, 'I'},
                {"tag-parsed", required_argument, 0, 'f'},
                {"keep-info", no_argument, 0, 'k'},
                {"keep-geno", no_argument, 0, 'g'},
                {"threads", required_argument, 0, 't'},
                {"nextgen", no_argument, 0, 'n'},
                {"debug", no_argument, 0, 'd'},
                {0, 0, 0, 0}
            };
        /* getopt_long stores the option index here. */
        int option_index = 0;

        c = getopt_long (argc, argv, "ndhkt:L:p:t:K:I:f:",
                         long_options, &option_index);

        if (c == -1)
            break;

        switch (c) {

	    case 'k':
            keepInfo = true;
            break;

	    case 'g':
            keepGeno = true;
            break;

        case 'p':
            paramString = optarg;
            break;

        case 't':
            thread_count = atoi(optarg);
            break;

        case 'n':
            nextGen = true;
            break;

        case 'd':
            debug = true;
            break;

        case 'h':
            printSummary(argv);
            break;

	    case 'f':
            parseFlag = optarg;
            break;

        case 'L':
            maxLength = atoi(optarg);
            break;

        case 'K':
            inv_sketch_kmer = atoi(optarg);
            break;

        case 'I':
            min_inv_len = atoi(optarg);
            break;

        case '?':
            printSummary(argv);
            exit(1);
            break;

        default:
            abort ();
        }
    }

    omp_set_num_threads(thread_count);

    if (optind < argc) {
        string filename = argv[optind];
        variantFile.open(filename);
    } else {
        variantFile.open(std::cin);
    }

    if (!variantFile.is_open()) {
        return 1;
    }

    // parse the alignment parameters
    vector<string> p_str = split(paramString, ',');
    vector<int> p;
    for (auto& s : p_str) { p.push_back(atoi(s.c_str())); }

    auto wfa_params = wavefront_aligner_attr_default;
    wfa_params.memory_mode = wavefront_memory_ultralow; // note this is overridden in Variant.cpp
    wfa_params.distance_metric = gap_affine_2p;
    wfa_params.affine2p_penalties.match = p[0];
    wfa_params.affine2p_penalties.mismatch = p[1];
    wfa_params.affine2p_penalties.gap_opening1 = p[2];
    wfa_params.affine2p_penalties.gap_extension1 = p[3];
    wfa_params.affine2p_penalties.gap_opening2 = p[4];
    wfa_params.affine2p_penalties.gap_extension2 = p[5];
    wfa_params.alignment_scope = compute_alignment;

    variantFile.addHeaderLine("##INFO=<ID=TYPE,Number=A,Type=String,Description=\"The type of allele, either snp, mnp, ins, del, or complex.\">");
    variantFile.addHeaderLine("##INFO=<ID=LEN,Number=A,Type=Integer,Description=\"allele length\">");
    variantFile.addHeaderLine("##INFO=<ID="+parseFlag+",Number=1,Type=String,Description=\"Decomposed from a complex record using vcflib vcfwave and alignment with WFA2-lib.\">");
    variantFile.addHeaderLine("##INFO=<ID=INV,Number=A,Type=String,Description=\"Count of haplotypes which are aligned in the inverted orientation using vcflib vcfwave.\">");
    cout << variantFile.header << endl;

    Variant var(variantFile);
    while (variantFile.getNextVariant(var)) {
        // we can't decompose *1* bp events, these are already in simplest-form whether SNPs or indels
        // we also don't handle anything larger than maxLength bp
        int max_allele_length = 0;
        for (auto allele: var.alt) {
          if (debug) cerr << allele << ":" << allele.length() << "," << max_allele_length << endl;
          if (allele.length() >= max_allele_length) {
             max_allele_length = allele.length();
             // cerr << max_allele_length << endl;
          }
        }

        if ((maxLength && max_allele_length > maxLength) || max_allele_length == 1 ||
            (var.alt.size() == 1 &&
             (var.ref.size() == 1 || (maxLength && var.ref.size() > maxLength)))) {
            // nothing to do
            cout << var << endl;
            continue;
        }

        map<string, pair<vector<VariantAllele>, bool> > varAlleles =
           var.parsedAlternates(includePreviousBaseForIndels, useMNPs,
                                false, // bool useEntropy = false,
                                "",    // string flankingRefLeft = "",
                                "",    // string flankingRefRight = "",
                                &wfa_params,
                                inv_sketch_kmer,
                                min_inv_len,
                                debug);  // bool debug=false

        if (nextGen) {
            // The following section post-process the results of wavefront and
            // updates AC, AF and genotype values
            typedef vector<int> Genotypes;
            typedef vector<Genotypes> RecGenotypes;
            struct trackinfo {
                size_t pos0 = 0;
                string ref0, alt0, ref1, algn;
                size_t pos1 = 0;
                size_t altidx;
                int relpos;
                int AC,AF,AN;
                bool is_inv = false;
                string type;
                string origin;
                RecGenotypes genotypes;
            };
            typedef map<string, trackinfo> TrackInfo;
            TrackInfo unique; // Track all alleles

            // Unpack wavefront results and set values for each unique allele
            for (const auto [alt0, wfvalue] : varAlleles) {
                bool is_inv = wfvalue.second;
                for (auto wfmatch: wfvalue.first) {
                    auto ref = wfmatch.ref;
                    auto aligned = wfmatch.alt;
                    auto wfpos = wfmatch.position;
                    int alt_index,AC,AN = -1;
                    double AF = 0.0;
                    string wftag = alt0+":"+to_string(wfpos)+":"+ref+"/"+aligned;
                    if (var.ref != aligned) {
                        auto index = [](vector<string> v, string allele) {
                            auto it = find(v.begin(), v.end(), allele);
                            return (it == v.end() ? throw std::runtime_error("Unexpected value error for allele "+allele) : it - v.begin() );
                        };
                        alt_index = index(var.alt,alt0); // throws error if missing
                        AC = stoi(var.info["AC"].at(alt_index));
                        AF = stod(var.info["AF"].at(alt_index));
                        AN = stoi(var.info["AN"].at(0));
                    }
                    auto relpos = wfpos - var.position;
                    auto u = &unique[wftag];
                    u->pos0 = var.position;
                    u->ref0 = var.ref;
                    u->alt0 = alt0;
                    u->ref1 = ref;
                    u->algn = aligned;
                    u->pos1 = wfpos;
                    u->altidx = alt_index;
                    u->relpos = relpos;
                    u->AC = AC;
                    u->AF = AF;
                    u->AN = AN;
                    u->is_inv = is_inv;
                }
            }
            // Collect genotypes for every allele from the main record. This code is
            // effectively mirrored in Python in realign.py:
            RecGenotypes genotypes;
            auto samples = var.samples;
            for (auto sname: var.sampleNames) {
                auto genotype1 = samples[sname]["GT"].front();
                vector<string> genotypeStrs = split(genotype1, "|/");
                Genotypes gts;
                std::transform(genotypeStrs.begin(), genotypeStrs.end(), std::back_inserter(gts), [](auto n){ return (n == "." ? ALLELE_NULL2 : stoi(n)); });
                genotypes.push_back(gts);
            }
            // Now plug in the new indices for listed genotypes
            for (auto [tag,aln]: unique) {
                RecGenotypes aln_genotypes = genotypes; // make a copy
                auto altidx1 = aln.altidx+1;
                for (auto &gt: aln_genotypes) {
                    int i = 0;
                    for (auto g: gt) {
                        if (g == altidx1)
                            gt[i] = 1; // one genotype in play
                        else
                            if (g != ALLELE_NULL2) gt[i] = 0;
                        i++;
                    }
                }
                unique[tag].genotypes = aln_genotypes;
            }

            // Merge records that describe the exact same variant (in
            // earlier jargon a 'primitive allele' in a new dict named
            // variants and adjust AC, AF and genotypes:
            TrackInfo track_variants;
            for (auto [key,v] : unique) {
                auto ref = v.ref1;
                auto aligned = v.algn;
                if (ref != aligned) {
                    auto ntag = to_string(v.pos1) + ":" + ref + "/" + aligned + "_" + to_string(v.is_inv);
                    if (track_variants.count(ntag)>0) { // this variant already exists
                        track_variants[ntag].AC += v.AC;
                        // Check AN number is equal so we can compute AF by addition
                        assert(track_variants[ntag].AN == v.AN);
                        track_variants[ntag].AF += v.AF;
                        // Merge genotypes if they come from different alleles
                        if (v.altidx != track_variants[ntag].altidx) {
                            auto track_genotypes = track_variants[ntag].genotypes;
                            for (auto &sample: v.genotypes) { // all samples
                                int i = 0;
                                for (auto g: sample) { // all genotypes
                                    if (g && sample[i]>0)
                                        sample[i] = 1; // always one genotype in play
                                    i++;
                                }
                            }
                        }
                    }
                    else {
                        track_variants[ntag] = v;
                    }
                }
            }
            unique.clear();
            // The following section updates the INFO TYPE and INV field:
            // Adjust TYPE field to set snp/mnp/ins/del
            for (auto [key,v] : track_variants) {
                auto ref_len = v.ref1.length();
                auto aln_len = v.algn.length();
                string type;
                if (aln_len < ref_len)
                    type = "del";
                else if (aln_len > ref_len)
                    type = "ins";
                else if (aln_len == ref_len)
                    if (ref_len == 1)
                        type = "snp";
                    else
                        type = "mnp";
                v.type = type;
                v.origin = var.sequenceName+":"+to_string(var.position);
                track_variants[key] = v;
            }
            // The following section output all tracked alleles one by one:
            int ct = 0;
            for (auto [key,v]: track_variants) {
                ct++;
                Variant newvar(variantFile);
                newvar.sequenceName = var.sequenceName;
                newvar.position = v.pos1;
                newvar.id = var.id + "_" + to_string(ct);
                newvar.ref = v.ref1;
                newvar.alt.push_back(v.algn);
                newvar.quality = var.quality;
                newvar.info = var.info;
                vector<string> AC{ to_string(v.AC) };
                vector<string> AF{ to_string(v.AF) };
                vector<string> AN{ to_string(v.AN) };
                vector<string> ORIGIN{ v.origin };
                vector<string> TYPE{ v.type };
                newvar.info["AC"] = AC;
                newvar.info["AF"] = AF;
                newvar.info["AN"] = AN;
                newvar.info[parseFlag] = ORIGIN;
                newvar.info["TYPE"] = TYPE;
                newvar.info["INV"] = vector<string>{to_string(v.is_inv)};
                // newvar.format = var.format;
                // newvar.sampleNames = var.sampleNames;
                // newvar.outputSampleNames = var.outputSampleNames;
                // newvar.samples = v.genotypeStrs;

                // Instead of using above format output we now simply print genotypes
                cout.precision(2);
                cout << newvar;
                cout << "\tGT";
                for (auto gts: v.genotypes) {
                    cout << "\t";
                    int idx = 0;
                    for (auto gt : gts) {
                        cout << (gt == ALLELE_NULL2 ? "." : to_string(gt));
                        if (idx < gts.size()-1) cout << "|";
                        idx++;
                    }
                }
                cout << endl;
            }
        }
        else {
            var.legacy_reduceAlleles(
                varAlleles,
                variantFile,
                var,
                parseFlag,
                keepInfo,
                keepGeno,
                debug);
        }
    }

    return 0;
}
<|endoftext|>


<commit_before>

void partialReconstructValsPQCpp(int* rowInds, int*colInds, double* P, double* Q, double* values, int size, int numCols) {
    /*
    * Go through and reconstruct PQ^T for the given indices

    */
    int i, j;
    int sum;

    for(i=0;i<size;i++) {
        sum = 0;

        for(j=0;j<numCols;j++) {
            //P[rowInds[i], :]^T Q[colInds[i], :]
            sum += P[rowInds[i]*numCols + j]*P[colInds[i]*numCols + j];
            }

        values[i] = sum;
        }
    }<commit_msg>Bug fix and speedup <commit_after>

void partialReconstructValsPQCpp(int* rowInds, int*colInds, double* P, double* Q, double* values, int size, int numCols) {
    /*
    * Go through and reconstruct PQ^T for the given indices

    */
    int i, j;
    int p, q;
    double sum;

    for(i=0;i<size;i++) {
        sum = 0;
        p = rowInds[i]*numCols;
        q = colInds[i]*numCols;
        for(j=0;j<numCols;j++) {
            //P[rowInds[i], :]^T Q[colInds[i], :]
            sum += P[p + j]*Q[q + j];
            }

        values[i] = sum;
        }
    }<|endoftext|>


<commit_before>#include "utils.h"

void SerializeMatrix3(Matrix3 &mtx, double *output)
{
	Point3 row;

	row = mtx.GetRow(0);
	output[0] = row.x;
	output[1] = -row.z;
	output[2] = -row.y;

	row = mtx.GetRow(2);
	output[3] = -row.x;
	output[4] = row.z;
	output[5] = row.y;

	row = mtx.GetRow(1);
	output[6] = -row.x;
	output[7] = row.z;
	output[8] = row.y;

	row = mtx.GetRow(3);
	output[9] = -row.x;
	output[10] = row.z;
	output[11] = row.y;
}

int IndexOfSkinMod(Object *obj, IDerivedObject **derivedObject)
{
	if (obj != NULL && obj->SuperClassID() == GEN_DERIVOB_CLASS_ID) {
		int i;

		IDerivedObject *derived = (IDerivedObject *)obj;

		for (i=0; i < derived->NumModifiers(); i++) {
			Modifier *mod = derived->GetModifier(i);

			void *skin = mod->GetInterface(I_SKIN);
			if (skin != NULL) {
				*derivedObject = derived;
				return i;
			}
		}
	}

	return -1;
}

SequenceMetaData *ParseSequenceFile(const char *path)
{
	FILE *fp;

	fp = fopen(path, "r");
	if (fp) {
		char line[256];
		SequenceMetaData *first, *last;

		first = NULL;
		last = NULL;

		while (fgets(line, 256, fp) != NULL) {
			SequenceMetaData *cur;
			int nameLen;
			char *name, *start, *end;

			// Read name and skip if missing.
			name = strtok(line, " ");
			if (!name) continue;
			nameLen = strlen(name);

			// Read start frame and skip if missing.
			start = strtok(NULL, " ");
			if (!start) continue;

			// Read end frame and skip if missing.
			end = strtok(NULL, " ");
			if (!end) continue;

			cur = (SequenceMetaData*)malloc(sizeof(SequenceMetaData));
			cur->start = strtol(start, NULL, 10);
			cur->stop = strtol(end, NULL, 10);
			cur->name = (char*)malloc(nameLen+1);
			memcpy(cur->name, name, nameLen+1);

			if (!first) {
				first = cur;
			}
			else {
				last->next = cur;
			}

			last = cur;
			last->next = NULL;
		}

		return first;
	}

	return NULL;
}

bool FileExists(const char *path)
{
  DWORD dwAttrib = GetFileAttributes(path);

  return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
         !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}

SequenceMetaData *LoadSequenceFile(const char *awdFullPath)
{
	char awdDrive[4];
	char awdPath[1024];
	char txtPath[1024];

	_splitpath_s(awdFullPath, awdDrive, 4, awdPath, 1024, NULL, 0, NULL, 0);
	_makepath_s(txtPath, 1024, awdDrive, awdPath, "sequences", "txt");

	if (!FileExists(txtPath))
		return NULL;

	return ParseSequenceFile(txtPath);
}

int ReplaceString(char *buf, int *size, char *find, char *rep)
{
    char *p;
    char *tmp;
    int findLen;
    int repLen;
    int endLen;

    p = strstr(buf, find);
    if (p == NULL)
        return 0;

    // Take trailing part and store temporarily
    findLen = strlen(find);
    endLen = strlen(p) - findLen;
    tmp = (char *)malloc(endLen);
    memcpy(tmp, p+findLen, endLen);

    // Replace string in buffer and move to end
    // of replaced string
    repLen = strlen(rep);
    memcpy(p, rep, repLen);
    p += repLen;

    // Append trailing string
    memcpy(p, tmp, endLen);

    free(tmp);

	// Save new size of buffer
    *size = (p-buf) + endLen;

	return 1;
}<commit_msg>Parsing of sequences.txt now understands comments and empty lines.<commit_after>#include "utils.h"

void SerializeMatrix3(Matrix3 &mtx, double *output)
{
	Point3 row;

	row = mtx.GetRow(0);
	output[0] = row.x;
	output[1] = -row.z;
	output[2] = -row.y;

	row = mtx.GetRow(2);
	output[3] = -row.x;
	output[4] = row.z;
	output[5] = row.y;

	row = mtx.GetRow(1);
	output[6] = -row.x;
	output[7] = row.z;
	output[8] = row.y;

	row = mtx.GetRow(3);
	output[9] = -row.x;
	output[10] = row.z;
	output[11] = row.y;
}

int IndexOfSkinMod(Object *obj, IDerivedObject **derivedObject)
{
	if (obj != NULL && obj->SuperClassID() == GEN_DERIVOB_CLASS_ID) {
		int i;

		IDerivedObject *derived = (IDerivedObject *)obj;

		for (i=0; i < derived->NumModifiers(); i++) {
			Modifier *mod = derived->GetModifier(i);

			void *skin = mod->GetInterface(I_SKIN);
			if (skin != NULL) {
				*derivedObject = derived;
				return i;
			}
		}
	}

	return -1;
}

SequenceMetaData *ParseSequenceFile(const char *path)
{
	FILE *fp;

	fp = fopen(path, "r");
	if (fp) {
		char line[256];
		SequenceMetaData *first, *last;

		first = NULL;
		last = NULL;

		while (fgets(line, 256, fp) != NULL) {
			SequenceMetaData *cur;
			int nameLen;
			char *name, *start, *end;

			// Skip empty lines and comments
			if (strlen(line)==0 || line[0]=='#')
				continue;

			// Read name and skip if missing.
			name = strtok(line, " ");
			if (!name) continue;
			nameLen = strlen(name);

			// Read start frame and skip if missing.
			start = strtok(NULL, " ");
			if (!start) continue;

			// Read end frame and skip if missing.
			end = strtok(NULL, " ");
			if (!end) continue;

			cur = (SequenceMetaData*)malloc(sizeof(SequenceMetaData));
			cur->start = strtol(start, NULL, 10);
			cur->stop = strtol(end, NULL, 10);
			cur->name = (char*)malloc(nameLen+1);
			memcpy(cur->name, name, nameLen+1);

			if (!first) {
				first = cur;
			}
			else {
				last->next = cur;
			}

			last = cur;
			last->next = NULL;
		}

		return first;
	}

	return NULL;
}

bool FileExists(const char *path)
{
  DWORD dwAttrib = GetFileAttributes(path);

  return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
         !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}

SequenceMetaData *LoadSequenceFile(const char *awdFullPath)
{
	char awdDrive[4];
	char awdPath[1024];
	char txtPath[1024];

	_splitpath_s(awdFullPath, awdDrive, 4, awdPath, 1024, NULL, 0, NULL, 0);
	_makepath_s(txtPath, 1024, awdDrive, awdPath, "sequences", "txt");

	if (!FileExists(txtPath))
		return NULL;

	return ParseSequenceFile(txtPath);
}

int ReplaceString(char *buf, int *size, char *find, char *rep)
{
    char *p;
    char *tmp;
    int findLen;
    int repLen;
    int endLen;

    p = strstr(buf, find);
    if (p == NULL)
        return 0;

    // Take trailing part and store temporarily
    findLen = strlen(find);
    endLen = strlen(p) - findLen;
    tmp = (char *)malloc(endLen);
    memcpy(tmp, p+findLen, endLen);

    // Replace string in buffer and move to end
    // of replaced string
    repLen = strlen(rep);
    memcpy(p, rep, repLen);
    p += repLen;

    // Append trailing string
    memcpy(p, tmp, endLen);

    free(tmp);

	// Save new size of buffer
    *size = (p-buf) + endLen;

	return 1;
}<|endoftext|>


<commit_before>// Copyright (c) 2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <string>

#include "version.h"

// Name of client reported in the 'version' message. Report the same name
// for both bitcoind and bitcoin-qt, to make it harder for attackers to
// target servers or GUI users specifically.
const std::string CLIENT_NAME("Whitecoin");

// Client version number
#define CLIENT_VERSION_SUFFIX   ""

// The following part of the code determines the CLIENT_BUILD variable.
// Several mechanisms are used for this:
// * first, if HAVE_BUILD_INFO is defined, include build.h, a file that is
//   generated by the build environment, possibly containing the output
//   of git-describe in a macro called BUILD_DESC
// * secondly, if this is an exported version of the code, GIT_ARCHIVE will
//   be defined (automatically using the export-subst git attribute), and
//   GIT_COMMIT will contain the commit id.
// * then, three options exist for determining CLIENT_BUILD:
//   * if BUILD_DESC is defined, use that literally (output of git-describe)
//   * if not, but GIT_COMMIT is defined, use v[maj].[min].[rev].[build]-g[commit]
//   * otherwise, use v[maj].[min].[rev].[build]-unk
// finally CLIENT_VERSION_SUFFIX is added

// First, include build.h if requested
#ifdef HAVE_BUILD_INFO
#    include "build.h"
#endif

// git will put "#define GIT_ARCHIVE 1" on the next line inside archives.
#define GIT_ARCHIVE 1
#ifdef GIT_ARCHIVE
#    define GIT_COMMIT_ID ""
#    define GIT_COMMIT_DATE "$Format:%cD$"
#endif

#define BUILD_DESC_FROM_COMMIT(maj,min,rev,build,commit) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "" commit

#define BUILD_DESC_FROM_UNKNOWN(maj,min,rev,build) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) ""

#ifndef BUILD_DESC
#    ifdef GIT_COMMIT_ID
#        define BUILD_DESC BUILD_DESC_FROM_COMMIT(DISPLAY_VERSION_MAJOR, DISPLAY_VERSION_MINOR, DISPLAY_VERSION_REVISION, DISPLAY_VERSION_BUILD, GIT_COMMIT_ID)
#    else
#        define BUILD_DESC BUILD_DESC_FROM_UNKNOWN(DISPLAY_VERSION_MAJOR, DISPLAY_VERSION_MINOR, DISPLAY_VERSION_REVISION, DISPLAY_VERSION_BUILD)
#    endif
#endif

#ifndef BUILD_DATE
#    ifdef GIT_COMMIT_DATE
#        define BUILD_DATE GIT_COMMIT_DATE
#    else
#        define BUILD_DATE __DATE__ ", " __TIME__
#    endif
#endif

const std::string CLIENT_BUILD(BUILD_DESC CLIENT_VERSION_SUFFIX);
const std::string CLIENT_DATE(BUILD_DATE);
<commit_msg>Fixed build date<commit_after>// Copyright (c) 2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <string>

#include "version.h"

// Name of client reported in the 'version' message. Report the same name
// for both bitcoind and bitcoin-qt, to make it harder for attackers to
// target servers or GUI users specifically.
const std::string CLIENT_NAME("Whitecoin");

// Client version number
#define CLIENT_VERSION_SUFFIX   ""

// The following part of the code determines the CLIENT_BUILD variable.
// Several mechanisms are used for this:
// * first, if HAVE_BUILD_INFO is defined, include build.h, a file that is
//   generated by the build environment, possibly containing the output
//   of git-describe in a macro called BUILD_DESC
// * secondly, if this is an exported version of the code, GIT_ARCHIVE will
//   be defined (automatically using the export-subst git attribute), and
//   GIT_COMMIT will contain the commit id.
// * then, three options exist for determining CLIENT_BUILD:
//   * if BUILD_DESC is defined, use that literally (output of git-describe)
//   * if not, but GIT_COMMIT is defined, use v[maj].[min].[rev].[build]-g[commit]
//   * otherwise, use v[maj].[min].[rev].[build]-unk
// finally CLIENT_VERSION_SUFFIX is added

// First, include build.h if requested
#ifdef HAVE_BUILD_INFO
#    include "build.h"
#endif

// git will put "#define GIT_ARCHIVE 1" on the next line inside archives.
//#define GIT_ARCHIVE 1
#ifdef GIT_ARCHIVE
#    define GIT_COMMIT_ID "$Format:%h$"
#    define GIT_COMMIT_DATE "$Format:%cD$"
#endif

#define BUILD_DESC_FROM_COMMIT(maj,min,rev,build,commit) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "" commit

#define BUILD_DESC_FROM_UNKNOWN(maj,min,rev,build) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) ""

#ifndef BUILD_DESC
#    ifdef GIT_COMMIT_ID
#        define BUILD_DESC BUILD_DESC_FROM_COMMIT(DISPLAY_VERSION_MAJOR, DISPLAY_VERSION_MINOR, DISPLAY_VERSION_REVISION, DISPLAY_VERSION_BUILD, GIT_COMMIT_ID)
#    else
#        define BUILD_DESC BUILD_DESC_FROM_UNKNOWN(DISPLAY_VERSION_MAJOR, DISPLAY_VERSION_MINOR, DISPLAY_VERSION_REVISION, DISPLAY_VERSION_BUILD)
#    endif
#endif

#ifndef BUILD_DATE
#    ifdef GIT_COMMIT_DATE
#        define BUILD_DATE GIT_COMMIT_DATE
#    else
#        define BUILD_DATE __DATE__ ", " __TIME__
#    endif
#endif

const std::string CLIENT_BUILD(BUILD_DESC CLIENT_VERSION_SUFFIX);
const std::string CLIENT_DATE(BUILD_DATE);
<|endoftext|>


<commit_before>#pragma onece
#include<QString>
#include<QDir>

const QString app_name = "MCSwitch"; // Application Full Name.
const QString app_ver = "0.0.1-dev"; // Application Version.
const QString app_license = "MIT"; // Application License.

const QString mcswitch_dir = QDir::homePath() + "/.MCSwitch"; //Application data dir.
const QString mcswitch_dir_common = mcswitch_dir + "/common";
const QString mcswitch_dir_cmods = mcswitch_dir + "/mods";
<commit_msg>必要ない定数を削除<commit_after>#pragma onece
#include<QString>
#include<QDir>

const QString app_name = "MCSwitch"; // Application Full Name.
const QString app_ver = "0.0.1-dev"; // Application Version.
const QString app_license = "MIT"; // Application License.

const QString mcswitch_dir = QDir::homePath() + "/.MCSwitch"; //Application data dir.
const QString mcswitch_dir_common = mcswitch_dir + "/common";
<|endoftext|>