diff --git a/src/gprs_rlcmac_ts_alloc.cpp b/src/gprs_rlcmac_ts_alloc.cpp index 4cc95392..835c199b 100644 --- a/src/gprs_rlcmac_ts_alloc.cpp +++ b/src/gprs_rlcmac_ts_alloc.cpp @@ -54,19 +54,11 @@ static char *set_flag_chars(char *buf, uint8_t val, char set_char, char unset_ch return buf; } -static bool test_and_set_bit(uint32_t *bits, size_t elem) -{ - bool was_set = bits[elem/32] & (1 << (elem % 32)); - bits[elem/32] |= (1 << (elem % 32)); - - return was_set; -} - -static int find_possible_pdchs(const struct gprs_rlcmac_trx *trx, size_t max_slots, uint8_t mask, - const char *mask_reason = NULL) +static uint8_t find_possible_pdchs(const struct gprs_rlcmac_trx *trx, uint8_t max_slots, uint8_t mask, + const char *mask_reason = NULL) { unsigned ts; - int valid_ts_set = 0; + uint8_t valid_ts_set = 0; int8_t last_tsc = -1; /* must be signed */ for (ts = 0; ts < ARRAY_SIZE(trx->pdch); ts++) { @@ -353,7 +345,7 @@ int alloc_algorithm_a(struct gprs_rlcmac_bts *bts, GprsMs *ms_, struct gprs_rlcm int trx_no; int tfi = -1; int usf = -1; - int mask = 0xff; + uint8_t mask = 0xff; const char *mask_reason = NULL; const GprsMs *ms = ms_; const gprs_rlcmac_tbf *tbf = tbf_; @@ -457,6 +449,58 @@ static inline unsigned compute_capacity(const struct gprs_rlcmac_trx *trx, int r return capacity; } +/*! Decide if a given slot should be skipped by multislot allocator + * + * \param[in] ms_class Pointer to MS Class object + * \param[in] check_tr Flag indicating whether we should check for Tra or Tta parameters for a given MS class + * \param[in] rx_window Receive window + * \param[in] tx_window Transmit window + * \param[in,out] checked_rx array with already checked RX timeslots + * \returns true if the slot should be skipped, false otherwise + */ +static bool skip_slot(uint8_t mslot_class, bool check_tr, + int16_t rx_window, int16_t tx_window, + uint32_t *checked_rx) +{ + uint8_t common_slot_count, req_common_slots, + rx_slot_count = pcu_bitcount(rx_window), + tx_slot_count = pcu_bitcount(tx_window); + + /* Check compliance with TS 45.002, table 6.4.2.2.1 */ + /* Whether to skip this round doesn not only depend on the bit + * sets but also on check_tr. Therefore this check must be done + * before doing the mslot_test_and_set_bit shortcut. */ + if (mslot_class_get_type(mslot_class) == 1) { + uint16_t slot_sum = rx_slot_count + tx_slot_count; + /* Assume down + up / dynamic. + * TODO: For ext-dynamic, down only, up only add more cases. + */ + if (slot_sum <= 6 && tx_slot_count < 3) { + if (!check_tr) + return true; /* Skip Tta */ + } else if (slot_sum > 6 && tx_slot_count < 3) { + if (check_tr) + return true; /* Skip Tra */ + } else + return true; /* No supported row in TS 45.002, table 6.4.2.2.1. */ + } + + /* Avoid repeated RX combination check */ + if (mslot_test_and_set_bit(checked_rx, rx_window)) + return true; + + /* Check number of common slots according to TS 45.002, ยง6.4.2.2 */ + common_slot_count = pcu_bitcount(tx_window & rx_window); + req_common_slots = OSMO_MIN(tx_slot_count, rx_slot_count); + if (mslot_class_get_type(mslot_class) == 1) + req_common_slots = OSMO_MIN(req_common_slots, 2); + + if (req_common_slots != common_slot_count) + return true; + + return false; +} + /*! Find set of slots available for allocation while taking MS class into account * * \param[in] trx Pointer to TRX object @@ -468,16 +512,12 @@ static inline unsigned compute_capacity(const struct gprs_rlcmac_trx *trx, int r int find_multi_slots(struct gprs_rlcmac_trx *trx, uint8_t mslot_class, uint8_t *ul_slots, uint8_t *dl_slots) { uint8_t Tx = mslot_class_get_tx(mslot_class), /* Max number of Tx slots */ - Sum = mslot_class_get_sum(mslot_class); /* Max number of Tx + Rx slots */ - int rx_window, tx_window, pdch_slots; + Sum = mslot_class_get_sum(mslot_class), /* Max number of Tx + Rx slots */ + max_slots, num_tx, mask_sel, pdch_slots, ul_ts, dl_ts; + int16_t rx_window, tx_window; char slot_info[9] = {0}; int max_capacity = -1; uint8_t max_ul_slots = 0, max_dl_slots = 0; - unsigned max_slots; - - unsigned ul_ts, dl_ts; - unsigned num_tx; - unsigned mask_sel; if (mslot_class) LOGP(DRLCMAC, LOGL_DEBUG, "Slot Allocation (Algorithm B) for class %d\n", @@ -519,13 +559,11 @@ int find_multi_slots(struct gprs_rlcmac_trx *trx, uint8_t mslot_class, uint8_t * /* Rotate group of TX slots: UUU-----, -UUU----, ..., UU-----U */ for (ul_ts = 0; ul_ts < 8; ul_ts += 1, tx_valid_win <<= 1) { - unsigned tx_slot_count; - int max_rx; uint16_t rx_valid_win; uint32_t checked_rx[256/32] = {0}; /* Wrap valid window */ - tx_valid_win = (tx_valid_win | tx_valid_win >> 8) & 0xff; + tx_valid_win = mslot_wrap_window(tx_valid_win); tx_window = tx_valid_win; @@ -540,10 +578,7 @@ int find_multi_slots(struct gprs_rlcmac_trx *trx, uint8_t mslot_class, uint8_t * if ((tx_window & (1 << ((ul_ts+num_tx-1) % 8))) == 0) continue; - tx_slot_count = pcu_bitcount(tx_window); - - max_rx = OSMO_MIN(mslot_class_get_rx(mslot_class), Sum - num_tx); - rx_valid_win = (1 << max_rx) - 1; + rx_valid_win = (1 << OSMO_MIN(mslot_class_get_rx(mslot_class), Sum - num_tx)) - 1; /* Rotate group of RX slots: DDD-----, -DDD----, ..., DD-----D */ for (dl_ts = 0; dl_ts < 8; dl_ts += 1, rx_valid_win <<= 1) { @@ -552,107 +587,14 @@ int find_multi_slots(struct gprs_rlcmac_trx *trx, uint8_t mslot_class, uint8_t * /* Validate with both Tta/Ttb/Trb and Ttb/Tra/Trb */ for (mask_sel = MASK_TT; mask_sel <= MASK_TR; mask_sel += 1) { - unsigned common_slot_count; - unsigned req_common_slots; - unsigned rx_slot_count; - uint16_t rx_bad; - uint8_t rx_good; int capacity; - /* Filter out bad slots */ - rx_bad = (uint16_t)(0xff & ~rx_mask[mask_sel]) << ul_ts; - rx_bad = (rx_bad | (rx_bad >> 8)) & 0xff; - rx_good = *dl_slots & ~rx_bad; - - /* TODO: CHECK this calculation -> separate function for unit - * testing */ - - rx_window = rx_good & rx_valid_win; - rx_slot_count = pcu_bitcount(rx_window); - -#if 0 - LOGP(DRLCMAC, LOGL_DEBUG, "n_tx=%d, n_rx=%d, mask_sel=%d, " - "tx=%02x, rx=%02x, mask=%02x, bad=%02x, good=%02x, " - "ul=%02x, dl=%02x\n", - tx_slot_count, rx_slot_count, mask_sel, - tx_window, rx_window, rx_mask[mask_sel], rx_bad, rx_good, - *ul_slots, *dl_slots); -#endif - - /* Check compliance with TS 45.002, table 6.4.2.2.1 */ - /* Whether to skip this round doesn not only depend on the bit - * sets but also on mask_sel. Therefore this check must be done - * before doing the test_and_set_bit shortcut. */ - if (mslot_class_get_type(mslot_class) == 1) { - unsigned slot_sum = rx_slot_count + tx_slot_count; - /* Assume down+up/dynamic. - * TODO: For ext-dynamic, down only, up only add more - * cases. - */ - if (slot_sum <= 6 && tx_slot_count < 3) { - if (mask_sel != MASK_TR) - /* Skip Tta */ - continue; - } else if (slot_sum > 6 && tx_slot_count < 3) { - if (mask_sel != MASK_TT) - /* Skip Tra */ - continue; - } else { - /* No supported row in table 6.4.2.2.1. */ -#ifdef ENABLE_TS_ALLOC_DEBUG - LOGP(DRLCMAC, LOGL_DEBUG, - "- Skipping DL/UL slots: (TS=0)\"%s\"(TS=7), " - "combination not supported\n", - set_flag_chars(set_flag_chars(set_flag_chars( - slot_info, - rx_bad, 'x', '.'), - rx_window, 'D'), - tx_window, 'U')); -#endif - continue; - } - } - - /* Avoid repeated RX combination check */ - if (test_and_set_bit(checked_rx, rx_window)) + rx_window = mslot_filter_bad(rx_mask[mask_sel], ul_ts, *dl_slots, rx_valid_win); + if (rx_window < 0) continue; - if (!rx_good) { -#ifdef ENABLE_TS_ALLOC_DEBUG - LOGP(DRLCMAC, LOGL_DEBUG, - "- Skipping DL/UL slots: (TS=0)\"%s\"(TS=7), " - "no DL slots available\n", - set_flag_chars(set_flag_chars(slot_info, - rx_bad, 'x', '.'), - tx_window, 'U')); -#endif - continue; - } - - if (!rx_window) - continue; - - /* Check number of common slots according to TS 54.002, 6.4.2.2 */ - common_slot_count = pcu_bitcount(tx_window & rx_window); - req_common_slots = OSMO_MIN(tx_slot_count, rx_slot_count); - if (mslot_class_get_type(mslot_class) == 1) - req_common_slots = OSMO_MIN(req_common_slots, 2); - - if (req_common_slots != common_slot_count) { -#ifdef ENABLE_TS_ALLOC_DEBUG - LOGP(DRLCMAC, LOGL_DEBUG, - "- Skipping DL/UL slots: (TS=0)\"%s\"(TS=7), " - "invalid number of common TS: %d (expected %d)\n", - set_flag_chars(set_flag_chars(set_flag_chars( - slot_info, - rx_bad, 'x', '.'), - rx_window, 'D'), - tx_window, 'U'), - common_slot_count, - req_common_slots); -#endif - continue; - } + if (skip_slot(mslot_class, mask_sel != MASK_TT, rx_window, tx_window, checked_rx)) + continue; /* Compute capacity */ capacity = compute_capacity(trx, rx_window, tx_window); diff --git a/src/mslot_class.c b/src/mslot_class.c index d403f001..2a482f18 100644 --- a/src/mslot_class.c +++ b/src/mslot_class.c @@ -260,3 +260,38 @@ void ts_format(char *buf, uint8_t dl_mask, uint8_t ul_mask) masked_override_with(buf, ul_mask, 'U'); masked_override_with(buf, ul_mask & dl_mask, 'C'); } + +uint16_t mslot_wrap_window(uint16_t win) +{ + return (win | win >> 8) & 0xFF; +} + +bool mslot_test_and_set_bit(uint32_t *bits, size_t elem) +{ + bool was_set = bits[elem/32] & (1 << (elem % 32)); + bits[elem/32] |= (1 << (elem % 32)); + + return was_set; +} + +/*! Filter out bad slots + * + * \param[in] mask TS selection mask + * \param[in] ul_slots set of UL timeslots + * \param[in] dl_slots set of DL timeslots + * \param[in] rx_valid_win Mask for valid RX window value + * \returns negative error code or RX window on success + */ +int16_t mslot_filter_bad(uint8_t mask, uint8_t ul_slots, uint8_t dl_slots, uint16_t rx_valid_win) +{ + uint8_t rx_good; + uint16_t rx_bad = (uint16_t)(0xFF & ~mask) << ul_slots; + + /* TODO: CHECK this calculation -> separate function for unit testing */ + rx_bad = (rx_bad | (rx_bad >> 8)) & 0xFF; + rx_good = dl_slots & ~rx_bad; + if (!rx_good) + return -1; + + return rx_good & rx_valid_win; +} diff --git a/src/mslot_class.h b/src/mslot_class.h index 445455f4..045fb317 100644 --- a/src/mslot_class.h +++ b/src/mslot_class.h @@ -57,3 +57,6 @@ int8_t find_free_usf(uint8_t usf_map); int8_t find_free_tfi(uint32_t tfi_map); void masked_override_with(char *buf, uint8_t mask, char set_char); void ts_format(char *buf, uint8_t dl_mask, uint8_t ul_mask); +uint16_t mslot_wrap_window(uint16_t win); +bool mslot_test_and_set_bit(uint32_t *bits, size_t elem); +int16_t mslot_filter_bad(uint8_t mask, uint8_t ul_slots, uint8_t dl_slots, uint16_t rx_valid_win); diff --git a/tests/alloc/MslotTest.cpp b/tests/alloc/MslotTest.cpp index 1fa28bf5..92f92fae 100644 --- a/tests/alloc/MslotTest.cpp +++ b/tests/alloc/MslotTest.cpp @@ -27,6 +27,7 @@ #include extern "C" { + #include "mslot_class.h" #include #include #include @@ -137,6 +138,13 @@ static inline void test_multislot_ends(bool seq) test_all_classes(trx, seq); } +static inline void test_window_wrapper() +{ + uint16_t i; + for (i = 0; i < 256 * 2 + 1; i++) + printf("W[%03u] -> %3u %s\n", + i, mslot_wrap_window(i), mslot_wrap_window(i) < 256 ? "OK" : "FAIL"); +} int main(int argc, char **argv) { @@ -163,6 +171,8 @@ int main(int argc, char **argv) test_multislot_ends(true); test_multislot_ends(false); + test_window_wrapper(); + return EXIT_SUCCESS; } diff --git a/tests/alloc/MslotTest.ok b/tests/alloc/MslotTest.ok index 86526bf7..a47cf57a 100644 --- a/tests/alloc/MslotTest.ok +++ b/tests/alloc/MslotTest.ok @@ -1730,3 +1730,516 @@ test_multislot_ends(): accumulative [ACC] multislot class 44 - UL: .......1 DL: .......1 [0] [ACC] multislot class 45 - UL: .......1 DL: .......1 [0] [ACC] multislot class 46 - UL: .......1 DL: .......1 [-22] +W[000] -> 0 OK +W[001] -> 1 OK +W[002] -> 2 OK +W[003] -> 3 OK +W[004] -> 4 OK +W[005] -> 5 OK +W[006] -> 6 OK +W[007] -> 7 OK +W[008] -> 8 OK +W[009] -> 9 OK +W[010] -> 10 OK +W[011] -> 11 OK +W[012] -> 12 OK +W[013] -> 13 OK +W[014] -> 14 OK +W[015] -> 15 OK +W[016] -> 16 OK +W[017] -> 17 OK +W[018] -> 18 OK +W[019] -> 19 OK +W[020] -> 20 OK +W[021] -> 21 OK +W[022] -> 22 OK +W[023] -> 23 OK +W[024] -> 24 OK +W[025] -> 25 OK +W[026] -> 26 OK +W[027] -> 27 OK +W[028] -> 28 OK +W[029] -> 29 OK +W[030] -> 30 OK +W[031] -> 31 OK +W[032] -> 32 OK +W[033] -> 33 OK +W[034] -> 34 OK +W[035] -> 35 OK +W[036] -> 36 OK +W[037] -> 37 OK +W[038] -> 38 OK +W[039] -> 39 OK +W[040] -> 40 OK +W[041] -> 41 OK +W[042] -> 42 OK +W[043] -> 43 OK +W[044] -> 44 OK +W[045] -> 45 OK +W[046] -> 46 OK +W[047] -> 47 OK +W[048] -> 48 OK +W[049] -> 49 OK +W[050] -> 50 OK +W[051] -> 51 OK +W[052] -> 52 OK +W[053] -> 53 OK +W[054] -> 54 OK +W[055] -> 55 OK +W[056] -> 56 OK +W[057] -> 57 OK +W[058] -> 58 OK +W[059] -> 59 OK +W[060] -> 60 OK +W[061] -> 61 OK +W[062] -> 62 OK +W[063] -> 63 OK +W[064] -> 64 OK +W[065] -> 65 OK +W[066] -> 66 OK +W[067] -> 67 OK +W[068] -> 68 OK +W[069] -> 69 OK +W[070] -> 70 OK +W[071] -> 71 OK +W[072] -> 72 OK +W[073] -> 73 OK +W[074] -> 74 OK +W[075] -> 75 OK +W[076] -> 76 OK +W[077] -> 77 OK +W[078] -> 78 OK +W[079] -> 79 OK +W[080] -> 80 OK +W[081] -> 81 OK +W[082] -> 82 OK +W[083] -> 83 OK +W[084] -> 84 OK +W[085] -> 85 OK +W[086] -> 86 OK +W[087] -> 87 OK +W[088] -> 88 OK +W[089] -> 89 OK +W[090] -> 90 OK +W[091] -> 91 OK +W[092] -> 92 OK +W[093] -> 93 OK +W[094] -> 94 OK +W[095] -> 95 OK +W[096] -> 96 OK +W[097] -> 97 OK +W[098] -> 98 OK +W[099] -> 99 OK +W[100] -> 100 OK +W[101] -> 101 OK +W[102] -> 102 OK +W[103] -> 103 OK +W[104] -> 104 OK +W[105] -> 105 OK +W[106] -> 106 OK +W[107] -> 107 OK +W[108] -> 108 OK +W[109] -> 109 OK +W[110] -> 110 OK +W[111] -> 111 OK +W[112] -> 112 OK +W[113] -> 113 OK +W[114] -> 114 OK +W[115] -> 115 OK +W[116] -> 116 OK +W[117] -> 117 OK +W[118] -> 118 OK +W[119] -> 119 OK +W[120] -> 120 OK +W[121] -> 121 OK +W[122] -> 122 OK +W[123] -> 123 OK +W[124] -> 124 OK +W[125] -> 125 OK +W[126] -> 126 OK +W[127] -> 127 OK +W[128] -> 128 OK +W[129] -> 129 OK +W[130] -> 130 OK +W[131] -> 131 OK +W[132] -> 132 OK +W[133] -> 133 OK +W[134] -> 134 OK +W[135] -> 135 OK +W[136] -> 136 OK +W[137] -> 137 OK +W[138] -> 138 OK +W[139] -> 139 OK +W[140] -> 140 OK +W[141] -> 141 OK +W[142] -> 142 OK +W[143] -> 143 OK +W[144] -> 144 OK +W[145] -> 145 OK +W[146] -> 146 OK +W[147] -> 147 OK +W[148] -> 148 OK +W[149] -> 149 OK +W[150] -> 150 OK +W[151] -> 151 OK +W[152] -> 152 OK +W[153] -> 153 OK +W[154] -> 154 OK +W[155] -> 155 OK +W[156] -> 156 OK +W[157] -> 157 OK +W[158] -> 158 OK +W[159] -> 159 OK +W[160] -> 160 OK +W[161] -> 161 OK +W[162] -> 162 OK +W[163] -> 163 OK +W[164] -> 164 OK +W[165] -> 165 OK +W[166] -> 166 OK +W[167] -> 167 OK +W[168] -> 168 OK +W[169] -> 169 OK +W[170] -> 170 OK +W[171] -> 171 OK +W[172] -> 172 OK +W[173] -> 173 OK +W[174] -> 174 OK +W[175] -> 175 OK +W[176] -> 176 OK +W[177] -> 177 OK +W[178] -> 178 OK +W[179] -> 179 OK +W[180] -> 180 OK +W[181] -> 181 OK +W[182] -> 182 OK +W[183] -> 183 OK +W[184] -> 184 OK +W[185] -> 185 OK +W[186] -> 186 OK +W[187] -> 187 OK +W[188] -> 188 OK +W[189] -> 189 OK +W[190] -> 190 OK +W[191] -> 191 OK +W[192] -> 192 OK +W[193] -> 193 OK +W[194] -> 194 OK +W[195] -> 195 OK +W[196] -> 196 OK +W[197] -> 197 OK +W[198] -> 198 OK +W[199] -> 199 OK +W[200] -> 200 OK +W[201] -> 201 OK +W[202] -> 202 OK +W[203] -> 203 OK +W[204] -> 204 OK +W[205] -> 205 OK +W[206] -> 206 OK +W[207] -> 207 OK +W[208] -> 208 OK +W[209] -> 209 OK +W[210] -> 210 OK +W[211] -> 211 OK +W[212] -> 212 OK +W[213] -> 213 OK +W[214] -> 214 OK +W[215] -> 215 OK +W[216] -> 216 OK +W[217] -> 217 OK +W[218] -> 218 OK +W[219] -> 219 OK +W[220] -> 220 OK +W[221] -> 221 OK +W[222] -> 222 OK +W[223] -> 223 OK +W[224] -> 224 OK +W[225] -> 225 OK +W[226] -> 226 OK +W[227] -> 227 OK +W[228] -> 228 OK +W[229] -> 229 OK +W[230] -> 230 OK +W[231] -> 231 OK +W[232] -> 232 OK +W[233] -> 233 OK +W[234] -> 234 OK +W[235] -> 235 OK +W[236] -> 236 OK +W[237] -> 237 OK +W[238] -> 238 OK +W[239] -> 239 OK +W[240] -> 240 OK +W[241] -> 241 OK +W[242] -> 242 OK +W[243] -> 243 OK +W[244] -> 244 OK +W[245] -> 245 OK +W[246] -> 246 OK +W[247] -> 247 OK +W[248] -> 248 OK +W[249] -> 249 OK +W[250] -> 250 OK +W[251] -> 251 OK +W[252] -> 252 OK +W[253] -> 253 OK +W[254] -> 254 OK +W[255] -> 255 OK +W[256] -> 1 OK +W[257] -> 1 OK +W[258] -> 3 OK +W[259] -> 3 OK +W[260] -> 5 OK +W[261] -> 5 OK +W[262] -> 7 OK +W[263] -> 7 OK +W[264] -> 9 OK +W[265] -> 9 OK +W[266] -> 11 OK +W[267] -> 11 OK +W[268] -> 13 OK +W[269] -> 13 OK +W[270] -> 15 OK +W[271] -> 15 OK +W[272] -> 17 OK +W[273] -> 17 OK +W[274] -> 19 OK +W[275] -> 19 OK +W[276] -> 21 OK +W[277] -> 21 OK +W[278] -> 23 OK +W[279] -> 23 OK +W[280] -> 25 OK +W[281] -> 25 OK +W[282] -> 27 OK +W[283] -> 27 OK +W[284] -> 29 OK +W[285] -> 29 OK +W[286] -> 31 OK +W[287] -> 31 OK +W[288] -> 33 OK +W[289] -> 33 OK +W[290] -> 35 OK +W[291] -> 35 OK +W[292] -> 37 OK +W[293] -> 37 OK +W[294] -> 39 OK +W[295] -> 39 OK +W[296] -> 41 OK +W[297] -> 41 OK +W[298] -> 43 OK +W[299] -> 43 OK +W[300] -> 45 OK +W[301] -> 45 OK +W[302] -> 47 OK +W[303] -> 47 OK +W[304] -> 49 OK +W[305] -> 49 OK +W[306] -> 51 OK +W[307] -> 51 OK +W[308] -> 53 OK +W[309] -> 53 OK +W[310] -> 55 OK +W[311] -> 55 OK +W[312] -> 57 OK +W[313] -> 57 OK +W[314] -> 59 OK +W[315] -> 59 OK +W[316] -> 61 OK +W[317] -> 61 OK +W[318] -> 63 OK +W[319] -> 63 OK +W[320] -> 65 OK +W[321] -> 65 OK +W[322] -> 67 OK +W[323] -> 67 OK +W[324] -> 69 OK +W[325] -> 69 OK +W[326] -> 71 OK +W[327] -> 71 OK +W[328] -> 73 OK +W[329] -> 73 OK +W[330] -> 75 OK +W[331] -> 75 OK +W[332] -> 77 OK +W[333] -> 77 OK +W[334] -> 79 OK +W[335] -> 79 OK +W[336] -> 81 OK +W[337] -> 81 OK +W[338] -> 83 OK +W[339] -> 83 OK +W[340] -> 85 OK +W[341] -> 85 OK +W[342] -> 87 OK +W[343] -> 87 OK +W[344] -> 89 OK +W[345] -> 89 OK +W[346] -> 91 OK +W[347] -> 91 OK +W[348] -> 93 OK +W[349] -> 93 OK +W[350] -> 95 OK +W[351] -> 95 OK +W[352] -> 97 OK +W[353] -> 97 OK +W[354] -> 99 OK +W[355] -> 99 OK +W[356] -> 101 OK +W[357] -> 101 OK +W[358] -> 103 OK +W[359] -> 103 OK +W[360] -> 105 OK +W[361] -> 105 OK +W[362] -> 107 OK +W[363] -> 107 OK +W[364] -> 109 OK +W[365] -> 109 OK +W[366] -> 111 OK +W[367] -> 111 OK +W[368] -> 113 OK +W[369] -> 113 OK +W[370] -> 115 OK +W[371] -> 115 OK +W[372] -> 117 OK +W[373] -> 117 OK +W[374] -> 119 OK +W[375] -> 119 OK +W[376] -> 121 OK +W[377] -> 121 OK +W[378] -> 123 OK +W[379] -> 123 OK +W[380] -> 125 OK +W[381] -> 125 OK +W[382] -> 127 OK +W[383] -> 127 OK +W[384] -> 129 OK +W[385] -> 129 OK +W[386] -> 131 OK +W[387] -> 131 OK +W[388] -> 133 OK +W[389] -> 133 OK +W[390] -> 135 OK +W[391] -> 135 OK +W[392] -> 137 OK +W[393] -> 137 OK +W[394] -> 139 OK +W[395] -> 139 OK +W[396] -> 141 OK +W[397] -> 141 OK +W[398] -> 143 OK +W[399] -> 143 OK +W[400] -> 145 OK +W[401] -> 145 OK +W[402] -> 147 OK +W[403] -> 147 OK +W[404] -> 149 OK +W[405] -> 149 OK +W[406] -> 151 OK +W[407] -> 151 OK +W[408] -> 153 OK +W[409] -> 153 OK +W[410] -> 155 OK +W[411] -> 155 OK +W[412] -> 157 OK +W[413] -> 157 OK +W[414] -> 159 OK +W[415] -> 159 OK +W[416] -> 161 OK +W[417] -> 161 OK +W[418] -> 163 OK +W[419] -> 163 OK +W[420] -> 165 OK +W[421] -> 165 OK +W[422] -> 167 OK +W[423] -> 167 OK +W[424] -> 169 OK +W[425] -> 169 OK +W[426] -> 171 OK +W[427] -> 171 OK +W[428] -> 173 OK +W[429] -> 173 OK +W[430] -> 175 OK +W[431] -> 175 OK +W[432] -> 177 OK +W[433] -> 177 OK +W[434] -> 179 OK +W[435] -> 179 OK +W[436] -> 181 OK +W[437] -> 181 OK +W[438] -> 183 OK +W[439] -> 183 OK +W[440] -> 185 OK +W[441] -> 185 OK +W[442] -> 187 OK +W[443] -> 187 OK +W[444] -> 189 OK +W[445] -> 189 OK +W[446] -> 191 OK +W[447] -> 191 OK +W[448] -> 193 OK +W[449] -> 193 OK +W[450] -> 195 OK +W[451] -> 195 OK +W[452] -> 197 OK +W[453] -> 197 OK +W[454] -> 199 OK +W[455] -> 199 OK +W[456] -> 201 OK +W[457] -> 201 OK +W[458] -> 203 OK +W[459] -> 203 OK +W[460] -> 205 OK +W[461] -> 205 OK +W[462] -> 207 OK +W[463] -> 207 OK +W[464] -> 209 OK +W[465] -> 209 OK +W[466] -> 211 OK +W[467] -> 211 OK +W[468] -> 213 OK +W[469] -> 213 OK +W[470] -> 215 OK +W[471] -> 215 OK +W[472] -> 217 OK +W[473] -> 217 OK +W[474] -> 219 OK +W[475] -> 219 OK +W[476] -> 221 OK +W[477] -> 221 OK +W[478] -> 223 OK +W[479] -> 223 OK +W[480] -> 225 OK +W[481] -> 225 OK +W[482] -> 227 OK +W[483] -> 227 OK +W[484] -> 229 OK +W[485] -> 229 OK +W[486] -> 231 OK +W[487] -> 231 OK +W[488] -> 233 OK +W[489] -> 233 OK +W[490] -> 235 OK +W[491] -> 235 OK +W[492] -> 237 OK +W[493] -> 237 OK +W[494] -> 239 OK +W[495] -> 239 OK +W[496] -> 241 OK +W[497] -> 241 OK +W[498] -> 243 OK +W[499] -> 243 OK +W[500] -> 245 OK +W[501] -> 245 OK +W[502] -> 247 OK +W[503] -> 247 OK +W[504] -> 249 OK +W[505] -> 249 OK +W[506] -> 251 OK +W[507] -> 251 OK +W[508] -> 253 OK +W[509] -> 253 OK +W[510] -> 255 OK +W[511] -> 255 OK +W[512] -> 2 OK