DCL 3.7.4
Loading...
Searching...
No Matches
MessageTree.cpp
Go to the documentation of this file.
1#include <dcl/Config.h>
2
3#include <dcl/Object.h>
4
5#include "MessageTree.h"
6
7#if __DCL_HAVE_THIS_FILE__
8#undef __THIS_FILE__
9static const char_t __THIS_FILE__[] = __T("fastpage/MessageTree.cpp");
10#endif
11
12__DCL_BEGIN_NAMESPACE
13
14#ifdef _MSC_VER
15#define __I64(c) c##I64
16#else // __GNUC__
17#define __I64(c) c##LL
18#endif
19
20static int64_t __POWER(int nBase, int nExponent)
21{
22 // base ^ exponent
23 __DCL_ASSERT(nBase > 0);
24
25 int64_t r = __I64(1);
26 while(nExponent--)
27 r *= nBase;
28
29 return r;
30}
31
32// default nWidth
33static const int __aWidth[16] = {
34//depth: 2 3 4 5 6 7 8 9
35 2147483646, 2097151, 55108, 6208, 1448, 511, 234, 127,
36//depth: 10 11 12 13 14 15 16 17
37 78, 52, 38, 28, 22, 18, 15, 13
38};
39
40static const int64_t __aPower[16][18] = {
41 { // base 2147483647
42 __I64(1), // 0
43 __I64(2147483647), // 1
44 __I64(4611686014132420609), // 2
45 __I64(0), // 3
46 },
47 { // base 2097151
48 __I64(1), // 0
49 __I64(2097151), // 1
50 __I64(4398042316801), // 2
51 __I64(9223358842721533951), // 3
52 __I64(0), // 4
53 },
54 { // base 55108
55 __I64(1), // 0
56 __I64(55108), // 1
57 __I64(3036891664), // 2
58 __I64(167357025819712), // 3
59 __I64(9222710978872688896), // 4
60 __I64(0), // 5
61 },
62 { // base 6208
63 __I64(1), // 0
64 __I64(6208), // 1
65 __I64(38539264), // 2
66 __I64(239251750912), // 3
67 __I64(1485274869661696), // 4
68 __I64(9220586390859808768), // 5
69 __I64(0), // 6
70 },
71 { // base 1448
72 __I64(1), // 0
73 __I64(1448), // 1
74 __I64(2096704), // 2
75 __I64(3036027392), // 3
76 __I64(4396167663616), // 4
77 __I64(6365650776915968), // 5
78 __I64(9217462324974321664), // 6
79 __I64(0), // 7
80 },
81 { // base 511
82 __I64(1), // 0
83 __I64(511), // 1
84 __I64(261121), // 2
85 __I64(133432831), // 3
86 __I64(68184176641), // 4
87 __I64(34842114263551), // 5
88 __I64(17804320388674561), // 6
89 __I64(9098007718612700671), // 7
90 __I64(0), // 8
91 },
92 { // base 234
93 __I64(1), // 0
94 __I64(234), // 1
95 __I64(54756), // 2
96 __I64(12812904), // 3
97 __I64(2998219536), // 4
98 __I64(701583371424), // 5
99 __I64(164170508913216), // 6
100 __I64(38415899085692544), // 7
101 __I64(8989320386052055296), // 8
102 __I64(0), // 9
103 },
104 { // base 127
105 __I64(1), // 0
106 __I64(127), // 1
107 __I64(16129), // 2
108 __I64(2048383), // 3
109 __I64(260144641), // 4
110 __I64(33038369407), // 5
111 __I64(4195872914689), // 6
112 __I64(532875860165503), // 7
113 __I64(67675234241018881), // 8
114 __I64(8594754748609397887), // 9
115 __I64(0), // 10
116 },
117 { // base 78
118 __I64(1), // 0
119 __I64(78), // 1
120 __I64(6084), // 2
121 __I64(474552), // 3
122 __I64(37015056), // 4
123 __I64(2887174368), // 5
124 __I64(225199600704), // 6
125 __I64(17565568854912), // 7
126 __I64(1370114370683136), // 8
127 __I64(106868920913284608), // 9
128 __I64(8335775831236199424), // 10
129 __I64(0), // 11
130 },
131 { // base 52
132 __I64(1), // 0
133 __I64(52), // 1
134 __I64(2704), // 2
135 __I64(140608), // 3
136 __I64(7311616), // 4
137 __I64(380204032), // 5
138 __I64(19770609664), // 6
139 __I64(1028071702528), // 7
140 __I64(53459728531456), // 8
141 __I64(2779905883635712), // 9
142 __I64(144555105949057024), // 10
143 __I64(7516865509350965248), // 11
144 __I64(0), // 12
145 },
146 { // base 38
147 __I64(1), // 0
148 __I64(38), // 1
149 __I64(1444), // 2
150 __I64(54872), // 3
151 __I64(2085136), // 4
152 __I64(79235168), // 5
153 __I64(3010936384), // 6
154 __I64(114415582592), // 7
155 __I64(4347792138496), // 8
156 __I64(165216101262848), // 9
157 __I64(6278211847988224), // 10
158 __I64(238572050223552512), // 11
159 __I64(9065737908494995456), // 12
160 __I64(0), // 13
161 },
162 { // base 28
163
164 __I64(1), // 0
165 __I64(28), // 1
166 __I64(784), // 2
167 __I64(21952), // 3
168 __I64(614656), // 4
169 __I64(17210368), // 5
170 __I64(481890304), // 6
171 __I64(13492928512), // 7
172 __I64(377801998336), // 8
173 __I64(10578455953408), // 9
174 __I64(296196766695424), // 10
175 __I64(8293509467471872), // 11
176 __I64(232218265089212416), // 12
177 __I64(6502111422497947648), // 13
178 __I64(0), // 14
179 },
180 { // base 22
181
182 __I64(1), // 0
183 __I64(22), // 1
184 __I64(484), // 2
185 __I64(10648), // 3
186 __I64(234256), // 4
187 __I64(5153632), // 5
188 __I64(113379904), // 6
189 __I64(2494357888), // 7
190 __I64(54875873536), // 8
191 __I64(1207269217792), // 9
192 __I64(26559922791424), // 10
193 __I64(584318301411328), // 11
194 __I64(12855002631049216), // 12
195 __I64(282810057883082752), // 13
196 __I64(6221821273427820544), // 14
197 __I64(0), // 15
198 },
199 { // base 18
200
201 __I64(1), // 0
202 __I64(18), // 1
203 __I64(324), // 2
204 __I64(5832), // 3
205 __I64(104976), // 4
206 __I64(1889568), // 5
207 __I64(34012224), // 6
208 __I64(612220032), // 7
209 __I64(11019960576), // 8
210 __I64(198359290368), // 9
211 __I64(3570467226624), // 10
212 __I64(64268410079232), // 11
213 __I64(1156831381426176), // 12
214 __I64(20822964865671168), // 13
215 __I64(374813367582081024), // 14
216 __I64(6746640616477458432), // 15
217 __I64(0), // 16
218 },
219 { // base 15
220
221 __I64(1), // 0
222 __I64(15), // 1
223 __I64(225), // 2
224 __I64(3375), // 3
225 __I64(50625), // 4
226 __I64(759375), // 5
227 __I64(11390625), // 6
228 __I64(170859375), // 7
229 __I64(2562890625), // 8
230 __I64(38443359375), // 9
231 __I64(576650390625), // 10
232 __I64(8649755859375), // 11
233 __I64(129746337890625), // 12
234 __I64(1946195068359375), // 13
235 __I64(29192926025390625), // 14
236 __I64(437893890380859375), // 15
237 __I64(6568408355712890625), // 16
238 __I64(0) // 17
239 },
240 { // base 13
241
242 __I64(1), // 0
243 __I64(13), // 1
244 __I64(169), // 2
245 __I64(2197), // 3
246 __I64(28561), // 4
247 __I64(371293), // 5
248 __I64(4826809), // 6
249 __I64(62748517), // 7
250 __I64(815730721), // 8
251 __I64(10604499373), // 9
252 __I64(137858491849), // 10
253 __I64(1792160394037), // 11
254 __I64(23298085122481), // 12
255 __I64(302875106592253), // 13
256 __I64(3937376385699289), // 14
257 __I64(51185893014090757), // 15
258 __I64(665416609183179841), // 16
259 __I64(8650415919381337933) // 17
260 }
261};
262
264{
265 __DCL_ASSERT(2 <= nDepth && nDepth <= 17);
266
267 return __aWidth[nDepth - 2];
268}
269
270inline int64_t MessageTree::POWER(int nExponent) const
271{
272#ifdef __DEBUG_ALGORITHM
273 // 알고리즘 검사용
274 // 데이터베이스에 4 x 4 인 샘플 데이터를 사용한다.
275 if (__nWidth == 4)
276 return __POWER(__nWidth, nExponent);
277#endif
278
279 __DCL_ASSERT(0 <= nExponent && nExponent <= 17);
280 int64_t r = __aPower[__nDepth - 2][nExponent];
281 __DCL_ASSERT(r != __I64(0));
282 return r;
283}
284
286{
287 __DCL_ASSERT(2 <= nDepth && nDepth <= 17);
288
289 __nWidth = __aWidth[nDepth - 2];
290 __nDepth = nDepth;
291
292 __nMinReplyID = 1;
293 __nMaxReplyID = ((POWER(__nDepth) - 1) / (__nWidth - 1));
294}
295
296MessageTree::MessageTree(int nDepth, int nWidth)
297{
298 __DCL_ASSERT(nWidth >= 2);
299 __DCL_ASSERT(nDepth >= 2);
300
301 __nWidth = nWidth;
302 __nDepth = nDepth;
303
304 __nMinReplyID = 1;
305 __nMaxReplyID = ((POWER(__nDepth) - 1) / (__nWidth - 1));
306}
307
309{
310 return __nMinReplyID;
311}
312
314{
315 return __nMaxReplyID;
316}
317
318int64_t MessageTree::getSiblingGap(int nDepthIndex) const
319{
320 __DCL_ASSERT(nDepthIndex >= 0);
321
322 // 형제노드간의 간격
323 // 전체 노드의 개수 중 nDepthIndex - 1 까지의 개수를 뺀 값에서
324 // nDepthIndex 까지의 개수로 나눈 값
325 if (nDepthIndex > 0)
326 return (__nMaxReplyID - POWER(nDepthIndex - 1))
327 / POWER(nDepthIndex);
328 else
329 return __nMaxReplyID;
330}
331
333 int64_t nReplyID,
334 Position& rPos
335) const
336{
337 __DCL_ASSERT(__nMinReplyID <= nReplyID); // 0 < nReplyID
338 __DCL_ASSERT(nReplyID <= __nMaxReplyID);
339
340 rPos.nParentID = 0;
341 rPos.nDepthIndex = 0;
342 rPos.nWidthIndex = 0;
343
344 int64_t __n = nReplyID - 1;
345 if (__n == 0) {
346 // 시작글(최상위 노드) ==> (0, 0)
347 return;
348 }
349
350 for(int i = 1; i < __nDepth; i++) {
351 // i == 1 ==> 0번째, 즉, 최상위 노드는 건너뛴다.
352 --__n;
353 int64_t nGap = getSiblingGap(i);
354 if (nGap > 1) {
355 int64_t nRemainder = __n % nGap;
356 if (nRemainder == 0) {
357 // nDepthIndex가 결정되었다.
358 rPos.nDepthIndex = i;
359 rPos.nWidthIndex = (int)(__n / nGap);
360 rPos.nParentID = nReplyID - (nGap * rPos.nWidthIndex) - 1;
361
362 break;
363 }
364
365 // tree의 가장 좌측으로 이동한다.
366 __n = nRemainder;
367 }
368 else {
369// __DCL_TRACE2(L"i[%d], __n[%lld]\n", i, __n);
370 rPos.nDepthIndex = i;
371 rPos.nWidthIndex = (int)__n;
372 rPos.nParentID = nReplyID - (nGap * rPos.nWidthIndex) - 1;
373 break;
374 }
375 }
376}
377
378int64_t MessageTree::getFirstChildID(int64_t nReplyID) const
379{
380 __DCL_ASSERT(0 <= nReplyID);
381 return nReplyID + 1;
382}
383
384int64_t MessageTree::getLastChildID(int64_t nReplyID) const
385{
386 __DCL_ASSERT(0 <= nReplyID);
387
388 Position rPos;
389 getPosition(nReplyID, rPos);
390
391 __DCL_ASSERT(rPos.nDepthIndex < (__nDepth - 1));
392
393 // nReplyID + 전체 자식노드의 개수 중 직 하위의 (nWidth - 1)/__nWidth
394 // POWER(__nDepth - rPos.nDepthIndex) / (__nWidth - 1)
395 // * (__nWidth - 1) / __nWidth
396
397 return nReplyID
398 + POWER(__nDepth - rPos.nDepthIndex) / __nWidth;
399
400 /*
401 // FirstChildID + 자식노드의 간격 * (__nWidth - 1)의 개수
402 return nReplyID + 1
403 + getSiblingGap(rPos.nDepthIndex + 1) * (__nWidth - 1);
404 */
405}
406
407int64_t MessageTree::getChildID(int64_t nReplyID, int nWidthIndex) const
408{
409 __DCL_ASSERT(0 <= nReplyID);
410 __DCL_ASSERT(0 <= nWidthIndex && nWidthIndex < __nWidth);
411
412 Position rPos;
413 getPosition(nReplyID, rPos);
414
415 __DCL_ASSERT(rPos.nDepthIndex < __nDepth);
416
417 return nReplyID + 1 + getSiblingGap(rPos.nDepthIndex + 1) * nWidthIndex;
418}
419
420__DCL_END_NAMESPACE
421
422#ifdef _CONSOLE
423
424#include <dcl/FileOutputStream.h>
425#include <dcl/Numeric.h>
426
427__DCL_USING_NAMESPACE
428
429int main(int argc, char* argv[])
430{
431 DCLInitialize(NULL, 2);
432
433 FileOutputStream out(1, 0, false);
434
435 if (argc < 3) {
436 out << L"USAGE: " << argv[0] << L" width depth [id]\n";
437 goto __done;
438 }
439
440 try {
441 int nWidth = UInteger::parse(argv[1]);
442 int nDepth = UInteger::parse(argv[2]);
443
444 MessageTree mt(nDepth, nWidth);
445
446 out << L"width : " << nWidth
447 << L"\ndepth : " << nDepth
448 << L"\nrange : " << mt.minReplyID()
449 << L" ~ " << mt.maxReplyID()
450 << L"\n";
451
452 out << L"\nleft:gap\n";
453
454 int nCol = 3;
455 int nDepthIndex;
456 int64_t nParentID = 1;
457 for(nDepthIndex = 1; nDepthIndex < nDepth; nDepthIndex++) {
458 int64_t nID = mt.getFirstChildID(nParentID);
459 int64_t nGap = mt.getSiblingGap(nDepthIndex);
460 out << nDepthIndex << L":" << nGap
461 << L" ==> ";
462 for(int i = 0; i < nCol; i++)
463 out << nID + nGap * i << L" ";
464 nCol++;
465 nParentID = nID;
466 out << L" ... " << nID + nGap * (nWidth - 1) << L"\n";
467 }
468
469 out << L"\nrifht:gap\n";
470 nParentID = 1;
471 nCol = 3;
472 for(nDepthIndex = 1; nDepthIndex < nDepth; nDepthIndex++) {
473 int64_t nID = mt.getLastChildID(nParentID);
474 int64_t nGap = mt.getSiblingGap(nDepthIndex);
475 out << nDepthIndex << L":" << nGap
476 << L" ==> ";
477 for(int i = 0; i < nCol; i++)
478 out << nID - (nGap * (nCol - i - 1)) << L" ";
479// nCol++;
480 nParentID = nID;
481 out << L"\n";
482 }
483
484 if (argc == 4) {
485 int64_t nReplyID = Int64::parse(argv[3]);
486
488 mt.getPosition(nReplyID, rPos);
489 out << L"\nID : " << nReplyID
490 << L"\nDepthIndex : " << rPos.nDepthIndex
491 << L"\nWidthIndex : " << rPos.nWidthIndex
492 << L"\nParent : " << rPos.nParentID
493 << L"\n";
494
495 if (rPos.nDepthIndex < nDepth - 1) {
496 out << L"\nFirstChildID: " << mt.getFirstChildID(nReplyID)
497 << L"\nLastChildID: " << mt.getLastChildID(nReplyID)
498 << L"\n";
499 for(int i = 0; (i < nWidth && i < 5); i++)
500 out << L"\n" << i << L"-st ChildID: "
501 << mt.getChildID(nReplyID, i);
502 out << L"\n";
503 }
504 }
505 }
506 catch (Exception* e) {
507 out << e->toStringAll() << L"\n";
508 e->destroy();
509 }
510
511__done :
512 DCLCleanup();
513
514 return 0;
515}
516
517#endif
#define __THIS_FILE__
Definition _trace.h:14
#define NULL
Definition Config.h:312
wchar_t char_t
Definition Config.h:247
IOException *size_t r
Definition MediaInfo.cpp:82
#define __I64(c)
#define __DCL_ASSERT(expr)
Definition Object.h:394
#define __T(str)
Definition Object.h:60
virtual void destroy()
Definition Exception.cpp:74
String toStringAll() const
Definition Exception.cpp:45
static int64_t parse(const wchar_t *_number, unsigned _base=10) __DCL_THROWS1(NumericConvertException *)
Definition Numeric.cpp:511
int64_t minReplyID() const
int64_t maxReplyID() const
int64_t getLastChildID(int64_t nReplyID) const
static int getDefaultWidth(int nDepth)
void getPosition(int64_t nReplyID, Position &rPos) const
int64_t getChildID(int64_t nReplyID, int nWidthIndex) const
MessageTree(int nDepth)
int64_t getSiblingGap(int nDepthIndex) const
int64_t getFirstChildID(int64_t nReplyID) const
static unsigned int parse(const wchar_t *_number, unsigned _base=10) __DCL_THROWS1(NumericConvertException *)
Definition Numeric.inl:72
int main(int argc, char *argv[])