/* * 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: * Gradient Systems */ #include "config.h" #include "porting.h" #include "init.h" #include #include "address.h" #include "dist.h" #include "r_params.h" #include "genrand.h" #include "columns.h" #include "tables.h" #include "tdefs.h" #include "permute.h" #include "scaling.h" static int s_nCountyCount = 0; static int s_nCityCount = 0; void resetCountCount(void) { s_nCountyCount = 0; s_nCityCount = 0; return; } /* * Routine: * Purpose: * Algorithm: * Data Structures: * * Params: * Returns: * Called By: * Calls: * Assumptions: * Side Effects: * TODO: None */ int mk_address(ds_addr_t *pAddr, int nColumn) { int i, nRegion; char *szZipPrefix, szAddr[100]; static int nMaxCities, nMaxCounties; tdef *pTdef; if (!InitConstants::mk_address_init) { nMaxCities = (int)get_rowcount(ACTIVE_CITIES); nMaxCounties = (int)get_rowcount(ACTIVE_COUNTIES); InitConstants::mk_address_init = 1; } /* street_number is [1..1000] */ genrand_integer(&pAddr->street_num, DIST_UNIFORM, 1, 1000, 0, nColumn); /* street names are picked from a distribution */ pick_distribution(&pAddr->street_name1, "street_names", 1, 1, nColumn); pick_distribution(&pAddr->street_name2, "street_names", 1, 2, nColumn); /* street type is picked from a distribution */ pick_distribution(&pAddr->street_type, "street_type", 1, 1, nColumn); /* suite number is alphabetic 50% of the time */ genrand_integer(&i, DIST_UNIFORM, 1, 100, 0, nColumn); if (i & 0x01) { sprintf(pAddr->suite_num, "Suite %d", (i >> 1) * 10); } else { sprintf(pAddr->suite_num, "Suite %c", ((i >> 1) % 25) + 'A'); } pTdef = getTdefsByNumber(getTableFromColumn(nColumn)); /* city is picked from a distribution which maps to large/medium/small */ if (pTdef->flags & FL_SMALL) { i = (int)get_rowcount(getTableFromColumn(nColumn)); genrand_integer(&i, DIST_UNIFORM, 1, (nMaxCities > i) ? i : nMaxCities, 0, nColumn); dist_member(&pAddr->city, "cities", i, 1); } else pick_distribution(&pAddr->city, "cities", 1, 6, nColumn); /* county is picked from a distribution, based on population and keys the * rest */ if (pTdef->flags & FL_SMALL) { i = (int)get_rowcount(getTableFromColumn(nColumn)); genrand_integer(&nRegion, DIST_UNIFORM, 1, (nMaxCounties > i) ? i : nMaxCounties, 0, nColumn); dist_member(&pAddr->county, "fips_county", nRegion, 2); } else nRegion = pick_distribution(&pAddr->county, "fips_county", 2, 1, nColumn); /* match state with the selected region/county */ dist_member(&pAddr->state, "fips_county", nRegion, 3); /* match the zip prefix with the selected region/county */ pAddr->zip = city_hash(0, pAddr->city); /* 00000 - 00600 are unused. Avoid them */ dist_member((void *)&szZipPrefix, "fips_county", nRegion, 5); if (!(szZipPrefix[0] - '0') && (pAddr->zip < 9400)) pAddr->zip += 600; pAddr->zip += (szZipPrefix[0] - '0') * 10000; sprintf(szAddr, "%d %s %s %s", pAddr->street_num, pAddr->street_name1, pAddr->street_name2, pAddr->street_type); pAddr->plus4 = city_hash(0, szAddr); dist_member(&pAddr->gmt_offset, "fips_county", nRegion, 6); strcpy(pAddr->country, "United States"); return (0); } /* * Routine: mk_streetnumber * Purpose: * one of a set of routines that creates addresses * Algorithm: * Data Structures: * * Params: * nTable: target table (and, by extension, address) to allow differing *distributions dest: destination for the random number Returns: Called By: * Calls: * Assumptions: * Side Effects: * TODO: 20030422 jms should be replaced if there is no table variation */ int mk_streetnumber(int nTable, int *dest) { genrand_integer(dest, DIST_UNIFORM, 1, 1000, 0, nTable); return (0); } /* * Routine: mk_suitenumber() * Purpose: * one of a set of routines that creates addresses * Algorithm: * Data Structures: * * Params: * nTable: target table (and, by extension, address) to allow differing *distributions dest: destination for the random number Returns: Called By: * Calls: * Assumptions: * Side Effects: * TODO: 20010615 JMS return code is meaningless */ int mk_suitenumber(int nTable, char *dest) { int i; genrand_integer(&i, DIST_UNIFORM, 1, 100, 0, nTable); if (i <= 50) { genrand_integer(&i, DIST_UNIFORM, 1, 1000, 0, nTable); sprintf(dest, "Suite %d", i); } else { genrand_integer(&i, DIST_UNIFORM, 0, 25, 0, nTable); sprintf(dest, "Suite %c", i + 'A'); } return (0); } /* * Routine: mk_streetname() * Purpose: * one of a set of routines that creates addresses * Algorithm: * use a staggered distibution and the 150 most common street names in the US * Data Structures: * * Params: * nTable: target table (and, by extension, address) to allow differing *distributions dest: destination for the street name Returns: Called By: Calls: * Assumptions: * Side Effects: * TODO: 20010615 JMS return code is meaningless */ int mk_streetname(int nTable, char *dest) { char *pTemp1 = NULL, *pTemp2 = NULL; pick_distribution((void *)&pTemp1, "street_names", (int)1, (int)1, nTable); pick_distribution((void *)&pTemp2, "street_names", (int)1, (int)2, nTable); if (strlen(pTemp2)) sprintf(dest, "%s %s", pTemp1, pTemp2); else strcpy(dest, pTemp1); return (0); } /* * Routine: mk_city * Purpose: * one of a set of routines that creates addresses * Algorithm: * use a staggered distibution of 1000 most common place names in the US * Data Structures: * * Params: * nTable: target table (and, by extension, address) to allow differing *distributions dest: destination for the city name Returns: Called By: Calls: * Assumptions: * Side Effects: * TODO: 20030423 jms should be replaced if there is no per-table variation */ int mk_city(int nTable, char **dest) { pick_distribution((void *)dest, "cities", (int)1, (int)get_int("_SCALE_INDEX"), 11); return (0); } /* * Routine: city_hash() * Purpose: * Algorithm: * Data Structures: * * Params: * Returns: * Called By: * Calls: * Assumptions: * Side Effects: * TODO: None */ int city_hash(int nTable, char *name) { char *cp; long long hash_value = 0, res = 0; // changed to long long from int for (cp = name; *cp; cp++) { hash_value *= 26; // simulate the overflow as if it were an int if (hash_value > MAXINT) { hash_value %= MAXINT; hash_value -= MAXINT; hash_value -= 2; } else if (hash_value < -MAXINT) { hash_value %= MAXINT; hash_value += MAXINT; hash_value += 2; } hash_value -= 'A'; hash_value += *cp; if (hash_value > 1000000) { hash_value %= 10000; res += hash_value; hash_value = 0; } } hash_value %= 1000; res += hash_value; res %= 10000; /* looking for a 4 digit result */ return (res); } /* * Routine: * one of a set of routines that creates addresses * Algorithm: * use a compound distribution of the 3500 counties in the US * Data Structures: * * Params: * nTable: target table (and, by extension, address) to allow differing *distributions dest: destination for the city name nRegion: the county selected * city: the city name selected * Returns: * Called By: * Calls: * Assumptions: * Side Effects: * TODO: 20010615 JMS return code is meaningless */ int mk_zipcode(int nTable, char *dest, int nRegion, char *city) { char *szZipPrefix = NULL; int nCityCode; int nPlusFour; dist_member((void *)&szZipPrefix, "fips_county", nRegion, 5); nCityCode = city_hash(nTable, city); genrand_integer(&nPlusFour, DIST_UNIFORM, 1, 9999, 0, nTable); sprintf(dest, "%s%04d-%04d", szZipPrefix, nCityCode, nPlusFour); return (0); }