<commit_before>
/*
 * Copyright (c) 2012 Karl N. Redgate
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/** \file UUID_Module.cc
 * \brief
 *
 */

#include <stdlib.h>

#include <tcl.h>
#include "tcl_util.h"

#include "logger.h"
#include "xuid.h"
#include "UUID.h"
#include "AppInit.h"

namespace { int debug = 0; }

/**
 */
static int
UUID_obj( ClientData data, Tcl_Interp *interp,
             int objc, Tcl_Obj * CONST *objv )
{
    UUID *uuid = (UUID *)data;

    if ( objc == 1 ) {
        Tcl_SetObjResult( interp, Tcl_NewLongObj((long)(uuid)) );
        return TCL_OK;
    }

    char *command = Tcl_GetStringFromObj( objv[1], NULL );
    if ( Tcl_StringMatch(command, "type") ) {
        Svc_SetResult( interp, "UUID", TCL_STATIC );
        return TCL_OK;
    }

    if ( Tcl_StringMatch(command, "data") ) {
        Tcl_Obj *obj = Tcl_NewByteArrayObj( uuid->raw(), 16 );
        Tcl_SetObjResult( interp, obj );
        return TCL_OK;
    }

    if ( Tcl_StringMatch(command, "string") ) {
        Tcl_Obj *obj = Tcl_NewStringObj( uuid->to_s(), -1 );
        Tcl_SetObjResult( interp, obj );
        return TCL_OK;
    }

    if ( Tcl_StringMatch(command, "set") ) {
        if ( objc < 3 ) {
            Tcl_ResetResult( interp );
            Tcl_WrongNumArgs( interp, 1, objv, "set value" );
            return TCL_ERROR;
        }
        char *uuid_string = Tcl_GetStringFromObj( objv[2], NULL );
        uuid->set( uuid_string );
        Tcl_Obj *obj = Tcl_NewStringObj( uuid->to_s(), -1 );
        Tcl_SetObjResult( interp, obj );
        return TCL_OK;
    }

    uint8_t *x = uuid->raw();
    if ( Tcl_StringMatch(command, "dump") ) {
        printf( "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
                x[0], x[1],  x[2],  x[3],  x[4],  x[5],  x[6],  x[7],
                x[8], x[9], x[10], x[11], x[12], x[13], x[14], x[15] );
        Tcl_ResetResult( interp );
        return TCL_OK;
    }

    Svc_SetResult( interp, "Unknown command for UUID object", TCL_STATIC );
    return TCL_ERROR;
}

/**
 */
static void
UUID_delete( ClientData data ) {
    UUID *uuid = (UUID *)data;
    delete uuid;
}

/**
 */
static int
UUID_cmd( ClientData data, Tcl_Interp *interp,
             int objc, Tcl_Obj * CONST *objv )
{
    if ( objc < 2 ) {
        Tcl_ResetResult( interp );
        Tcl_WrongNumArgs( interp, 1, objv, "name [value]" );
        return TCL_ERROR;
    }
    char *name = Tcl_GetStringFromObj( objv[1], NULL );

    if ( objc == 2 ) {
        UUID *object = new UUID();
        Tcl_CreateObjCommand( interp, name, UUID_obj, (ClientData)object, UUID_delete );
        Svc_SetResult( interp, name, TCL_VOLATILE );
        return TCL_OK;
    }

    if ( objc != 3 ) {
        Tcl_ResetResult( interp );
        Tcl_WrongNumArgs( interp, 1, objv, "name value" );
        return TCL_ERROR;
    }
    char *uuid_string = Tcl_GetStringFromObj( objv[2], NULL );
    UUID *object = new UUID( uuid_string );
    Tcl_CreateObjCommand( interp, name, UUID_obj, (ClientData)object, UUID_delete );
    Svc_SetResult( interp, name, TCL_VOLATILE );
    return TCL_OK;
}

/**
 */
static bool
UUID_Module( Tcl_Interp *interp ) {
    Tcl_Command command;

    Tcl_Namespace *ns = Tcl_CreateNamespace(interp, "UUID", (ClientData)0, NULL);
    if ( ns == NULL ) {
        return false;
    }

    if ( Tcl_LinkVar(interp, "UUID::debug", (char *)&debug, TCL_LINK_INT) != TCL_OK ) {
        log_err( "failed to link ICMPv6::debug" );
        exit( 1 );
    }

    command = Tcl_CreateObjCommand(interp, "UUID", UUID_cmd, (ClientData)0, NULL);
    if ( command == NULL ) {
        return false;
    }

    return true;
}

app_init( UUID_Module );

/* vim: set autoindent expandtab sw=4 syntax=c : */
<commit_msg>add guid commands impl<commit_after>
/*
 * Copyright (c) 2012 Karl N. Redgate
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/** \file UUID_Module.cc
 * \brief
 *
 */

#include <stdlib.h>

#include <tcl.h>
#include "tcl_util.h"

#include "logger.h"
#include "xuid.h"
#include "UUID.h"
#include "AppInit.h"

namespace { int debug = 0; }

/**
 */
static int
UUID_obj( ClientData data, Tcl_Interp *interp,
             int objc, Tcl_Obj * CONST *objv )
{
    UUID *uuid = (UUID *)data;

    if ( objc == 1 ) {
        Tcl_SetObjResult( interp, Tcl_NewLongObj((long)(uuid)) );
        return TCL_OK;
    }

    char *command = Tcl_GetStringFromObj( objv[1], NULL );
    if ( Tcl_StringMatch(command, "type") ) {
        Svc_SetResult( interp, "UUID", TCL_STATIC );
        return TCL_OK;
    }

    if ( Tcl_StringMatch(command, "data") ) {
        Tcl_Obj *obj = Tcl_NewByteArrayObj( uuid->raw(), 16 );
        Tcl_SetObjResult( interp, obj );
        return TCL_OK;
    }

    if ( Tcl_StringMatch(command, "string") ) {
        Tcl_Obj *obj = Tcl_NewStringObj( uuid->to_s(), -1 );
        Tcl_SetObjResult( interp, obj );
        return TCL_OK;
    }

    if ( Tcl_StringMatch(command, "set") ) {
        if ( objc < 3 ) {
            Tcl_ResetResult( interp );
            Tcl_WrongNumArgs( interp, 1, objv, "set value" );
            return TCL_ERROR;
        }
        char *uuid_string = Tcl_GetStringFromObj( objv[2], NULL );
        uuid->set( uuid_string );
        Tcl_Obj *obj = Tcl_NewStringObj( uuid->to_s(), -1 );
        Tcl_SetObjResult( interp, obj );
        return TCL_OK;
    }

    uint8_t *x = uuid->raw();
    if ( Tcl_StringMatch(command, "dump") ) {
        printf( "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
                x[0], x[1],  x[2],  x[3],  x[4],  x[5],  x[6],  x[7],
                x[8], x[9], x[10], x[11], x[12], x[13], x[14], x[15] );
        Tcl_ResetResult( interp );
        return TCL_OK;
    }

    Svc_SetResult( interp, "Unknown command for UUID object", TCL_STATIC );
    return TCL_ERROR;
}

/**
 */
static void
UUID_delete( ClientData data ) {
    UUID *uuid = (UUID *)data;
    delete uuid;
}

/**
 */
static int
UUID_cmd( ClientData data, Tcl_Interp *interp,
             int objc, Tcl_Obj * CONST *objv )
{
    if ( objc < 2 ) {
        Tcl_ResetResult( interp );
        Tcl_WrongNumArgs( interp, 1, objv, "name [value]" );
        return TCL_ERROR;
    }
    char *name = Tcl_GetStringFromObj( objv[1], NULL );

    if ( objc == 2 ) {
        UUID *object = new UUID();
        Tcl_CreateObjCommand( interp, name, UUID_obj, (ClientData)object, UUID_delete );
        Svc_SetResult( interp, name, TCL_VOLATILE );
        return TCL_OK;
    }

    if ( objc != 3 ) {
        Tcl_ResetResult( interp );
        Tcl_WrongNumArgs( interp, 1, objv, "name value" );
        return TCL_ERROR;
    }
    char *uuid_string = Tcl_GetStringFromObj( objv[2], NULL );
    UUID *object = new UUID( uuid_string );
    Tcl_CreateObjCommand( interp, name, UUID_obj, (ClientData)object, UUID_delete );
    Svc_SetResult( interp, name, TCL_VOLATILE );
    return TCL_OK;
}

/**
 */
static int
guid_obj( ClientData data, Tcl_Interp *interp,
             int objc, Tcl_Obj * CONST *objv )
{
    guid_t *guid = (guid_t *)data;
    char buffer[36];

    if ( objc == 1 ) {
        Tcl_SetObjResult( interp, Tcl_NewLongObj((long)(guid)) );
        return TCL_OK;
    }

    char *command = Tcl_GetStringFromObj( objv[1], NULL );
    if ( Tcl_StringMatch(command, "type") ) {
        Svc_SetResult( interp, "UUID", TCL_STATIC );
        return TCL_OK;
    }

#if 0
    if ( Tcl_StringMatch(command, "data") ) {
        Tcl_Obj *obj = Tcl_NewByteArrayObj( uuid->raw(), 16 );
        Tcl_SetObjResult( interp, obj );
        return TCL_OK;
    }
#endif

    if ( Tcl_StringMatch(command, "string") ) {
        format_guid( buffer, guid );
        Tcl_Obj *obj = Tcl_NewStringObj( buffer, 36 );
        Tcl_SetObjResult( interp, obj );
        return TCL_OK;
    }

    if ( Tcl_StringMatch(command, "set") ) {
        if ( objc < 3 ) {
            Tcl_ResetResult( interp );
            Tcl_WrongNumArgs( interp, 1, objv, "set value" );
            return TCL_ERROR;
        }
        char *guid_string = Tcl_GetStringFromObj( objv[2], NULL );
        parse_guid( guid_string, guid );
        format_guid( buffer, guid );
        Tcl_Obj *obj = Tcl_NewStringObj( buffer, 36 );
        Tcl_SetObjResult( interp, obj );
        return TCL_OK;
    }

#if 0
    uint8_t *x = uuid->raw();
    if ( Tcl_StringMatch(command, "dump") ) {
        printf( "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
                x[0], x[1],  x[2],  x[3],  x[4],  x[5],  x[6],  x[7],
                x[8], x[9], x[10], x[11], x[12], x[13], x[14], x[15] );
        Tcl_ResetResult( interp );
        return TCL_OK;
    }
#endif

    Svc_SetResult( interp, "Unknown command for UUID object", TCL_STATIC );
    return TCL_ERROR;
}

/**
 */
static void
guid_delete( ClientData data ) {
    guid_t *guid = (guid_t *)data;
    free( guid );
}

/**
 */
static int
guid_cmd( ClientData data, Tcl_Interp *interp,
             int objc, Tcl_Obj * CONST *objv )
{
    if ( objc < 2 ) {
        Tcl_ResetResult( interp );
        Tcl_WrongNumArgs( interp, 1, objv, "name [value]" );
        return TCL_ERROR;
    }
    char *name = Tcl_GetStringFromObj( objv[1], NULL );

    if ( objc == 2 ) {
        guid_t *object = (guid_t *)malloc( sizeof(guid_t) );
        Tcl_CreateObjCommand( interp, name, guid_obj, (ClientData)object, guid_delete );
        Svc_SetResult( interp, name, TCL_VOLATILE );
        return TCL_OK;
    }

    if ( objc != 3 ) {
        Tcl_ResetResult( interp );
        Tcl_WrongNumArgs( interp, 1, objv, "name value" );
        return TCL_ERROR;
    }

    char *guid_string = Tcl_GetStringFromObj( objv[2], NULL );
    guid_t *object = (guid_t *)malloc( sizeof(guid_t) );
    Tcl_CreateObjCommand( interp, name, guid_obj, (ClientData)object, guid_delete );
    Svc_SetResult( interp, name, TCL_VOLATILE );
    return TCL_OK;
}

