// Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved.
//
// NVIDIA CORPORATION and its licensors retain all intellectual property
// and proprietary rights in and to this software, related documentation
// and any modifications thereto.  Any use, reproduction, disclosure or
// distribution of this software and related documentation without an express
// license agreement from NVIDIA CORPORATION is strictly prohibited.
//
#include <OgnTutorialVectorizedPassthroughDatabase.h>

// The method used by the computation to perform the passthrough
// 0 = simple copy, no vectorization
#define TUTO_PASSTHROUGH_METHOD_SIMPLE 0

// 1 = vectorized copy by moving the entire database to the next instance
#define TUTO_PASSTHROUGH_METHOD_DB 1

// 2 = vectorized copy by indexing the instance directly per attribute
#define TUTO_PASSTHROUGH_METHOD_ATTR 2

// 3 = vectorized copy using raw data
#define TUTO_PASSTHROUGH_METHOD_RAW 3

//By default, use the most efficient method
#define TUTO_PASSTHROUGH_METHOD TUTO_PASSTHROUGH_METHOD_RAW

// This node perform a copy of its input to its output
class OgnTutorialVectorizedPassthrough
{
public:
#if TUTO_PASSTHROUGH_METHOD == TUTO_PASSTHROUGH_METHOD_SIMPLE
    // begin-regular
    static bool compute(OgnTutorialVectorizedPassthroughDatabase& db)
    {
        db.outputs.value() = db.inputs.value();
        return true;
    }
    // end-regular
#elif TUTO_PASSTHROUGH_METHOD == TUTO_PASSTHROUGH_METHOD_DB
    // begin-db
    static size_t computeVectorized(OgnTutorialVectorizedPassthroughDatabase& db, size_t count)
    {
        for(size_t idx = 0; idx < count; ++idx)
        {
            db.outputs.value() = db.inputs.value();
            db.moveToNextInstance();
        }
        return count;
    }
    // end-db
#elif TUTO_PASSTHROUGH_METHOD == TUTO_PASSTHROUGH_METHOD_ATTR
    // begin-attr
    static size_t computeVectorized(OgnTutorialVectorizedPassthroughDatabase& db, size_t count)
    {
        for(size_t idx = 0; idx < count; ++idx)
            db.outputs.value(idx) = db.inputs.value(idx);
        return count;
    }
    // end-attr
#elif TUTO_PASSTHROUGH_METHOD == TUTO_PASSTHROUGH_METHOD_RAW
    // begin-raw
    static size_t computeVectorized(OgnTutorialVectorizedPassthroughDatabase& db, size_t count)
    {
        auto spanIn = db.inputs.value.vectorized(count);
        auto spanOut = db.outputs.value.vectorized(count);

        memcpy(spanOut.data(), spanIn.data(), count * sizeof(float));

        return count;
    }
    // end-raw
#endif
};

REGISTER_OGN_NODE()
