typedef struct WhereOrCost WhereOrCost;
typedef struct WhereOrSet WhereOrSet;
-/*
-** Cost X is tracked as 10*log2(X) stored in a 16-bit integer. The
-** maximum cost for ordinary tables is 64*(2**63) which becomes 6900.
-** (Virtual tables can return a larger cost, but let's assume they do not.)
-** So all costs can be stored in a 16-bit integer without risk
-** of overflow.
-**
-** Costs are estimates, so no effort is made to compute 10*log2(X) exactly.
-** Instead, a close estimate is used. Any value of X=1 is stored as 0.
-** X=2 is 10. X=3 is 16. X=1000 is 99. etc. Negative values are allowed.
-** A WhereCost of -10 means 0.5. WhereCost of -20 means 0.25. And so forth.
-**
-** The tool/wherecosttest.c source file implements a command-line program
-** that will convert WhereCosts to integers, convert integers to WhereCosts
-** and do addition and multiplication on WhereCost values. The wherecosttest
-** command-line program is a useful utility to have around when working with
-** this module.
-*/
-typedef short int WhereCost;
-
/*
** This object contains information needed to implement a single nested
** loop in WHERE clause.
#endif
u8 iTab; /* Position in FROM clause of table for this loop */
u8 iSortIdx; /* Sorting index number. 0==None */
- WhereCost rSetup; /* One-time setup cost (ex: create transient index) */
- WhereCost rRun; /* Cost of running each loop */
- WhereCost nOut; /* Estimated number of output rows */
+ LogEst rSetup; /* One-time setup cost (ex: create transient index) */
+ LogEst rRun; /* Cost of running each loop */
+ LogEst nOut; /* Estimated number of output rows */
union {
struct { /* Information for internal btree tables */
int nEq; /* Number of equality constraints */
*/
struct WhereOrCost {
Bitmask prereq; /* Prerequisites */
- WhereCost rRun; /* Cost of running this subquery */
- WhereCost nOut; /* Number of outputs for this subquery */
+ LogEst rRun; /* Cost of running this subquery */
+ LogEst nOut; /* Number of outputs for this subquery */
};
/* The WhereOrSet object holds a set of possible WhereOrCosts that
struct WherePath {
Bitmask maskLoop; /* Bitmask of all WhereLoop objects in this path */
Bitmask revLoop; /* aLoop[]s that should be reversed for ORDER BY */
- WhereCost nRow; /* Estimated number of rows generated by this path */
- WhereCost rCost; /* Total cost of this path */
+ LogEst nRow; /* Estimated number of rows generated by this path */
+ LogEst rCost; /* Total cost of this path */
u8 isOrdered; /* True if this path satisfies ORDER BY */
u8 isOrderedValid; /* True if the isOrdered field is valid */
WhereLoop **aLoop; /* Array of WhereLoop objects implementing this path */
WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */
WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
} u;
- WhereCost truthProb; /* Probability of truth for this expression */
+ LogEst truthProb; /* Probability of truth for this expression */
u16 eOperator; /* A WO_xx value describing <op> */
u8 wtFlags; /* TERM_xxx bit flags. See below */
u8 nChild; /* Number of children that must disable us */
ExprList *pResultSet; /* Result set. DISTINCT operates on these */
WhereLoop *pLoops; /* List of all WhereLoop objects */
Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
- WhereCost nRowOut; /* Estimated number of output rows */
+ LogEst nRowOut; /* Estimated number of output rows */
u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
u8 bOBSat; /* ORDER BY satisfied by indices */
u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */
#define WHERE_MULTI_OR 0x00002000 /* OR using multiple indices */
#define WHERE_AUTO_INDEX 0x00004000 /* Uses an ephemeral index */
-
-/* Convert a WhereCost value (10 times log2(X)) into its integer value X.
-** A rough approximation is used. The value returned is not exact.
-*/
-static u64 whereCostToInt(WhereCost x){
- u64 n;
- if( x<10 ) return 1;
- n = x%10;
- x /= 10;
- if( n>=5 ) n -= 2;
- else if( n>=1 ) n -= 1;
- if( x>=3 ) return (n+8)<<(x-3);
- return (n+8)>>(3-x);
-}
-
/*
** Return the estimated number of output rows from a WHERE clause
*/
u64 sqlite3WhereOutputRowCount(WhereInfo *pWInfo){
- return whereCostToInt(pWInfo->nRowOut);
+ return sqlite3LogEstToInt(pWInfo->nRowOut);
}
/*
static int whereOrInsert(
WhereOrSet *pSet, /* The WhereOrSet to be updated */
Bitmask prereq, /* Prerequisites of the new entry */
- WhereCost rRun, /* Run-cost of the new entry */
- WhereCost nOut /* Number of outputs for the new entry */
+ LogEst rRun, /* Run-cost of the new entry */
+ LogEst nOut /* Number of outputs for the new entry */
){
u16 i;
WhereOrCost *p;
}
}
-/* Forward declaration */
-static WhereCost whereCost(tRowcnt x);
-
/*
** Add a single new WhereTerm entry to the WhereClause object pWC.
** The new WhereTerm object is constructed from Expr p and with wtFlags.
}
pTerm = &pWC->a[idx = pWC->nTerm++];
if( p && ExprHasProperty(p, EP_Unlikely) ){
- pTerm->truthProb = whereCost(p->iTable) - 99;
+ pTerm->truthProb = sqlite3LogEst(p->iTable) - 99;
}else{
pTerm->truthProb = -1;
}
return 0;
}
-/*
-** Find (an approximate) sum of two WhereCosts. This computation is
-** not a simple "+" operator because WhereCost is stored as a logarithmic
-** value.
-**
-*/
-static WhereCost whereCostAdd(WhereCost a, WhereCost b){
- static const unsigned char x[] = {
- 10, 10, /* 0,1 */
- 9, 9, /* 2,3 */
- 8, 8, /* 4,5 */
- 7, 7, 7, /* 6,7,8 */
- 6, 6, 6, /* 9,10,11 */
- 5, 5, 5, /* 12-14 */
- 4, 4, 4, 4, /* 15-18 */
- 3, 3, 3, 3, 3, 3, /* 19-24 */
- 2, 2, 2, 2, 2, 2, 2, /* 25-31 */
- };
- if( a>=b ){
- if( a>b+49 ) return a;
- if( a>b+31 ) return a+1;
- return a+x[a-b];
- }else{
- if( b>a+49 ) return b;
- if( b>a+31 ) return b+1;
- return b+x[b-a];
- }
-}
-
-/*
-** Convert an integer into a WhereCost. In other words, compute a
-** good approximatation for 10*log2(x).
-*/
-static WhereCost whereCost(tRowcnt x){
- static WhereCost a[] = { 0, 2, 3, 5, 6, 7, 8, 9 };
- WhereCost y = 40;
- if( x<8 ){
- if( x<2 ) return 0;
- while( x<8 ){ y -= 10; x <<= 1; }
- }else{
- while( x>255 ){ y += 40; x >>= 4; }
- while( x>15 ){ y += 10; x >>= 1; }
- }
- return a[x&7] + y - 10;
-}
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-/*
-** Convert a double (as received from xBestIndex of a virtual table)
-** into a WhereCost. In other words, compute an approximation for
-** 10*log2(x).
-*/
-static WhereCost whereCostFromDouble(double x){
- u64 a;
- WhereCost e;
- assert( sizeof(x)==8 && sizeof(a)==8 );
- if( x<=1 ) return 0;
- if( x<=2000000000 ) return whereCost((tRowcnt)x);
- memcpy(&a, &x, 8);
- e = (a>>52) - 1022;
- return e*10;
-}
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
/*
** Estimate the logarithm of the input value to base 2.
*/
-static WhereCost estLog(WhereCost N){
- WhereCost x = whereCost(N);
+static LogEst estLog(LogEst N){
+ LogEst x = sqlite3LogEst(N);
return x>33 ? x - 33 : 0;
}
**
** then nEq is set to 0.
**
-** When this function is called, *pnOut is set to the whereCost() of the
+** When this function is called, *pnOut is set to the sqlite3LogEst() of the
** number of rows that the index scan is expected to visit without
** considering the range constraints. If nEq is 0, this is the number of
** rows in the index. Assuming no error occurs, *pnOut is adjusted (reduced)
WhereLoopBuilder *pBuilder,
WhereTerm *pLower, /* Lower bound on the range. ex: "x>123" Might be NULL */
WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */
- WhereCost *pnOut /* IN/OUT: Number of rows visited */
+ LogEst *pnOut /* IN/OUT: Number of rows visited */
){
int rc = SQLITE_OK;
int nOut = (int)*pnOut;
- WhereCost nNew;
+ LogEst nNew;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
Index *p = pBuilder->pNew->u.btree.pIndex;
pBuilder->pRec = pRec;
if( rc==SQLITE_OK ){
if( iUpper>iLower ){
- nNew = whereCost(iUpper - iLower);
+ nNew = sqlite3LogEst(iUpper - iLower);
}else{
- nNew = 10; assert( 10==whereCost(2) );
+ nNew = 10; assert( 10==sqlite3LogEst(2) );
}
if( nNew<nOut ){
nOut = nNew;
}
- *pnOut = (WhereCost)nOut;
+ *pnOut = (LogEst)nOut;
WHERETRACE(0x100, ("range scan regions: %u..%u est=%d\n",
(u32)iLower, (u32)iUpper, nOut));
return SQLITE_OK;
** A BETWEEN operator, therefore, reduces the search space 16-fold */
nNew = nOut;
if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ){
- nNew -= 20; assert( 20==whereCost(4) );
+ nNew -= 20; assert( 20==sqlite3LogEst(4) );
nOut--;
}
if( pUpper ){
- nNew -= 20; assert( 20==whereCost(4) );
+ nNew -= 20; assert( 20==sqlite3LogEst(4) );
nOut--;
}
if( nNew<10 ) nNew = 10;
if( nNew<nOut ) nOut = nNew;
- *pnOut = (WhereCost)nOut;
+ *pnOut = (LogEst)nOut;
return rc;
}
WhereLoopBuilder *pBuilder, /* The WhereLoop factory */
struct SrcList_item *pSrc, /* FROM clause term being analyzed */
Index *pProbe, /* An index on pSrc */
- WhereCost nInMul /* log(Number of iterations due to IN) */
+ LogEst nInMul /* log(Number of iterations due to IN) */
){
WhereInfo *pWInfo = pBuilder->pWInfo; /* WHERE analyse context */
Parse *pParse = pWInfo->pParse; /* Parsing context */
u16 saved_nLTerm; /* Original value of pNew->nLTerm */
int saved_nEq; /* Original value of pNew->u.btree.nEq */
u32 saved_wsFlags; /* Original value of pNew->wsFlags */
- WhereCost saved_nOut; /* Original value of pNew->nOut */
+ LogEst saved_nOut; /* Original value of pNew->nOut */
int iCol; /* Index of the column in the table */
int rc = SQLITE_OK; /* Return code */
- WhereCost nRowEst; /* Estimated index selectivity */
- WhereCost rLogSize; /* Logarithm of table size */
+ LogEst nRowEst; /* Estimated index selectivity */
+ LogEst rLogSize; /* Logarithm of table size */
WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */
pNew = pBuilder->pNew;
assert( pNew->u.btree.nEq<=pProbe->nColumn );
if( pNew->u.btree.nEq < pProbe->nColumn ){
iCol = pProbe->aiColumn[pNew->u.btree.nEq];
- nRowEst = whereCost(pProbe->aiRowEst[pNew->u.btree.nEq+1]);
+ nRowEst = sqlite3LogEst(pProbe->aiRowEst[pNew->u.btree.nEq+1]);
if( nRowEst==0 && pProbe->onError==OE_None ) nRowEst = 1;
}else{
iCol = -1;
saved_prereq = pNew->prereq;
saved_nOut = pNew->nOut;
pNew->rSetup = 0;
- rLogSize = estLog(whereCost(pProbe->aiRowEst[0]));
+ rLogSize = estLog(sqlite3LogEst(pProbe->aiRowEst[0]));
for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){
int nIn = 0;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
pNew->wsFlags |= WHERE_COLUMN_IN;
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
/* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */
- nIn = 46; assert( 46==whereCost(25) );
+ nIn = 46; assert( 46==sqlite3LogEst(25) );
}else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
/* "x IN (value, value, ...)" */
- nIn = whereCost(pExpr->x.pList->nExpr);
+ nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
}
pNew->rRun += nIn;
pNew->u.btree.nEq++;
pNew->wsFlags |= WHERE_COLUMN_NULL;
pNew->u.btree.nEq++;
/* TUNING: IS NULL selects 2 rows */
- nIn = 10; assert( 10==whereCost(2) );
+ nIn = 10; assert( 10==sqlite3LogEst(2) );
pNew->nOut = nRowEst + nInMul + nIn;
}else if( pTerm->eOperator & (WO_GT|WO_GE) ){
testcase( pTerm->eOperator & WO_GT );
}
assert( nOut==0 || rc==SQLITE_OK );
if( nOut ){
- nOut = whereCost(nOut);
+ nOut = sqlite3LogEst(nOut);
pNew->nOut = MIN(nOut, saved_nOut);
}
}
if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){
/* Each row involves a step of the index, then a binary search of
** the main table */
- pNew->rRun = whereCostAdd(pNew->rRun, rLogSize>27 ? rLogSize-17 : 10);
+ pNew->rRun = sqlite3LogEstAdd(pNew->rRun,rLogSize>27 ? rLogSize-17 : 10);
}
/* Step cost for each output row */
- pNew->rRun = whereCostAdd(pNew->rRun, pNew->nOut);
+ pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut);
whereLoopOutputAdjust(pBuilder->pWC, pNew, pSrc->iCursor);
rc = whereLoopInsert(pBuilder, pNew);
if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
int rc = SQLITE_OK; /* Return code */
int iSortIdx = 1; /* Index number */
int b; /* A boolean value */
- WhereCost rSize; /* number of rows in the table */
- WhereCost rLogSize; /* Logarithm of the number of rows in the table */
+ LogEst rSize; /* number of rows in the table */
+ LogEst rLogSize; /* Logarithm of the number of rows in the table */
WhereClause *pWC; /* The parsed WHERE clause */
pNew = pBuilder->pNew;
}
pProbe = &sPk;
}
- rSize = whereCost(pSrc->pTab->nRowEst);
+ rSize = sqlite3LogEst(pSrc->pTab->nRowEst);
rLogSize = estLog(rSize);
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
/* TUNING: One-time cost for computing the automatic index is
** approximately 7*N*log2(N) where N is the number of rows in
** the table being indexed. */
- pNew->rSetup = rLogSize + rSize + 28; assert( 28==whereCost(7) );
+ pNew->rSetup = rLogSize + rSize + 28; assert( 28==sqlite3LogEst(7) );
/* TUNING: Each index lookup yields 20 rows in the table. This
** is more than the usual guess of 10 rows, since we have no way
** of knowning how selective the index will ultimately be. It would
** not be unreasonable to make this value much larger. */
- pNew->nOut = 43; assert( 43==whereCost(20) );
- pNew->rRun = whereCostAdd(rLogSize,pNew->nOut);
+ pNew->nOut = 43; assert( 43==sqlite3LogEst(20) );
+ pNew->rRun = sqlite3LogEstAdd(rLogSize,pNew->nOut);
pNew->wsFlags = WHERE_AUTO_INDEX;
pNew->prereq = mExtra | pTerm->prereqRight;
rc = whereLoopInsert(pBuilder, pNew);
/* Full table scan */
pNew->iSortIdx = b ? iSortIdx : 0;
/* TUNING: Cost of full table scan is 3*(N + log2(N)).
- ** + The extra 4 factor is to encourage the use of indexed lookups
+ ** + The extra 3 factor is to encourage the use of indexed lookups
** over full scans. */
- pNew->rRun = whereCostAdd(rSize,rLogSize) + 16;
+ pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + 16;
whereLoopOutputAdjust(pWC, pNew, pSrc->iCursor);
rc = whereLoopInsert(pBuilder, pNew);
pNew->nOut = rSize;
pNew->iSortIdx = b ? iSortIdx : 0;
if( m==0 ){
/* TUNING: Cost of a covering index scan is K*(N + log2(N)).
- ** + The extra factor K of between 1.0 and 3.0 is added to
- ** encourage the use of indexed lookups. The value of K
- ** depends on the iScanRatio value for the index.
+ ** + The extra factor K of between 1.1 (iScanRatio between 0
+ ** and 9) and 2.8 (iScanRatio between 126 and 127) is added
+ ** to encourage the use of indexed lookups.
*/
- pNew->rRun = whereCostAdd(rSize,rLogSize) + pProbe->iScanRatio/9 + 1;
+ pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + pProbe->iScanRatio/9 + 1;
}else{
assert( b!=0 );
/* TUNING: Cost of scanning a non-covering index is (N+1)*log2(N)
pNew->u.vtab.isOrdered = (u8)((pIdxInfo->nOrderBy!=0)
&& pIdxInfo->orderByConsumed);
pNew->rSetup = 0;
- pNew->rRun = whereCostFromDouble(pIdxInfo->estimatedCost);
+ pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost);
/* TUNING: Every virtual table query returns 25 rows */
- pNew->nOut = 46; assert( 46==whereCost(25) );
+ pNew->nOut = 46; assert( 46==sqlite3LogEst(25) );
whereLoopInsert(pBuilder, pNew);
if( pNew->u.vtab.needFree ){
sqlite3_free(pNew->u.vtab.idxStr);
for(i=0; i<sPrev.n; i++){
for(j=0; j<sCur.n; j++){
whereOrInsert(&sSum, sPrev.a[i].prereq | sCur.a[j].prereq,
- whereCostAdd(sPrev.a[i].rRun, sCur.a[j].rRun),
- whereCostAdd(sPrev.a[i].nOut, sCur.a[j].nOut));
+ sqlite3LogEstAdd(sPrev.a[i].rRun, sCur.a[j].rRun),
+ sqlite3LogEstAdd(sPrev.a[i].nOut, sCur.a[j].nOut));
}
}
}
** Return SQLITE_OK on success or SQLITE_NOMEM of a memory allocation
** error occurs.
*/
-static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
+static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
int mxChoice; /* Maximum number of simultaneous paths tracked */
int nLoop; /* Number of terms in the join */
Parse *pParse; /* Parsing context */
int iLoop; /* Loop counter over the terms of the join */
int ii, jj; /* Loop counters */
int mxI = 0; /* Index of next entry to replace */
- WhereCost rCost; /* Cost of a path */
- WhereCost nOut; /* Number of outputs */
- WhereCost mxCost = 0; /* Maximum cost of a set of paths */
- WhereCost mxOut = 0; /* Maximum nOut value on the set of paths */
- WhereCost rSortCost; /* Cost to do a sort */
+ LogEst rCost; /* Cost of a path */
+ LogEst nOut; /* Number of outputs */
+ LogEst mxCost = 0; /* Maximum cost of a set of paths */
+ LogEst mxOut = 0; /* Maximum nOut value on the set of paths */
+ LogEst rSortCost; /* Cost to do a sort */
int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */
WherePath *aFrom; /* All nFrom paths at the previous level */
WherePath *aTo; /* The nTo best paths at the current level */
** TUNING: Do not let the number of iterations go above 25. If the cost
** of computing an automatic index is not paid back within the first 25
** rows, then do not use the automatic index. */
- aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==whereCost(25) );
+ aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==sqlite3LogEst(25) );
nFrom = 1;
/* Precompute the cost of sorting the final result set, if the caller
if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue;
/* At this point, pWLoop is a candidate to be the next loop.
** Compute its cost */
- rCost = whereCostAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
- rCost = whereCostAdd(rCost, pFrom->rCost);
+ rCost = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
+ rCost = sqlite3LogEstAdd(rCost, pFrom->rCost);
nOut = pFrom->nRow + pWLoop->nOut;
maskNew = pFrom->maskLoop | pWLoop->maskSelf;
if( !isOrderedValid ){
case 0: /* No. pFrom+pWLoop will require a separate sort */
isOrdered = 0;
isOrderedValid = 1;
- rCost = whereCostAdd(rCost, rSortCost);
+ rCost = sqlite3LogEstAdd(rCost, rSortCost);
break;
default: /* Cannot tell yet. Try again on the next iteration */
break;
pLoop->nLTerm = 1;
pLoop->u.btree.nEq = 1;
/* TUNING: Cost of a rowid lookup is 10 */
- pLoop->rRun = 33; /* 33==whereCost(10) */
+ pLoop->rRun = 33; /* 33==sqlite3LogEst(10) */
}else{
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
assert( pLoop->aLTermSpace==pLoop->aLTerm );
pLoop->u.btree.nEq = j;
pLoop->u.btree.pIndex = pIdx;
/* TUNING: Cost of a unique index lookup is 15 */
- pLoop->rRun = 39; /* 39==whereCost(15) */
+ pLoop->rRun = 39; /* 39==sqlite3LogEst(15) */
break;
}
}
if( pLoop->wsFlags ){
- pLoop->nOut = (WhereCost)1;
+ pLoop->nOut = (LogEst)1;
pWInfo->a[0].pWLoop = pLoop;
pLoop->maskSelf = getMask(&pWInfo->sMaskSet, iCur);
pWInfo->a[0].iTabCur = iCur;
**
*************************************************************************
** This file contains a simple command-line utility for converting from
-** integers and WhereCost values and back again and for doing simple
-** arithmetic operations (multiple and add) on WhereCost values.
+** integers and LogEst values and back again and for doing simple
+** arithmetic operations (multiple and add) on LogEst values.
**
** Usage:
**
-** ./wherecosttest ARGS
+** ./LogEst ARGS
**
** Arguments:
**
** 'x' Multiple the top two elements of the stack
** '+' Add the top two elements of the stack
-** NUM Convert NUM from integer to WhereCost and push onto the stack
-** ^NUM Interpret NUM as a WhereCost and push onto stack.
+** NUM Convert NUM from integer to LogEst and push onto the stack
+** ^NUM Interpret NUM as a LogEst and push onto stack.
**
** Examples:
**
-** To convert 123 from WhereCost to integer:
+** To convert 123 from LogEst to integer:
**
-** ./wherecosttest ^123
+** ./LogEst ^123
**
-** To convert 123456 from integer to WhereCost:
+** To convert 123456 from integer to LogEst:
**
-** ./wherecosttest 123456
+** ./LogEst 123456
**
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
+#include <assert.h>
+#include <string.h>
+#include "sqlite3.h"
-typedef unsigned short int WhereCost; /* 10 times log2() */
+typedef short int LogEst; /* 10 times log2() */
-WhereCost whereCostMultiply(WhereCost a, WhereCost b){ return a+b; }
-WhereCost whereCostAdd(WhereCost a, WhereCost b){
+LogEst logEstMultiply(LogEst a, LogEst b){ return a+b; }
+LogEst logEstAdd(LogEst a, LogEst b){
static const unsigned char x[] = {
10, 10, /* 0,1 */
9, 9, /* 2,3 */
3, 3, 3, 3, 3, 3, /* 19-24 */
2, 2, 2, 2, 2, 2, 2, /* 25-31 */
};
- if( a<b ){ WhereCost t = a; a = b; b = t; }
+ if( a<b ){ LogEst t = a; a = b; b = t; }
if( a>b+49 ) return a;
if( a>b+31 ) return a+1;
return a+x[a-b];
}
-WhereCost whereCostFromInteger(int x){
- static WhereCost a[] = { 0, 2, 3, 5, 6, 7, 8, 9 };
- WhereCost y = 40;
+LogEst logEstFromInteger(sqlite3_uint64 x){
+ static LogEst a[] = { 0, 2, 3, 5, 6, 7, 8, 9 };
+ LogEst y = 40;
if( x<8 ){
if( x<2 ) return 0;
while( x<8 ){ y -= 10; x <<= 1; }
}
return a[x&7] + y - 10;
}
-static unsigned long int whereCostToInt(WhereCost x){
+static unsigned long int logEstToInt(LogEst x){
unsigned long int n;
if( x<10 ) return 1;
n = x%10;
if( x>=3 ) return (n+8)<<(x-3);
return (n+8)>>(3-x);
}
+static LogEst logEstFromDouble(double x){
+ sqlite3_uint64 a;
+ LogEst e;
+ assert( sizeof(x)==8 && sizeof(a)==8 );
+ if( x<=0 ) return -32768;
+ if( x<1 ) return -logEstFromDouble(1/x);
+ if( x<=2000000000 ) return logEstFromInteger((sqlite3_uint64)x);
+ memcpy(&a, &x, 8);
+ e = (a>>52) - 1022;
+ return e*10;
+}
+
+int isFloat(const char *z){
+ while( z[0] ){
+ if( z[0]=='.' || z[0]=='E' || z[0]=='e' ) return 1;
+ z++;
+ }
+ return 0;
+}
int main(int argc, char **argv){
int i;
int n = 0;
- WhereCost a[100];
+ LogEst a[100];
for(i=1; i<argc; i++){
const char *z = argv[i];
if( z[0]=='+' ){
if( n>=2 ){
- a[n-2] = whereCostAdd(a[n-2],a[n-1]);
+ a[n-2] = logEstAdd(a[n-2],a[n-1]);
n--;
}
}else if( z[0]=='x' ){
if( n>=2 ){
- a[n-2] = whereCostMultiply(a[n-2],a[n-1]);
+ a[n-2] = logEstMultiply(a[n-2],a[n-1]);
n--;
}
}else if( z[0]=='^' ){
a[n++] = atoi(z+1);
+ }else if( isFloat(z) ){
+ a[n++] = logEstFromDouble(atof(z));
}else{
- a[n++] = whereCostFromInteger(atoi(z));
+ a[n++] = logEstFromInteger(atoi(z));
}
}
for(i=n-1; i>=0; i--){
- printf("%d (%lu)\n", a[i], whereCostToInt(a[i]));
+ if( a[i]<0 ){
+ printf("%d (%f)\n", a[i], 1.0/(double)logEstToInt(-a[i]));
+ }else{
+ printf("%d (%lu)\n", a[i], logEstToInt(a[i]));
+ }
}
return 0;
}