1 // ========================================================================== 2 // SeqAn - The Library for Sequence Analysis 3 // ========================================================================== 4 // Copyright (c) 2006-2018, Knut Reinert, FU Berlin 5 // All rights reserved. 6 // 7 // Redistribution and use in source and binary forms, with or without 8 // modification, are permitted provided that the following conditions are met: 9 // 10 // * Redistributions of source code must retain the above copyright 11 // notice, this list of conditions and the following disclaimer. 12 // * Redistributions in binary form must reproduce the above copyright 13 // notice, this list of conditions and the following disclaimer in the 14 // documentation and/or other materials provided with the distribution. 15 // * Neither the name of Knut Reinert or the FU Berlin nor the names of 16 // its contributors may be used to endorse or promote products derived 17 // from this software without specific prior written permission. 18 // 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 // ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE 23 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 29 // DAMAGE. 30 // 31 // ========================================================================== 32 // Author: David Weese <david.weese@fu-berlin.de> 33 // Author: Manuel Holtgrewe <manuel.holtgrewe@fu-berlin.de> 34 // ========================================================================== 35 36 // TODO(holtgrew): Split into modified_string_mod_view.h and modified_iterator_mod_view.h. 37 // TODO(holtgrew): Move out convert() 38 39 #ifndef SEQAN_MODIFIER_MODIFIER_VIEW_H_ 40 #define SEQAN_MODIFIER_MODIFIER_VIEW_H_ 41 42 namespace seqan 43 { 44 45 // ========================================================================== 46 // Forwards 47 // ========================================================================== 48 49 // ========================================================================== 50 // Classes 51 // ========================================================================== 52 53 // -------------------------------------------------------------------------- 54 // Class ModView 55 // -------------------------------------------------------------------------- 56 57 /*! 58 * @class ModViewModifiedIterator 59 * @extends ModifiedIterator 60 * @headerfile <seqan/modifier.h> 61 * 62 * @brief Transforms the character of a host using a custom functor. 63 * 64 * @signature template <typename THost, typename TFunctor> 65 * class ModifiedIterator<THost, ModView<TFunctor> >; 66 * 67 * @tparam THost The host iterator. 68 * @tparam TFunctor A unary functor type. 69 */ 70 71 /*! 72 * @class ModViewModifiedString 73 * @extends ModifiedString 74 * @headerfile <seqan/modifier.h> 75 * 76 * @brief Transforms the character of a host using a custom functor. 77 * 78 * @signature template <typename THost, typename TFunctor> 79 * class ModifiedString<THost, ModView<TFunctor> >; 80 * 81 * @tparam THost The host iterator. 82 * @tparam TFunctor A unary functor type. 83 */ 84 85 template <typename TFunctor> 86 struct ModView {}; 87 88 template <typename TFunctor> 89 struct ModViewCargo 90 { 91 TFunctor func; 92 ModViewCargoModViewCargo93 ModViewCargo() : func() 94 {} 95 }; 96 97 template <typename THost, typename TFunctor> 98 class ModifiedIterator<THost, ModView<TFunctor> > 99 { 100 public: 101 typedef typename Cargo<ModifiedIterator>::Type TCargo_; 102 103 THost _host; 104 TCargo_ _cargo; 105 106 mutable typename Value<ModifiedIterator>::Type tmp_value; 107 ModifiedIterator()108 ModifiedIterator() : _host(), tmp_value() 109 {} 110 111 template <typename TOtherHost> ModifiedIterator(ModifiedIterator<TOtherHost,ModView<TFunctor>> & origin)112 ModifiedIterator(ModifiedIterator<TOtherHost, ModView<TFunctor> > & origin) : 113 _host(origin._host), _cargo(origin._cargo), tmp_value() 114 {} 115 116 explicit ModifiedIterator(THost const & host)117 ModifiedIterator(THost const & host) : 118 _host(host), tmp_value() 119 {} 120 ModifiedIterator(THost const & host,TFunctor const & functor)121 ModifiedIterator(THost const & host, TFunctor const & functor): 122 _host(host), tmp_value() 123 { 124 cargo(*this).func = functor; 125 } 126 }; 127 128 // -------------------------------------------------------------------------- 129 // Class ModifiedString 130 // -------------------------------------------------------------------------- 131 132 template <typename THost, typename TFunctor> 133 class ModifiedString<THost, ModView<TFunctor> > 134 { 135 public: 136 typedef typename Pointer_<THost>::Type THostPointer_; 137 typedef typename Cargo<ModifiedString>::Type TCargo_; 138 139 mutable THostPointer_ _host; 140 TCargo_ _cargo; 141 142 mutable typename Value<ModifiedString>::Type tmp_value; 143 144 // Default constructor. ModifiedString()145 ModifiedString() : _host(), tmp_value() 146 {} 147 148 // Construct with the actual host. 149 explicit ModifiedString(typename Parameter_<THost>::Type host)150 ModifiedString(typename Parameter_<THost>::Type host): 151 _host(_toPointer(host)), tmp_value() 152 {} 153 154 // Construct with the functor. 155 explicit ModifiedString(TFunctor const & functor)156 ModifiedString(TFunctor const & functor): 157 _host(), tmp_value() 158 { 159 cargo(*this).func = functor; 160 } 161 162 // Constructor for creating a ModifiedString with const host from a non-const host. 163 template <typename THost_> 164 explicit ModifiedString(THost_ & host,SEQAN_CTOR_ENABLE_IF (IsConstructible<THost,THost_>))165 ModifiedString(THost_ & host, 166 SEQAN_CTOR_ENABLE_IF(IsConstructible<THost, THost_>)) : 167 _host(_toPointer(host)), tmp_value() 168 { 169 ignoreUnusedVariableWarning(dummy); 170 } 171 172 // Construct with the actual host; variant with functor. ModifiedString(typename Parameter_<THost>::Type host,TFunctor const & functor)173 ModifiedString(typename Parameter_<THost>::Type host, TFunctor const & functor) : 174 _host(_toPointer(host)), tmp_value() 175 { 176 cargo(*this).func = functor; 177 } 178 179 // Constructor for creating a ModifiedString with const host with a non-const host; variant with functor. 180 template <typename THost_> 181 explicit ModifiedString(THost_ & host,TFunctor const & functor,SEQAN_CTOR_ENABLE_IF (IsConstructible<THost,THost_>))182 ModifiedString(THost_ & host, 183 TFunctor const & functor, 184 SEQAN_CTOR_ENABLE_IF(IsConstructible<THost, THost_>)) : 185 _host(_toPointer(host)), tmp_value() 186 { 187 ignoreUnusedVariableWarning(dummy); 188 cargo(*this).func = functor; 189 } 190 191 // Constructor for innermost type; hand down to _host which is a ModifiedString itself. 192 template <typename THost_> 193 explicit ModifiedString(THost_ && host,SEQAN_CTOR_ENABLE_IF (IsAnInnerHost<typename RemoveReference<THost>::Type,typename RemoveReference<THost_>::Type>))194 ModifiedString(THost_ && host, 195 SEQAN_CTOR_ENABLE_IF(IsAnInnerHost< 196 typename RemoveReference<THost>::Type, 197 typename RemoveReference<THost_>::Type >)) : 198 _host(std::forward<THost_>(host)), tmp_value() 199 { 200 ignoreUnusedVariableWarning(dummy); 201 } 202 203 // Constructor for innermost type; hand down to _host which is a ModifiedString itself. Variant with functor. 204 template <typename THost_> 205 explicit ModifiedString(THost_ && host,TFunctor const & functor,SEQAN_CTOR_ENABLE_IF (IsAnInnerHost<typename RemoveReference<THost>::Type,typename RemoveReference<THost_>::Type>))206 ModifiedString(THost_ && host, 207 TFunctor const & functor, 208 SEQAN_CTOR_ENABLE_IF(IsAnInnerHost< 209 typename RemoveReference<THost>::Type, 210 typename RemoveReference<THost_>::Type >)) : 211 _host(std::forward<THost_>(host)), tmp_value() 212 { 213 ignoreUnusedVariableWarning(dummy); 214 cargo(*this).func = functor; 215 } 216 217 template <typename TPos> 218 inline typename Reference<ModifiedString>::Type 219 operator[](TPos pos) 220 { 221 return value(*this, pos); 222 } 223 224 template <typename TPos> 225 inline typename Reference<ModifiedString const>::Type 226 operator[](TPos pos) const 227 { 228 return value(*this, pos); 229 } 230 }; 231 232 // ========================================================================== 233 // Metafunctions 234 // ========================================================================== 235 236 // -------------------------------------------------------------------------- 237 // Metafunction Cargo [ModifiedIterator] 238 // -------------------------------------------------------------------------- 239 240 template <typename THost, typename TFunctor> 241 struct Cargo<ModifiedIterator<THost, ModView<TFunctor> > > 242 { 243 typedef ModViewCargo<TFunctor> Type; 244 }; 245 246 // -------------------------------------------------------------------------- 247 // Metafunction Value [ModifiedIterator] 248 // -------------------------------------------------------------------------- 249 250 template <typename THost, typename TFunctor> 251 struct Value<ModifiedIterator<THost, ModView<TFunctor> > > 252 { 253 typedef typename TFunctor::result_type TResult_; 254 typedef typename RemoveConst_<TResult_>::Type Type; 255 }; 256 257 template <typename THost, typename TFunctor> 258 struct Value<ModifiedIterator<THost, ModView<TFunctor> > const> : 259 Value<ModifiedIterator<THost, ModView<TFunctor> > > 260 {}; 261 262 // -------------------------------------------------------------------------- 263 // Metafunction GetValue [ModifiedIterator] 264 // -------------------------------------------------------------------------- 265 266 template <typename THost, typename TFunctor> 267 struct GetValue<ModifiedIterator<THost, ModView<TFunctor> > > : 268 Value<ModifiedIterator<THost, ModView<TFunctor> > > 269 {}; 270 271 template <typename THost, typename TFunctor> 272 struct GetValue<ModifiedIterator<THost, ModView<TFunctor> > const> : 273 Value<ModifiedIterator<THost, ModView<TFunctor> > > 274 {}; 275 276 // -------------------------------------------------------------------------- 277 // Metafunction Reference [ModifiedIterator] 278 // -------------------------------------------------------------------------- 279 280 template <typename THost, typename TFunctor> 281 struct Reference<ModifiedIterator<THost, ModView<TFunctor> > > : 282 Value<ModifiedIterator<THost, ModView<TFunctor> > > 283 {}; 284 285 template <typename THost, typename TFunctor> 286 struct Reference<ModifiedIterator<THost, ModView<TFunctor> > const> : 287 Value<ModifiedIterator<THost, ModView<TFunctor> > > 288 {}; 289 290 // NOTE(h-2): ModView element access is always by copy never by reference 291 // This is a workaround for dangling references to the stack when 292 // combining infixes and modified views, more precisely: 293 // if you iterate over an infix of a modview then value() on the iterator 294 // will return reference to the tmp_value inside the moditerator 295 // which might have been destructed. 296 // This is a more general problem that stems from the fact that 297 // "virtual strings" of the same type (infixes, modstrings) can be 298 // automatically compacted into one layer, but combinations cannot. 299 // This workaround happens in ModView, because it is used less frequently 300 // then Infixes. 301 302 // -------------------------------------------------------------------------- 303 // Metafunction Cargo [ModifiedString] 304 // -------------------------------------------------------------------------- 305 306 template <typename THost, typename TFunctor> 307 struct Cargo< ModifiedString<THost, ModView<TFunctor> > > 308 { 309 typedef ModViewCargo<TFunctor> Type; 310 }; 311 312 // ========================================================================== 313 // Functions 314 // ========================================================================== 315 316 // -------------------------------------------------------------------------- 317 // Function getValue() [ModifiedIterator] 318 // -------------------------------------------------------------------------- 319 320 template <typename THost, typename TFunctor> 321 inline typename GetValue<ModifiedIterator<THost, ModView<TFunctor> > >::Type 322 getValue(ModifiedIterator<THost, ModView<TFunctor> > & me) 323 { 324 return cargo(me).func(*host(me)); 325 } 326 327 template <typename THost, typename TFunctor> 328 inline typename GetValue<ModifiedIterator<THost, ModView<TFunctor> > const>::Type 329 getValue(ModifiedIterator<THost, ModView<TFunctor> > const & me) 330 { 331 return cargo(me).func(*host(me)); 332 } 333 334 // -------------------------------------------------------------------------- 335 // Function value() [ModifiedIterator] 336 // -------------------------------------------------------------------------- 337 338 template <typename THost, typename TFunctor> 339 inline typename GetValue<ModifiedIterator<THost, ModView<TFunctor> > >::Type 340 value(ModifiedIterator<THost, ModView<TFunctor> > & me) 341 { 342 return getValue(me); 343 } 344 345 template <typename THost, typename TFunctor> 346 inline typename GetValue<ModifiedIterator<THost, ModView<TFunctor> > const>::Type 347 value(ModifiedIterator<THost, ModView<TFunctor> > const & me) 348 { 349 return getValue(me); 350 } 351 352 // -------------------------------------------------------------------------- 353 // Function getValue() [ModifiedString] 354 // -------------------------------------------------------------------------- 355 356 template <typename THost, typename TFunctor, typename TPos> 357 inline typename GetValue<ModifiedString<THost, ModView<TFunctor> > >::Type 358 getValue(ModifiedString<THost, ModView<TFunctor> > & me, TPos pos) 359 { 360 return cargo(me).func(getValue(host(me), pos)); 361 } 362 363 template <typename THost, typename TFunctor, typename TPos> 364 inline typename GetValue<ModifiedString<THost, ModView<TFunctor> > const>::Type 365 getValue(ModifiedString<THost, ModView<TFunctor> > const & me, TPos pos) 366 { 367 return cargo(me).func(getValue(host(me), pos)); 368 } 369 370 // -------------------------------------------------------------------------- 371 // Function value() [ModifiedString] 372 // -------------------------------------------------------------------------- 373 374 template <typename THost, typename TFunctor, typename TPos> 375 inline typename GetValue<ModifiedString<THost, ModView<TFunctor> > >::Type 376 value(ModifiedString<THost, ModView<TFunctor> > & me, TPos pos) 377 { 378 return getValue(me, pos); 379 } 380 381 template <typename THost, typename TFunctor, typename TPos> 382 inline typename GetValue<ModifiedString<THost, ModView<TFunctor> > const>::Type 383 value(ModifiedString<THost, ModView<TFunctor> > const & me, TPos pos) 384 { 385 return getValue(me, pos); 386 } 387 388 // -------------------------------------------------------------------------- 389 // Function assignModViewFunctor() 390 // -------------------------------------------------------------------------- 391 392 template <typename THost, typename TFunctor> 393 inline void 394 assignModViewFunctor(ModifiedString<THost, ModView<TFunctor> > & me, TFunctor const & functor) 395 { 396 cargo(me).func = functor; 397 } 398 399 // -------------------------------------------------------------------------- 400 // Function convert() 401 // -------------------------------------------------------------------------- 402 403 template < typename TSequence, typename TFunctor > 404 inline void 405 convert(TSequence & sequence, TFunctor const &F) 406 { 407 #if defined (_OPENMP) && defined (SEQAN_PARALLEL) 408 // OpenMP does not support for loop with iterators. Therefore use index variables. 409 typedef typename Position<TSequence>::Type TPos; 410 typedef typename MakeSigned_<TPos>::Type TSignedPos; 411 412 #pragma omp parallel for if(length(sequence) > 1000000) 413 for(TSignedPos p = 0; p < (TSignedPos)length(sequence); ++p) 414 sequence[p] = F(sequence[p]); 415 416 #else 417 typedef typename Iterator<TSequence, Standard>::Type TIter; 418 419 TIter it = begin(sequence, Standard()); 420 TIter itEnd = end(sequence, Standard()); 421 for(; it != itEnd; ++it) 422 *it = F(*it); 423 #endif 424 } 425 426 template < typename TSequence, typename TFunctor > 427 inline void 428 convert(TSequence const & sequence, TFunctor const &F) 429 { 430 #if defined (_OPENMP) && defined (SEQAN_PARALLEL) 431 // OpenMP does not support for loop with iterators. Therefore use index variables. 432 typedef typename Position<TSequence>::Type TPos; 433 typedef typename MakeSigned_<TPos>::Type TSignedPos; 434 435 #pragma omp parallel for if(length(sequence) > 1000000) 436 for(TSignedPos p = 0; p < (TSignedPos)length(sequence); ++p) 437 sequence[p] = F(sequence[p]); 438 439 #else 440 typedef typename Iterator<TSequence const, Standard>::Type TIter; 441 442 TIter it = begin(sequence, Standard()); 443 TIter itEnd = end(sequence, Standard()); 444 for(; it != itEnd; ++it) 445 *it = F(*it); 446 #endif 447 } 448 449 } // namespace seqan 450 451 #endif // SEQAN_MODIFIER_MODIFIER_VIEW_H_ 452