274 lines
8.9 KiB
C++
274 lines
8.9 KiB
C++
/*
|
|
* Legal Notice
|
|
*
|
|
* This document and associated source code (the "Work") is a part of a
|
|
* benchmark specification maintained by the TPC.
|
|
*
|
|
* The TPC reserves all right, title, and interest to the Work as provided
|
|
* under U.S. and international laws, including without limitation all patent
|
|
* and trademark rights therein.
|
|
*
|
|
* No Warranty
|
|
*
|
|
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
|
|
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
|
|
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
|
|
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
|
|
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
|
|
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
|
|
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
|
|
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
|
|
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
|
|
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
|
|
* WITH REGARD TO THE WORK.
|
|
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
|
|
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
|
|
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
|
|
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
|
|
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
|
|
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
|
|
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
|
|
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
|
|
*
|
|
* Contributors
|
|
* - Sergey Vasilevskiy, Doug Johnson
|
|
*/
|
|
|
|
/******************************************************************************
|
|
* Description: Implementation of the CustomerSelection class.
|
|
* (see CustomerSelction.h for details)
|
|
******************************************************************************/
|
|
|
|
#include "main/EGenTables_stdafx.h"
|
|
|
|
using namespace TPCE;
|
|
|
|
/*
|
|
* Default constructor.
|
|
*/
|
|
CCustomerSelection::CCustomerSelection()
|
|
: m_pRND(NULL), m_iStartFromCustomer(0 + iTIdentShift), m_iCustomerCount(0), m_bPartitionByCID(false),
|
|
m_iPartitionPercent(0), m_iMyStartFromCustomer(0 + iTIdentShift), m_iMyCustomerCount(0) {
|
|
}
|
|
|
|
/*
|
|
* Constructor to set the customer range when not partitioining
|
|
*/
|
|
CCustomerSelection::CCustomerSelection(CRandom *pRND, TIdent iStartFromCustomer, TIdent iCustomerCount)
|
|
: m_pRND(pRND), m_iStartFromCustomer(iStartFromCustomer + iTIdentShift), m_iCustomerCount(iCustomerCount),
|
|
m_bPartitionByCID(false), m_iPartitionPercent(0), m_iMyStartFromCustomer(0 + iTIdentShift),
|
|
m_iMyCustomerCount(0) {
|
|
}
|
|
|
|
/*
|
|
* Constructor to set subrange when partitioning by C_ID.
|
|
*/
|
|
CCustomerSelection::CCustomerSelection(CRandom *pRND, TIdent iStartFromCustomer, TIdent iCustomerCount,
|
|
int iPartitionPercent, TIdent iMyStartFromCustomer, TIdent iMyCustomerCount)
|
|
: m_pRND(pRND), m_iStartFromCustomer(iStartFromCustomer + iTIdentShift), m_iCustomerCount(iCustomerCount)
|
|
|
|
,
|
|
m_bPartitionByCID(true), m_iPartitionPercent(iPartitionPercent),
|
|
m_iMyStartFromCustomer(iMyStartFromCustomer + iTIdentShift), m_iMyCustomerCount(iMyCustomerCount) {
|
|
if ((iStartFromCustomer == iMyStartFromCustomer) && (iCustomerCount == iMyCustomerCount)) {
|
|
// Even though the partitioning constructor was called, we're apparently
|
|
// not really partitioning.
|
|
m_bPartitionByCID = false;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Re-set the customer range for the partition.
|
|
*/
|
|
void CCustomerSelection::SetPartitionRange(TIdent iStartFromCustomer, TIdent iCustomerCount) {
|
|
if (m_bPartitionByCID) {
|
|
m_iMyStartFromCustomer = iStartFromCustomer;
|
|
m_iMyCustomerCount = iCustomerCount;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Forward permutation.
|
|
*/
|
|
TIdent CCustomerSelection::Permute(TIdent iLow, TIdent iHigh) {
|
|
return ((677 * iLow + 33 * (iHigh + 1)) % 1000);
|
|
}
|
|
|
|
/*
|
|
* Inverse permutation.
|
|
*/
|
|
TIdent CCustomerSelection::InversePermute(TIdent iLow, TIdent iHigh) {
|
|
// Extra mod to make the result always positive
|
|
//
|
|
return (((((613 * (iLow - 33 * (iHigh + 1))) % 1000) + 1000) % 1000));
|
|
}
|
|
|
|
/*
|
|
* Return scrambled inverse customer id in range of 0 to 999.
|
|
*/
|
|
UINT CCustomerSelection::GetInverseCID(TIdent C_ID) {
|
|
UINT iCHigh = (UINT)CHigh(C_ID);
|
|
UINT iInverseCID = (UINT)InversePermute(CLow(C_ID), iCHigh);
|
|
|
|
if (iInverseCID < 200) // Tier 1: value 0 to 199
|
|
{
|
|
return ((3 * iInverseCID + (iCHigh + 1)) % 200);
|
|
} else {
|
|
if (iInverseCID < 800) // Tier 2: value 200 to 799
|
|
{
|
|
return (((59 * iInverseCID + 47 * (iCHigh + 1)) % 600) + 200);
|
|
} else // Tier 3: value 800 to 999
|
|
{
|
|
return (((23 * iInverseCID + 17 * (iCHigh + 1)) % 200) + 800);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Return customer tier.
|
|
*/
|
|
eCustomerTier CCustomerSelection::GetTier(TIdent C_ID) {
|
|
TIdent iRevC_ID = InversePermute(CLow(C_ID), CHigh(C_ID));
|
|
|
|
if (iRevC_ID < 200) {
|
|
return eCustomerTierOne;
|
|
} else {
|
|
if (iRevC_ID < 800) {
|
|
return eCustomerTierTwo;
|
|
} else {
|
|
return eCustomerTierThree;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Return a non-uniform random customer and the associated tier.
|
|
*/
|
|
void CCustomerSelection::GenerateRandomCustomer(TIdent &C_ID, eCustomerTier &C_TIER) {
|
|
// Can't use this function if there is no external RNG.
|
|
//
|
|
if (m_pRND == NULL) {
|
|
return;
|
|
}
|
|
|
|
double fCW = m_pRND->RndDoubleIncrRange(0.0001, 2000, 0.000000001);
|
|
|
|
// Uniformly select the higher portion of the C_ID.
|
|
// Use "short-circuit" logic to avoid unnecessary call to RNG.
|
|
TIdent iCHigh;
|
|
if (m_bPartitionByCID && m_pRND->RndPercent(m_iPartitionPercent)) {
|
|
// Generate a load unit inside the partition.
|
|
iCHigh = (m_pRND->RndInt64Range(m_iMyStartFromCustomer,
|
|
m_iMyStartFromCustomer + m_iMyCustomerCount - 1) -
|
|
1) // minus 1 for the upper boundary case
|
|
/ 1000;
|
|
} else {
|
|
// Generate a load unit across the entire range
|
|
iCHigh = (m_pRND->RndInt64Range(m_iStartFromCustomer,
|
|
m_iStartFromCustomer + m_iCustomerCount - 1) -
|
|
1) // minus 1 for the upper boundary case
|
|
/ 1000;
|
|
}
|
|
|
|
// Non-uniformly select the lower portion of the C_ID.
|
|
//
|
|
int iCLow;
|
|
|
|
if (fCW <= 200) {
|
|
// tier one
|
|
//
|
|
iCLow = (int)ceil(sqrt(22500 + 500 * fCW) - 151);
|
|
|
|
C_TIER = eCustomerTierOne;
|
|
} else {
|
|
if (fCW <= 1400) {
|
|
// tier two
|
|
//
|
|
iCLow = (int)ceil(sqrt(290000 + 1000 * fCW) - 501);
|
|
|
|
C_TIER = eCustomerTierTwo;
|
|
} else {
|
|
// tier three
|
|
//
|
|
iCLow = (int)ceil(149 + sqrt(500 * fCW - 277500));
|
|
|
|
C_TIER = eCustomerTierThree;
|
|
}
|
|
}
|
|
|
|
C_ID = iCHigh * 1000 + Permute(iCLow, iCHigh) + 1;
|
|
}
|
|
|
|
/////////*
|
|
////////* Return a non-uniform random customer and tier.
|
|
////////*/
|
|
////////void CCustomerSelection::GenerateCustomerIdAndTier(TIdent &C_ID,
|
|
/// eCustomerTier &C_TIER, bool bAcrossEntireRange)
|
|
////////{
|
|
//////// // Can't use this function if there is no external RNG.
|
|
//////// //
|
|
//////// if (m_pRND == NULL)
|
|
//////// {
|
|
//////// return;
|
|
//////// }
|
|
////////
|
|
//////// double fCW = m_pRND->RndDoubleRange(0.0001, 2000);
|
|
////////
|
|
//////// // Select uniformly higher portion of the Customer ID.
|
|
//////// //
|
|
//////// TIdent iCHigh;
|
|
//////// if (bAcrossEntireRange)
|
|
//////// {
|
|
//////// // Generate a load unit across the entire range
|
|
//////// iCHigh = (m_pRND->RndInt64Range(1,
|
|
/// m_iAdjustedTotalCustomerCount) - 1) // minus 1 for the upper boundary case
|
|
//////// / 1000;
|
|
//////// if( iCHigh >= ( m_iStartFromCustomer / 1000 ))
|
|
//////// {
|
|
//////// iCHigh += ( m_iCustomerCount / 1000 );
|
|
//////// }
|
|
//////// }
|
|
//////// else
|
|
//////// {
|
|
//////// // Generate a load unit inside the parition.
|
|
//////// iCHigh = (m_pRND->RndInt64Range(m_iStartFromCustomer,
|
|
//////// m_iStartFromCustomer +
|
|
/// m_iCustomerCount - 1) - 1) // minus 1 for the upper boundary case
|
|
//////// / 1000;
|
|
//////// }
|
|
////////
|
|
//////// // Select non-uniformly the lower portion of the Customer ID.
|
|
//////// //
|
|
//////// int iCLow;
|
|
////////
|
|
//////// if (fCW <= 200)
|
|
//////// {
|
|
//////// // tier one
|
|
//////// //
|
|
//////// iCLow = (int) ceil( sqrt(22500 + 500 * fCW) - 151 );
|
|
////////
|
|
//////// C_TIER = eCustomerTierOne;
|
|
//////// }
|
|
//////// else
|
|
//////// {
|
|
//////// if (fCW <=1400)
|
|
//////// {
|
|
//////// // tier two
|
|
//////// //
|
|
//////// iCLow = (int) ceil( sqrt(290000 + 1000 * fCW) - 501 );
|
|
////////
|
|
//////// C_TIER = eCustomerTierTwo;
|
|
//////// }
|
|
//////// else
|
|
//////// {
|
|
//////// // tier three
|
|
//////// //
|
|
//////// iCLow = (int) ceil( 149 + sqrt(500 * fCW - 277500) );
|
|
////////
|
|
//////// C_TIER = eCustomerTierThree;
|
|
//////// }
|
|
//////// }
|
|
////////
|
|
//////// C_ID = iCHigh * 1000 + Permute(iCLow, iCHigh) + 1;
|
|
////////}
|