Files
email-tracker/external/duckdb/third_party/tpce-tool/main/CustomerSelection.cpp
2025-10-24 19:21:19 -05:00

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;
////////}