Team Fortress 2 Source Code as on 22/4/2020
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.

679 lines
15 KiB

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