/**
 */
static bool
UUID_Module( Tcl_Interp *interp ) {
    Tcl_Command command;

    Tcl_Namespace *ns = Tcl_CreateNamespace(interp, "UUID", (ClientData)0, NULL);
    if ( ns == NULL ) {
        return false;
    }

    if ( Tcl_LinkVar(interp, "UUID::debug", (char *)&debug, TCL_LINK_INT) != TCL_OK ) {
        log_err( "failed to link ICMPv6::debug" );
        exit( 1 );
    }

    command = Tcl_CreateObjCommand(interp, "UUID", UUID_cmd, (ClientData)0, NULL);
    if ( command == NULL ) {
        return false;
    }

    return true;
}

app_init( UUID_Module );

/* vim: set autoindent expandtab sw=4 syntax=c : */
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/generic/memory/lib/utils/shared/mss_generic_consts.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2018,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file mss_generic_consts.H
/// @brief Common constants to be shared
///

// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
// *HWP HWP Backup: Louis Stermole <stermole@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: HB:FSP

#ifndef _MSS_GENERIC_CONSTS_H_
#define _MSS_GENERIC_CONSTS_H_

#include <cstdint>

namespace mss
{

///
/// @brief Common conversions
///
enum conversions
{
    CONVERT_PS_IN_A_NS      = 1000,     ///< 1000 pico in an nano
    CONVERT_PS_IN_A_US      = 1000000,  ///< 1000000 picos in a micro
    MHZ_TO_KHZ              = 1000,
    SEC_IN_HOUR             = 60 * 60,  ///< seconds in an hour, used for scrub times
    NIBBLES_PER_BYTE = 2,
    BITS_PER_NIBBLE = 4,
    BITS_PER_BYTE = 8,
};

///
/// @brief FFDC generic codes
///
enum generic_ffdc_codes
{
    // Starting at 0x1%%% to avoid
    // any collisions with values
    // from controller specific ffdc codes
    SET_ATTR_DIMM_TYPE = 0x1000,
    SET_ATTR_DRAM_GEN = 0x1001,
    SET_ATTR_HYBRID = 0x1002,
    SET_ATTR_HYBRID_MEDIA = 0x1003,
    SET_ATTR_MASTER_RANKS = 0x1004,
    PRE_DATA_ENGINE_CTOR = 0x1005,
    GET_FIELD = 0x1006,
    READ_SPD_FIELD = 0x1007,
    BASE_CFG_PARAM_SELECT = 0x1008,
    DIMM_MODULE_PARAM_SELECT = 0x1009,
    BASE_CFG_FACTORY = 0x100A,
    DIMM_MODULE_FACTORY = 0x100B,
    GET_TAAMIN = 0x100C,
    GET_TCKMIN = 0x100D,
    GET_TCKMAX = 0x100E,
    GET_TIMEBASES_FTB = 0x100F,
    GET_TIMEBASES_MTB = 0x1010,
    GET_SUPPORTED_REV = 0x1011,
    TRASMIN = 0x1012,
    TRCMIN = 0x1013,
    TRFC1MIN = 0x1014,
    TRFC2MIN = 0x1015,
    TRFC4MIN = 0x1016,
    TFAWMIN = 0x1017,
    TWTR_S_MIN = 0x1018,
    TWRMIN = 0x1019,
    TWTR_L_MIN = 0x101A,
    DEVICE_TYPE = 0x101B,
    BASE_MODULE_TYPE = 0x101C,
    BAD_SPD_DATA = 0x101C,
    SET_FIELD = 0x101D,
};

///
/// @brief Supported proc types
///
enum proc_type
{
    NIMBUS,
    AXONE,
};

///
/// @brief JEDEC supported DDR4 speeds
///
enum ddr4_dimm_speeds
{
    DIMM_SPEED_1600 = 1600,
    DIMM_SPEED_1866 = 1866,
    DIMM_SPEED_2133 = 2133,
    DIMM_SPEED_2400 = 2400,
    DIMM_SPEED_2666 = 2666,
    DIMM_SPEED_2933 = 2933,
    DIMM_SPEED_3200 = 3200,
};

namespace spd
{

///
/// @brief SPD revisions - not tied any particular module
///
enum rev : uint8_t
{
    V1_0 = 0x10, ///< represents Rev 1.0
    V1_1 = 0x11, ///< represents Rev 1.1
    V1_2 = 0x12, ///< represents Rev 1.2

    // These module revisions can vary independently
    // so we track the largest decoded revision here.
    GEN_SEC_MAX = V1_1,
    RDIMM_MAX = V1_1,
    LRDIMM_MAX = V1_2,
};

///
/// @brief SPD module parameters
/// @note helps distinguish SPD decoder sections
///
enum parameters
{
    UNINITIALIZED,
    BASE_CNFG,
    RDIMM_MODULE,
    LRDIMM_MODULE,
    NVDIMM_MODULE,
};

///
/// @brief DRAM generation selector
/// @note values set to SPD settings
///
enum device_type
{
    DDR4 = 0x0c,
};

///
/// @brief DIMM type selector
/// @note values set to SPD settings
///
enum dimm_type
{
    RDIMM = 0b0001,
    LRDIMM = 0b0100,
};

enum guard_band : uint16_t
{
    // Used for caclulating spd timing values - from JEDEC rounding algorithm
    // Correction factor is 1% (for DDR3) or 2.5% (for DDR4)
    // when doing integer math, we add-in the inverse correction factor
    // Formula used for derivation:
    // Guardband = 1000 * (1000* correction_factor) - 1
    INVERSE_DDR4_CORRECTION_FACTOR = 974, ///< DDR4 correction factor
};

}// spd
}// mss

#endif
<commit_msg>Moves conversions to be in the generic code space<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/generic/memory/lib/utils/shared/mss_generic_consts.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2018,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file mss_generic_consts.H
/// @brief Common constants to be shared
///

// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
// *HWP HWP Backup: Louis Stermole <stermole@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: HB:FSP

#ifndef _MSS_GENERIC_CONSTS_H_
#define _MSS_GENERIC_CONSTS_H_

#include <cstdint>

namespace mss
{

///
/// @brief FFDC generic codes
///
enum generic_ffdc_codes
{
    // Starting at 0x1%%% to avoid
    // any collisions with values
    // from controller specific ffdc codes
    SET_ATTR_DIMM_TYPE = 0x1000,
    SET_ATTR_DRAM_GEN = 0x1001,
    SET_ATTR_HYBRID = 0x1002,
    SET_ATTR_HYBRID_MEDIA = 0x1003,
    SET_ATTR_MASTER_RANKS = 0x1004,
    PRE_DATA_ENGINE_CTOR = 0x1005,
    GET_FIELD = 0x1006,
    READ_SPD_FIELD = 0x1007,
    BASE_CFG_PARAM_SELECT = 0x1008,
    DIMM_MODULE_PARAM_SELECT = 0x1009,
    BASE_CFG_FACTORY = 0x100A,
    DIMM_MODULE_FACTORY = 0x100B,
    GET_TAAMIN = 0x100C,
    GET_TCKMIN = 0x100D,
    GET_TCKMAX = 0x100E,
    GET_TIMEBASES_FTB = 0x100F,
    GET_TIMEBASES_MTB = 0x1010,
    GET_SUPPORTED_REV = 0x1011,
    TRASMIN = 0x1012,
    TRCMIN = 0x1013,
    TRFC1MIN = 0x1014,
    TRFC2MIN = 0x1015,
    TRFC4MIN = 0x1016,
    TFAWMIN = 0x1017,
    TWTR_S_MIN = 0x1018,
    TWRMIN = 0x1019,
    TWTR_L_MIN = 0x101A,
    DEVICE_TYPE = 0x101B,
    BASE_MODULE_TYPE = 0x101C,
    BAD_SPD_DATA = 0x101D,
    SET_FIELD = 0x101E,
};

///
/// @brief Supported proc types
///
enum proc_type
{
    NIMBUS,
    AXONE,
};

///
/// @brief Supported memory controller types
///
enum class mc_type
{
    NIMBUS,
    CENTAUR,
    EXPLORER,
};

///
/// @brief JEDEC supported DDR speeds
/// @note Includes DDR4 and DDR5 only
///
enum ddr_dimm_speeds
{
    // Supported frequencies
    DIMM_SPEED_1600 = 1600,
    DIMM_SPEED_1866 = 1866,
    DIMM_SPEED_2133 = 2133,
    DIMM_SPEED_2400 = 2400,
    DIMM_SPEED_2666 = 2666,
    DIMM_SPEED_2933 = 2933,
    DIMM_SPEED_3200 = 3200,
    DIMM_SPEED_3600 = 3600,
    DIMM_SPEED_4000 = 4000,
    DIMM_SPEED_4400 = 4400,
    DIMM_SPEED_4800 = 4800,

    // Max/Mins for specific generations here
    DDR4_MIN_SPEED = 1600,
    DDR4_MAX_SPEED = 3200,
    DDR5_MIN_SPEED = 3200,
    DDR5_MAX_SPEED = 4800,
};

namespace spd
{

///
/// @brief SPD revisions - not tied any particular module
///
enum rev : uint8_t
{
    V1_0 = 0x10, ///< represents Rev 1.0
    V1_1 = 0x11, ///< represents Rev 1.1
    V1_2 = 0x12, ///< represents Rev 1.2

    // These module revisions can vary independently
    // so we track the largest decoded revision here.
    GEN_SEC_MAX = V1_1,
    RDIMM_MAX = V1_1,
    LRDIMM_MAX = V1_2,
};

///
/// @brief SPD module parameters
/// @note helps distinguish SPD decoder sections
///
enum parameters
{
    UNINITIALIZED,
    BASE_CNFG,
    RDIMM_MODULE,
    LRDIMM_MODULE,
    NVDIMM_MODULE,
};

///
/// @brief DRAM generation selector
/// @note values set to SPD settings
///
enum device_type
{
    DDR4 = 0x0c,
};

///
/// @brief DIMM type selector
/// @note values set to SPD settings
///
enum dimm_type
{
    RDIMM = 0b0001,
    LRDIMM = 0b0100,
};

enum guard_band : uint16_t
{
    // Used for caclulating spd timing values - from JEDEC rounding algorithm
    // Correction factor is 1% (for DDR3) or 2.5% (for DDR4)
    // when doing integer math, we add-in the inverse correction factor
    // Formula used for derivation:
    // Guardband = 1000 * (1000* correction_factor) - 1
    INVERSE_DDR4_CORRECTION_FACTOR = 974, ///< DDR4 correction factor
};

}// spd

enum conversions
{
    NIBBLES_PER_BYTE = 2,
    BITS_PER_NIBBLE = 4,
    BITS_PER_BYTE = 8,

    CONVERT_PS_IN_A_NS      = 1000,     ///< 1000 pico in an nano
    CONVERT_PS_IN_A_US      = 1000000,  ///< 1000000 picos in a micro

    DELAY_1NS               = 1,
    DELAY_10NS              = 10 ,      ///< general purpose 10  ns delay for HW mode
    DELAY_100NS             = 100,      ///< general purpose 100 ns delay for HW mode
    DELAY_1US               = 1000,     ///< general purpose 1 usec delay for HW mode
    DELAY_10US              = 10000,    ///< general purpose 1 usec delay for HW mode
    DELAY_100US             = 100000,   ///< general purpose 100 usec delay for HW mode
    DELAY_1MS               = 1000000,  ///< general purpose 1 ms delay for HW mode

    MHZ_TO_KHZ              = 1000,
    SEC_IN_HOUR             = 60 * 60,  ///< seconds in an hour, used for scrub times
};

}// mss

