diff options
author | Jacek Antonelli | 2008-08-15 23:44:48 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:48 -0500 |
commit | 9b4f54c826ffa4f94efa866068c9d6ecdfb4b424 (patch) | |
tree | 2f8ae193ab487088962e628f1ee9dee2f5901f01 /linden/indra/llmath | |
parent | Second Life viewer sources 1.13.2.12 (diff) | |
download | meta-impy-9b4f54c826ffa4f94efa866068c9d6ecdfb4b424.zip meta-impy-9b4f54c826ffa4f94efa866068c9d6ecdfb4b424.tar.gz meta-impy-9b4f54c826ffa4f94efa866068c9d6ecdfb4b424.tar.bz2 meta-impy-9b4f54c826ffa4f94efa866068c9d6ecdfb4b424.tar.xz |
Second Life viewer sources 1.13.2.15
Diffstat (limited to 'linden/indra/llmath')
-rw-r--r-- | linden/indra/llmath/llrand.cpp | 59 | ||||
-rw-r--r-- | linden/indra/llmath/llrand.h | 134 | ||||
-rw-r--r-- | linden/indra/llmath/lluuid.cpp | 75 | ||||
-rw-r--r-- | linden/indra/llmath/llvolume.cpp | 24 |
4 files changed, 191 insertions, 101 deletions
diff --git a/linden/indra/llmath/llrand.cpp b/linden/indra/llmath/llrand.cpp index 38e0639..4c214c4 100644 --- a/linden/indra/llmath/llrand.cpp +++ b/linden/indra/llmath/llrand.cpp | |||
@@ -1,6 +1,6 @@ | |||
1 | /** | 1 | /** |
2 | * @file llrand.cpp | 2 | * @file llrand.cpp |
3 | * @brief a few useful math functions. | 3 | * @brief Global random generator. |
4 | * | 4 | * |
5 | * Copyright (c) 2000-2007, Linden Research, Inc. | 5 | * Copyright (c) 2000-2007, Linden Research, Inc. |
6 | * | 6 | * |
@@ -30,45 +30,34 @@ | |||
30 | #include "llrand.h" | 30 | #include "llrand.h" |
31 | #include "lluuid.h" | 31 | #include "lluuid.h" |
32 | 32 | ||
33 | /* Put this back if you re-enabled slamFPCW | 33 | static LLRandLagFib2281 gRandomGenerator(LLUUID::getRandomSeed()); |
34 | #if LL_WINDOWS | ||
35 | #include <float.h> | ||
36 | #else | ||
37 | #include <stdlib.h> | ||
38 | #endif | ||
39 | */ | ||
40 | 34 | ||
41 | void slamFPCW( void ) | 35 | S32 ll_rand() |
42 | { | 36 | { |
43 | /* | 37 | return (S32)(gRandomGenerator() * RAND_MAX); |
44 | #if LL_WINDOWS | ||
45 | // for Intel based CPUs, slam the FP control word directly | ||
46 | WORD wTemp, wSave; | ||
47 | |||
48 | __asm fstcw wSave | ||
49 | if ( (wSave & 0x300) // Not single mode | ||
50 | ||(0x3f != (wSave & 0x3f)) // Exceptions enabled | ||
51 | ||(wSave & 0xC00)) // Not round to nearest mode | ||
52 | { | ||
53 | __asm | ||
54 | { | ||
55 | mov ax, wSave | ||
56 | and ax, not 300h ;; single mode | ||
57 | or ax, 3fh ;; disable all exceptions | ||
58 | and ax, not 0xC00 ;; round to nearest mode | ||
59 | mov wTemp, ax | ||
60 | fldcw wTemp | ||
61 | } | ||
62 | } | ||
63 | #endif | ||
64 | */ | ||
65 | } | 38 | } |
66 | 39 | ||
67 | LLRand gLindenLabRandomNumber(LLUUID::getRandomSeed()); | 40 | S32 ll_rand(S32 val) |
41 | { | ||
42 | return (S32)(gRandomGenerator() * val); | ||
43 | } | ||
44 | |||
45 | F32 ll_frand() | ||
46 | { | ||
47 | return (F32)gRandomGenerator(); | ||
48 | } | ||
68 | 49 | ||
69 | F32 frand(F32 val) | 50 | F32 ll_frand(F32 val) |
70 | { | 51 | { |
71 | // return (val * (F32)rand()/(F32)RAND_MAX); | 52 | return (F32)gRandomGenerator() * val; |
72 | return gLindenLabRandomNumber.llfrand(val); | ||
73 | } | 53 | } |
74 | 54 | ||
55 | F64 ll_drand() | ||
56 | { | ||
57 | return gRandomGenerator(); | ||
58 | } | ||
59 | |||
60 | F64 ll_drand(F64 val) | ||
61 | { | ||
62 | return gRandomGenerator() * val; | ||
63 | } | ||
diff --git a/linden/indra/llmath/llrand.h b/linden/indra/llmath/llrand.h index db9f353..47b5651 100644 --- a/linden/indra/llmath/llrand.h +++ b/linden/indra/llmath/llrand.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /** | 1 | /** |
2 | * @file llrand.h | 2 | * @file llrand.h |
3 | * @brief Some useful math functions. | 3 | * @brief Information, functions, and typedefs for randomness. |
4 | * | 4 | * |
5 | * Copyright (c) 2000-2007, Linden Research, Inc. | 5 | * Copyright (c) 2000-2007, Linden Research, Inc. |
6 | * | 6 | * |
@@ -28,61 +28,101 @@ | |||
28 | #ifndef LL_LLRAND_H | 28 | #ifndef LL_LLRAND_H |
29 | #define LL_LLRAND_H | 29 | #define LL_LLRAND_H |
30 | 30 | ||
31 | // As long as you #include "llviewerprecompiledheaders.h", | 31 | #include "boost/random/lagged_fibonacci.hpp" |
32 | // you can use "gLindenLabRandomNumber.llfrand( range );" which returns a | 32 | #include "boost/random/mersenne_twister.hpp" |
33 | // random number F32 ranging from 0.0f to range. | ||
34 | // -Ventrella - Sept 30, 2005 | ||
35 | 33 | ||
36 | // Slams Intel processors into Single Precision FP mode | 34 | /** |
37 | // (which is not any faster on modern hardware) | 35 | * Use the boost random number generators if you want a stateful |
38 | void slamFPCW( void ); | 36 | * random numbers. If you want more random numbers, use the |
39 | 37 | * c-functions since they will generate faster/better randomness | |
40 | class LLRand | 38 | * across the process. |
41 | { | 39 | * |
42 | public: | 40 | * I tested some of the boost random engines, and picked a good double |
43 | LLRand(U32 seed) : mSeed(seed) {} | 41 | * generator and a good integer generator. I also took some timings |
44 | ~LLRand() {} | 42 | * for them on linux using gcc 3.3.5. The harness also did some other |
45 | 43 | * fairly trivial operations to try to limit compiler optimizations, | |
46 | void seed(U32 seed) { mSeed = seed; } | 44 | * so these numbers are only good for relative comparisons. |
45 | * | ||
46 | * usec/inter algorithm | ||
47 | * 0.21 boost::minstd_rand0 | ||
48 | * 0.039 boost:lagged_fibonacci19937 | ||
49 | * 0.036 boost:lagged_fibonacci607 | ||
50 | * 0.44 boost::hellekalek1995 | ||
51 | * 0.44 boost::ecuyer1988 | ||
52 | * 0.042 boost::rand48 | ||
53 | * 0.043 boost::mt11213b | ||
54 | * 0.028 stdlib random() | ||
55 | * 0.05 stdlib lrand48() | ||
56 | * 0.034 stdlib rand() | ||
57 | * 0.020 the old & lame LLRand | ||
58 | */ | ||
47 | 59 | ||
48 | U32 llrand() | 60 | /** |
49 | { | 61 | *@brief Generate a float from [0, RAND_MAX). |
50 | mSeed = U64L(1664525) * mSeed + U64L(1013904223); | 62 | */ |
51 | return (U32)mSeed; | 63 | S32 ll_rand(); |
52 | } | ||
53 | 64 | ||
54 | U32 llrand(U32 val) | 65 | /** |
55 | { | 66 | *@brief Generate a float from [0, val). |
56 | mSeed = U64L(1664525) * mSeed + U64L(1013904223); | 67 | */ |
57 | return (U32)(mSeed) % val; | 68 | S32 ll_rand(S32 val); |
58 | } | ||
59 | 69 | ||
60 | // val is the maximum | 70 | /** |
61 | F32 llfrand(F32 val) | 71 | *@brief Generate a float from [0, 1.0). |
62 | { | 72 | */ |
63 | const U32 FP_ONE = 0x3f800000; | 73 | F32 ll_frand(); |
64 | const U32 FP_MASK = 0x007fffff; | ||
65 | U32 ir = llrand(); | ||
66 | 74 | ||
67 | ir = FP_ONE | (FP_MASK & ir); | 75 | /** |
68 | 76 | *@brief Generate a float from [0, val). | |
69 | // generate random float | 77 | */ |
70 | F32 fr = (*(F32 *)&ir); | 78 | F32 ll_frand(F32 val); |
71 | 79 | ||
72 | // correct to [0..1) | 80 | /** |
73 | fr -= 1.f; | 81 | *@brief Generate a double from [0, 1.0). |
82 | */ | ||
83 | F64 ll_drand(); | ||
74 | 84 | ||
75 | fr *= val; | 85 | /** |
86 | *@brief Generate a double from [0, val). | ||
87 | */ | ||
88 | F64 ll_drand(F64 val); | ||
76 | 89 | ||
77 | return fr; | 90 | /** |
78 | } | 91 | * @brief typedefs for good boost lagged fibonacci. |
79 | 92 | * @see boost::lagged_fibonacci | |
80 | public: | 93 | * |
81 | U64 mSeed; | 94 | * These generators will quickly generate doubles. Note the memory |
82 | }; | 95 | * requirements, because they are somewhat high. I chose the smallest |
96 | * one, and one comparable in speed but higher periodicity without | ||
97 | * outrageous memory requirements. | ||
98 | * To use: | ||
99 | * LLRandLagFib607 foo((U32)time(NULL)); | ||
100 | * double bar = foo(); | ||
101 | */ | ||
83 | 102 | ||
84 | F32 frand(F32 val); | 103 | typedef boost::lagged_fibonacci607 LLRandLagFib607; |
104 | /**< | ||
105 | * lengh of cycle: 2^32,000 | ||
106 | * memory: 607*sizeof(double) (about 5K) | ||
107 | */ | ||
85 | 108 | ||
86 | extern LLRand gLindenLabRandomNumber; | 109 | typedef boost::lagged_fibonacci2281 LLRandLagFib2281; |
110 | /**< | ||
111 | * lengh of cycle: 2^120,000 | ||
112 | * memory: 2281*sizeof(double) (about 17K) | ||
113 | */ | ||
87 | 114 | ||
115 | /** | ||
116 | * @breif typedefs for a good boost mersenne twister implementation. | ||
117 | * @see boost::mersenne_twister | ||
118 | * | ||
119 | * This fairly quickly generates U32 values | ||
120 | * To use: | ||
121 | * LLRandMT19937 foo((U32)time(NULL)); | ||
122 | * U32 bar = foo(); | ||
123 | * | ||
124 | * lengh of cycle: 2^19,937-1 | ||
125 | * memory: about 2496 bytes | ||
126 | */ | ||
127 | typedef boost::mt11213b LLRandMT19937; | ||
88 | #endif | 128 | #endif |
diff --git a/linden/indra/llmath/lluuid.cpp b/linden/indra/llmath/lluuid.cpp index 216dac9..3fb31a6 100644 --- a/linden/indra/llmath/lluuid.cpp +++ b/linden/indra/llmath/lluuid.cpp | |||
@@ -110,6 +110,40 @@ unsigned int decode( char const * fiveChars ) throw( bad_input_data ) | |||
110 | } | 110 | } |
111 | */ | 111 | */ |
112 | 112 | ||
113 | #define LL_USE_JANKY_RANDOM_NUMBER_GENERATOR 0 | ||
114 | #if LL_USE_JANKY_RANDOM_NUMBER_GENERATOR | ||
115 | /** | ||
116 | * @brief a global for | ||
117 | */ | ||
118 | static U64 sJankyRandomSeed(LLUUID::getRandomSeed()); | ||
119 | |||
120 | /** | ||
121 | * @brief generate a random U32. | ||
122 | */ | ||
123 | U32 janky_fast_random_bytes() | ||
124 | { | ||
125 | sJankyRandomSeed = U64L(1664525) * sJankyRandomSeed + U64L(1013904223); | ||
126 | return (U32)sJankyRandomSeed; | ||
127 | } | ||
128 | |||
129 | /** | ||
130 | * @brief generate a random U32 from [0, val) | ||
131 | */ | ||
132 | U32 janky_fast_random_byes_range(U32 val) | ||
133 | { | ||
134 | sJankyRandomSeed = U64L(1664525) * sJankyRandomSeed + U64L(1013904223); | ||
135 | return (U32)(sJankyRandomSeed) % val; | ||
136 | } | ||
137 | |||
138 | /** | ||
139 | * @brief generate a random U32 from [0, val) | ||
140 | */ | ||
141 | U32 janky_fast_random_seeded_bytes(U32 seed, U32 val) | ||
142 | { | ||
143 | seed = U64L(1664525) * (U64)(seed) + U64L(1013904223); | ||
144 | return (U32)(seed) % val; | ||
145 | } | ||
146 | #endif | ||
113 | 147 | ||
114 | // Common to all UUID implementations | 148 | // Common to all UUID implementations |
115 | void LLUUID::toString(char *out) const | 149 | void LLUUID::toString(char *out) const |
@@ -395,8 +429,16 @@ static void get_random_bytes(void *buf, int nbytes) | |||
395 | int i; | 429 | int i; |
396 | char *cp = (char *) buf; | 430 | char *cp = (char *) buf; |
397 | 431 | ||
432 | // *NOTE: If we are not using the janky generator ll_rand() | ||
433 | // generates at least 3 good bytes of data since it is 0 to | ||
434 | // RAND_MAX. This could be made more efficient by copying all the | ||
435 | // bytes. | ||
398 | for (i=0; i < nbytes; i++) | 436 | for (i=0; i < nbytes; i++) |
399 | *cp++ = gLindenLabRandomNumber.llrand() & 0xFF; | 437 | #if LL_USE_JANKY_RANDOM_NUMBER_GENERATOR |
438 | *cp++ = janky_fast_random_bytes() & 0xFF; | ||
439 | #else | ||
440 | *cp++ = ll_rand() & 0xFF; | ||
441 | #endif | ||
400 | return; | 442 | return; |
401 | } | 443 | } |
402 | 444 | ||
@@ -738,18 +780,18 @@ void LLUUID::getCurrentTime(uuid_time_t *timestamp) | |||
738 | 780 | ||
739 | void LLUUID::generate() | 781 | void LLUUID::generate() |
740 | { | 782 | { |
741 | // Create a UUID. | 783 | // Create a UUID. |
742 | 784 | uuid_time_t timestamp; | |
743 | |||
744 | uuid_time_t timestamp; | ||
745 | 785 | ||
746 | static unsigned char node_id[6]; | 786 | static unsigned char node_id[6]; |
747 | static int has_init = 0; | 787 | static int has_init = 0; |
748 | 788 | ||
749 | // Create a UUID. | 789 | // Create a UUID. |
750 | static uuid_time_t time_last = {0,0}; | 790 | static uuid_time_t time_last = {0,0}; |
751 | static U16 clock_seq = 0; | 791 | static U16 clock_seq = 0; |
752 | static LLRand random_generator(0); // dummy seed. reset it below | 792 | #if LL_USE_JANKY_RANDOM_NUMBER_GENERATOR |
793 | static U32 seed = 0L; // dummy seed. reset it below | ||
794 | #endif | ||
753 | if (!has_init) | 795 | if (!has_init) |
754 | { | 796 | { |
755 | if (getNodeID(node_id) <= 0) | 797 | if (getNodeID(node_id) <= 0) |
@@ -764,8 +806,15 @@ void LLUUID::generate() | |||
764 | } | 806 | } |
765 | 807 | ||
766 | getCurrentTime(&time_last); | 808 | getCurrentTime(&time_last); |
767 | random_generator.seed(time_last.low); | 809 | #if LL_USE_JANKY_RANDOM_NUMBER_GENERATOR |
768 | clock_seq = (U16) random_generator.llrand(65536); | 810 | seed = time_last.low; |
811 | #endif | ||
812 | |||
813 | #if LL_USE_JANKY_RANDOM_NUMBER_GENERATOR | ||
814 | clock_seq = (U16)janky_fast_random_seeded_bytes(seed, 65536); | ||
815 | #else | ||
816 | clock_seq = (U16)ll_rand(65536); | ||
817 | #endif | ||
769 | has_init = 1; | 818 | has_init = 1; |
770 | } | 819 | } |
771 | 820 | ||
diff --git a/linden/indra/llmath/llvolume.cpp b/linden/indra/llmath/llvolume.cpp index 14d4cdf..c527e85 100644 --- a/linden/indra/llmath/llvolume.cpp +++ b/linden/indra/llmath/llvolume.cpp | |||
@@ -725,6 +725,8 @@ BOOL LLProfileParams::importFile(FILE *fp) | |||
725 | { | 725 | { |
726 | const S32 BUFSIZE = 16384; | 726 | const S32 BUFSIZE = 16384; |
727 | char buffer[BUFSIZE]; | 727 | char buffer[BUFSIZE]; |
728 | // *NOTE: changing the size or type of these buffers will require | ||
729 | // changing the sscanf below. | ||
728 | char keyword[256]; | 730 | char keyword[256]; |
729 | char valuestr[256]; | 731 | char valuestr[256]; |
730 | keyword[0] = 0; | 732 | keyword[0] = 0; |
@@ -735,7 +737,7 @@ BOOL LLProfileParams::importFile(FILE *fp) | |||
735 | while (!feof(fp)) | 737 | while (!feof(fp)) |
736 | { | 738 | { |
737 | fgets(buffer, BUFSIZE, fp); | 739 | fgets(buffer, BUFSIZE, fp); |
738 | sscanf(buffer, " %s %s", keyword, valuestr); | 740 | sscanf(buffer, " %255s %255s", keyword, valuestr); |
739 | if (!keyword) | 741 | if (!keyword) |
740 | { | 742 | { |
741 | continue; | 743 | continue; |
@@ -795,6 +797,8 @@ BOOL LLProfileParams::importLegacyStream(std::istream& input_stream) | |||
795 | { | 797 | { |
796 | const S32 BUFSIZE = 16384; | 798 | const S32 BUFSIZE = 16384; |
797 | char buffer[BUFSIZE]; | 799 | char buffer[BUFSIZE]; |
800 | // *NOTE: changing the size or type of these buffers will require | ||
801 | // changing the sscanf below. | ||
798 | char keyword[256]; | 802 | char keyword[256]; |
799 | char valuestr[256]; | 803 | char valuestr[256]; |
800 | keyword[0] = 0; | 804 | keyword[0] = 0; |
@@ -805,7 +809,7 @@ BOOL LLProfileParams::importLegacyStream(std::istream& input_stream) | |||
805 | while (input_stream.good()) | 809 | while (input_stream.good()) |
806 | { | 810 | { |
807 | input_stream.getline(buffer, BUFSIZE); | 811 | input_stream.getline(buffer, BUFSIZE); |
808 | sscanf(buffer, " %s %s", keyword, valuestr); | 812 | sscanf(buffer, " %255s %255s", keyword, valuestr); |
809 | if (!keyword) | 813 | if (!keyword) |
810 | { | 814 | { |
811 | continue; | 815 | continue; |
@@ -1215,6 +1219,8 @@ BOOL LLPathParams::importFile(FILE *fp) | |||
1215 | { | 1219 | { |
1216 | const S32 BUFSIZE = 16384; | 1220 | const S32 BUFSIZE = 16384; |
1217 | char buffer[BUFSIZE]; | 1221 | char buffer[BUFSIZE]; |
1222 | // *NOTE: changing the size or type of these buffers will require | ||
1223 | // changing the sscanf below. | ||
1218 | char keyword[256]; | 1224 | char keyword[256]; |
1219 | char valuestr[256]; | 1225 | char valuestr[256]; |
1220 | keyword[0] = 0; | 1226 | keyword[0] = 0; |
@@ -1227,7 +1233,7 @@ BOOL LLPathParams::importFile(FILE *fp) | |||
1227 | while (!feof(fp)) | 1233 | while (!feof(fp)) |
1228 | { | 1234 | { |
1229 | fgets(buffer, BUFSIZE, fp); | 1235 | fgets(buffer, BUFSIZE, fp); |
1230 | sscanf(buffer, " %s %s", keyword, valuestr); | 1236 | sscanf(buffer, " %255s %255s", keyword, valuestr); |
1231 | if (!keyword) | 1237 | if (!keyword) |
1232 | { | 1238 | { |
1233 | continue; | 1239 | continue; |
@@ -1354,6 +1360,8 @@ BOOL LLPathParams::importLegacyStream(std::istream& input_stream) | |||
1354 | { | 1360 | { |
1355 | const S32 BUFSIZE = 16384; | 1361 | const S32 BUFSIZE = 16384; |
1356 | char buffer[BUFSIZE]; | 1362 | char buffer[BUFSIZE]; |
1363 | // *NOTE: changing the size or type of these buffers will require | ||
1364 | // changing the sscanf below. | ||
1357 | char keyword[256]; | 1365 | char keyword[256]; |
1358 | char valuestr[256]; | 1366 | char valuestr[256]; |
1359 | keyword[0] = 0; | 1367 | keyword[0] = 0; |
@@ -1366,7 +1374,7 @@ BOOL LLPathParams::importLegacyStream(std::istream& input_stream) | |||
1366 | while (input_stream.good()) | 1374 | while (input_stream.good()) |
1367 | { | 1375 | { |
1368 | input_stream.getline(buffer, BUFSIZE); | 1376 | input_stream.getline(buffer, BUFSIZE); |
1369 | sscanf(buffer, " %s %s", keyword, valuestr); | 1377 | sscanf(buffer, " %255s %255s", keyword, valuestr); |
1370 | if (!keyword) | 1378 | if (!keyword) |
1371 | { | 1379 | { |
1372 | continue; | 1380 | continue; |
@@ -3340,13 +3348,15 @@ BOOL LLVolumeParams::importFile(FILE *fp) | |||
3340 | //llinfos << "importing volume" << llendl; | 3348 | //llinfos << "importing volume" << llendl; |
3341 | const S32 BUFSIZE = 16384; | 3349 | const S32 BUFSIZE = 16384; |
3342 | char buffer[BUFSIZE]; | 3350 | char buffer[BUFSIZE]; |
3351 | // *NOTE: changing the size or type of this buffer will require | ||
3352 | // changing the sscanf below. | ||
3343 | char keyword[256]; | 3353 | char keyword[256]; |
3344 | keyword[0] = 0; | 3354 | keyword[0] = 0; |
3345 | 3355 | ||
3346 | while (!feof(fp)) | 3356 | while (!feof(fp)) |
3347 | { | 3357 | { |
3348 | fgets(buffer, BUFSIZE, fp); | 3358 | fgets(buffer, BUFSIZE, fp); |
3349 | sscanf(buffer, " %s", keyword); | 3359 | sscanf(buffer, " %255s", keyword); |
3350 | if (!keyword) | 3360 | if (!keyword) |
3351 | { | 3361 | { |
3352 | continue; | 3362 | continue; |
@@ -3391,6 +3401,8 @@ BOOL LLVolumeParams::importLegacyStream(std::istream& input_stream) | |||
3391 | { | 3401 | { |
3392 | //llinfos << "importing volume" << llendl; | 3402 | //llinfos << "importing volume" << llendl; |
3393 | const S32 BUFSIZE = 16384; | 3403 | const S32 BUFSIZE = 16384; |
3404 | // *NOTE: changing the size or type of this buffer will require | ||
3405 | // changing the sscanf below. | ||
3394 | char buffer[BUFSIZE]; | 3406 | char buffer[BUFSIZE]; |
3395 | char keyword[256]; | 3407 | char keyword[256]; |
3396 | keyword[0] = 0; | 3408 | keyword[0] = 0; |
@@ -3398,7 +3410,7 @@ BOOL LLVolumeParams::importLegacyStream(std::istream& input_stream) | |||
3398 | while (input_stream.good()) | 3410 | while (input_stream.good()) |
3399 | { | 3411 | { |
3400 | input_stream.getline(buffer, BUFSIZE); | 3412 | input_stream.getline(buffer, BUFSIZE); |
3401 | sscanf(buffer, " %s", keyword); | 3413 | sscanf(buffer, " %255s", keyword); |
3402 | if (!keyword) | 3414 | if (!keyword) |
3403 | { | 3415 | { |
3404 | continue; | 3416 | continue; |