Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

684 lines
15 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #ifndef STDIO_H
  9. #include <stdio.h>
  10. #endif
  11. #ifndef STRING_H
  12. #include <string.h>
  13. #endif
  14. #ifndef QUANTIZE_H
  15. #include <quantize.h>
  16. #endif
  17. #include <stdlib.h>
  18. #include <math.h>
  19. // NOTE: This has to be the last file included!
  20. #include "tier0/memdbgon.h"
  21. static int current_ndims;
  22. static struct QuantizedValue *current_root;
  23. static int current_ssize;
  24. static uint8 *current_weights;
  25. double SquaredError;
  26. #define SPLIT_THEN_SORT 1
  27. #define SQ(x) ((x)*(x))
  28. static struct QuantizedValue *AllocQValue(void)
  29. {
  30. struct QuantizedValue *ret=new QuantizedValue;
  31. ret->Samples=0;
  32. ret->Children[0]=ret->Children[1]=0;
  33. ret->NSamples=0;
  34. ret->ErrorMeasure=new double[current_ndims];
  35. ret->Mean=new uint8[current_ndims];
  36. ret->Mins=new uint8[current_ndims];
  37. ret->Maxs=new uint8[current_ndims];
  38. ret->Sums=new int [current_ndims];
  39. memset(ret->Sums,0,sizeof(int)*current_ndims);
  40. ret->NQuant=0;
  41. ret->sortdim=-1;
  42. return ret;
  43. }
  44. void FreeQuantization(struct QuantizedValue *t)
  45. {
  46. if (t)
  47. {
  48. delete[] t->ErrorMeasure;
  49. delete[] t->Mean;
  50. delete[] t->Mins;
  51. delete[] t->Maxs;
  52. FreeQuantization(t->Children[0]);
  53. FreeQuantization(t->Children[1]);
  54. delete[] t->Sums;
  55. delete[] t;
  56. }
  57. }
  58. static int QNumSort(void const *a, void const *b)
  59. {
  60. int32 as=((struct Sample *) a)->QNum;
  61. int32 bs=((struct Sample *) b)->QNum;
  62. if (as==bs) return 0;
  63. return (as>bs)?1:-1;
  64. }
  65. #if SPLIT_THEN_SORT
  66. #else
  67. static int current_sort_dim;
  68. static int samplesort(void const *a, void const *b)
  69. {
  70. uint8 as=((struct Sample *) a)->Value[current_sort_dim];
  71. uint8 bs=((struct Sample *) b)->Value[current_sort_dim];
  72. if (as==bs) return 0;
  73. return (as>bs)?1:-1;
  74. }
  75. #endif
  76. static int sortlong(void const *a, void const *b)
  77. {
  78. // treat the entire vector of values as a long integer for duplicate removal.
  79. return memcmp(((struct Sample *) a)->Value,
  80. ((struct Sample *) b)->Value,current_ndims);
  81. }
  82. #define NEXTSAMPLE(s) ( (struct Sample *) (((uint8 *) s)+current_ssize))
  83. #define SAMPLE(s,i) NthSample(s,i,current_ndims)
  84. static void SetNDims(int n)
  85. {
  86. current_ssize=sizeof(struct Sample)+(n-1);
  87. current_ndims=n;
  88. }
  89. int CompressSamples(struct Sample *s, int nsamples, int ndims)
  90. {
  91. SetNDims(ndims);
  92. qsort(s,nsamples,current_ssize,sortlong);
  93. // now, they are all sorted by treating all dimensions as a large number.
  94. // we may now remove duplicates.
  95. struct Sample *src=s;
  96. struct Sample *dst=s;
  97. struct Sample *lastdst=dst;
  98. dst=NEXTSAMPLE(dst); // copy first sample to get the ball rolling
  99. src=NEXTSAMPLE(src);
  100. int noutput=1;
  101. while(--nsamples) // while some remain
  102. {
  103. if (memcmp(src->Value,lastdst->Value,current_ndims))
  104. {
  105. // yikes, a difference has been found!
  106. memcpy(dst,src,current_ssize);
  107. lastdst=dst;
  108. dst=NEXTSAMPLE(dst);
  109. noutput++;
  110. }
  111. else
  112. lastdst->Count++;
  113. src=NEXTSAMPLE(src);
  114. }
  115. return noutput;
  116. }
  117. void PrintSamples(struct Sample const *s, int nsamples, int ndims)
  118. {
  119. SetNDims(ndims);
  120. int cnt=0;
  121. while(nsamples--)
  122. {
  123. printf("sample #%d, count=%d, values=\n { ",cnt++,s->Count);
  124. for(int d=0;d<ndims;d++)
  125. printf("%02x,",s->Value[d]);
  126. printf("}\n");
  127. s=NEXTSAMPLE(s);
  128. }
  129. }
  130. void PrintQTree(struct QuantizedValue const *p,int idlevel)
  131. {
  132. int i;
  133. if (p)
  134. {
  135. for(i=0;i<idlevel;i++)
  136. printf(" ");
  137. printf("node=%p NSamples=%d value=%d Mean={",p,p->NSamples,p->value);
  138. for(i=0;i<current_ndims;i++)
  139. printf("%x,",p->Mean[i]);
  140. printf("}\n");
  141. for(i=0;i<idlevel;i++)
  142. printf(" ");
  143. printf("Errors={");
  144. for(i=0;i<current_ndims;i++)
  145. printf("%f,",p->ErrorMeasure[i]);
  146. printf("}\n");
  147. for(i=0;i<idlevel;i++)
  148. printf(" ");
  149. printf("Mins={");
  150. for(i=0;i<current_ndims;i++)
  151. printf("%d,",p->Mins[i]);
  152. printf("} Maxs={");
  153. for(i=0;i<current_ndims;i++)
  154. printf("%d,",p->Maxs[i]);
  155. printf("}\n");
  156. PrintQTree(p->Children[0],idlevel+2);
  157. PrintQTree(p->Children[1],idlevel+2);
  158. }
  159. }
  160. static void UpdateStats(struct QuantizedValue *v)
  161. {
  162. // first, find mean
  163. int32 Means[MAXDIMS];
  164. double Errors[MAXDIMS];
  165. double WorstError[MAXDIMS];
  166. int i,j;
  167. memset(Means,0,sizeof(Means));
  168. int N=0;
  169. for(i=0;i<v->NSamples;i++)
  170. {
  171. struct Sample *s=SAMPLE(v->Samples,i);
  172. N+=s->Count;
  173. for(j=0;j<current_ndims;j++)
  174. {
  175. uint8 v=s->Value[j];
  176. Means[j]+=v*s->Count;
  177. }
  178. }
  179. for(j=0;j<current_ndims;j++)
  180. {
  181. if (N) v->Mean[j]=(uint8) (Means[j]/N);
  182. Errors[j]=WorstError[j]=0.;
  183. }
  184. for(i=0;i<v->NSamples;i++)
  185. {
  186. struct Sample *s=SAMPLE(v->Samples,i);
  187. double c=s->Count;
  188. for(j=0;j<current_ndims;j++)
  189. {
  190. double diff=SQ(s->Value[j]-v->Mean[j]);
  191. Errors[j]+=c*diff; // charles uses abs not sq()
  192. if (diff>WorstError[j])
  193. WorstError[j]=diff;
  194. }
  195. }
  196. v->TotalError=0.;
  197. double ErrorScale=1.; // /sqrt((double) (N));
  198. for(j=0;j<current_ndims;j++)
  199. {
  200. v->ErrorMeasure[j]=(ErrorScale*Errors[j]*current_weights[j]);
  201. v->TotalError+=v->ErrorMeasure[j];
  202. #if SPLIT_THEN_SORT
  203. v->ErrorMeasure[j]*=WorstError[j];
  204. #endif
  205. }
  206. v->TotSamples=N;
  207. }
  208. static int ErrorDim;
  209. static double ErrorVal;
  210. static struct QuantizedValue *ErrorNode;
  211. static void UpdateWorst(struct QuantizedValue *q)
  212. {
  213. if (q->Children[0])
  214. {
  215. // not a leaf node
  216. UpdateWorst(q->Children[0]);
  217. UpdateWorst(q->Children[1]);
  218. }
  219. else
  220. {
  221. if (q->TotalError>ErrorVal)
  222. {
  223. ErrorVal=q->TotalError;
  224. ErrorNode=q;
  225. ErrorDim=0;
  226. for(int d=0;d<current_ndims;d++)
  227. if (q->ErrorMeasure[d]>q->ErrorMeasure[ErrorDim])
  228. ErrorDim=d;
  229. }
  230. }
  231. }
  232. static int FindWorst(void)
  233. {
  234. ErrorVal=-1.;
  235. UpdateWorst(current_root);
  236. return (ErrorVal>0);
  237. }
  238. static void SubdivideNode(struct QuantizedValue *n, int whichdim)
  239. {
  240. int NAdded=0;
  241. int i;
  242. #if SPLIT_THEN_SORT
  243. // we will try the "split then sort" method. This works by finding the
  244. // means for all samples above and below the mean along the given axis.
  245. // samples are then split into two groups, with the selection based upon
  246. // which of the n-dimensional means the sample is closest to.
  247. double LocalMean[MAXDIMS][2];
  248. int totsamps[2];
  249. for(i=0;i<current_ndims;i++)
  250. LocalMean[i][0]=LocalMean[i][1]=0.;
  251. totsamps[0]=totsamps[1]=0;
  252. uint8 minv=255;
  253. uint8 maxv=0;
  254. struct Sample *minS=0,*maxS=0;
  255. for(i=0;i<n->NSamples;i++)
  256. {
  257. uint8 v;
  258. int whichside=1;
  259. struct Sample *sl;
  260. sl=SAMPLE(n->Samples,i);
  261. v=sl->Value[whichdim];
  262. if (v<minv) { minv=v; minS=sl; }
  263. if (v>maxv) { maxv=v; maxS=sl; }
  264. if (v<n->Mean[whichdim])
  265. whichside=0;
  266. totsamps[whichside]+=sl->Count;
  267. for(int d=0;d<current_ndims;d++)
  268. LocalMean[d][whichside]+=
  269. sl->Count*sl->Value[d];
  270. }
  271. if (totsamps[0] && totsamps[1])
  272. for(i=0;i<current_ndims;i++)
  273. {
  274. LocalMean[i][0]/=totsamps[0];
  275. LocalMean[i][1]/=totsamps[1];
  276. }
  277. else
  278. {
  279. // it is possible that the clustering failed to split the samples.
  280. // this can happen with a heavily biased sample (i.e. all black
  281. // with a few stars). If this happens, we will cluster around the
  282. // extrema instead. LocalMean[i][0] will be the point with the lowest
  283. // value on the dimension and LocalMean[i][1] the one with the lowest
  284. // value.
  285. for(int i=0;i<current_ndims;i++)
  286. {
  287. LocalMean[i][0]=minS->Value[i];
  288. LocalMean[i][1]=maxS->Value[i];
  289. }
  290. }
  291. // now, we have 2 n-dimensional means. We will label each sample
  292. // for which one it is nearer to by using the QNum field.
  293. for(i=0;i<n->NSamples;i++)
  294. {
  295. double dist[2];
  296. dist[0]=dist[1]=0.;
  297. struct Sample *s=SAMPLE(n->Samples,i);
  298. for(int d=0;d<current_ndims;d++)
  299. for(int w=0;w<2;w++)
  300. dist[w]+=current_weights[d]*SQ(LocalMean[d][w]-s->Value[d]);
  301. s->QNum=(dist[0]<dist[1]);
  302. }
  303. // hey ho! we have now labelled each one with a candidate bin. Let's
  304. // sort the array by moving the 0-labelled ones to the head of the array.
  305. n->sortdim=-1;
  306. qsort(n->Samples,n->NSamples,current_ssize,QNumSort);
  307. for(i=0;i<n->NSamples;i++,NAdded++)
  308. if (SAMPLE(n->Samples,i)->QNum)
  309. break;
  310. #else
  311. if (whichdim != n->sortdim)
  312. {
  313. current_sort_dim=whichdim;
  314. qsort(n->Samples,n->NSamples,current_ssize,samplesort);
  315. n->sortdim=whichdim;
  316. }
  317. // now, the samples are sorted along the proper dimension. we need
  318. // to find the place to cut in order to split the node. this is
  319. // complicated by the fact that each sample entry can represent many
  320. // samples. What we will do is start at the beginning of the array,
  321. // adding samples to the first node, until either the number added
  322. // is >=TotSamples/2, or there is only one left.
  323. int TotAdded=0;
  324. for(;;)
  325. {
  326. if (NAdded==n->NSamples-1)
  327. break;
  328. if (TotAdded>=n->TotSamples/2)
  329. break;
  330. TotAdded+=SAMPLE(n->Samples,NAdded)->Count;
  331. NAdded++;
  332. }
  333. #endif
  334. struct QuantizedValue *a=AllocQValue();
  335. a->sortdim=n->sortdim;
  336. a->Samples=n->Samples;
  337. a->NSamples=NAdded;
  338. n->Children[0]=a;
  339. UpdateStats(a);
  340. a=AllocQValue();
  341. a->Samples=SAMPLE(n->Samples,NAdded);
  342. a->NSamples=n->NSamples-NAdded;
  343. a->sortdim=n->sortdim;
  344. n->Children[1]=a;
  345. UpdateStats(a);
  346. }
  347. static int colorid=0;
  348. static void Label(struct QuantizedValue *q, int updatecolor)
  349. {
  350. // fill in max/min values for tree, etc.
  351. if (q)
  352. {
  353. Label(q->Children[0],updatecolor);
  354. Label(q->Children[1],updatecolor);
  355. if (! q->Children[0]) // leaf node?
  356. {
  357. if (updatecolor)
  358. {
  359. q->value=colorid++;
  360. for(int j=0;j<q->NSamples;j++)
  361. {
  362. SAMPLE(q->Samples,j)->QNum=q->value;
  363. SAMPLE(q->Samples,j)->qptr=q;
  364. }
  365. }
  366. for(int i=0;i<current_ndims;i++)
  367. {
  368. q->Mins[i]=q->Mean[i];
  369. q->Maxs[i]=q->Mean[i];
  370. }
  371. }
  372. else
  373. for(int i=0;i<current_ndims;i++)
  374. {
  375. q->Mins[i]=MIN(q->Children[0]->Mins[i],q->Children[1]->Mins[i]);
  376. q->Maxs[i]=MAX(q->Children[0]->Maxs[i],q->Children[1]->Maxs[i]);
  377. }
  378. }
  379. }
  380. struct QuantizedValue *FindQNode(struct QuantizedValue const *q, int32 code)
  381. {
  382. if (! (q->Children[0]))
  383. if (code==q->value) return (struct QuantizedValue *) q;
  384. else return 0;
  385. else
  386. {
  387. struct QuantizedValue *found=FindQNode(q->Children[0],code);
  388. if (! found) found=FindQNode(q->Children[1],code);
  389. return found;
  390. }
  391. }
  392. void CheckInRange(struct QuantizedValue *q, uint8 *max, uint8 *min)
  393. {
  394. if (q)
  395. {
  396. if (q->Children[0])
  397. {
  398. // non-leaf node
  399. CheckInRange(q->Children[0],q->Maxs, q->Mins);
  400. CheckInRange(q->Children[1],q->Maxs, q->Mins);
  401. CheckInRange(q->Children[0],max, min);
  402. CheckInRange(q->Children[1],max, min);
  403. }
  404. for (int i=0;i<current_ndims;i++)
  405. {
  406. if (q->Maxs[i]>max[i]) printf("error1\n");
  407. if (q->Mins[i]<min[i]) printf("error2\n");
  408. }
  409. }
  410. }
  411. struct QuantizedValue *Quantize(struct Sample *s, int nsamples, int ndims,
  412. int nvalues, uint8 *weights, int firstvalue)
  413. {
  414. SetNDims(ndims);
  415. current_weights=weights;
  416. current_root=AllocQValue();
  417. current_root->Samples=s;
  418. current_root->NSamples=nsamples;
  419. UpdateStats(current_root);
  420. while(--nvalues)
  421. {
  422. if (! FindWorst())
  423. break; // if <n unique ones, stop now
  424. SubdivideNode(ErrorNode,ErrorDim);
  425. }
  426. colorid=firstvalue;
  427. Label(current_root,1);
  428. return current_root;
  429. }
  430. double MinimumError(struct QuantizedValue const *q, uint8 const *sample,
  431. int ndims, uint8 const *weights)
  432. {
  433. double err=0;
  434. for(int i=0;i<ndims;i++)
  435. {
  436. int val1;
  437. int val2=sample[i];
  438. if ((q->Mins[i]<=val2) && (q->Maxs[i]>=val2)) val1=val2;
  439. else
  440. {
  441. val1=(val2<=q->Mins[i])?q->Mins[i]:q->Maxs[i];
  442. }
  443. err+=weights[i]*SQ(val1-val2);
  444. }
  445. return err;
  446. }
  447. double MaximumError(struct QuantizedValue const *q, uint8 const *sample,
  448. int ndims, uint8 const *weights)
  449. {
  450. double err=0;
  451. for(int i=0;i<ndims;i++)
  452. {
  453. int val2=sample[i];
  454. int val1=(abs(val2-q->Mins[i])>abs(val2-q->Maxs[i]))?
  455. q->Mins[i]:
  456. q->Maxs[i];
  457. err+=weights[i]*SQ(val2-val1);
  458. }
  459. return err;
  460. }
  461. // heap (priority queue) routines used for nearest-neghbor searches
  462. struct FHeap {
  463. int heap_n;
  464. double *heap[MAXQUANT];
  465. };
  466. void InitHeap(struct FHeap *h)
  467. {
  468. h->heap_n=0;
  469. }
  470. void UpHeap(int k, struct FHeap *h)
  471. {
  472. double *tmpk=h->heap[k];
  473. double tmpkn=*tmpk;
  474. while((k>1) && (tmpkn <= *(h->heap[k/2])))
  475. {
  476. h->heap[k]=h->heap[k/2];
  477. k/=2;
  478. }
  479. h->heap[k]=tmpk;
  480. }
  481. void HeapInsert(struct FHeap *h,double *elem)
  482. {
  483. h->heap_n++;
  484. h->heap[h->heap_n]=elem;
  485. UpHeap(h->heap_n,h);
  486. }
  487. void DownHeap(int k, struct FHeap *h)
  488. {
  489. double *v=h->heap[k];
  490. while(k<=h->heap_n/2)
  491. {
  492. int j=2*k;
  493. if (j<h->heap_n)
  494. if (*(h->heap[j]) >= *(h->heap[j+1]))
  495. j++;
  496. if (*v < *(h->heap[j]))
  497. {
  498. h->heap[k]=v;
  499. return;
  500. }
  501. h->heap[k]=h->heap[j]; k=j;
  502. }
  503. h->heap[k]=v;
  504. }
  505. void *RemoveHeapItem(struct FHeap *h)
  506. {
  507. void *ret=0;
  508. if (h->heap_n!=0)
  509. {
  510. ret=h->heap[1];
  511. h->heap[1]=h->heap[h->heap_n];
  512. h->heap_n--;
  513. DownHeap(1,h);
  514. }
  515. return ret;
  516. }
  517. // now, nearest neighbor finder. Use a heap to traverse the tree, stopping
  518. // when there are no nodes with a minimum error < the current error.
  519. struct FHeap TheQueue;
  520. #define PUSHNODE(a) { \
  521. (a)->MinError=MinimumError(a,sample,ndims,weights); \
  522. if ((a)->MinError < besterror) HeapInsert(&TheQueue,&(a)->MinError); \
  523. }
  524. struct QuantizedValue *FindMatch(uint8 const *sample, int ndims,
  525. uint8 *weights, struct QuantizedValue *q)
  526. {
  527. InitHeap(&TheQueue);
  528. struct QuantizedValue *bestmatch=0;
  529. double besterror=1.0e63;
  530. PUSHNODE(q);
  531. for(;;)
  532. {
  533. struct QuantizedValue *test=(struct QuantizedValue *)
  534. RemoveHeapItem(&TheQueue);
  535. if (! test) break; // heap empty
  536. // printf("got pop node =%p minerror=%f\n",test,test->MinError);
  537. if (test->MinError>besterror) break;
  538. if (test->Children[0])
  539. {
  540. // it's a parent node. put the children on the queue
  541. struct QuantizedValue *c1=test->Children[0];
  542. struct QuantizedValue *c2=test->Children[1];
  543. c1->MinError=MinimumError(c1,sample,ndims,weights);
  544. if (c1->MinError < besterror)
  545. HeapInsert(&TheQueue,&(c1->MinError));
  546. c2->MinError=MinimumError(c2,sample,ndims,weights);
  547. if (c2->MinError < besterror)
  548. HeapInsert(&TheQueue,&(c2->MinError));
  549. }
  550. else
  551. {
  552. // it's a leaf node. This must be a new minimum or the MinError
  553. // test would have failed.
  554. if (test->MinError < besterror)
  555. {
  556. bestmatch=test;
  557. besterror=test->MinError;
  558. }
  559. }
  560. }
  561. if (bestmatch)
  562. {
  563. SquaredError+=besterror;
  564. bestmatch->NQuant++;
  565. for(int i=0;i<ndims;i++)
  566. bestmatch->Sums[i]+=sample[i];
  567. }
  568. return bestmatch;
  569. }
  570. static void RecalcMeans(struct QuantizedValue *q)
  571. {
  572. if (q)
  573. {
  574. if (q->Children[0])
  575. {
  576. // not a leaf, invoke recursively.
  577. RecalcMeans(q->Children[0]);
  578. RecalcMeans(q->Children[0]);
  579. }
  580. else
  581. {
  582. // it's a leaf. Set the means
  583. if (q->NQuant)
  584. {
  585. for(int i=0;i<current_ndims;i++)
  586. {
  587. q->Mean[i]=(uint8) (q->Sums[i]/q->NQuant);
  588. q->Sums[i]=0;
  589. }
  590. q->NQuant=0;
  591. }
  592. }
  593. }
  594. }
  595. void OptimizeQuantizer(struct QuantizedValue *q, int ndims)
  596. {
  597. SetNDims(ndims);
  598. RecalcMeans(q); // reset q values
  599. Label(q,0); // update max/mins
  600. }
  601. static void RecalcStats(struct QuantizedValue *q)
  602. {
  603. if (q)
  604. {
  605. UpdateStats(q);
  606. RecalcStats(q->Children[0]);
  607. RecalcStats(q->Children[1]);
  608. }
  609. }
  610. void RecalculateValues(struct QuantizedValue *q, int ndims)
  611. {
  612. SetNDims(ndims);
  613. RecalcStats(q);
  614. Label(q,0);
  615. }