#endif
<|endoftext|>


<commit_before>#include "SolidWall.h"
#include "FlowModelSinglePhase.h"
#include "FlowModelTwoPhase.h"

registerMooseObject("RELAP7App", SolidWall);

template <>
InputParameters
validParams<SolidWall>()
{
  InputParameters params = validParams<FlowBoundary>();
  return params;
}

SolidWall::SolidWall(const InputParameters & params) : FlowBoundary(params) {}

void
SolidWall::check() const
{
  if ((FlowModel::getSpatialDiscretizationType() == FlowModel::rDG) &&
      (_flow_model_id == RELAP7::FM_TWO_PHASE_NCG))
    logSpatialDiscretizationNotImplementedError(FlowModel::getSpatialDiscretizationType());
}

void
SolidWall::addMooseObjects1Phase()
{
  ExecFlagEnum userobject_execute_on(MooseUtils::getDefaultExecFlagEnum());
  userobject_execute_on = {EXEC_INITIAL, EXEC_LINEAR, EXEC_NONLINEAR};

  // boundary flux user object
  const std::string boundary_flux_name = genName(name(), "boundary_flux");
  {
    const std::string class_name = "BoundaryFlux3EqnGhostWall";
    InputParameters params = _factory.getValidParams(class_name);
    params.set<UserObjectName>("numerical_flux") = _numerical_flux_name;
    params.set<ExecFlagEnum>("execute_on") = userobject_execute_on;
    _sim.addUserObject(class_name, boundary_flux_name, params);
  }

  // BCs
  addWeakBC3Eqn(boundary_flux_name);

  // Strongly impose zero velocity for CG
  if (FlowModel::getSpatialDiscretizationType() == FlowModel::CG)
  {
    InputParameters params = _factory.getValidParams("DirichletBC");
    params.set<NonlinearVariableName>("variable") = FlowModelSinglePhase::RHOUA;
    params.set<std::vector<BoundaryName>>("boundary") = getBoundaryNames();
    params.set<Real>("value") = 0.;
    _sim.addBoundaryCondition("DirichletBC", genName(name(), "rhou"), params);
  }
}

void
SolidWall::addMooseObjects2Phase()
{
  if (FlowModel::getSpatialDiscretizationType() == FlowModel::CG)
  {
    {
      InputParameters params = _factory.getValidParams("DirichletBC");
      params.set<NonlinearVariableName>("variable") = FlowModelTwoPhase::ALPHA_RHOU_A_LIQUID;
      params.set<std::vector<BoundaryName>>("boundary") = getBoundaryNames();
      params.set<Real>("value") = 0.;
      _sim.addBoundaryCondition("DirichletBC", genName(name(), "arhouA_liquid"), params);
    }
    {
      InputParameters params = _factory.getValidParams("DirichletBC");
      params.set<NonlinearVariableName>("variable") = FlowModelTwoPhase::ALPHA_RHOU_A_VAPOR;
      params.set<std::vector<BoundaryName>>("boundary") = getBoundaryNames();
      params.set<Real>("value") = 0.;
      _sim.addBoundaryCondition("DirichletBC", genName(name(), "arhouA_vapor"), params);
    }
  }
  else if (FlowModel::getSpatialDiscretizationType() == FlowModel::rDG)
  {
    ExecFlagEnum userobject_execute_on(MooseUtils::getDefaultExecFlagEnum());
    userobject_execute_on = {EXEC_INITIAL, EXEC_LINEAR, EXEC_NONLINEAR};

    // boundary flux user object
    const std::string boundary_flux_name = genName(name(), "boundary_flux");
    {
      const std::string class_name = "BoundaryFlux7EqnGhostWall";
      InputParameters params = _factory.getValidParams(class_name);
      params.set<UserObjectName>("numerical_flux") = _numerical_flux_name;
      params.set<ExecFlagEnum>("execute_on") = userobject_execute_on;
      _sim.addUserObject(class_name, boundary_flux_name, params);
    }

    // BCs
    addWeakBC7Eqn(boundary_flux_name);
  }
}

void
SolidWall::addMooseObjects()
{
  if (_flow_model_id == RELAP7::FM_SINGLE_PHASE)
    addMooseObjects1Phase();
  else if (_flow_model_id == RELAP7::FM_TWO_PHASE || _flow_model_id == RELAP7::FM_TWO_PHASE_NCG)
    addMooseObjects2Phase();
}
<commit_msg>Moved FlowModelID to THM.<commit_after>#include "SolidWall.h"
#include "FlowModelSinglePhase.h"
#include "FlowModelTwoPhase.h"

registerMooseObject("RELAP7App", SolidWall);

template <>
InputParameters
validParams<SolidWall>()
{
  InputParameters params = validParams<FlowBoundary>();
  return params;
}

SolidWall::SolidWall(const InputParameters & params) : FlowBoundary(params) {}

void
SolidWall::check() const
{
  if ((FlowModel::getSpatialDiscretizationType() == FlowModel::rDG) &&
      (_flow_model_id == RELAP7::FM_TWO_PHASE_NCG))
    logSpatialDiscretizationNotImplementedError(FlowModel::getSpatialDiscretizationType());
}

void
SolidWall::addMooseObjects1Phase()
{
  ExecFlagEnum userobject_execute_on(MooseUtils::getDefaultExecFlagEnum());
  userobject_execute_on = {EXEC_INITIAL, EXEC_LINEAR, EXEC_NONLINEAR};

  // boundary flux user object
  const std::string boundary_flux_name = genName(name(), "boundary_flux");
  {
    const std::string class_name = "BoundaryFlux3EqnGhostWall";
    InputParameters params = _factory.getValidParams(class_name);
    params.set<UserObjectName>("numerical_flux") = _numerical_flux_name;
    params.set<ExecFlagEnum>("execute_on") = userobject_execute_on;
    _sim.addUserObject(class_name, boundary_flux_name, params);
  }

  // BCs
  addWeakBC3Eqn(boundary_flux_name);

  // Strongly impose zero velocity for CG
  if (FlowModel::getSpatialDiscretizationType() == FlowModel::CG)
  {
    InputParameters params = _factory.getValidParams("DirichletBC");
    params.set<NonlinearVariableName>("variable") = FlowModelSinglePhase::RHOUA;
    params.set<std::vector<BoundaryName>>("boundary") = getBoundaryNames();
    params.set<Real>("value") = 0.;
    _sim.addBoundaryCondition("DirichletBC", genName(name(), "rhou"), params);
  }
}

void
SolidWall::addMooseObjects2Phase()
{
  if (FlowModel::getSpatialDiscretizationType() == FlowModel::CG)
  {
    {
      InputParameters params = _factory.getValidParams("DirichletBC");
      params.set<NonlinearVariableName>("variable") = FlowModelTwoPhase::ALPHA_RHOU_A_LIQUID;
      params.set<std::vector<BoundaryName>>("boundary") = getBoundaryNames();
      params.set<Real>("value") = 0.;
      _sim.addBoundaryCondition("DirichletBC", genName(name(), "arhouA_liquid"), params);
    }
    {
      InputParameters params = _factory.getValidParams("DirichletBC");
      params.set<NonlinearVariableName>("variable") = FlowModelTwoPhase::ALPHA_RHOU_A_VAPOR;
      params.set<std::vector<BoundaryName>>("boundary") = getBoundaryNames();
      params.set<Real>("value") = 0.;
      _sim.addBoundaryCondition("DirichletBC", genName(name(), "arhouA_vapor"), params);
    }
  }
  else if (FlowModel::getSpatialDiscretizationType() == FlowModel::rDG)
  {
    ExecFlagEnum userobject_execute_on(MooseUtils::getDefaultExecFlagEnum());
    userobject_execute_on = {EXEC_INITIAL, EXEC_LINEAR, EXEC_NONLINEAR};

    // boundary flux user object
    const std::string boundary_flux_name = genName(name(), "boundary_flux");
    {
      const std::string class_name = "BoundaryFlux7EqnGhostWall";
      InputParameters params = _factory.getValidParams(class_name);
      params.set<UserObjectName>("numerical_flux") = _numerical_flux_name;
      params.set<ExecFlagEnum>("execute_on") = userobject_execute_on;
      _sim.addUserObject(class_name, boundary_flux_name, params);
    }

    // BCs
    addWeakBC7Eqn(boundary_flux_name);
  }
}

void
SolidWall::addMooseObjects()
{
  if (_flow_model_id == THM::FM_SINGLE_PHASE)
    addMooseObjects1Phase();
  else if (_flow_model_id == RELAP7::FM_TWO_PHASE || _flow_model_id == RELAP7::FM_TWO_PHASE_NCG)
    addMooseObjects2Phase();
}
<|endoftext|>


<commit_before>/*
 * Copyright 2002, Log4cpp Project. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */

#include <log4cpp/threading/Threading.hh>
#include <cstdlib>
#include "StringUtil.hh"

#if defined(LOG4CPP_HAVE_THREADING) && defined(LOG4CPP_USE_PTHREADS)

namespace log4cpp {
    namespace threading {

        std::string getThreadId() {
            char buffer[4*sizeof(long)];
            int bufsize = sizeof(buffer)/sizeof(buffer[0]);
            int n = ::snprintf(buffer, bufsize, "%lu", pthread_self());	// thread id unsigned
            if (n >= bufsize) {
            	// escape to heap allocation
				char *buff_alloc;
				int size = ::asprintf(&buff_alloc, "%lu", pthread_self());	// thread id unsigned
				if (size < 0) {
					throw std::bad_alloc();
				}
				std::string res(buff_alloc);
				free(buff_alloc);
				return res;
            }
            return std::string(buffer);
        }

    }
}

#endif // LOG4CPP_HAVE_THREADING && LOG4CPP_USE_PTHREADS
<commit_msg>src/PThreads.cpp<commit_after>/*
 * Copyright 2002, Log4cpp Project. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */

#include <log4cpp/threading/Threading.hh>
#include <cstdlib>

#if defined(LOG4CPP_HAVE_THREADING) && defined(LOG4CPP_USE_PTHREADS)

namespace log4cpp {
    namespace threading {

        std::string getThreadId() {
            char buffer[4*sizeof(long)];
            int bufsize = sizeof(buffer)/sizeof(buffer[0]);
            int n = ::snprintf(buffer, bufsize, "%lu", pthread_self());	// thread id unsigned
            if (n >= bufsize) {
            	// escape to heap allocation
				char *buff_alloc;
				int size = ::asprintf(&buff_alloc, "%lu", pthread_self());	// thread id unsigned
				if (size < 0) {
					throw std::bad_alloc();
				}
				std::string res(buff_alloc);
				free(buff_alloc);
				return res;
            }
            return std::string(buffer);
        }

    }
}

#endif // LOG4CPP_HAVE_THREADING && LOG4CPP_USE_PTHREADS
<|endoftext|>


<commit_before>
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "SkBenchmark.h"
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkDashPathEffect.h"
#include "SkPaint.h"
#include "SkPath.h"
#include "SkRandom.h"
#include "SkString.h"
#include "SkTDArray.h"

/*
 *  Cases to consider:
 *
 *  1. antialiasing on/off (esp. width <= 1)
 *  2. strokewidth == 0, 1, 2
 *  3. hline, vline, diagonal, rect, oval
 *  4. dots [1,1] ([N,N] where N=strokeWidth?) or arbitrary (e.g. [2,1] or [1,2,3,2])
 */
static void path_hline(SkPath* path) {
    path->moveTo(SkIntToScalar(10), SkIntToScalar(10));
    path->lineTo(SkIntToScalar(600), SkIntToScalar(10));
}

class DashBench : public SkBenchmark {
protected:
    SkString            fName;
    SkTDArray<SkScalar> fIntervals;
    int                 fWidth;
    SkPoint             fPts[2];
    bool                fDoClip;

