1/* 2 * This file contains hard constraint wrappers required by both, MFE and 3 * partition function version of exterior loop evaluation 4 */ 5 6struct hc_ext_def_dat { 7 unsigned int n; 8 unsigned char *mx; 9 unsigned char **mx_window; 10 unsigned int *sn; 11 int *hc_up; 12 void *hc_dat; 13 vrna_callback_hc_evaluate *hc_f; 14}; 15 16PRIVATE unsigned char 17hc_ext_cb_def(int i, 18 int j, 19 int k, 20 int l, 21 unsigned char d, 22 void *data); 23 24 25PRIVATE unsigned char 26hc_ext_cb_sn(int i, 27 int j, 28 int k, 29 int l, 30 unsigned char d, 31 void *data); 32 33 34PRIVATE unsigned char 35hc_ext_cb_def_window(int i, 36 int j, 37 int k, 38 int l, 39 unsigned char d, 40 void *data); 41 42 43PRIVATE unsigned char 44hc_ext_cb_def_user(int i, 45 int j, 46 int k, 47 int l, 48 unsigned char d, 49 void *data); 50 51 52PRIVATE unsigned char 53hc_ext_cb_def_sn_user(int i, 54 int j, 55 int k, 56 int l, 57 unsigned char d, 58 void *data); 59 60 61PRIVATE unsigned char 62hc_ext_cb_def_user_window(int i, 63 int j, 64 int k, 65 int l, 66 unsigned char d, 67 void *data); 68 69 70PRIVATE INLINE vrna_callback_hc_evaluate * 71prepare_hc_ext_def(vrna_fold_compound_t *fc, 72 struct hc_ext_def_dat *dat); 73 74 75PRIVATE INLINE vrna_callback_hc_evaluate * 76prepare_hc_ext_def_window(vrna_fold_compound_t *fc, 77 struct hc_ext_def_dat *dat); 78 79 80/* 81 ################################# 82 # BEGIN OF FUNCTION DEFINITIONS # 83 ################################# 84 */ 85PRIVATE unsigned char 86hc_ext_cb_def(int i, 87 int j, 88 int k, 89 int l, 90 unsigned char d, 91 void *data) 92{ 93 int di, dj; 94 unsigned char eval; 95 unsigned int n; 96 struct hc_ext_def_dat *dat = (struct hc_ext_def_dat *)data; 97 98 eval = (unsigned char)0; 99 di = k - i; 100 dj = j - l; 101 n = dat->n; 102 103 switch (d) { 104 case VRNA_DECOMP_EXT_EXT_STEM: 105 if (dat->mx[n * j + l] & VRNA_CONSTRAINT_CONTEXT_EXT_LOOP) { 106 eval = (unsigned char)1; 107 if (i != l) { 108 /* otherwise, stem spans from i to j */ 109 di = l - k - 1; 110 if ((di != 0) && (dat->hc_up[k + 1] < di)) 111 eval = (unsigned char)0; 112 } 113 } 114 115 break; 116 117 case VRNA_DECOMP_EXT_STEM_EXT: 118 if (dat->mx[n * k + i] & VRNA_CONSTRAINT_CONTEXT_EXT_LOOP) { 119 eval = (unsigned char)1; 120 if (i != l) { 121 /* otherwise, stem spans from i to j */ 122 di = l - k - 1; 123 if ((di != 0) && (dat->hc_up[k + 1] < di)) 124 eval = (unsigned char)0; 125 } 126 } 127 128 break; 129 130 case VRNA_DECOMP_EXT_EXT_STEM1: 131 if (dat->mx[n * (j - 1) + l] & VRNA_CONSTRAINT_CONTEXT_EXT_LOOP) { 132 eval = (unsigned char)1; 133 if (dat->hc_up[j] == 0) 134 eval = (unsigned char)0; 135 136 if (i != l) { 137 /* otherwise, stem spans from i to j - 1 */ 138 di = l - k - 1; 139 140 if ((di != 0) && (dat->hc_up[k + 1] < di)) 141 eval = (unsigned char)0; 142 } 143 } 144 145 break; 146 147 case VRNA_DECOMP_EXT_EXT_EXT: 148 eval = (unsigned char)1; 149 di = l - k - 1; 150 if ((di != 0) && (dat->hc_up[k + 1] < di)) 151 eval = (unsigned char)0; 152 153 break; 154 155 case VRNA_DECOMP_EXT_STEM: 156 if (dat->mx[n * k + l] & VRNA_CONSTRAINT_CONTEXT_EXT_LOOP) { 157 eval = (unsigned char)1; 158 if ((di != 0) && (dat->hc_up[i] < di)) 159 eval = (unsigned char)0; 160 161 if ((dj != 0) && (dat->hc_up[l + 1] < dj)) 162 eval = (unsigned char)0; 163 } 164 165 break; 166 167 case VRNA_DECOMP_EXT_EXT: 168 eval = (unsigned char)1; 169 if ((di != 0) && (dat->hc_up[i] < di)) 170 eval = (unsigned char)0; 171 172 if ((dj != 0) && (dat->hc_up[l + 1] < dj)) 173 eval = (unsigned char)0; 174 175 break; 176 177 case VRNA_DECOMP_EXT_UP: 178 di = j - i + 1; 179 eval = (dat->hc_up[i] >= di) ? (unsigned char)1 : (unsigned char)0; 180 break; 181 182 case VRNA_DECOMP_EXT_STEM_OUTSIDE: 183 if (dat->mx[n * k + l] & VRNA_CONSTRAINT_CONTEXT_EXT_LOOP) 184 eval = (unsigned char)1; 185 186 break; 187 188 default: 189 vrna_message_warning("hc_cb@exterior_loops.c: " 190 "Unrecognized decomposition %d", 191 d); 192 } 193 194 return eval; 195} 196 197 198PRIVATE unsigned char 199hc_ext_cb_sn(int i, 200 int j, 201 int k, 202 int l, 203 unsigned char d, 204 void *data) 205{ 206 unsigned int *sn; 207 unsigned char eval; 208 struct hc_ext_def_dat *dat = (struct hc_ext_def_dat *)data; 209 210 sn = dat->sn; 211 eval = (unsigned char)0; 212 213 /* for now with the 'old' cofold implementation, we allow for any decomposition */ 214 return (unsigned char)1; 215 216 switch (d) { 217 case VRNA_DECOMP_EXT_EXT_STEM1: 218 if (sn[j - 1] != sn[j]) 219 break; 220 221 /* fall through */ 222 case VRNA_DECOMP_EXT_EXT_STEM: 223 /* fall through */ 224 case VRNA_DECOMP_EXT_STEM_EXT: 225 /* fall through */ 226 case VRNA_DECOMP_EXT_EXT_EXT: 227 if (sn[k] == sn[l]) 228 eval = (unsigned char)1; 229 230 break; 231 232 case VRNA_DECOMP_EXT_STEM: 233 /* fall through */ 234 case VRNA_DECOMP_EXT_EXT: 235 if ((sn[i] == sn[k]) && (sn[l] == sn[j])) 236 eval = (unsigned char)1; 237 238 break; 239 240 case VRNA_DECOMP_EXT_UP: 241 if (sn[i] == sn[j]) 242 eval = (unsigned char)1; 243 244 break; 245 246 default: 247 vrna_message_warning("hc_cb@exterior_loops.c: " 248 "Unrecognized decomposition %d", 249 d); 250 } 251 252 return eval; 253} 254 255 256PRIVATE unsigned char 257hc_ext_cb_def_window(int i, 258 int j, 259 int k, 260 int l, 261 unsigned char d, 262 void *data) 263{ 264 int di, dj; 265 unsigned char eval; 266 struct hc_ext_def_dat *dat = (struct hc_ext_def_dat *)data; 267 268 eval = (unsigned char)0; 269 di = k - i; 270 dj = j - l; 271 272 switch (d) { 273 case VRNA_DECOMP_EXT_EXT_STEM: 274 if (dat->mx_window[l][j - l] & VRNA_CONSTRAINT_CONTEXT_EXT_LOOP) { 275 eval = (unsigned char)1; 276 if (i != l) { 277 /* otherwise, stem spans from i to j */ 278 di = l - k - 1; 279 if ((di != 0) && (dat->hc_up[k + 1] < di)) 280 eval = (unsigned char)0; 281 } 282 } 283 284 break; 285 286 case VRNA_DECOMP_EXT_STEM_EXT: 287 if (dat->mx_window[i][k - i] & VRNA_CONSTRAINT_CONTEXT_EXT_LOOP) { 288 eval = (unsigned char)1; 289 if (j != k) { 290 /* otherwise, stem spans from i to j */ 291 dj = l - k - 1; 292 if ((dj != 0) && (dat->hc_up[k + 1] < dj)) 293 eval = (unsigned char)0; 294 } 295 } 296 297 break; 298 299 case VRNA_DECOMP_EXT_EXT_STEM1: 300 if (dat->mx_window[l][j - 1 - l] & VRNA_CONSTRAINT_CONTEXT_EXT_LOOP) { 301 eval = (unsigned char)1; 302 303 if (dat->hc_up[j] == 0) 304 eval = (unsigned char)0; 305 306 if (i != l) { 307 /* otherwise, stem spans from i to j - 1 */ 308 di = l - k - 1; 309 310 if ((di != 0) && (dat->hc_up[k + 1] < di)) 311 eval = (unsigned char)0; 312 } 313 } 314 315 break; 316 317 case VRNA_DECOMP_EXT_STEM_EXT1: 318 if (dat->mx_window[i + 1][k - (i + 1)] & VRNA_CONSTRAINT_CONTEXT_EXT_LOOP) { 319 eval = (unsigned char)1; 320 321 if (dat->hc_up[i] == 0) 322 eval = (unsigned char)0; 323 324 if (j != k) { 325 /* otherwise, stem spans from i + 1 to j */ 326 dj = l - k - 1; 327 328 if ((dj != 0) && (dat->hc_up[k + 1] < dj)) 329 eval = (unsigned char)0; 330 } 331 } 332 333 break; 334 335 case VRNA_DECOMP_EXT_STEM: 336 if (dat->mx_window[k][l - k] & VRNA_CONSTRAINT_CONTEXT_EXT_LOOP) { 337 eval = (unsigned char)1; 338 if ((di != 0) && (dat->hc_up[i] < di)) 339 eval = (unsigned char)0; 340 341 if ((dj != 0) && (dat->hc_up[l + 1] < dj)) 342 eval = (unsigned char)0; 343 } 344 345 break; 346 347 case VRNA_DECOMP_EXT_EXT_EXT: 348 eval = (unsigned char)1; 349 di = l - k - 1; 350 if ((di != 0) && (dat->hc_up[k + 1] < di)) 351 eval = (unsigned char)0; 352 353 break; 354 355 case VRNA_DECOMP_EXT_EXT: 356 eval = (unsigned char)1; 357 if ((di != 0) && (dat->hc_up[i] < di)) 358 eval = (unsigned char)0; 359 360 if ((dj != 0) && (dat->hc_up[l + 1] < dj)) 361 eval = (unsigned char)0; 362 363 break; 364 365 case VRNA_DECOMP_EXT_UP: 366 di = j - i + 1; 367 eval = (dat->hc_up[i] >= di) ? (unsigned char)1 : (unsigned char)0; 368 break; 369 370 default: 371 vrna_message_warning("hc_cb@exterior_loops.c: " 372 "Unrecognized decomposition %d", 373 d); 374 } 375 376 return eval; 377} 378 379 380PRIVATE unsigned char 381hc_ext_cb_def_sn(int i, 382 int j, 383 int k, 384 int l, 385 unsigned char d, 386 void *data) 387{ 388 unsigned char eval; 389 390 eval = hc_ext_cb_def(i, j, k, l, d, data); 391 eval = hc_ext_cb_sn(i, j, k, l, d, data) ? eval : (unsigned char)0; 392 393 return eval; 394} 395 396 397PRIVATE unsigned char 398hc_ext_cb_def_user(int i, 399 int j, 400 int k, 401 int l, 402 unsigned char d, 403 void *data) 404{ 405 unsigned char eval; 406 struct hc_ext_def_dat *dat = (struct hc_ext_def_dat *)data; 407 408 eval = hc_ext_cb_def(i, j, k, l, d, data); 409 eval = (dat->hc_f(i, j, k, l, d, dat->hc_dat)) ? eval : (unsigned char)0; 410 411 return eval; 412} 413 414 415PRIVATE unsigned char 416hc_ext_cb_def_sn_user(int i, 417 int j, 418 int k, 419 int l, 420 unsigned char d, 421 void *data) 422{ 423 unsigned char eval; 424 struct hc_ext_def_dat *dat = (struct hc_ext_def_dat *)data; 425 426 eval = hc_ext_cb_def(i, j, k, l, d, data); 427 eval = hc_ext_cb_sn(i, j, k, l, d, data) ? eval : (unsigned char)0; 428 eval = dat->hc_f(i, j, k, l, d, dat->hc_dat) ? eval : (unsigned char)0; 429 430 return eval; 431} 432 433 434PRIVATE unsigned char 435hc_ext_cb_def_user_window(int i, 436 int j, 437 int k, 438 int l, 439 unsigned char d, 440 void *data) 441{ 442 unsigned char eval; 443 struct hc_ext_def_dat *dat = (struct hc_ext_def_dat *)data; 444 445 eval = hc_ext_cb_def_window(i, j, k, l, d, data); 446 eval = dat->hc_f(i, j, k, l, d, dat->hc_dat) ? eval : (unsigned char)0; 447 448 return eval; 449} 450 451 452PRIVATE INLINE vrna_callback_hc_evaluate * 453prepare_hc_ext_def(vrna_fold_compound_t *fc, 454 struct hc_ext_def_dat *dat) 455{ 456 dat->mx = fc->hc->mx; 457 dat->n = fc->length; 458 dat->hc_up = fc->hc->up_ext; 459 dat->sn = fc->strand_number; 460 461 if (fc->hc->f) { 462 dat->hc_f = fc->hc->f; 463 dat->hc_dat = fc->hc->data; 464 return (fc->strands == 1) ? &hc_ext_cb_def_user : &hc_ext_cb_def_sn_user; 465 } 466 467 return (fc->strands == 1) ? &hc_ext_cb_def : &hc_ext_cb_def_sn; 468} 469 470 471PRIVATE INLINE vrna_callback_hc_evaluate * 472prepare_hc_ext_def_window(vrna_fold_compound_t *fc, 473 struct hc_ext_def_dat *dat) 474{ 475 dat->mx_window = fc->hc->matrix_local; 476 dat->hc_up = fc->hc->up_ext; 477 dat->sn = fc->strand_number; 478 479 if (fc->hc->f) { 480 dat->hc_f = fc->hc->f; 481 dat->hc_dat = fc->hc->data; 482 return &hc_ext_cb_def_user_window; 483 } 484 485 return &hc_ext_cb_def_window; 486} 487