    enum {
        N = SkBENCHLOOP(100)
    };
public:
    DashBench(void* param, const SkScalar intervals[], int count, int width,
              bool doClip = false) : INHERITED(param) {
        fIntervals.append(count, intervals);
        for (int i = 0; i < count; ++i) {
            fIntervals[i] *= width;
        }
        fWidth = width;
        fName.printf("dash_%d_%s", width, doClip ? "clipped" : "noclip");
        fDoClip = doClip;

        fPts[0].set(SkIntToScalar(10), SkIntToScalar(10));
        fPts[1].set(SkIntToScalar(600), SkIntToScalar(10));
    }

    virtual void makePath(SkPath* path) {
        path_hline(path);
    }

protected:
    virtual const char* onGetName() SK_OVERRIDE {
        return fName.c_str();
    }

    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
        SkPaint paint;
        this->setupPaint(&paint);
        paint.setStyle(SkPaint::kStroke_Style);
        paint.setStrokeWidth(SkIntToScalar(fWidth));
        paint.setAntiAlias(false);

        SkPath path;
        this->makePath(&path);

        paint.setPathEffect(new SkDashPathEffect(fIntervals.begin(),
                                                 fIntervals.count(), 0))->unref();

        if (fDoClip) {
            SkRect r = path.getBounds();
            r.inset(-SkIntToScalar(20), -SkIntToScalar(20));
            // now move it so we don't intersect
            r.offset(0, r.height() * 3 / 2);
            canvas->clipRect(r);
        }

        this->handlePath(canvas, path, paint, N);
    }

    virtual void handlePath(SkCanvas* canvas, const SkPath& path,
                            const SkPaint& paint, int N) {
        for (int i = 0; i < N; ++i) {
//            canvas->drawPoints(SkCanvas::kLines_PointMode, 2, fPts, paint);
            canvas->drawPath(path, paint);
        }
    }

private:
    typedef SkBenchmark INHERITED;
};

class RectDashBench : public DashBench {
public:
    RectDashBench(void* param, const SkScalar intervals[], int count, int width, bool doClip = false)
    : INHERITED(param, intervals, count, width) {
        fName.append("_rect");
    }

protected:
    virtual void handlePath(SkCanvas* canvas, const SkPath& path,
                            const SkPaint& paint, int N) SK_OVERRIDE {
        SkPoint pts[2];
        if (!path.isLine(pts) || pts[0].fY != pts[1].fY) {
            this->INHERITED::handlePath(canvas, path, paint, N);
        } else {
            SkRect rect;
            rect.fLeft = pts[0].fX;
            rect.fTop = pts[0].fY - paint.getStrokeWidth() / 2;
            rect.fRight = rect.fLeft + SkIntToScalar(fWidth);
            rect.fBottom = rect.fTop + paint.getStrokeWidth();

            SkPaint p(paint);
            p.setStyle(SkPaint::kFill_Style);
            p.setPathEffect(NULL);

            int count = SkScalarRoundToInt((pts[1].fX - pts[0].fX) / (2*fWidth));
            SkScalar dx = SkIntToScalar(2 * fWidth);

            for (int i = 0; i < N*10; ++i) {
                SkRect r = rect;
                for (int j = 0; j < count; ++j) {
                    canvas->drawRect(r, p);
                    r.offset(dx, 0);
                }
            }
        }
    }

private:
    typedef DashBench INHERITED;
};

static void make_unit_star(SkPath* path, int n) {
    SkScalar rad = -SK_ScalarPI / 2;
    const SkScalar drad = (n >> 1) * SK_ScalarPI * 2 / n;

    path->moveTo(0, -SK_Scalar1);
    for (int i = 1; i < n; i++) {
        rad += drad;
        SkScalar cosV, sinV = SkScalarSinCos(rad, &cosV);
        path->lineTo(cosV, sinV);
    }
    path->close();
}

static void make_poly(SkPath* path) {
    make_unit_star(path, 9);
    SkMatrix matrix;
    matrix.setScale(SkIntToScalar(100), SkIntToScalar(100));
    path->transform(matrix);
}

static void make_quad(SkPath* path) {
    SkScalar x0 = SkIntToScalar(10);
    SkScalar y0 = SkIntToScalar(10);
    path->moveTo(x0, y0);
    path->quadTo(x0,                    y0 + 400 * SK_Scalar1,
                 x0 + 600 * SK_Scalar1, y0 + 400 * SK_Scalar1);
}

static void make_cubic(SkPath* path) {
    SkScalar x0 = SkIntToScalar(10);
    SkScalar y0 = SkIntToScalar(10);
    path->moveTo(x0, y0);
    path->cubicTo(x0,                    y0 + 400 * SK_Scalar1,
                  x0 + 600 * SK_Scalar1, y0 + 400 * SK_Scalar1,
                  x0 + 600 * SK_Scalar1, y0);
}

class MakeDashBench : public SkBenchmark {
    SkString fName;
    SkPath   fPath;
    SkAutoTUnref<SkPathEffect> fPE;

    enum {
        N = SkBENCHLOOP(400)
    };

public:
    MakeDashBench(void* param, void (*proc)(SkPath*), const char name[]) : INHERITED(param) {
        fName.printf("makedash_%s", name);
        proc(&fPath);

        SkScalar vals[] = { SkIntToScalar(4), SkIntToScalar(4) };
        fPE.reset(new SkDashPathEffect(vals, 2, 0));
    }

protected:
    virtual const char* onGetName() SK_OVERRIDE {
        return fName.c_str();
    }

    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
        SkPath dst;
        for (int i = 0; i < N; ++i) {
            SkStrokeRec rec(SkStrokeRec::kHairline_InitStyle);

            fPE->filterPath(&dst, fPath, &rec);
            dst.rewind();
        }
    }

private:
    typedef SkBenchmark INHERITED;
};

class DashLineBench : public SkBenchmark {
    SkString fName;
    SkPath   fPath;
    SkAutoTUnref<SkPathEffect> fPE;

    enum {
        N = SkBENCHLOOP(200)
    };

public:
    DashLineBench(void* param) : INHERITED(param) {
        fName.printf("dashline");

        SkScalar vals[] = { SkIntToScalar(1), SkIntToScalar(1) };
        fPE.reset(new SkDashPathEffect(vals, 2, 0));
    }

protected:
    virtual const char* onGetName() SK_OVERRIDE {
        return fName.c_str();
    }

    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
        SkPaint paint;
        this->setupPaint(&paint);
        paint.setStrokeWidth(1);
        paint.setPathEffect(fPE);
        for (int i = 0; i < N; ++i) {
            canvas->drawLine(10, 10, 640, 10, paint);
        }
    }

private:
    typedef SkBenchmark INHERITED;
};

///////////////////////////////////////////////////////////////////////////////

static const SkScalar gDots[] = { SK_Scalar1, SK_Scalar1 };

#define PARAM(array)    array, SK_ARRAY_COUNT(array)

static SkBenchmark* gF0(void* p) { return new DashBench(p, PARAM(gDots), 0); }
static SkBenchmark* gF1(void* p) { return new DashBench(p, PARAM(gDots), 1); }
static SkBenchmark* gF2(void* p) { return new DashBench(p, PARAM(gDots), 1, true); }
static SkBenchmark* gF3(void* p) { return new DashBench(p, PARAM(gDots), 4); }
static SkBenchmark* gF4(void* p) { return new MakeDashBench(p, make_poly, "poly"); }
static SkBenchmark* gF5(void* p) { return new MakeDashBench(p, make_quad, "quad"); }
static SkBenchmark* gF6(void* p) { return new MakeDashBench(p, make_cubic, "cubic"); }
static SkBenchmark* gF7(void* p) { return new DashLineBench(p); }

static BenchRegistry gR0(gF0);
static BenchRegistry gR1(gF1);
static BenchRegistry gR2(gF2);
static BenchRegistry gR3(gF3);
static BenchRegistry gR4(gF4);
static BenchRegistry gR5(gF5);
static BenchRegistry gR6(gF6);
static BenchRegistry gR7(gF7);
<commit_msg>add more cases to dashline: circle-vs-square, 0,1,2 stroke_width<commit_after>
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "SkBenchmark.h"
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkDashPathEffect.h"
#include "SkPaint.h"
#include "SkPath.h"
#include "SkRandom.h"
#include "SkString.h"
#include "SkTDArray.h"

/*
 *  Cases to consider:
 *
 *  1. antialiasing on/off (esp. width <= 1)
 *  2. strokewidth == 0, 1, 2
 *  3. hline, vline, diagonal, rect, oval
 *  4. dots [1,1] ([N,N] where N=strokeWidth?) or arbitrary (e.g. [2,1] or [1,2,3,2])
 */
static void path_hline(SkPath* path) {
    path->moveTo(SkIntToScalar(10), SkIntToScalar(10));
    path->lineTo(SkIntToScalar(600), SkIntToScalar(10));
}

class DashBench : public SkBenchmark {
protected:
    SkString            fName;
    SkTDArray<SkScalar> fIntervals;
    int                 fWidth;
    SkPoint             fPts[2];
    bool                fDoClip;

    enum {
        N = SkBENCHLOOP(100)
    };
public:
    DashBench(void* param, const SkScalar intervals[], int count, int width,
              bool doClip = false) : INHERITED(param) {
        fIntervals.append(count, intervals);
        for (int i = 0; i < count; ++i) {
            fIntervals[i] *= width;
        }
        fWidth = width;
        fName.printf("dash_%d_%s", width, doClip ? "clipped" : "noclip");
        fDoClip = doClip;

        fPts[0].set(SkIntToScalar(10), SkIntToScalar(10));
        fPts[1].set(SkIntToScalar(600), SkIntToScalar(10));
    }

    virtual void makePath(SkPath* path) {
        path_hline(path);
    }

protected:
    virtual const char* onGetName() SK_OVERRIDE {
        return fName.c_str();
    }

    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
        SkPaint paint;
        this->setupPaint(&paint);
        paint.setStyle(SkPaint::kStroke_Style);
        paint.setStrokeWidth(SkIntToScalar(fWidth));
        paint.setAntiAlias(false);

        SkPath path;
        this->makePath(&path);

        paint.setPathEffect(new SkDashPathEffect(fIntervals.begin(),
                                                 fIntervals.count(), 0))->unref();

        if (fDoClip) {
            SkRect r = path.getBounds();
            r.inset(-SkIntToScalar(20), -SkIntToScalar(20));
            // now move it so we don't intersect
            r.offset(0, r.height() * 3 / 2);
            canvas->clipRect(r);
        }

        this->handlePath(canvas, path, paint, N);
    }

    virtual void handlePath(SkCanvas* canvas, const SkPath& path,
                            const SkPaint& paint, int N) {
        for (int i = 0; i < N; ++i) {
//            canvas->drawPoints(SkCanvas::kLines_PointMode, 2, fPts, paint);
            canvas->drawPath(path, paint);
        }
    }

private:
    typedef SkBenchmark INHERITED;
};

class RectDashBench : public DashBench {
public:
    RectDashBench(void* param, const SkScalar intervals[], int count, int width, bool doClip = false)
    : INHERITED(param, intervals, count, width) {
        fName.append("_rect");
    }

protected:
    virtual void handlePath(SkCanvas* canvas, const SkPath& path,
                            const SkPaint& paint, int N) SK_OVERRIDE {
        SkPoint pts[2];
        if (!path.isLine(pts) || pts[0].fY != pts[1].fY) {
            this->INHERITED::handlePath(canvas, path, paint, N);
        } else {
            SkRect rect;
            rect.fLeft = pts[0].fX;
            rect.fTop = pts[0].fY - paint.getStrokeWidth() / 2;
            rect.fRight = rect.fLeft + SkIntToScalar(fWidth);
            rect.fBottom = rect.fTop + paint.getStrokeWidth();

            SkPaint p(paint);
            p.setStyle(SkPaint::kFill_Style);
            p.setPathEffect(NULL);

            int count = SkScalarRoundToInt((pts[1].fX - pts[0].fX) / (2*fWidth));
            SkScalar dx = SkIntToScalar(2 * fWidth);

            for (int i = 0; i < N*10; ++i) {
                SkRect r = rect;
                for (int j = 0; j < count; ++j) {
                    canvas->drawRect(r, p);
                    r.offset(dx, 0);
                }
            }
        }
    }

private:
    typedef DashBench INHERITED;
};

static void make_unit_star(SkPath* path, int n) {
    SkScalar rad = -SK_ScalarPI / 2;
    const SkScalar drad = (n >> 1) * SK_ScalarPI * 2 / n;

    path->moveTo(0, -SK_Scalar1);
    for (int i = 1; i < n; i++) {
        rad += drad;
        SkScalar cosV, sinV = SkScalarSinCos(rad, &cosV);
        path->lineTo(cosV, sinV);
    }
    path->close();
}

static void make_poly(SkPath* path) {
    make_unit_star(path, 9);
    SkMatrix matrix;
    matrix.setScale(SkIntToScalar(100), SkIntToScalar(100));
    path->transform(matrix);
}

static void make_quad(SkPath* path) {
    SkScalar x0 = SkIntToScalar(10);
    SkScalar y0 = SkIntToScalar(10);
    path->moveTo(x0, y0);
    path->quadTo(x0,                    y0 + 400 * SK_Scalar1,
                 x0 + 600 * SK_Scalar1, y0 + 400 * SK_Scalar1);
}

static void make_cubic(SkPath* path) {
    SkScalar x0 = SkIntToScalar(10);
    SkScalar y0 = SkIntToScalar(10);
    path->moveTo(x0, y0);
    path->cubicTo(x0,                    y0 + 400 * SK_Scalar1,
                  x0 + 600 * SK_Scalar1, y0 + 400 * SK_Scalar1,
                  x0 + 600 * SK_Scalar1, y0);
}

class MakeDashBench : public SkBenchmark {
    SkString fName;
    SkPath   fPath;
    SkAutoTUnref<SkPathEffect> fPE;

    enum {
        N = SkBENCHLOOP(400)
    };

public:
    MakeDashBench(void* param, void (*proc)(SkPath*), const char name[]) : INHERITED(param) {
        fName.printf("makedash_%s", name);
        proc(&fPath);

        SkScalar vals[] = { SkIntToScalar(4), SkIntToScalar(4) };
        fPE.reset(new SkDashPathEffect(vals, 2, 0));
    }

protected:
    virtual const char* onGetName() SK_OVERRIDE {
        return fName.c_str();
    }

    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
        SkPath dst;
        for (int i = 0; i < N; ++i) {
            SkStrokeRec rec(SkStrokeRec::kHairline_InitStyle);

            fPE->filterPath(&dst, fPath, &rec);
            dst.rewind();
        }
    }

private:
    typedef SkBenchmark INHERITED;
};

/*
 *  We try to special case square dashes (intervals are equal to strokewidth).
 */
class DashLineBench : public SkBenchmark {
    SkString fName;
    SkPath   fPath;
    SkScalar fStrokeWidth;
    bool     fIsRound;
    SkAutoTUnref<SkPathEffect> fPE;

    enum {
        N = SkBENCHLOOP(200)
    };

public:
    DashLineBench(void* param, SkScalar width, bool isRound) : INHERITED(param) {
        fName.printf("dashline_%g_%s", SkScalarToFloat(width), isRound ? "circle" : "square");
        fStrokeWidth = width;
        fIsRound = isRound;

        SkScalar vals[] = { SK_Scalar1, SK_Scalar1 };
        fPE.reset(new SkDashPathEffect(vals, 2, 0));
    }

protected:
    virtual const char* onGetName() SK_OVERRIDE {
        return fName.c_str();
    }

    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
        SkPaint paint;
        this->setupPaint(&paint);
        paint.setStrokeWidth(fStrokeWidth);
        paint.setStrokeCap(fIsRound ? SkPaint::kRound_Cap : SkPaint::kSquare_Cap);
        paint.setPathEffect(fPE);
        for (int i = 0; i < N; ++i) {
            canvas->drawLine(10 * SK_Scalar1, 10 * SK_Scalar1,
                             640 * SK_Scalar1, 10 * SK_Scalar1, paint);
        }
    }

private:
    typedef SkBenchmark INHERITED;
};

///////////////////////////////////////////////////////////////////////////////

static const SkScalar gDots[] = { SK_Scalar1, SK_Scalar1 };

#define PARAM(array)    array, SK_ARRAY_COUNT(array)

static SkBenchmark* gF0(void* p) { return new DashBench(p, PARAM(gDots), 0); }
static SkBenchmark* gF1(void* p) { return new DashBench(p, PARAM(gDots), 1); }
static SkBenchmark* gF2(void* p) { return new DashBench(p, PARAM(gDots), 1, true); }
static SkBenchmark* gF3(void* p) { return new DashBench(p, PARAM(gDots), 4); }
static SkBenchmark* gF4(void* p) { return new MakeDashBench(p, make_poly, "poly"); }
static SkBenchmark* gF5(void* p) { return new MakeDashBench(p, make_quad, "quad"); }
static SkBenchmark* gF6(void* p) { return new MakeDashBench(p, make_cubic, "cubic"); }
static SkBenchmark* gF700(void* p) { return new DashLineBench(p, 0, false); }
static SkBenchmark* gF710(void* p) { return new DashLineBench(p, SK_Scalar1, false); }
static SkBenchmark* gF720(void* p) { return new DashLineBench(p, 2 * SK_Scalar1, false); }
static SkBenchmark* gF701(void* p) { return new DashLineBench(p, 0, true); }
static SkBenchmark* gF711(void* p) { return new DashLineBench(p, SK_Scalar1, true); }
static SkBenchmark* gF721(void* p) { return new DashLineBench(p, 2 * SK_Scalar1, true); }

static BenchRegistry gR0(gF0);
static BenchRegistry gR1(gF1);
static BenchRegistry gR2(gF2);
static BenchRegistry gR3(gF3);
static BenchRegistry gR4(gF4);
static BenchRegistry gR5(gF5);
static BenchRegistry gR6(gF6);
static BenchRegistry gR700(gF700);
static BenchRegistry gR710(gF710);
static BenchRegistry gR720(gF720);
static BenchRegistry gR701(gF701);
static BenchRegistry gR711(gF711);
static BenchRegistry gR721(gF721);
<|endoftext|>


<commit_before><commit_msg>glTF rendering: moving in walktrough mode is to fast<commit_after><|endoftext|>


<commit_before>#ifndef HELPERS_HPP
#define HELPERS_HPP

#include <QList>

namespace cutehmi {
namespace dataacquisition {
namespace internal {

/**
 * Merge column values into single @a COLUMN_VALUES structure, so that elements are stored in particular order.
 * @tparam COLUMN_VALUES column values type.
 * @tparam SIZE size of @a columnValues array.
 * @param mergedValues reference to a structure where results shall be stored.
 * @param columnValues column values arrays. Arrays should be sorted as if they were sorted by @a compare function in descending(!)
 * order (thus typically some sort of "less than" compare function shall be used to maintain descending order).
 * @param compare function which compares
 */
template <typename COLUMN_VALUES, std::size_t SIZE>
void mergeColumnValues(COLUMN_VALUES & result, const COLUMN_VALUES * columnValues, std::function<bool(const COLUMN_VALUES & a, int aIndex, const COLUMN_VALUES & b, int bIndex)> compare)
{

	// Let's introduce a queue, which keeps indices of tables from which elements should be added to the resulting table.
	QList<int> queue;
	for (int i = 0; i < SIZE; i++)
		if (!columnValues[i].tagName.isEmpty())
			queue.append(i);

	// Sort the queue so that elements belonging to a table with highest close time appear first.
	std::sort(queue.begin(), queue.end(), [& columnValues, compare](int a, int b) -> bool {
		return compare(columnValues[a], 0, columnValues[b], 0);
	});
	std::reverse(queue.begin(), queue.end());	// Turn to descending order.

	int indices[SIZE] = {0};	// This array keeps actual elements index for each individual table.
	while (!queue.isEmpty()) {
		int appended = queue.takeFirst();	// First element of queue denotes a table from which values should be taken.
		result.append(columnValues[appended], indices[appended]);
		indices[appended]++;

		// If there are more elements in the table which has been appended, they should find their place in queue.
		if (indices[appended] < columnValues[appended].tagName.count()) {
			int insertIndex = 0;
			while (insertIndex < queue.count()
					&& compare(columnValues[appended], indices[appended], columnValues[queue.at(insertIndex)], indices[queue.at(insertIndex)]))
				insertIndex++;
			queue.insert(insertIndex, appended);
		}
	}
}

}
}
}

#endif // HELPERS_HPP
<commit_msg>Use Qt-compatible size type.<commit_after>#ifndef HELPERS_HPP
#define HELPERS_HPP

#include <QList>

namespace cutehmi {
namespace dataacquisition {
namespace internal {

/**
 * Merge column values into single @a COLUMN_VALUES structure, so that elements are stored in particular order.
 * @tparam COLUMN_VALUES column values type.
 * @tparam SIZE size of @a columnValues array.
 * @param mergedValues reference to a structure where results shall be stored.
 * @param columnValues column values arrays. Arrays should be sorted as if they were sorted by @a compare function in descending(!)
 * order (thus typically some sort of "less than" compare function shall be used to maintain descending order).
 * @param compare function which compares
 */
template <typename COLUMN_VALUES, int SIZE>
void mergeColumnValues(COLUMN_VALUES & result, const COLUMN_VALUES * columnValues, std::function<bool(const COLUMN_VALUES & a, int aIndex, const COLUMN_VALUES & b, int bIndex)> compare)
{

	// Let's introduce a queue, which keeps indices of tables from which elements should be added to the resulting table.
	QList<int> queue;
	for (int i = 0; i < SIZE; i++)
		if (!columnValues[i].tagName.isEmpty())
			queue.append(i);

	// Sort the queue so that elements belonging to a table with highest close time appear first.
	std::sort(queue.begin(), queue.end(), [& columnValues, compare](int a, int b) -> bool {
		return compare(columnValues[a], 0, columnValues[b], 0);
	});
	std::reverse(queue.begin(), queue.end());	// Turn to descending order.

	int indices[SIZE] = {0};	// This array keeps actual elements index for each individual table.
	while (!queue.isEmpty()) {
		int appended = queue.takeFirst();	// First element of queue denotes a table from which values should be taken.
		result.append(columnValues[appended], indices[appended]);
		indices[appended]++;

		// If there are more elements in the table which has been appended, they should find their place in queue.
		if (indices[appended] < columnValues[appended].tagName.count()) {
			int insertIndex = 0;
			while (insertIndex < queue.count()
					&& compare(columnValues[appended], indices[appended], columnValues[queue.at(insertIndex)], indices[queue.at(insertIndex)]))
				insertIndex++;
			queue.insert(insertIndex, appended);
		}
	}
}

}
}
}

#endif // HELPERS_HPP
<|endoftext|>


<commit_before>/**
 * This file is part of TelepathyQt4
 *
 * @copyright Copyright (C) 2009 Collabora Ltd. <http://www.collabora.co.uk/>
 * @copyright Copyright (C) 2009 Nokia Corporation
 * @license LGPL 2.1
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <TelepathyQt4/PendingSendMessage>

#include "TelepathyQt4/_gen/pending-send-message.moc.hpp"

#include <TelepathyQt4/ContactMessenger>
#include <TelepathyQt4/Message>
#include <TelepathyQt4/TextChannel>

namespace Tp
{

struct TELEPATHY_QT4_NO_EXPORT PendingSendMessage::Private
{
    Private(const Message &message)
        : message(message)
    {
    }

    QString token;
    Message message;
};

/**
 * \class PendingSendMessage
 * \ingroup clientchannel
 * \headerfile TelepathyQt4/pending-send-message.h <TelepathyQt4/PendingSendMessage>
 *
 * \brief The PendingSendMessage class represents the parameters of and the
 * reply to an asynchronous message send request.
 *
 * See \ref async_model
 */

PendingSendMessage::PendingSendMessage(const TextChannelPtr &channel, const Message &message)
    : PendingOperation(channel),
      mPriv(new Private(message))
{
}

PendingSendMessage::PendingSendMessage(const ContactMessengerPtr &messenger, const Message &message)
    : PendingOperation(messenger),
      mPriv(new Private(message))
{
}

PendingSendMessage::~PendingSendMessage()
{
    delete mPriv;
}

/**
 * Return the channel used to send the message if this instance was created using
 * TextChannel. If it was created using ContactMessenger, return a null TextChannelPtr.
 *
 * \return A TextChannelPtr object.
 */
TextChannelPtr PendingSendMessage::channel() const
{
    return TextChannelPtr(qobject_cast<TextChannel*>((TextChannel*) object().data()));
}

/**
 * Return the contact messenger used to send the message if this instance was created using
 * ContactMessenger. If it was created using TextChannel, return a null ContactMessengerPtr.
 *
 * \return A ContactMessengerPtr object.
 */
ContactMessengerPtr PendingSendMessage::messenger() const
{
    return ContactMessengerPtr(qobject_cast<ContactMessenger*>((ContactMessenger*) object().data()));
}

QString PendingSendMessage::sentMessageToken() const
{
    return mPriv->token;
}

Message PendingSendMessage::message() const
{
    return mPriv->message;
}

void PendingSendMessage::onTextSent(QDBusPendingCallWatcher *watcher)
{
    QDBusPendingReply<> reply = *watcher;

    if (reply.isError()) {
        setFinishedWithError(reply.error());
    } else {
        setFinished();
    }
    watcher->deleteLater();
}

void PendingSendMessage::onMessageSent(QDBusPendingCallWatcher *watcher)
{
    QDBusPendingReply<QString> reply = *watcher;

    if (reply.isError()) {
        setFinishedWithError(reply.error());
    } else {
        mPriv->token = reply.value();
        setFinished();
    }
    watcher->deleteLater();
}

void PendingSendMessage::onCDMessageSent(QDBusPendingCallWatcher *watcher)
{
    QDBusPendingReply<QString> reply = *watcher;

    if (reply.isError()) {
        QDBusError error = reply.error();
        if (error.name() == TP_QT4_DBUS_ERROR_UNKNOWN_METHOD ||
            error.name() == TP_QT4_DBUS_ERROR_UNKNOWN_INTERFACE) {
            setFinishedWithError(TP_QT4_ERROR_NOT_IMPLEMENTED,
                    QLatin1String("Channel Dispatcher implementation (e.g. mission-control), "
                        "does not support interface CD.I.Messages"));
        } else {
            setFinishedWithError(error);
        }
    } else {
        mPriv->token = reply.value();
        setFinished();
    }
    watcher->deleteLater();
}

} // Tp
<commit_msg>PendingSendMessage: Update docs.<commit_after>/**
 * This file is part of TelepathyQt4
 *
 * @copyright Copyright (C) 2009 Collabora Ltd. <http://www.collabora.co.uk/>
 * @copyright Copyright (C) 2009 Nokia Corporation
 * @license LGPL 2.1
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <TelepathyQt4/PendingSendMessage>

#include "TelepathyQt4/_gen/pending-send-message.moc.hpp"

#include <TelepathyQt4/ContactMessenger>
#include <TelepathyQt4/Message>
#include <TelepathyQt4/TextChannel>

namespace Tp
{

struct TELEPATHY_QT4_NO_EXPORT PendingSendMessage::Private
{
    Private(const Message &message)
        : message(message)
    {
    }

    QString token;
    Message message;
};

/**
 * \class PendingSendMessage
 * \ingroup clientchannel
 * \headerfile TelepathyQt4/pending-send-message.h <TelepathyQt4/PendingSendMessage>
 *
 * \brief The PendingSendMessage class represents the parameters of and the
 * reply to an asynchronous message send request.
 *
 * See \ref async_model
 */

PendingSendMessage::PendingSendMessage(const TextChannelPtr &channel, const Message &message)
    : PendingOperation(channel),
      mPriv(new Private(message))
{
}

PendingSendMessage::PendingSendMessage(const ContactMessengerPtr &messenger, const Message &message)
    : PendingOperation(messenger),
      mPriv(new Private(message))
{
}

PendingSendMessage::~PendingSendMessage()
{
    delete mPriv;
}

/**
 * Return the channel used to send the message if this instance was created using
 * TextChannel. If it was created using ContactMessenger, return a null TextChannelPtr.
 *
 * \return A pointer to the TextChannel object, or a null TextChannelPtr if created using
 *         ContactMessenger.
 */
TextChannelPtr PendingSendMessage::channel() const
{
    return TextChannelPtr(qobject_cast<TextChannel*>((TextChannel*) object().data()));
}

/**
 * Return the contact messenger used to send the message if this instance was created using
 * ContactMessenger. If it was created using TextChannel, return a null ContactMessengerPtr.
 *
 * \return A pointer to the ContactMessenger object, or a null ContactMessengerPtr if created using
 *         TextChannel.
 */
ContactMessengerPtr PendingSendMessage::messenger() const
{
    return ContactMessengerPtr(qobject_cast<ContactMessenger*>((ContactMessenger*) object().data()));
}

QString PendingSendMessage::sentMessageToken() const
{
    return mPriv->token;
}

Message PendingSendMessage::message() const
{
    return mPriv->message;
}

void PendingSendMessage::onTextSent(QDBusPendingCallWatcher *watcher)
{
    QDBusPendingReply<> reply = *watcher;

    if (reply.isError()) {
        setFinishedWithError(reply.error());
    } else {
        setFinished();
    }
    watcher->deleteLater();
}

void PendingSendMessage::onMessageSent(QDBusPendingCallWatcher *watcher)
{
    QDBusPendingReply<QString> reply = *watcher;

    if (reply.isError()) {
        setFinishedWithError(reply.error());
    } else {
        mPriv->token = reply.value();
        setFinished();
    }
    watcher->deleteLater();
}

void PendingSendMessage::onCDMessageSent(QDBusPendingCallWatcher *watcher)
{
    QDBusPendingReply<QString> reply = *watcher;

    if (reply.isError()) {
        QDBusError error = reply.error();
        if (error.name() == TP_QT4_DBUS_ERROR_UNKNOWN_METHOD ||
            error.name() == TP_QT4_DBUS_ERROR_UNKNOWN_INTERFACE) {
            setFinishedWithError(TP_QT4_ERROR_NOT_IMPLEMENTED,
                    QLatin1String("Channel Dispatcher implementation (e.g. mission-control), "
                        "does not support interface CD.I.Messages"));
        } else {
            setFinishedWithError(error);
        }
    } else {
        mPriv->token = reply.value();
        setFinished();
    }
    watcher->deleteLater();
}

} // Tp
<|endoftext|>


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

#include <memory>
#include <cmath>
#include "Eigen/Dense"
#include "Eigen/src/Core/util/Constants.h"
#include "Eigen/src/Geometry/Quaternion.h"
#include "absl/memory/memory.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include "mediapipe/framework/calculator_framework.h"
#include "mediapipe/framework/port/ret_check.h"
#include "mediapipe/framework/port/status.h"
#include "mediapipe/graphs/object_detection_3d/calculators/box.h"
#include "mediapipe/graphs/object_detection_3d/calculators/model_matrix.pb.h"
#include "mediapipe/graphs/instantmotiontracking/calculators/transformations.h"

namespace mediapipe {

namespace {
  using Matrix4fCM = Eigen::Matrix<float, 4, 4, Eigen::ColMajor>;
  using Vector3f = Eigen::Vector3f;
  using Matrix3f = Eigen::Matrix3f;
  using DiagonalMatrix3f = Eigen::DiagonalMatrix<float, 3>;
  constexpr char kAnchorsTag[] = "ANCHORS";
  constexpr char kIMUDataTag[] = "IMU_DATA";
  constexpr char kUserRotationsTag[] = "USER_ROTATIONS";
  constexpr char kUserScalingsTag[] = "USER_SCALINGS";
  constexpr char kModelMatricesTag[] = "MODEL_MATRICES";
  constexpr char kFOVSidePacketTag[] = "FOV";
  constexpr char kAspectRatioSidePacketTag[] = "ASPECT_RATIO";
  // (68 degrees, 4:3 for Pixel 4)
  float vertical_fov_radians_ = 0;
  float aspect_ratio_ = 0;
  // initial Z value (-50 is center point in visual range for OpenGL render)
  const float initial_z_ = -50;
}

// Intermediary for rotation and translation data to model matrix usable by
// gl_animation_overlay_calculator. For information on the construction of OpenGL
// objects and transformations (including a breakdown of model matrices), please
// visit: https://open.gl/transformations
//
// Input Side Packets:
//  FOV - Vertical field of view for device [REQUIRED - Defines perspective matrix]
//  ASPECT_RATIO - Aspect ratio of device [REQUIRED - Defines perspective matrix]
//
// Input:
//  ANCHORS - Anchor data with normalized x,y,z coordinates [REQUIRED]
//  IMU_DATA - float[3] of [roll, pitch, yaw] of device [REQUIRED]
//  USER_ROTATIONS - UserRotations with corresponding radians of rotation [REQUIRED]
//  TRANSLATION_DATA - All stickers final translation data (vector of
//  Translation objects) [REQUIRED]
// Output:
//  MODEL_MATRICES - TimedModelMatrixProtoList of all objects to render [REQUIRED]
//
// Example config:
// node{
//  calculator: "MatricesManagerCalculator"
//  input_stream: "ANCHORS:tracked_scaled_anchor_data"
//  input_stream: "IMU_DATA:imu_data"
//  input_stream: "USER_ROTATIONS:user_rotation_data"
//  input_stream: "TRANSLATION_DATA:final_translation_data"
//  output_stream: "MODEL_MATRICES:model_matrices"
// }

class MatricesManagerCalculator : public CalculatorBase {
  public:
    static ::mediapipe::Status GetContract(CalculatorContract* cc);
    ::mediapipe::Status Open(CalculatorContext* cc) override;
    ::mediapipe::Status Process(CalculatorContext* cc) override;
  private:
    const DiagonalMatrix3f GenerateUserScalingMatrix(const float scale_factor);
    const Matrix3f GenerateUserRotationMatrix(const float rotation_radians);
    const Matrix4fCM GenerateEigenModelMatrix(const Vector3f translation_vector,
      const Matrix3f rotation_submatrix);
    const Vector3f GenerateAnchorVector(const Anchor tracked_anchor);
    const Matrix3f GenerateIMURotationSubmatrix(const float yaw, const float pitch, const float roll);

    // Returns a user scaling increment associated with the sticker_id
    // TODO: Adjust lookup function if total number of stickers is uncapped to improve performance
    const float GetUserScaler(const std::vector<UserScaling> scalings, const int sticker_id) {
      for (const UserScaling &user_scaling : scalings) {
        if (user_scaling.sticker_id == sticker_id) {
          return user_scaling.scaling_increment;
        }
      }
    }
    // Returns a user rotation in radians associated with the sticker_id
    const float GetUserRotation(const std::vector<UserRotation> rotations, const int sticker_id) {
      for (const UserRotation &rotation : rotations) {
        if (rotation.sticker_id == sticker_id) {
          return rotation.radians;
        }
      }
    }
};

REGISTER_CALCULATOR(MatricesManagerCalculator);

::mediapipe::Status MatricesManagerCalculator::GetContract(
    CalculatorContract* cc) {
  RET_CHECK(cc->Inputs().HasTag(kAnchorsTag)
    && cc->Inputs().HasTag(kIMUDataTag)
    && cc->Inputs().HasTag(kUserRotationsTag)
    && cc->Inputs().HasTag(kUserScalingsTag)
    && cc->InputSidePackets().HasTag(kFOVSidePacketTag)
    && cc->InputSidePackets().HasTag(kAspectRatioSidePacketTag));
  RET_CHECK(cc->Outputs().HasTag(kModelMatricesTag));

  if (cc->Inputs().HasTag(kAnchorsTag)) {
    cc->Inputs().Tag(kAnchorsTag).Set<std::vector<Anchor>>();
  }
  if (cc->Inputs().HasTag(kIMUDataTag)) {
    cc->Inputs().Tag(kIMUDataTag).Set<float[]>();
  }
  if (cc->Inputs().HasTag(kUserScalingsTag)) {
      cc->Inputs().Tag(kUserScalingsTag).Set<std::vector<UserScaling>>();
  }
  if (cc->Inputs().HasTag(kUserRotationsTag)) {
    cc->Inputs().Tag(kUserRotationsTag).Set<std::vector<UserRotation>>();
  }
  if (cc->Outputs().HasTag(kModelMatricesTag)) {
    cc->Outputs().Tag(kModelMatricesTag).Set<TimedModelMatrixProtoList>();
  }

  cc->InputSidePackets().Tag(kFOVSidePacketTag).Set<float>();
  cc->InputSidePackets().Tag(kAspectRatioSidePacketTag).Set<float>();

  return ::mediapipe::OkStatus();
}

::mediapipe::Status MatricesManagerCalculator::Open(CalculatorContext* cc) {
  cc->SetOffset(TimestampDiff(0));
  // Set device properties from side packets
  vertical_fov_radians_ = cc->InputSidePackets().Tag(kFOVSidePacketTag).Get<float>();
  aspect_ratio_ = cc->InputSidePackets().Tag(kAspectRatioSidePacketTag).Get<float>();
  return ::mediapipe::OkStatus();
}

::mediapipe::Status MatricesManagerCalculator::Process(CalculatorContext* cc) {
  auto model_matrices = std::make_unique<TimedModelMatrixProtoList>();
  TimedModelMatrixProtoList* model_matrix_list = model_matrices.get();
  model_matrix_list->clear_model_matrix();

  const std::vector<UserRotation> user_rotation_data =
      cc->Inputs().Tag(kUserRotationsTag).Get<std::vector<UserRotation>>();

  const std::vector<UserScaling> user_scaling_data =
        cc->Inputs().Tag(kUserScalingsTag).Get<std::vector<UserScaling>>();

  const std::vector<Anchor> translation_data =
      cc->Inputs()
          .Tag(kAnchorsTag)
          .Get<std::vector<Anchor>>();

  // Device IMU Data definitions
  const float yaw = cc->Inputs().Tag(kIMUDataTag).Get<float[]>()[0];
  const float pitch = cc->Inputs().Tag(kIMUDataTag).Get<float[]>()[1];
  const float roll = cc->Inputs().Tag(kIMUDataTag).Get<float[]>()[2];
  // We can pre-generate the IMU submatrix as this remains unchanged for all objects
  const Matrix3f imu_rotation_submatrix = GenerateIMURotationSubmatrix(yaw, pitch, roll);

  for (const Anchor &anchor : translation_data) {
    const int id = anchor.sticker_id;

    TimedModelMatrixProto* model_matrix =
        model_matrix_list->add_model_matrix();
    model_matrix->set_id(id);

    // The user transformation data associate with this sticker must be defined
    const float rotation = GetUserRotation(user_rotation_data, id);
    const float scaler = GetUserScaler(user_scaling_data, id);

    // A vector representative of a user's sticker rotation transformation can be created
    const Matrix3f user_rotation_submatrix = GenerateUserRotationMatrix(rotation);
    // The user transformation data can be concatenated into a final rotation submatrix with the
    // device IMU rotational data
    const Matrix3f rotation_submatrix = imu_rotation_submatrix * user_rotation_submatrix;

    // Next, the submatrix representative of the user's scaling transformation must be generated
    const DiagonalMatrix3f user_scaling_submatrix = GenerateUserScalingMatrix(scaler);

    // A vector representative of the translation of the object in OpenGL coordinate space must be generated
    const Vector3f translation_vector = GenerateAnchorVector(anchor);

    // Concatenate all model matrix data
    const Matrix4fCM final_model_matrix = GenerateEigenModelMatrix(translation_vector, user_scaling_submatrix * rotation_submatrix);

    // The generated model matrix must be mapped to TimedModelMatrixProto (col-wise)
    for (int x = 0; x < final_model_matrix.rows(); ++x) {
      for (int y = 0; y < final_model_matrix.cols(); ++y) {
        model_matrix->add_matrix_entries(final_model_matrix(x, y));
      }
    }
  }

  cc->Outputs()
      .Tag(kModelMatricesTag)
      .Add(model_matrices.release(), cc->InputTimestamp());

  return ::mediapipe::OkStatus();
}

// Using a specified rotation value in radians, generate a rotation matrix for use with base rotation submatrix
const Matrix3f MatricesManagerCalculator::GenerateUserRotationMatrix(const float rotation_radians) {
  Eigen::Matrix3f user_rotation_submatrix;
    user_rotation_submatrix =
        // The rotation in radians must be inverted to rotate the object
        // with the direction of finger movement from the user (system dependent)
        Eigen::AngleAxisf(-rotation_radians, Eigen::Vector3f::UnitY()) *
        Eigen::AngleAxisf(0, Eigen::Vector3f::UnitZ()) *
        Eigen::AngleAxisf(0, Eigen::Vector3f::UnitX());
  // Matrix must be transposed due to the method of submatrix generation in Eigen
  return user_rotation_submatrix.transpose();
}

// Using a specified scale factor, generate a scaling matrix for use with base rotation submatrix
const DiagonalMatrix3f MatricesManagerCalculator::GenerateUserScalingMatrix(const float scale_factor) {
  DiagonalMatrix3f scaling_matrix(scale_factor, scale_factor, scale_factor);
  return scaling_matrix;
}

// TODO: Investigate possible differences in warping of tracking speed across screen
// Using the sticker anchor data, a translation vector can be generated in OpenGL coordinate space
const Vector3f MatricesManagerCalculator::GenerateAnchorVector(const Anchor tracked_anchor) {
  // Using an initial_z value in OpenGL space, generate a new base z-axis value to mimic scaling by distance.
  const float z = initial_z_ * tracked_anchor.z;

  // Using triangle geometry, the minimum for a y-coordinate that will appear in the view field
  // for the given z value above can be found.
  const float y_minimum = z * (tan(vertical_fov_radians_ / 2));

  // The aspect ratio of the device and y_minimum calculated above can be used to find the
  // minimum value for x that will appear in the view field of the device screen.
  const float x_minimum = y_minimum * (1.0 / aspect_ratio_);

  // Given the minimum bounds of the screen in OpenGL space, the tracked anchor coordinates
  // can be converted to OpenGL coordinate space.
  //
  // (i.e: X and Y will be converted from [0.0-1.0] space to [x_minimum, -x_minimum] space
  // and [y_minimum, -y_minimum] space respectively)
  const float x = (-2 * tracked_anchor.x * x_minimum) + x_minimum;
  const float y = (-2 * tracked_anchor.y * y_minimum) + y_minimum;

  // A translation transformation vector can be generated via Eigen
  const Vector3f t_vector(x,y,z);
  return t_vector;
}

// Using the yaw, pitch, and roll, a rotation submatrix can be generated,
// universal to each object appearing in the device view
const Matrix3f MatricesManagerCalculator::GenerateIMURotationSubmatrix(
  const float yaw, const float pitch, const float roll) {
  Eigen::Matrix3f r_submatrix;
    r_submatrix =
        // The yaw value is associated with the Y-axis.
        Eigen::AngleAxisf(yaw, Eigen::Vector3f::UnitY()) *
        // The roll value is associated with the Z-axis.
        Eigen::AngleAxisf(roll, Eigen::Vector3f::UnitZ()) *
        // The pitch value is associated with the X-axis.
        // The (-M_PI/2) must be added in order to adjust the default
        // rendering of the object (the object should appear in the upright
        // orientation upon initial render of the scene - this is entirely
        // dependent on the construction of the .obj file).
        Eigen::AngleAxisf(pitch - (M_PI / 2), Eigen::Vector3f::UnitX());
    // Matrix must be transposed due to the method of submatrix generation in Eigen
    return r_submatrix.transpose();
}

// Generates a model matrix via Eigen with appropriate transformations
const Matrix4fCM MatricesManagerCalculator::GenerateEigenModelMatrix(
    Vector3f translation_vector, Matrix3f rotation_submatrix) {
  // Define basic empty model matrix
  Matrix4fCM mvp_matrix;

  // Set the translation vector
  mvp_matrix.topRightCorner<3, 1>() = translation_vector;

  // Set the rotation submatrix
  mvp_matrix.topLeftCorner<3, 3>() = rotation_submatrix;

  // Set trailing 1.0 required by OpenGL to define coordinate space
  mvp_matrix(3,3) = 1.0;

  return mvp_matrix;
}
}
<commit_msg>Adjustments to scaling and Aspect Ratio calculations<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <memory>
#include <cmath>
#include "Eigen/Dense"
#include "Eigen/src/Core/util/Constants.h"
#include "Eigen/src/Geometry/Quaternion.h"
#include "absl/memory/memory.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include "mediapipe/framework/calculator_framework.h"
#include "mediapipe/framework/port/ret_check.h"
#include "mediapipe/framework/port/status.h"
#include "mediapipe/graphs/object_detection_3d/calculators/box.h"
#include "mediapipe/graphs/object_detection_3d/calculators/model_matrix.pb.h"
#include "mediapipe/graphs/instantmotiontracking/calculators/transformations.h"

namespace mediapipe {

namespace {
  using Matrix4fCM = Eigen::Matrix<float, 4, 4, Eigen::ColMajor>;
  using Vector3f = Eigen::Vector3f;
  using Matrix3f = Eigen::Matrix3f;
  using DiagonalMatrix3f = Eigen::DiagonalMatrix<float, 3>;
  constexpr char kAnchorsTag[] = "ANCHORS";
  constexpr char kIMUDataTag[] = "IMU_DATA";
  constexpr char kUserRotationsTag[] = "USER_ROTATIONS";
  constexpr char kUserScalingsTag[] = "USER_SCALINGS";
  constexpr char kModelMatricesTag[] = "MODEL_MATRICES";
  constexpr char kFOVSidePacketTag[] = "FOV";
  constexpr char kAspectRatioSidePacketTag[] = "ASPECT_RATIO";
  float vertical_fov_radians_ = 0;
  float aspect_ratio_ = 0;
  // initial Z value (-10 is center point in visual range for OpenGL render)
  const float initial_z_ = -10;
}

// Intermediary for rotation and translation data to model matrix usable by
// gl_animation_overlay_calculator. For information on the construction of OpenGL
// objects and transformations (including a breakdown of model matrices), please
// visit: https://open.gl/transformations
//
// Input Side Packets:
//  FOV - Vertical field of view for device [REQUIRED - Defines perspective matrix]
//  ASPECT_RATIO - Aspect ratio of device [REQUIRED - Defines perspective matrix]
//
// Input:
//  ANCHORS - Anchor data with normalized x,y,z coordinates [REQUIRED]
//  IMU_DATA - float[3] of [roll, pitch, yaw] of device [REQUIRED]
//  USER_ROTATIONS - UserRotations with corresponding radians of rotation [REQUIRED]
//  TRANSLATION_DATA - All stickers final translation data (vector of
//  Translation objects) [REQUIRED]
// Output:
//  MODEL_MATRICES - TimedModelMatrixProtoList of all objects to render [REQUIRED]
//
// Example config:
// node{
//  calculator: "MatricesManagerCalculator"
//  input_stream: "ANCHORS:tracked_scaled_anchor_data"
//  input_stream: "IMU_DATA:imu_data"
//  input_stream: "USER_ROTATIONS:user_rotation_data"
//  input_stream: "TRANSLATION_DATA:final_translation_data"
//  output_stream: "MODEL_MATRICES:model_matrices"
// }

class MatricesManagerCalculator : public CalculatorBase {
  public:
    static ::mediapipe::Status GetContract(CalculatorContract* cc);
    ::mediapipe::Status Open(CalculatorContext* cc) override;
    ::mediapipe::Status Process(CalculatorContext* cc) override;
  private:
    const DiagonalMatrix3f GenerateUserScalingMatrix(const float scale_factor);
    const Matrix3f GenerateUserRotationMatrix(const float rotation_radians);
    const Matrix4fCM GenerateEigenModelMatrix(const Vector3f translation_vector,
      const Matrix3f rotation_submatrix);
    const Vector3f GenerateAnchorVector(const Anchor tracked_anchor);
    const Matrix3f GenerateIMURotationSubmatrix(const float yaw, const float pitch, const float roll);

    // Returns a user scaling increment associated with the sticker_id
    // TODO: Adjust lookup function if total number of stickers is uncapped to improve performance
    const float GetUserScaler(const std::vector<UserScaling> scalings, const int sticker_id) {
      for (const UserScaling &user_scaling : scalings) {
        if (user_scaling.sticker_id == sticker_id) {
          return user_scaling.scaling_increment;
        }
      }
    }
    // Returns a user rotation in radians associated with the sticker_id
    const float GetUserRotation(const std::vector<UserRotation> rotations, const int sticker_id) {
      for (const UserRotation &rotation : rotations) {
        if (rotation.sticker_id == sticker_id) {
          return rotation.radians;
        }
      }
    }
};

REGISTER_CALCULATOR(MatricesManagerCalculator);

::mediapipe::Status MatricesManagerCalculator::GetContract(
    CalculatorContract* cc) {
  RET_CHECK(cc->Inputs().HasTag(kAnchorsTag)
    && cc->Inputs().HasTag(kIMUDataTag)
    && cc->Inputs().HasTag(kUserRotationsTag)
    && cc->Inputs().HasTag(kUserScalingsTag)
    && cc->InputSidePackets().HasTag(kFOVSidePacketTag)
    && cc->InputSidePackets().HasTag(kAspectRatioSidePacketTag));
  RET_CHECK(cc->Outputs().HasTag(kModelMatricesTag));

  if (cc->Inputs().HasTag(kAnchorsTag)) {
    cc->Inputs().Tag(kAnchorsTag).Set<std::vector<Anchor>>();
  }
  if (cc->Inputs().HasTag(kIMUDataTag)) {
    cc->Inputs().Tag(kIMUDataTag).Set<float[]>();
  }
  if (cc->Inputs().HasTag(kUserScalingsTag)) {
      cc->Inputs().Tag(kUserScalingsTag).Set<std::vector<UserScaling>>();
  }
  if (cc->Inputs().HasTag(kUserRotationsTag)) {
    cc->Inputs().Tag(kUserRotationsTag).Set<std::vector<UserRotation>>();
  }
  if (cc->Outputs().HasTag(kModelMatricesTag)) {
    cc->Outputs().Tag(kModelMatricesTag).Set<TimedModelMatrixProtoList>();
  }

  cc->InputSidePackets().Tag(kFOVSidePacketTag).Set<float>();
  cc->InputSidePackets().Tag(kAspectRatioSidePacketTag).Set<float>();

  return ::mediapipe::OkStatus();
}

::mediapipe::Status MatricesManagerCalculator::Open(CalculatorContext* cc) {
  cc->SetOffset(TimestampDiff(0));
  // Set device properties from side packets
  vertical_fov_radians_ = cc->InputSidePackets().Tag(kFOVSidePacketTag).Get<float>();
  aspect_ratio_ = cc->InputSidePackets().Tag(kAspectRatioSidePacketTag).Get<float>();
  return ::mediapipe::OkStatus();
}

::mediapipe::Status MatricesManagerCalculator::Process(CalculatorContext* cc) {
  auto model_matrices = std::make_unique<TimedModelMatrixProtoList>();
  TimedModelMatrixProtoList* model_matrix_list = model_matrices.get();
  model_matrix_list->clear_model_matrix();

  const std::vector<UserRotation> user_rotation_data =
      cc->Inputs().Tag(kUserRotationsTag).Get<std::vector<UserRotation>>();

  const std::vector<UserScaling> user_scaling_data =
        cc->Inputs().Tag(kUserScalingsTag).Get<std::vector<UserScaling>>();

  const std::vector<Anchor> translation_data =
      cc->Inputs()
          .Tag(kAnchorsTag)
          .Get<std::vector<Anchor>>();

  // Device IMU Data definitions
  const float yaw = cc->Inputs().Tag(kIMUDataTag).Get<float[]>()[0];
  const float pitch = cc->Inputs().Tag(kIMUDataTag).Get<float[]>()[1];
  const float roll = cc->Inputs().Tag(kIMUDataTag).Get<float[]>()[2];
  // We can pre-generate the IMU submatrix as this remains unchanged for all objects
  const Matrix3f imu_rotation_submatrix = GenerateIMURotationSubmatrix(yaw, pitch, roll);

  for (const Anchor &anchor : translation_data) {
    const int id = anchor.sticker_id;

    TimedModelMatrixProto* model_matrix =
        model_matrix_list->add_model_matrix();
    model_matrix->set_id(id);

    // The user transformation data associate with this sticker must be defined
    const float rotation = GetUserRotation(user_rotation_data, id);
    const float scaler = GetUserScaler(user_scaling_data, id);

    // A vector representative of a user's sticker rotation transformation can be created
    const Matrix3f user_rotation_submatrix = GenerateUserRotationMatrix(rotation);
    // The user transformation data can be concatenated into a final rotation submatrix with the
    // device IMU rotational data
    const Matrix3f rotation_submatrix = imu_rotation_submatrix * user_rotation_submatrix;

    // Next, the submatrix representative of the user's scaling transformation must be generated
    const DiagonalMatrix3f user_scaling_submatrix = GenerateUserScalingMatrix(scaler);

    // A vector representative of the translation of the object in OpenGL coordinate space must be generated
    const Vector3f translation_vector = GenerateAnchorVector(anchor);

    // Concatenate all model matrix data
    const Matrix4fCM final_model_matrix = GenerateEigenModelMatrix(translation_vector, user_scaling_submatrix * rotation_submatrix);

    // The generated model matrix must be mapped to TimedModelMatrixProto (col-wise)
    for (int x = 0; x < final_model_matrix.rows(); ++x) {
      for (int y = 0; y < final_model_matrix.cols(); ++y) {
        model_matrix->add_matrix_entries(final_model_matrix(x, y));
      }
    }
  }

  cc->Outputs()
      .Tag(kModelMatricesTag)
      .Add(model_matrices.release(), cc->InputTimestamp());

  return ::mediapipe::OkStatus();
}

// Using a specified rotation value in radians, generate a rotation matrix for use with base rotation submatrix
const Matrix3f MatricesManagerCalculator::GenerateUserRotationMatrix(const float rotation_radians) {
  Eigen::Matrix3f user_rotation_submatrix;
    user_rotation_submatrix =
        // The rotation in radians must be inverted to rotate the object
        // with the direction of finger movement from the user (system dependent)
        Eigen::AngleAxisf(-rotation_radians, Eigen::Vector3f::UnitY()) *
        Eigen::AngleAxisf(0, Eigen::Vector3f::UnitZ()) *
        Eigen::AngleAxisf(0, Eigen::Vector3f::UnitX());
  // Matrix must be transposed due to the method of submatrix generation in Eigen
  return user_rotation_submatrix.transpose();
}

// Using a specified scale factor, generate a scaling matrix for use with base rotation submatrix
const DiagonalMatrix3f MatricesManagerCalculator::GenerateUserScalingMatrix(const float scale_factor) {
  DiagonalMatrix3f scaling_matrix(scale_factor, scale_factor, scale_factor);
  return scaling_matrix;
}

// TODO: Investigate possible differences in warping of tracking speed across screen
// Using the sticker anchor data, a translation vector can be generated in OpenGL coordinate space
const Vector3f MatricesManagerCalculator::GenerateAnchorVector(const Anchor tracked_anchor) {
  // Using an initial_z value in OpenGL space, generate a new base z-axis value to mimic scaling by distance.
  const float z = initial_z_ * tracked_anchor.z;

  // Using triangle geometry, the minimum for a y-coordinate that will appear in the view field
  // for the given z value above can be found.
  const float y_minimum = z * (tan(vertical_fov_radians_ / 2));

  // The aspect ratio of the device and y_minimum calculated above can be used to find the
  // minimum value for x that will appear in the view field of the device screen.
  const float x_minimum = y_minimum * (1.0 / aspect_ratio_);

  // Given the minimum bounds of the screen in OpenGL space, the tracked anchor coordinates
  // can be converted to OpenGL coordinate space.
  //
  // (i.e: X and Y will be converted from [0.0-1.0] space to [x_minimum, -x_minimum] space
  // and [y_minimum, -y_minimum] space respectively)
  const float x = (-2 * tracked_anchor.x * x_minimum) + x_minimum;
  const float y = (-2 * tracked_anchor.y * y_minimum) + y_minimum;

  // A translation transformation vector can be generated via Eigen
  const Vector3f t_vector(x,y,z);
  return t_vector;
}

// Using the yaw, pitch, and roll, a rotation submatrix can be generated,
// universal to each object appearing in the device view
const Matrix3f MatricesManagerCalculator::GenerateIMURotationSubmatrix(
  const float yaw, const float pitch, const float roll) {
  Eigen::Matrix3f r_submatrix;
    r_submatrix =
        // The yaw value is associated with the Y-axis.
        Eigen::AngleAxisf(yaw, Eigen::Vector3f::UnitY()) *
        // The roll value is associated with the Z-axis.
        Eigen::AngleAxisf(roll, Eigen::Vector3f::UnitZ()) *
        // The pitch value is associated with the X-axis.
        // The (-M_PI/2) must be added in order to adjust the default
        // rendering of the object (the object should appear in the upright
        // orientation upon initial render of the scene - this is entirely
        // dependent on the construction of the .obj file).
        Eigen::AngleAxisf(pitch - (M_PI / 2), Eigen::Vector3f::UnitX());
    // Matrix must be transposed due to the method of submatrix generation in Eigen
    return r_submatrix.transpose();
}

// Generates a model matrix via Eigen with appropriate transformations
const Matrix4fCM MatricesManagerCalculator::GenerateEigenModelMatrix(
    Vector3f translation_vector, Matrix3f rotation_submatrix) {
  // Define basic empty model matrix
  Matrix4fCM mvp_matrix;

  // Set the translation vector
  mvp_matrix.topRightCorner<3, 1>() = translation_vector;

  // Set the rotation submatrix
  mvp_matrix.topLeftCorner<3, 3>() = rotation_submatrix;

  // Set trailing 1.0 required by OpenGL to define coordinate space
  mvp_matrix(3,3) = 1.0;

  return mvp_matrix;
}
}
<|endoftext|>