Image Component Library (ICL)
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
SSEUtils.h
Go to the documentation of this file.
00001 /********************************************************************
00002 **                Image Component Library (ICL)                    **
00003 **                                                                 **
00004 ** Copyright (C) 2006-2013 CITEC, University of Bielefeld          **
00005 **                         Neuroinformatics Group                  **
00006 ** Website: www.iclcv.org and                                      **
00007 **          http://opensource.cit-ec.de/projects/icl               **
00008 **                                                                 **
00009 ** File   : ICLUtils/src/ICLUtils/SSEUtils.h                       **
00010 ** Module : ICLUtils                                               **
00011 ** Authors: Sergius Gaulik                                         **
00012 **                                                                 **
00013 **                                                                 **
00014 ** GNU LESSER GENERAL PUBLIC LICENSE                               **
00015 ** This file may be used under the terms of the GNU Lesser General **
00016 ** Public License version 3.0 as published by the                  **
00017 **                                                                 **
00018 ** Free Software Foundation and appearing in the file LICENSE.LGPL **
00019 ** included in the packaging of this file.  Please review the      **
00020 ** following information to ensure the license requirements will   **
00021 ** be met: http://www.gnu.org/licenses/lgpl-3.0.txt                **
00022 **                                                                 **
00023 ** The development of this software was supported by the           **
00024 ** Excellence Cluster EXC 277 Cognitive Interaction Technology.    **
00025 ** The Excellence Cluster EXC 277 is a grant of the Deutsche       **
00026 ** Forschungsgemeinschaft (DFG) in the context of the German       **
00027 ** Excellence Initiative.                                          **
00028 **                                                                 **
00029 ********************************************************************/
00030 
00031 #pragma once
00032 
00033 #include <ICLUtils/CompatMacros.h>
00034 #include <ICLUtils/SSETypes.h>
00035 
00036 namespace icl{
00037   namespace utils{
00038 
00039     #ifdef ICL_HAVE_SSE2
00040 
00041       // ++ rounding ++ //
00042 
00043       // possible modes:
00044       // _MM_ROUND_NEAREST
00045       // _MM_ROUND_DOWN
00046       // _MM_ROUND_UP
00047       // _MM_ROUND_TOWARD_ZERO
00048 
00049       static const unsigned int INITIAL_ROUNDING_MODE = _MM_GET_ROUNDING_MODE();
00050       static unsigned int PREVIOUS_ROUNDING_MODE = INITIAL_ROUNDING_MODE;
00051 
00052       inline void sse_restore_initial_rounding_mode() {
00053         _MM_SET_ROUNDING_MODE(INITIAL_ROUNDING_MODE);
00054       }
00055 
00056       inline void sse_restore_previous_rounding_mode() {
00057         const unsigned int mode = _MM_GET_ROUNDING_MODE();
00058         _MM_SET_ROUNDING_MODE(PREVIOUS_ROUNDING_MODE);
00059         PREVIOUS_ROUNDING_MODE = mode;
00060       }
00061 
00062       inline void sse_set_rounding_mode(const unsigned int mode) {
00063         PREVIOUS_ROUNDING_MODE = _MM_GET_ROUNDING_MODE();
00064         _MM_SET_ROUNDING_MODE(mode);
00065       }
00066 
00067       // -- rounding -- //
00068 
00069 
00070       // ++ alignment ++ //
00071 
00072       template<class T>
00073       inline int sse_is_16byte_aligned(const T *ptr) {
00074         return !(((uintptr_t)ptr) & 15);
00075       }
00076 
00077       template<class T>
00078       inline int sse_is_not_16byte_aligned(const T *ptr) {
00079         return (((uintptr_t)ptr) & 15);
00080       }
00081 
00082       template<class T>
00083       inline int sse_is_aligned(const T *ptr, const unsigned int bytes) {
00084         return !(((uintptr_t)ptr) & (bytes-1));
00085       }
00086 
00087       template<class T>
00088       inline int sse_is_not_aligned(const T *ptr, const unsigned int bytes) {
00089         return (((uintptr_t)ptr) & (bytes-1));
00090       }
00091 
00092       // -- alignment -- //
00093 
00094 
00095       // ++ conditions ++ //
00096 
00097       template<class T>
00098       inline T sse_if(const T &vIf, const T &v0) {
00099         T ret = (v0 & vIf);
00100         return ret;
00101       }
00102 
00103       template<class T>
00104       inline T sse_ifelse(const T &vIf, const T &v0, const T &v1) {
00105         T ret = (v0 & vIf);
00106         ret += andnot(v1, vIf);
00107         return ret;
00108       }
00109 
00110       // -- conditions -- //
00111 
00112 
00113       // ++ for-loops ++ //
00114 
00115       // the sse_for functions can be implemented compact in only one function
00116       // using pointer-to-pointer, but it is slower than the current
00117       // implementation of many versions
00118 
00119       template<class S, class D>
00120       inline void sse_for(const S *src0,
00121                           D *dst0, D *dstEnd,
00122                           void (*subMethod)(const S*, D*),
00123                           void (*subSSEMethod)(const S*, D*),
00124                           long step) {
00125         D *dstSSEEnd = dstEnd - (step - 1);
00126 
00127         for (; dst0<dstSSEEnd;) {
00128             // convert 'rvalues' values at the same time
00129             (*subSSEMethod)(src0, dst0);
00130 
00131             // increment pointers to the next values
00132             src0 += step;
00133             dst0 += step;
00134         }
00135 
00136         for (; dst0<dstEnd; ++src0, ++dst0) {
00137           // convert 1 value
00138           (*subMethod)(src0, dst0);
00139         }
00140       }
00141 
00142       template<class S, class D>
00143       inline void sse_for(const S *src0,
00144                           D *dst0, D *dst1, D *dstEnd,
00145                           void (*subMethod)(const S*, D*, D*),
00146                           void (*subSSEMethod)(const S*, D*, D*),
00147                           long step) {
00148         D *dstSSEEnd = dstEnd - (step - 1);
00149 
00150         for (; dst0<dstSSEEnd;) {
00151             // convert 'rvalues' values at the same time
00152             (*subSSEMethod)(src0, dst0, dst1);
00153 
00154             // increment pointers to the next values
00155             src0 += step;
00156             dst0 += step;
00157             dst1 += step;
00158         }
00159 
00160         for (; dst0<dstEnd; ++src0, ++dst0, ++dst1) {
00161           // convert 1 value
00162           (*subMethod)(src0, dst0, dst1);
00163         }
00164       }
00165 
00166       template<class S, class D>
00167       inline void sse_for(const S *src0,
00168                           D *dst0, D *dst1, D *dst2, D *dstEnd,
00169                           void (*subMethod)(const S*, D*, D*, D*),
00170                           void (*subSSEMethod)(const S*, D*, D*, D*),
00171                           long step) {
00172         D *dstSSEEnd = dstEnd - (step - 1);
00173 
00174         for (; dst0<dstSSEEnd;) {
00175             // convert 'rvalues' values at the same time
00176             (*subSSEMethod)(src0, dst0, dst1, dst2);
00177 
00178             // increment pointers to the next values
00179             src0 += step;
00180             dst0 += step;
00181             dst1 += step;
00182             dst2 += step;
00183         }
00184 
00185         for (; dst0<dstEnd; ++src0, ++dst0, ++dst1, ++dst2) {
00186           // convert 1 value
00187           (*subMethod)(src0, dst0, dst1, dst2);
00188         }
00189       }
00190 
00191       template<class S, class D>
00192       inline void sse_for(const S *src0,
00193                           D *dst0, D *dst1, D *dst2, D *dst3, D *dstEnd,
00194                           void (*subMethod)(const S*, D*, D*, D*, D*),
00195                           void (*subSSEMethod)(const S*, D*, D*, D*, D*),
00196                           long step) {
00197         D *dstSSEEnd = dstEnd - (step - 1);
00198 
00199         for (; dst0<dstSSEEnd;) {
00200             // convert 'rvalues' values at the same time
00201             (*subSSEMethod)(src0, dst0, dst1, dst2, dst3);
00202 
00203             // increment pointers to the next values
00204             src0 += step;
00205             dst0 += step;
00206             dst1 += step;
00207             dst2 += step;
00208             dst3 += step;
00209         }
00210 
00211         for (; dst0<dstEnd; ++src0, ++dst0, ++dst1, ++dst2, ++dst3) {
00212           // convert 1 value
00213           (*subMethod)(src0, dst0, dst1, dst2, dst3);
00214         }
00215       }
00216 
00217       template<class S, class D>
00218       inline void sse_for(const S *src0, const S *src1,
00219                           D *dst0, D *dstEnd,
00220                           void (*subMethod)(const S*, const S*, D*),
00221                           void (*subSSEMethod)(const S*, const S*, D*),
00222                           long step) {
00223         D *dstSSEEnd = dstEnd - (step - 1);
00224 
00225         for (; dst0<dstSSEEnd;) {
00226             // convert 'rvalues' values at the same time
00227             (*subSSEMethod)(src0, src1, dst0);
00228 
00229             // increment pointers to the next values
00230             src0 += step;
00231             src1 += step;
00232             dst0 += step;
00233         }
00234 
00235         for (; dst0<dstEnd; ++src0, ++src1, ++dst0) {
00236           // convert 1 value
00237           (*subMethod)(src0, src1, dst0);
00238         }
00239       }
00240 
00241       template<class S, class D>
00242       inline void sse_for(const S *src0, const S *src1,
00243                           D *dst0, D *dst1, D *dstEnd,
00244                           void (*subMethod)(const S*, const S*, D*, D*),
00245                           void (*subSSEMethod)(const S*, const S*, D*, D*),
00246                           long step) {
00247         D *dstSSEEnd = dstEnd - (step - 1);
00248 
00249         for (; dst0<dstSSEEnd;) {
00250             // convert 'rvalues' values at the same time
00251             (*subSSEMethod)(src0, src1, dst0, dst1);
00252 
00253             // increment pointers to the next values
00254             src0 += step;
00255             src1 += step;
00256             dst0 += step;
00257             dst1 += step;
00258         }
00259 
00260         for (; dst0<dstEnd; ++src0, ++src1, ++dst0, ++dst1) {
00261           // convert 1 value
00262           (*subMethod)(src0, src1, dst0, dst1);
00263         }
00264       }
00265 
00266       template<class S, class D>
00267       inline void sse_for(const S *src0, const S *src1,
00268                           D *dst0, D *dst1, D *dst2, D *dstEnd,
00269                           void (*subMethod)(const S*, const S*, D*, D*, D*),
00270                           void (*subSSEMethod)(const S*, const S*, D*, D*, D*),
00271                           long step) {
00272         D *dstSSEEnd = dstEnd - (step - 1);
00273 
00274         for (; dst0<dstSSEEnd;) {
00275             // convert 'rvalues' values at the same time
00276             (*subSSEMethod)(src0, src1, dst0, dst1, dst2);
00277 
00278             // increment pointers to the next values
00279             src0 += step;
00280             src1 += step;
00281             dst0 += step;
00282             dst1 += step;
00283             dst2 += step;
00284         }
00285 
00286         for (; dst0<dstEnd; ++src0, ++src1, ++dst0, ++dst1, ++dst2) {
00287           // convert 1 value
00288           (*subMethod)(src0, src1, dst0, dst1, dst2);
00289         }
00290       }
00291 
00292       template<class S, class D>
00293       inline void sse_for(const S *src0, const S *src1,
00294                           D *dst0, D *dst1, D *dst2, D* dst3, D *dstEnd,
00295                           void (*subMethod)(const S*, const S*, D*, D*, D*, D*),
00296                           void (*subSSEMethod)(const S*, const S*, D*, D*, D*, D*),
00297                           long step) {
00298         D *dstSSEEnd = dstEnd - (step - 1);
00299 
00300         for (; dst0<dstSSEEnd;) {
00301             // convert 'rvalues' values at the same time
00302             (*subSSEMethod)(src0, src1, dst0, dst1, dst2, dst3);
00303 
00304             // increment pointers to the next values
00305             src0 += step;
00306             src1 += step;
00307             dst0 += step;
00308             dst1 += step;
00309             dst2 += step;
00310             dst3 += step;
00311         }
00312 
00313         for (; dst0<dstEnd; ++src0, ++src1, ++dst0, ++dst1, ++dst2, ++dst3) {
00314           // convert 1 value
00315           (*subMethod)(src0, src1, dst0, dst1, dst2, dst3);
00316         }
00317       }
00318 
00319       template<class S, class D>
00320       inline void sse_for(const S *src0, const S *src1, const S *src2,
00321                           D *dst0, D *dstEnd,
00322                           void (*subMethod)(const S*, const S*, const S*, D*),
00323                           void (*subSSEMethod)(const S*, const S*, const S*, D*),
00324                           long step) {
00325         D *dstSSEEnd = dstEnd - (step - 1);
00326 
00327         for (; dst0<dstSSEEnd;) {
00328             // convert 'rvalues' values at the same time
00329             (*subSSEMethod)(src0, src1, src2, dst0);
00330 
00331             // increment pointers to the next values
00332             src0 += step;
00333             src1 += step;
00334             src2 += step;
00335             dst0 += step;
00336         }
00337 
00338         for (; dst0<dstEnd; ++src0, ++src1, ++src2, ++dst0) {
00339           // convert 1 value
00340           (*subMethod)(src0, src1, src2, dst0);
00341         }
00342       }
00343 
00344       template<class S, class D>
00345       inline void sse_for(const S *src0, const S *src1, const S *src2,
00346                           D *dst0, D *dst1, D *dstEnd,
00347                           void (*subMethod)(const S*, const S*, const S*, D*, D*),
00348                           void (*subSSEMethod)(const S*, const S*, const S*, D*, D*),
00349                           long step) {
00350         D *dstSSEEnd = dstEnd - (step - 1);
00351 
00352         for (; dst0<dstSSEEnd;) {
00353             // convert 'rvalues' values at the same time
00354             (*subSSEMethod)(src0, src1, src2, dst0, dst1);
00355 
00356             // increment pointers to the next values
00357             src0 += step;
00358             src1 += step;
00359             src2 += step;
00360             dst0 += step;
00361             dst1 += step;
00362         }
00363 
00364         for (; dst0<dstEnd; ++src0, ++src1, ++src2, ++dst0, ++dst1) {
00365           // convert 1 value
00366           (*subMethod)(src0, src1, src2, dst0, dst1);
00367         }
00368       }
00369 
00370       template<class S, class D>
00371       inline void sse_for(const S *src0, const S *src1, const S *src2,
00372                           D *dst0, D *dst1, D *dst2, D *dstEnd,
00373                           void (*subMethod)(const S*, const S*, const S*, D*, D*, D*),
00374                           void (*subSSEMethod)(const S*, const S*, const S*, D*, D*, D*),
00375                           long step) {
00376         D *dstSSEEnd = dstEnd - (step - 1);
00377 
00378         for (; dst0<dstSSEEnd;) {
00379             // convert 'rvalues' values at the same time
00380             (*subSSEMethod)(src0, src1, src2, dst0, dst1, dst2);
00381 
00382             // increment pointers to the next values
00383             src0 += step;
00384             src1 += step;
00385             src2 += step;
00386             dst0 += step;
00387             dst1 += step;
00388             dst2 += step;
00389         }
00390 
00391         for (; dst0<dstEnd; ++src0, ++src1, ++src2, ++dst0, ++dst1, ++dst2) {
00392           // convert 1 value
00393           (*subMethod)(src0, src1, src2, dst0, dst1, dst2);
00394         }
00395       }
00396 
00397       template<class S, class D>
00398       inline void sse_for(const S *src0, const S *src1, const S *src2,
00399                           D *dst0, D *dst1, D *dst2, D* dst3, D *dstEnd,
00400                           void (*subMethod)(const S*, const S*, const S*, D*, D*, D*, D*),
00401                           void (*subSSEMethod)(const S*, const S*, const S*, D*, D*, D*, D*),
00402                           long step) {
00403         D *dstSSEEnd = dstEnd - (step - 1);
00404 
00405         for (; dst0<dstSSEEnd;) {
00406             // convert 'rvalues' values at the same time
00407             (*subSSEMethod)(src0, src1, src2, dst0, dst1, dst2, dst3);
00408 
00409             // increment pointers to the next values
00410             src0 += step;
00411             src1 += step;
00412             src2 += step;
00413             dst0 += step;
00414             dst1 += step;
00415             dst2 += step;
00416             dst3 += step;
00417         }
00418 
00419         for (; dst0<dstEnd; ++src0, ++src1, ++src2, ++dst0, ++dst1, ++dst2, ++dst3) {
00420           // convert 1 value
00421           (*subMethod)(src0, src1, src2, dst0, dst1, dst2, dst3);
00422         }
00423       }
00424 
00425       template<class S, class D>
00426       inline void sse_for(const S *src0, const S *src1, const S *src2, const S *src3,
00427                           D *dst0, D *dstEnd,
00428                           void (*subMethod)(const S*, const S*, const S*, const S*, D*),
00429                           void (*subSSEMethod)(const S*, const S*, const S*, const S*, D*),
00430                           long step) {
00431         D *dstSSEEnd = dstEnd - (step - 1);
00432 
00433         for (; dst0<dstSSEEnd;) {
00434             // convert 'rvalues' values at the same time
00435             (*subSSEMethod)(src0, src1, src2, src3, dst0);
00436 
00437             // increment pointers to the next values
00438             src0 += step;
00439             src1 += step;
00440             src2 += step;
00441             src3 += step;
00442             dst0 += step;
00443         }
00444 
00445         for (; dst0<dstEnd; ++src0, ++src1, ++src2, ++src3, ++dst0) {
00446           // convert 1 value
00447           (*subMethod)(src0, src1, src2, src3, dst0);
00448         }
00449       }
00450 
00451       template<class S, class D>
00452       inline void sse_for(const S *src0, const S *src1, const S *src2, const S *src3,
00453                           D *dst0, D *dst1, D *dstEnd,
00454                           void (*subMethod)(const S*, const S*, const S*, const S*, D*, D*),
00455                           void (*subSSEMethod)(const S*, const S*, const S*, const S*, D*, D*),
00456                           long step) {
00457         D *dstSSEEnd = dstEnd - (step - 1);
00458 
00459         for (; dst0<dstSSEEnd;) {
00460             // convert 'rvalues' values at the same time
00461             (*subSSEMethod)(src0, src1, src2, src3, dst0, dst1);
00462 
00463             // increment pointers to the next values
00464             src0 += step;
00465             src1 += step;
00466             src2 += step;
00467             src3 += step;
00468             dst0 += step;
00469             dst1 += step;
00470         }
00471 
00472         for (; dst0<dstEnd; ++src0, ++src1, ++src2, ++src3, ++dst0, ++dst1) {
00473           // convert 1 value
00474           (*subMethod)(src0, src1, src2, src3, dst0, dst1);
00475         }
00476       }
00477 
00478       template<class S, class D>
00479       inline void sse_for(const S *src0, const S *src1, const S *src2, const S *src3,
00480                           D *dst0, D *dst1, D *dst2, D *dstEnd,
00481                           void (*subMethod)(const S*, const S*, const S*, const S*, D*, D*, D*),
00482                           void (*subSSEMethod)(const S*, const S*, const S*, const S*, D*, D*, D*),
00483                           long step) {
00484         D *dstSSEEnd = dstEnd - (step - 1);
00485 
00486         for (; dst0<dstSSEEnd;) {
00487             // convert 'rvalues' values at the same time
00488             (*subSSEMethod)(src0, src1, src2, src3, dst0, dst1, dst2);
00489 
00490             // increment pointers to the next values
00491             src0 += step;
00492             src1 += step;
00493             src2 += step;
00494             src3 += step;
00495             dst0 += step;
00496             dst1 += step;
00497             dst2 += step;
00498         }
00499 
00500         for (; dst0<dstEnd; ++src0, ++src1, ++src2, ++src3, ++dst0, ++dst1, ++dst2) {
00501           // convert 1 value
00502           (*subMethod)(src0, src1, src2, src3, dst0, dst1, dst2);
00503         }
00504       }
00505 
00506       template<class S, class D>
00507       inline void sse_for(const S *src0, const S *src1, const S *src2, const S *src3,
00508                           D *dst0, D *dst1, D *dst2, D* dst3, D *dstEnd,
00509                           void (*subMethod)(const S*, const S*, const S*, const S*, D*, D*, D*, D*),
00510                           void (*subSSEMethod)(const S*, const S*, const S*, const S*, D*, D*, D*, D*),
00511                           long step) {
00512         D *dstSSEEnd = dstEnd - (step - 1);
00513 
00514         for (; dst0<dstSSEEnd;) {
00515             // convert 'rvalues' values at the same time
00516             (*subSSEMethod)(src0, src1, src2, src3, dst0, dst1, dst2, dst3);
00517 
00518             // increment pointers to the next values
00519             src0 += step;
00520             src1 += step;
00521             src2 += step;
00522             src3 += step;
00523             dst0 += step;
00524             dst1 += step;
00525             dst2 += step;
00526             dst3 += step;
00527         }
00528 
00529         for (; dst0<dstEnd; ++src0, ++src1, ++src2, ++src3, ++dst0, ++dst1, ++dst2, ++dst3) {
00530           // convert 1 value
00531           (*subMethod)(src0, src1, src2, src3, dst0, dst1, dst2, dst3);
00532         }
00533       }
00534 
00535       // the sse_for functions can be implemented compact in only one function
00536       // using pointer-to-pointer, but it is slower than the current
00537       // implementation of many versions
00538 
00539       template<class S, class D>
00540       inline void sse_for(const S *src0,
00541                           D *dst0, D *dstEnd,
00542                           void (*subMethod)(const S*, D*),
00543                           void (*subSSEMethod)(const S*, D*),
00544                           long srcStep, long dstStep) {
00545         D *dstSSEEnd = dstEnd - (dstStep - 1);
00546         long sStep, dStep;
00547 
00548         if (srcStep < dstStep) {
00549           dStep = dstStep / srcStep;
00550           sStep = 1;
00551         } else {
00552           sStep = srcStep / dstStep;
00553           dStep = 1;
00554         }
00555 
00556         for (; dst0<dstSSEEnd;) {
00557             // convert 'rvalues' values at the same time
00558             (*subSSEMethod)(src0, dst0);
00559 
00560             // increment pointers to the next values
00561             src0 += srcStep;
00562             dst0 += dstStep;
00563         }
00564 
00565         for (; dst0<dstEnd; src0 += sStep, dst0 += dStep) {
00566           // convert 1 value
00567           (*subMethod)(src0, dst0);
00568         }
00569       }
00570 
00571       template<class S, class D>
00572       inline void sse_for(const S *src0,
00573                           D *dst0, D *dst1, D *dstEnd,
00574                           void (*subMethod)(const S*, D*, D*),
00575                           void (*subSSEMethod)(const S*, D*, D*),
00576                           long srcStep, long dstStep) {
00577         D *dstSSEEnd = dstEnd - (dstStep - 1);
00578         long sStep, dStep;
00579 
00580         if (srcStep < dstStep) {
00581           dStep = dstStep / srcStep;
00582           sStep = 1;
00583         } else {
00584           sStep = srcStep / dstStep;
00585           dStep = 1;
00586         }
00587 
00588         for (; dst0<dstSSEEnd;) {
00589             // convert 'rvalues' values at the same time
00590             (*subSSEMethod)(src0, dst0, dst1);
00591 
00592             // increment pointers to the next values
00593             src0 += srcStep;
00594             dst0 += dstStep;
00595             dst1 += dstStep;
00596         }
00597 
00598         for (; dst0<dstEnd; src0 += sStep, dst0 += dStep, dst1 += dStep) {
00599           // convert 1 value
00600           (*subMethod)(src0, dst0, dst1);
00601         }
00602       }
00603 
00604       template<class S, class D>
00605       inline void sse_for(const S *src0,
00606                           D *dst0, D *dst1, D *dst2, D *dstEnd,
00607                           void (*subMethod)(const S*, D*, D*, D*),
00608                           void (*subSSEMethod)(const S*, D*, D*, D*),
00609                           long srcStep, long dstStep) {
00610         D *dstSSEEnd = dstEnd - (dstStep - 1);
00611         long sStep, dStep;
00612 
00613         if (srcStep < dstStep) {
00614           dStep = dstStep / srcStep;
00615           sStep = 1;
00616         } else {
00617           sStep = srcStep / dstStep;
00618           dStep = 1;
00619         }
00620 
00621         for (; dst0<dstSSEEnd;) {
00622             // convert 'rvalues' values at the same time
00623             (*subSSEMethod)(src0, dst0, dst1, dst2);
00624 
00625             // increment pointers to the next values
00626             src0 += srcStep;
00627             dst0 += dstStep;
00628             dst1 += dstStep;
00629             dst2 += dstStep;
00630         }
00631 
00632         for (; dst0<dstEnd; src0 += sStep, dst0 += dStep, dst1 += dStep, dst2 += dStep) {
00633           // convert 1 value
00634           (*subMethod)(src0, dst0, dst1, dst2);
00635         }
00636       }
00637 
00638       template<class S, class D>
00639       inline void sse_for(const S *src0,
00640                           D *dst0, D *dst1, D *dst2, D *dst3, D *dstEnd,
00641                           void (*subMethod)(const S*, D*, D*, D*, D*),
00642                           void (*subSSEMethod)(const S*, D*, D*, D*, D*),
00643                           long srcStep, long dstStep) {
00644         D *dstSSEEnd = dstEnd - (dstStep - 1);
00645         long sStep, dStep;
00646 
00647         if (srcStep < dstStep) {
00648           dStep = dstStep / srcStep;
00649           sStep = 1;
00650         } else {
00651           sStep = srcStep / dstStep;
00652           dStep = 1;
00653         }
00654 
00655         for (; dst0<dstSSEEnd;) {
00656             // convert 'rvalues' values at the same time
00657             (*subSSEMethod)(src0, dst0, dst1, dst2, dst3);
00658 
00659             // increment pointers to the next values
00660             src0 += srcStep;
00661             dst0 += dstStep;
00662             dst1 += dstStep;
00663             dst2 += dstStep;
00664             dst3 += dstStep;
00665         }
00666 
00667         for (; dst0<dstEnd; src0 += sStep, dst0 += dStep, dst1 += dStep, dst2 += dStep, dst3 += dStep) {
00668           // convert 1 value
00669           (*subMethod)(src0, dst0, dst1, dst2, dst3);
00670         }
00671       }
00672 
00673       template<class S, class D>
00674       inline void sse_for(const S *src0, const S *src1,
00675                           D *dst0, D *dstEnd,
00676                           void (*subMethod)(const S*, const S*, D*),
00677                           void (*subSSEMethod)(const S*, const S*, D*),
00678                           long srcStep, long dstStep) {
00679         D *dstSSEEnd = dstEnd - (dstStep - 1);
00680         long sStep, dStep;
00681 
00682         if (srcStep < dstStep) {
00683           dStep = dstStep / srcStep;
00684           sStep = 1;
00685         } else {
00686           sStep = srcStep / dstStep;
00687           dStep = 1;
00688         }
00689 
00690         for (; dst0<dstSSEEnd;) {
00691             // convert 'rvalues' values at the same time
00692             (*subSSEMethod)(src0, src1, dst0);
00693 
00694             // increment pointers to the next values
00695             src0 += srcStep;
00696             src1 += srcStep;
00697             dst0 += dstStep;
00698         }
00699 
00700         for (; dst0<dstEnd; src0 += sStep, src1 += sStep, dst0 += dStep) {
00701           // convert 1 value
00702           (*subMethod)(src0, src1, dst0);
00703         }
00704       }
00705 
00706       template<class S, class D>
00707       inline void sse_for(const S *src0, const S *src1,
00708                           D *dst0, D *dst1, D *dstEnd,
00709                           void (*subMethod)(const S*, const S*, D*, D*),
00710                           void (*subSSEMethod)(const S*, const S*, D*, D*),
00711                           long srcStep, long dstStep) {
00712         D *dstSSEEnd = dstEnd - (dstStep - 1);
00713         long sStep, dStep;
00714 
00715         if (srcStep < dstStep) {
00716           dStep = dstStep / srcStep;
00717           sStep = 1;
00718         } else {
00719           sStep = srcStep / dstStep;
00720           dStep = 1;
00721         }
00722 
00723         for (; dst0<dstSSEEnd;) {
00724             // convert 'rvalues' values at the same time
00725             (*subSSEMethod)(src0, src1, dst0, dst1);
00726 
00727             // increment pointers to the next values
00728             src0 += srcStep;
00729             src1 += srcStep;
00730             dst0 += dstStep;
00731             dst1 += dstStep;
00732         }
00733 
00734         for (; dst0<dstEnd; src0 += sStep, src1 += sStep, dst0 += dStep, dst1 += dStep) {
00735           // convert 1 value
00736           (*subMethod)(src0, src1, dst0, dst1);
00737         }
00738       }
00739 
00740       template<class S, class D>
00741       inline void sse_for(const S *src0, const S *src1,
00742                           D *dst0, D *dst1, D *dst2, D *dstEnd,
00743                           void (*subMethod)(const S*, const S*, D*, D*, D*),
00744                           void (*subSSEMethod)(const S*, const S*, D*, D*, D*),
00745                           long srcStep, long dstStep) {
00746         D *dstSSEEnd = dstEnd - (dstStep - 1);
00747         long sStep, dStep;
00748 
00749         if (srcStep < dstStep) {
00750           dStep = dstStep / srcStep;
00751           sStep = 1;
00752         } else {
00753           sStep = srcStep / dstStep;
00754           dStep = 1;
00755         }
00756 
00757         for (; dst0<dstSSEEnd;) {
00758             // convert 'rvalues' values at the same time
00759             (*subSSEMethod)(src0, src1, dst0, dst1, dst2);
00760 
00761             // increment pointers to the next values
00762             src0 += srcStep;
00763             src1 += srcStep;
00764             dst0 += dstStep;
00765             dst1 += dstStep;
00766             dst2 += dstStep;
00767         }
00768 
00769         for (; dst0<dstEnd; src0 += sStep, src1 += sStep, dst0 += dStep, dst1 += dStep, dst2 += dStep) {
00770           // convert 1 value
00771           (*subMethod)(src0, src1, dst0, dst1, dst2);
00772         }
00773       }
00774 
00775       template<class S, class D>
00776       inline void sse_for(const S *src0, const S *src1,
00777                           D *dst0, D *dst1, D *dst2, D* dst3, D *dstEnd,
00778                           void (*subMethod)(const S*, const S*, D*, D*, D*, D*),
00779                           void (*subSSEMethod)(const S*, const S*, D*, D*, D*, D*),
00780                           long srcStep, long dstStep) {
00781         D *dstSSEEnd = dstEnd - (dstStep - 1);
00782         long sStep, dStep;
00783 
00784         if (srcStep < dstStep) {
00785           dStep = dstStep / srcStep;
00786           sStep = 1;
00787         } else {
00788           sStep = srcStep / dstStep;
00789           dStep = 1;
00790         }
00791 
00792         for (; dst0<dstSSEEnd;) {
00793             // convert 'rvalues' values at the same time
00794             (*subSSEMethod)(src0, src1, dst0, dst1, dst2, dst3);
00795 
00796             // increment pointers to the next values
00797             src0 += srcStep;
00798             src1 += srcStep;
00799             dst0 += dstStep;
00800             dst1 += dstStep;
00801             dst2 += dstStep;
00802             dst3 += dstStep;
00803         }
00804 
00805         for (; dst0<dstEnd; src0 += sStep, src1 += sStep, dst0 += dStep, dst1 += dStep, dst2 += dStep, dst3 += dStep) {
00806           // convert 1 value
00807           (*subMethod)(src0, src1, dst0, dst1, dst2, dst3);
00808         }
00809       }
00810 
00811       template<class S, class D>
00812       inline void sse_for(const S *src0, const S *src1, const S *src2,
00813                           D *dst0, D *dstEnd,
00814                           void (*subMethod)(const S*, const S*, const S*, D*),
00815                           void (*subSSEMethod)(const S*, const S*, const S*, D*),
00816                           long srcStep, long dstStep) {
00817         D *dstSSEEnd = dstEnd - (dstStep - 1);
00818         long sStep, dStep;
00819 
00820         if (srcStep < dstStep) {
00821           dStep = dstStep / srcStep;
00822           sStep = 1;
00823         } else {
00824           sStep = srcStep / dstStep;
00825           dStep = 1;
00826         }
00827 
00828         for (; dst0<dstSSEEnd;) {
00829             // convert 'rvalues' values at the same time
00830             (*subSSEMethod)(src0, src1, src2, dst0);
00831 
00832             // increment pointers to the next values
00833             src0 += srcStep;
00834             src1 += srcStep;
00835             src2 += srcStep;
00836             dst0 += dstStep;
00837         }
00838 
00839         for (; dst0<dstEnd; src0 += sStep, src1 += sStep, src2 += sStep, dst0 += dStep) {
00840           // convert 1 value
00841           (*subMethod)(src0, src1, src2, dst0);
00842         }
00843       }
00844 
00845       template<class S, class D>
00846       inline void sse_for(const S *src0, const S *src1, const S *src2,
00847                           D *dst0, D *dst1, D *dstEnd,
00848                           void (*subMethod)(const S*, const S*, const S*, D*, D*),
00849                           void (*subSSEMethod)(const S*, const S*, const S*, D*, D*),
00850                           long srcStep, long dstStep) {
00851         D *dstSSEEnd = dstEnd - (dstStep - 1);
00852         long sStep, dStep;
00853 
00854         if (srcStep < dstStep) {
00855           dStep = dstStep / srcStep;
00856           sStep = 1;
00857         } else {
00858           sStep = srcStep / dstStep;
00859           dStep = 1;
00860         }
00861 
00862         for (; dst0<dstSSEEnd;) {
00863             // convert 'rvalues' values at the same time
00864             (*subSSEMethod)(src0, src1, src2, dst0, dst1);
00865 
00866             // increment pointers to the next values
00867             src0 += srcStep;
00868             src1 += srcStep;
00869             src2 += srcStep;
00870             dst0 += dstStep;
00871             dst1 += dstStep;
00872         }
00873 
00874         for (; dst0<dstEnd; src0 += sStep, src1 += sStep, src2 += sStep, dst0 += dStep, dst1 += dStep) {
00875           // convert 1 value
00876           (*subMethod)(src0, src1, src2, dst0, dst1);
00877         }
00878       }
00879 
00880       template<class S, class D>
00881       inline void sse_for(const S *src0, const S *src1, const S *src2,
00882                           D *dst0, D *dst1, D *dst2, D *dstEnd,
00883                           void (*subMethod)(const S*, const S*, const S*, D*, D*, D*),
00884                           void (*subSSEMethod)(const S*, const S*, const S*, D*, D*, D*),
00885                           long srcStep, long dstStep) {
00886         D *dstSSEEnd = dstEnd - (dstStep - 1);
00887         long sStep, dStep;
00888 
00889         if (srcStep < dstStep) {
00890           dStep = dstStep / srcStep;
00891           sStep = 1;
00892         } else {
00893           sStep = srcStep / dstStep;
00894           dStep = 1;
00895         }
00896 
00897         for (; dst0<dstSSEEnd;) {
00898             // convert 'rvalues' values at the same time
00899             (*subSSEMethod)(src0, src1, src2, dst0, dst1, dst2);
00900 
00901             // increment pointers to the next values
00902             src0 += srcStep;
00903             src1 += srcStep;
00904             src2 += srcStep;
00905             dst0 += dstStep;
00906             dst1 += dstStep;
00907             dst2 += dstStep;
00908         }
00909 
00910         for (; dst0<dstEnd; src0 += sStep, src1 += sStep, src2 += sStep, dst0 += dStep, dst1 += dStep, dst2 += dStep) {
00911           // convert 1 value
00912           (*subMethod)(src0, src1, src2, dst0, dst1, dst2);
00913         }
00914       }
00915 
00916       template<class S, class D>
00917       inline void sse_for(const S *src0, const S *src1, const S *src2,
00918                           D *dst0, D *dst1, D *dst2, D* dst3, D *dstEnd,
00919                           void (*subMethod)(const S*, const S*, const S*, D*, D*, D*, D*),
00920                           void (*subSSEMethod)(const S*, const S*, const S*, D*, D*, D*, D*),
00921                           long srcStep, long dstStep) {
00922         D *dstSSEEnd = dstEnd - (dstStep - 1);
00923         long sStep, dStep;
00924 
00925         if (srcStep < dstStep) {
00926           dStep = dstStep / srcStep;
00927           sStep = 1;
00928         } else {
00929           sStep = srcStep / dstStep;
00930           dStep = 1;
00931         }
00932 
00933         for (; dst0<dstSSEEnd;) {
00934             // convert 'rvalues' values at the same time
00935             (*subSSEMethod)(src0, src1, src2, dst0, dst1, dst2, dst3);
00936 
00937             // increment pointers to the next values
00938             src0 += srcStep;
00939             src1 += srcStep;
00940             src2 += srcStep;
00941             dst0 += dstStep;
00942             dst1 += dstStep;
00943             dst2 += dstStep;
00944             dst3 += dstStep;
00945         }
00946 
00947         for (; dst0<dstEnd; src0 += sStep, src1 += sStep, src2 += sStep, dst0 += dStep, dst1 += dStep, dst2 += dStep, dst3 += dStep) {
00948           // convert 1 value
00949           (*subMethod)(src0, src1, src2, dst0, dst1, dst2, dst3);
00950         }
00951       }
00952 
00953       template<class S, class D>
00954       inline void sse_for(const S *src0, const S *src1, const S *src2, const S *src3,
00955                           D *dst0, D *dstEnd,
00956                           void (*subMethod)(const S*, const S*, const S*, const S*, D*),
00957                           void (*subSSEMethod)(const S*, const S*, const S*, const S*, D*),
00958                           long srcStep, long dstStep) {
00959         D *dstSSEEnd = dstEnd - (dstStep - 1);
00960         long sStep, dStep;
00961 
00962         if (srcStep < dstStep) {
00963           dStep = dstStep / srcStep;
00964           sStep = 1;
00965         } else {
00966           sStep = srcStep / dstStep;
00967           dStep = 1;
00968         }
00969 
00970         for (; dst0<dstSSEEnd;) {
00971             // convert 'rvalues' values at the same time
00972             (*subSSEMethod)(src0, src1, src2, src3, dst0);
00973 
00974             // increment pointers to the next values
00975             src0 += srcStep;
00976             src1 += srcStep;
00977             src2 += srcStep;
00978             src3 += srcStep;
00979             dst0 += dstStep;
00980         }
00981 
00982         for (; dst0<dstEnd; src0 += sStep, src1 += sStep, src2 += sStep, src3 += sStep, dst0 += dStep) {
00983           // convert 1 value
00984           (*subMethod)(src0, src1, src2, src3, dst0);
00985         }
00986       }
00987 
00988       template<class S, class D>
00989       inline void sse_for(const S *src0, const S *src1, const S *src2, const S *src3,
00990                           D *dst0, D *dst1, D *dstEnd,
00991                           void (*subMethod)(const S*, const S*, const S*, const S*, D*, D*),
00992                           void (*subSSEMethod)(const S*, const S*, const S*, const S*, D*, D*),
00993                           long srcStep, long dstStep) {
00994         D *dstSSEEnd = dstEnd - (dstStep - 1);
00995         long sStep, dStep;
00996 
00997         if (srcStep < dstStep) {
00998           dStep = dstStep / srcStep;
00999           sStep = 1;
01000         } else {
01001           sStep = srcStep / dstStep;
01002           dStep = 1;
01003         }
01004 
01005         for (; dst0<dstSSEEnd;) {
01006             // convert 'rvalues' values at the same time
01007             (*subSSEMethod)(src0, src1, src2, src3, dst0, dst1);
01008 
01009             // increment pointers to the next values
01010             src0 += srcStep;
01011             src1 += srcStep;
01012             src2 += srcStep;
01013             src3 += srcStep;
01014             dst0 += dstStep;
01015             dst1 += dstStep;
01016         }
01017 
01018         for (; dst0<dstEnd; src0 += sStep, src1 += sStep, src2 += sStep, src3 += sStep, dst0 += dStep, dst1 += dStep) {
01019           // convert 1 value
01020           (*subMethod)(src0, src1, src2, src3, dst0, dst1);
01021         }
01022       }
01023 
01024       template<class S, class D>
01025       inline void sse_for(const S *src0, const S *src1, const S *src2, const S *src3,
01026                           D *dst0, D *dst1, D *dst2, D *dstEnd,
01027                           void (*subMethod)(const S*, const S*, const S*, const S*, D*, D*, D*),
01028                           void (*subSSEMethod)(const S*, const S*, const S*, const S*, D*, D*, D*),
01029                           long srcStep, long dstStep) {
01030         D *dstSSEEnd = dstEnd - (dstStep - 1);
01031         long sStep, dStep;
01032 
01033         if (srcStep < dstStep) {
01034           dStep = dstStep / srcStep;
01035           sStep = 1;
01036         } else {
01037           sStep = srcStep / dstStep;
01038           dStep = 1;
01039         }
01040 
01041         for (; dst0<dstSSEEnd;) {
01042             // convert 'rvalues' values at the same time
01043             (*subSSEMethod)(src0, src1, src2, src3, dst0, dst1, dst2);
01044 
01045             // increment pointers to the next values
01046             src0 += srcStep;
01047             src1 += srcStep;
01048             src2 += srcStep;
01049             src3 += srcStep;
01050             dst0 += dstStep;
01051             dst1 += dstStep;
01052             dst2 += dstStep;
01053         }
01054 
01055         for (; dst0<dstEnd; src0 += sStep, src1 += sStep, src2 += sStep, src3 += sStep, dst0 += dStep, dst1 += dStep, dst2 += dStep) {
01056           // convert 1 value
01057           (*subMethod)(src0, src1, src2, src3, dst0, dst1, dst2);
01058         }
01059       }
01060 
01061       template<class S, class D>
01062       inline void sse_for(const S *src0, const S *src1, const S *src2, const S *src3,
01063                           D *dst0, D *dst1, D *dst2, D* dst3, D *dstEnd,
01064                           void (*subMethod)(const S*, const S*, const S*, const S*, D*, D*, D*, D*),
01065                           void (*subSSEMethod)(const S*, const S*, const S*, const S*, D*, D*, D*, D*),
01066                           long srcStep, long dstStep) {
01067         D *dstSSEEnd = dstEnd - (dstStep - 1);
01068         long sStep, dStep;
01069 
01070         if (srcStep < dstStep) {
01071           dStep = dstStep / srcStep;
01072           sStep = 1;
01073         } else {
01074           sStep = srcStep / dstStep;
01075           dStep = 1;
01076         }
01077 
01078         for (; dst0<dstSSEEnd;) {
01079             // convert 'rvalues' values at the same time
01080             (*subSSEMethod)(src0, src1, src2, src3, dst0, dst1, dst2, dst3);
01081 
01082             // increment pointers to the next values
01083             src0 += srcStep;
01084             src1 += srcStep;
01085             src2 += srcStep;
01086             src3 += srcStep;
01087             dst0 += dstStep;
01088             dst1 += dstStep;
01089             dst2 += dstStep;
01090             dst3 += dstStep;
01091         }
01092 
01093         for (; dst0<dstEnd; src0 += sStep, src1 += sStep, src2 += sStep, src3 += sStep, dst0 += dStep, dst1 += dStep, dst2 += dStep, dst3 += dStep) {
01094           // convert 1 value
01095           (*subMethod)(src0, src1, src2, src3, dst0, dst1, dst2, dst3);
01096         }
01097       }
01098 
01099       // -- for-loops -- //
01100 
01101 
01102       // ++ for-loops with ROI ++ //
01103 
01104       // the sse_for functions can be implemented compact in only one function
01105       // using pointer-to-pointer, but it is slower than the current
01106       // implementation of many versions
01107 
01108       template<class S, class D>
01109       inline void sse_for(const S *src0,
01110                           D *dst0, D *dstEnd,
01111                           long srcWidth, long dstWidth, long lineWidth,
01112                           void (*subMethod)(const S*, D*),
01113                           void (*subSSEMethod)(const S*, D*),
01114                           long step) {
01115         D *dstLEnd   = dst0 + lineWidth;
01116         D *dstSSEEnd = dstLEnd - (step - 1);
01117         long srcOffset = srcWidth - lineWidth;
01118         long dstOffset = dstWidth - lineWidth;
01119 
01120         for (; dst0<dstEnd;) {
01121           if (dst0<dstSSEEnd) {
01122             // convert 'rvalues' values at the same time
01123             (*subSSEMethod)(src0, dst0);
01124 
01125             // increment pointers to the next values
01126             src0 += step;
01127             dst0 += step;
01128           } else {
01129             for (; dst0<dstLEnd; ++src0, ++dst0) {
01130               // convert 1 value
01131               (*subMethod)(src0, dst0);
01132             }
01133 
01134             // move all pointers to the next line
01135             dstLEnd   += dstWidth;
01136             dstSSEEnd += dstWidth;
01137             src0 += srcOffset;
01138             dst0 += dstOffset;
01139           }
01140         }
01141       }
01142 
01143       template<class S, class D>
01144       inline void sse_for(const S *src0,
01145                           D *dst0, D *dst1, D *dstEnd,
01146                           long srcWidth, long dstWidth, long lineWidth,
01147                           void (*subMethod)(const S*, D*, D*),
01148                           void (*subSSEMethod)(const S*, D*, D*),
01149                           long step) {
01150         D *dstLEnd   = dst0 + lineWidth;
01151         D *dstSSEEnd = dstLEnd - (step - 1);
01152         long srcOffset = srcWidth - lineWidth;
01153         long dstOffset = dstWidth - lineWidth;
01154 
01155         for (; dst0<dstEnd;) {
01156           if (dst0<dstSSEEnd) {
01157             // convert 'rvalues' values at the same time
01158             (*subSSEMethod)(src0, dst0, dst1);
01159 
01160             // increment pointers to the next values
01161             src0 += step;
01162             dst0 += step;
01163             dst1 += step;
01164           } else {
01165             for (; dst0<dstLEnd; ++src0, ++dst0, ++dst1) {
01166               // convert 1 value
01167               (*subMethod)(src0, dst0, dst1);
01168             }
01169 
01170             // move all pointers to the next line
01171             dstLEnd   += dstWidth;
01172             dstSSEEnd += dstWidth;
01173             src0 += srcOffset;
01174             dst0 += dstOffset;
01175             dst1 += dstOffset;
01176           }
01177         }
01178       }
01179 
01180       template<class S, class D>
01181       inline void sse_for(const S *src0,
01182                           D *dst0, D *dst1, D *dst2, D *dstEnd,
01183                           long srcWidth, long dstWidth, long lineWidth,
01184                           void (*subMethod)(const S*, D*, D*, D*),
01185                           void (*subSSEMethod)(const S*, D*, D*, D*),
01186                           long step) {
01187         D *dstLEnd   = dst0 + lineWidth;
01188         D *dstSSEEnd = dstLEnd - (step - 1);
01189         long srcOffset = srcWidth - lineWidth;
01190         long dstOffset = dstWidth - lineWidth;
01191 
01192         for (; dst0<dstEnd;) {
01193           if (dst0<dstSSEEnd) {
01194             // convert 'rvalues' values at the same time
01195             (*subSSEMethod)(src0, dst0, dst1, dst2);
01196 
01197             // increment pointers to the next values
01198             src0 += step;
01199             dst0 += step;
01200             dst1 += step;
01201             dst2 += step;
01202           } else {
01203             for (; dst0<dstLEnd; ++src0, ++dst0, ++dst1, ++dst2) {
01204               // convert 1 value
01205               (*subMethod)(src0, dst0, dst1, dst2);
01206             }
01207 
01208             // move all pointers to the next line
01209             dstLEnd   += dstWidth;
01210             dstSSEEnd += dstWidth;
01211             src0 += srcOffset;
01212             dst0 += dstOffset;
01213             dst1 += dstOffset;
01214             dst2 += dstOffset;
01215           }
01216         }
01217       }
01218 
01219       template<class S, class D>
01220       inline void sse_for(const S *src0,
01221                           D *dst0, D *dst1, D *dst2, D *dst3, D *dstEnd,
01222                           long srcWidth, long dstWidth, long lineWidth,
01223                           void (*subMethod)(const S*, D*, D*, D*, D*),
01224                           void (*subSSEMethod)(const S*, D*, D*, D*, D*),
01225                           long step) {
01226         D *dstLEnd   = dst0 + lineWidth;
01227         D *dstSSEEnd = dstLEnd - (step - 1);
01228         long srcOffset = srcWidth - lineWidth;
01229         long dstOffset = dstWidth - lineWidth;
01230 
01231         for (; dst0<dstEnd;) {
01232           if (dst0<dstSSEEnd) {
01233             // convert 'rvalues' values at the same time
01234             (*subSSEMethod)(src0, dst0, dst1, dst2, dst3);
01235 
01236             // increment pointers to the next values
01237             src0 += step;
01238             dst0 += step;
01239             dst1 += step;
01240             dst2 += step;
01241             dst3 += step;
01242           } else {
01243             for (; dst0<dstLEnd; ++src0, ++dst0, ++dst1, ++dst2, ++dst3) {
01244               // convert 1 value
01245               (*subMethod)(src0, dst0, dst1, dst2, dst3);
01246             }
01247 
01248             // move all pointers to the next line
01249             dstLEnd   += dstWidth;
01250             dstSSEEnd += dstWidth;
01251             src0 += srcOffset;
01252             dst0 += dstOffset;
01253             dst1 += dstOffset;
01254             dst2 += dstOffset;
01255             dst3 += dstOffset;
01256           }
01257         }
01258       }
01259 
01260       template<class S, class D>
01261       inline void sse_for(const S *src0, const S *src1,
01262                           D *dst0, D *dst1, D *dstEnd,
01263                           long srcWidth, long dstWidth, long lineWidth,
01264                           void (*subMethod)(const S*, const S*, D*, D*),
01265                           void (*subSSEMethod)(const S*, const S*, D*, D*),
01266                           long step) {
01267         D *dstLEnd   = dst0 + lineWidth;
01268         D *dstSSEEnd = dstLEnd - (step - 1);
01269         long srcOffset = srcWidth - lineWidth;
01270         long dstOffset = dstWidth - lineWidth;
01271 
01272         for (; dst0<dstEnd;) {
01273           if (dst0<dstSSEEnd) {
01274             // convert 'rvalues' values at the same time
01275             (*subSSEMethod)(src0, src1, dst0, dst1);
01276 
01277             // increment pointers to the next values
01278             src0 += step;
01279             src1 += step;
01280             dst0 += step;
01281             dst1 += step;
01282           } else {
01283             for (; dst0<dstLEnd; ++src0, ++src1, ++dst0, ++dst1) {
01284               // convert 1 value
01285               (*subMethod)(src0, src1, dst0, dst1);
01286             }
01287 
01288             // move all pointers to the next line
01289             dstLEnd   += dstWidth;
01290             dstSSEEnd += dstWidth;
01291             src0 += srcOffset;
01292             src1 += srcOffset;
01293             dst0 += dstOffset;
01294             dst1 += dstOffset;
01295           }
01296         }
01297       }
01298 
01299       template<class S, class D>
01300       inline void sse_for(const S *src0, const S *src1,
01301                           D *dst0, D *dst1, D *dst2, D *dstEnd,
01302                           long srcWidth, long dstWidth, long lineWidth,
01303                           void (*subMethod)(const S*, const S*, D*, D*, D*),
01304                           void (*subSSEMethod)(const S*, const S*, D*, D*, D*),
01305                           long step) {
01306         D *dstLEnd   = dst0 + lineWidth;
01307         D *dstSSEEnd = dstLEnd - (step - 1);
01308         long srcOffset = srcWidth - lineWidth;
01309         long dstOffset = dstWidth - lineWidth;
01310 
01311         for (; dst0<dstEnd;) {
01312           if (dst0<dstSSEEnd) {
01313             // convert 'rvalues' values at the same time
01314             (*subSSEMethod)(src0, src1, dst0, dst1, dst2);
01315 
01316             // increment pointers to the next values
01317             src0 += step;
01318             src1 += step;
01319             dst0 += step;
01320             dst1 += step;
01321             dst2 += step;
01322           } else {
01323             for (; dst0<dstLEnd; ++src0, ++src1, ++dst0, ++dst1, ++dst2) {
01324               // convert 1 value
01325               (*subMethod)(src0, src1, dst0, dst1, dst2);
01326             }
01327 
01328             // move all pointers to the next line
01329             dstLEnd   += dstWidth;
01330             dstSSEEnd += dstWidth;
01331             src0 += srcOffset;
01332             src1 += srcOffset;
01333             dst0 += dstOffset;
01334             dst1 += dstOffset;
01335             dst2 += dstOffset;
01336           }
01337         }
01338       }
01339 
01340       template<class S, class D>
01341       inline void sse_for(const S *src0, const S *src1,
01342                           D *dst0, D *dst1, D *dst2, D *dst3, D *dstEnd,
01343                           long srcWidth, long dstWidth, long lineWidth,
01344                           void (*subMethod)(const S*, const S*, D*, D*, D*, D*),
01345                           void (*subSSEMethod)(const S*, const S*, D*, D*, D*, D*),
01346                           long step) {
01347         D *dstLEnd   = dst0 + lineWidth;
01348         D *dstSSEEnd = dstLEnd - (step - 1);
01349         long srcOffset = srcWidth - lineWidth;
01350         long dstOffset = dstWidth - lineWidth;
01351 
01352         for (; dst0<dstEnd;) {
01353           if (dst0<dstSSEEnd) {
01354             // convert 'rvalues' values at the same time
01355             (*subSSEMethod)(src0, src1, dst0, dst1, dst2, dst3);
01356 
01357             // increment pointers to the next values
01358             src0 += step;
01359             src1 += step;
01360             dst0 += step;
01361             dst1 += step;
01362             dst2 += step;
01363             dst3 += step;
01364           } else {
01365             for (; dst0<dstLEnd; ++src0, ++src1, ++dst0, ++dst1, ++dst2, ++dst3) {
01366               // convert 1 value
01367               (*subMethod)(src0, src1, dst0, dst1, dst2, dst3);
01368             }
01369 
01370             // move all pointers to the next line
01371             dstLEnd   += dstWidth;
01372             dstSSEEnd += dstWidth;
01373             src0 += srcOffset;
01374             src1 += srcOffset;
01375             dst0 += dstOffset;
01376             dst1 += dstOffset;
01377             dst2 += dstOffset;
01378             dst3 += dstOffset;
01379           }
01380         }
01381       }
01382 
01383       template<class S, class D>
01384       inline void sse_for(const S *src0, const S *src1, const S *src2,
01385                           D *dst0, D *dstEnd,
01386                           long srcWidth, long dstWidth, long lineWidth,
01387                           void (*subMethod)(const S*, const S*, const S*, D*),
01388                           void (*subSSEMethod)(const S*, const S*, const S*, D*),
01389                           long step) {
01390         D *dstLEnd   = dst0 + lineWidth;
01391         D *dstSSEEnd = dstLEnd - (step - 1);
01392         long srcOffset = srcWidth - lineWidth;
01393         long dstOffset = dstWidth - lineWidth;
01394 
01395         for (; dst0<dstEnd;) {
01396           if (dst0<dstSSEEnd) {
01397             // convert 'rvalues' values at the same time
01398             (*subSSEMethod)(src0, src1, src2, dst0);
01399 
01400             // increment pointers to the next values
01401             src0 += step;
01402             src1 += step;
01403             src2 += step;
01404             dst0 += step;
01405           } else {
01406             for (; dst0<dstLEnd; ++src0, ++src1, ++src2, ++dst0) {
01407               // convert 1 value
01408               (*subMethod)(src0, src1, src2, dst0);
01409             }
01410 
01411             // move all pointers to the next line
01412             dstLEnd   += dstWidth;
01413             dstSSEEnd += dstWidth;
01414             src0 += srcOffset;
01415             src1 += srcOffset;
01416             src2 += srcOffset;
01417             dst0 += dstOffset;
01418           }
01419         }
01420       }
01421 
01422       template<class S, class D>
01423       inline void sse_for(const S *src0, const S *src1, const S *src2,
01424                           D *dst0, D *dst1, D *dstEnd,
01425                           long srcWidth, long dstWidth, long lineWidth,
01426                           void (*subMethod)(const S*, const S*, const S*, D*, D*),
01427                           void (*subSSEMethod)(const S*, const S*, const S*, D*, D*),
01428                           long step) {
01429         D *dstLEnd   = dst0 + lineWidth;
01430         D *dstSSEEnd = dstLEnd - (step - 1);
01431         long srcOffset = srcWidth - lineWidth;
01432         long dstOffset = dstWidth - lineWidth;
01433 
01434         for (; dst0<dstEnd;) {
01435           if (dst0<dstSSEEnd) {
01436             // convert 'rvalues' values at the same time
01437             (*subSSEMethod)(src0, src1, src2, dst0, dst1);
01438 
01439             // increment pointers to the next values
01440             src0 += step;
01441             src1 += step;
01442             src2 += step;
01443             dst0 += step;
01444             dst1 += step;
01445           } else {
01446             for (; dst0<dstLEnd; ++src0, ++src1, ++src2, ++dst0, ++dst1) {
01447               // convert 1 value
01448               (*subMethod)(src0, src1, src2, dst0, dst1);
01449             }
01450 
01451             // move all pointers to the next line
01452             dstLEnd   += dstWidth;
01453             dstSSEEnd += dstWidth;
01454             src0 += srcOffset;
01455             src1 += srcOffset;
01456             src2 += srcOffset;
01457             dst0 += dstOffset;
01458             dst1 += dstOffset;
01459           }
01460         }
01461       }
01462 
01463       template<class S, class D>
01464       inline void sse_for(const S *src0, const S *src1, const S *src2,
01465                           D *dst0, D *dst1, D *dst2, D *dstEnd,
01466                           long srcWidth, long dstWidth, long lineWidth,
01467                           void (*subMethod)(const S*, const S*, const S*, D*, D*, D*),
01468                           void (*subSSEMethod)(const S*, const S*, const S*, D*, D*, D*),
01469                           long step) {
01470         D *dstLEnd   = dst0 + lineWidth;
01471         D *dstSSEEnd = dstLEnd - (step - 1);
01472         long srcOffset = srcWidth - lineWidth;
01473         long dstOffset = dstWidth - lineWidth;
01474 
01475         for (; dst0<dstEnd;) {
01476           if (dst0<dstSSEEnd) {
01477             // convert 'rvalues' values at the same time
01478             (*subSSEMethod)(src0, src1, src2, dst0, dst1, dst2);
01479 
01480             // increment pointers to the next values
01481             src0 += step;
01482             src1 += step;
01483             src2 += step;
01484             dst0 += step;
01485             dst1 += step;
01486             dst2 += step;
01487           } else {
01488             for (; dst0<dstLEnd; ++src0, ++src1, ++src2, ++dst0, ++dst1, ++dst2) {
01489               // convert 1 value
01490               (*subMethod)(src0, src1, src2, dst0, dst1, dst2);
01491             }
01492 
01493             // move all pointers to the next line
01494             dstLEnd   += dstWidth;
01495             dstSSEEnd += dstWidth;
01496             src0 += srcOffset;
01497             src1 += srcOffset;
01498             src2 += srcOffset;
01499             dst0 += dstOffset;
01500             dst1 += dstOffset;
01501             dst2 += dstOffset;
01502           }
01503         }
01504       }
01505 
01506       template<class S, class D>
01507       inline void sse_for(const S *src0, const S *src1, const S *src2,
01508                           D *dst0, D *dst1, D *dst2, D* dst3, D *dstEnd,
01509                           long srcWidth, long dstWidth, long lineWidth,
01510                           void (*subMethod)(const S*, const S*, const S*, D*, D*, D*, D*),
01511                           void (*subSSEMethod)(const S*, const S*, const S*, D*, D*, D*, D*),
01512                           long step) {
01513         D *dstLEnd   = dst0 + lineWidth;
01514         D *dstSSEEnd = dstLEnd - (step - 1);
01515         long srcOffset = srcWidth - lineWidth;
01516         long dstOffset = dstWidth - lineWidth;
01517 
01518         for (; dst0<dstEnd;) {
01519           if (dst0<dstSSEEnd) {
01520             // convert 'rvalues' values at the same time
01521             (*subSSEMethod)(src0, src1, src2, dst0, dst1, dst2, dst3);
01522 
01523             // increment pointers to the next values
01524             src0 += step;
01525             src1 += step;
01526             src2 += step;
01527             dst0 += step;
01528             dst1 += step;
01529             dst2 += step;
01530             dst3 += step;
01531           } else {
01532             for (; dst0<dstLEnd; ++src0, ++src1, ++src2, ++dst0, ++dst1, ++dst2, ++dst3) {
01533               // convert 1 value
01534               (*subMethod)(src0, src1, src2, dst0, dst1, dst2, dst3);
01535             }
01536 
01537             // move all pointers to the next line
01538             dstLEnd   += dstWidth;
01539             dstSSEEnd += dstWidth;
01540             src0 += srcOffset;
01541             src1 += srcOffset;
01542             src2 += srcOffset;
01543             dst0 += dstOffset;
01544             dst1 += dstOffset;
01545             dst2 += dstOffset;
01546             dst3 += dstOffset;
01547           }
01548         }
01549       }
01550 
01551       template<class S, class D>
01552       inline void sse_for(const S *src0, const S *src1, const S *src2, const S *src3,
01553                           D *dst0, D *dstEnd,
01554                           long srcWidth, long dstWidth, long lineWidth,
01555                           void (*subMethod)(const S*, const S*, const S*, const S*, D*),
01556                           void (*subSSEMethod)(const S*, const S*, const S*, const S*, D*),
01557                           long step) {
01558         D *dstLEnd   = dst0 + lineWidth;
01559         D *dstSSEEnd = dstLEnd - (step - 1);
01560         long srcOffset = srcWidth - lineWidth;
01561         long dstOffset = dstWidth - lineWidth;
01562 
01563         for (; dst0<dstEnd;) {
01564           if (dst0<dstSSEEnd) {
01565             // convert 'rvalues' values at the same time
01566             (*subSSEMethod)(src0, src1, src2, src3, dst0);
01567 
01568             // increment pointers to the next values
01569             src0 += step;
01570             src1 += step;
01571             src2 += step;
01572             src3 += step;
01573             dst0 += step;
01574           } else {
01575             for (; dst0<dstLEnd; ++src0, ++src1, ++src2, ++src3, ++dst0) {
01576               // convert 1 value
01577               (*subMethod)(src0, src1, src2, src3, dst0);
01578             }
01579 
01580             // move all pointers to the next line
01581             dstLEnd   += dstWidth;
01582             dstSSEEnd += dstWidth;
01583             src0 += srcOffset;
01584             src1 += srcOffset;
01585             src2 += srcOffset;
01586             src3 += srcOffset;
01587             dst0 += dstOffset;
01588           }
01589         }
01590       }
01591 
01592       template<class S, class D>
01593       inline void sse_for(const S *src0, const S *src1, const S *src2, const S *src3,
01594                           D *dst0, D *dst1, D *dstEnd,
01595                           long srcWidth, long dstWidth, long lineWidth,
01596                           void (*subMethod)(const S*, const S*, const S*, const S*, D*, D*),
01597                           void (*subSSEMethod)(const S*, const S*, const S*, const S*, D*, D*),
01598                           long step) {
01599         D *dstLEnd   = dst0 + lineWidth;
01600         D *dstSSEEnd = dstLEnd - (step - 1);
01601         long srcOffset = srcWidth - lineWidth;
01602         long dstOffset = dstWidth - lineWidth;
01603 
01604         for (; dst0<dstEnd;) {
01605           if (dst0<dstSSEEnd) {
01606             // convert 'rvalues' values at the same time
01607             (*subSSEMethod)(src0, src1, src2, src3, dst0, dst1);
01608 
01609             // increment pointers to the next values
01610             src0 += step;
01611             src1 += step;
01612             src2 += step;
01613             src3 += step;
01614             dst0 += step;
01615             dst1 += step;
01616           } else {
01617             for (; dst0<dstLEnd; ++src0, ++src1, ++src2, ++src3, ++dst0, ++dst1) {
01618               // convert 1 value
01619               (*subMethod)(src0, src1, src2, src3, dst0, dst1);
01620             }
01621 
01622             // move all pointers to the next line
01623             dstLEnd   += dstWidth;
01624             dstSSEEnd += dstWidth;
01625             src0 += srcOffset;
01626             src1 += srcOffset;
01627             src2 += srcOffset;
01628             src3 += srcOffset;
01629             dst0 += dstOffset;
01630             dst1 += dstOffset;
01631           }
01632         }
01633       }
01634 
01635       template<class S, class D>
01636       inline void sse_for(const S *src0, const S *src1, const S *src2, const S *src3,
01637                           D *dst0, D *dst1, D *dst2, D *dstEnd,
01638                           long srcWidth, long dstWidth, long lineWidth,
01639                           void (*subMethod)(const S*, const S*, const S*, const S*, D*, D*, D*),
01640                           void (*subSSEMethod)(const S*, const S*, const S*, const S*, D*, D*, D*),
01641                           long step) {
01642         D *dstLEnd   = dst0 + lineWidth;
01643         D *dstSSEEnd = dstLEnd - (step - 1);
01644         long srcOffset = srcWidth - lineWidth;
01645         long dstOffset = dstWidth - lineWidth;
01646 
01647         for (; dst0<dstEnd;) {
01648           if (dst0<dstSSEEnd) {
01649             // convert 'rvalues' values at the same time
01650             (*subSSEMethod)(src0, src1, src2, src3, dst0, dst1, dst2);
01651 
01652             // increment pointers to the next values
01653             src0 += step;
01654             src1 += step;
01655             src2 += step;
01656             src3 += step;
01657             dst0 += step;
01658             dst1 += step;
01659             dst2 += step;
01660           } else {
01661             for (; dst0<dstLEnd; ++src0, ++src1, ++src2, ++src3, ++dst0, ++dst1, ++dst2) {
01662               // convert 1 value
01663               (*subMethod)(src0, src1, src2, src3, dst0, dst1, dst2);
01664             }
01665 
01666             // move all pointers to the next line
01667             dstLEnd   += dstWidth;
01668             dstSSEEnd += dstWidth;
01669             src0 += srcOffset;
01670             src1 += srcOffset;
01671             src2 += srcOffset;
01672             src3 += srcOffset;
01673             dst0 += dstOffset;
01674             dst1 += dstOffset;
01675             dst2 += dstOffset;
01676           }
01677         }
01678       }
01679 
01680       template<class S, class D>
01681       inline void sse_for(const S *src0, const S *src1, const S *src2, const S *src3,
01682                           D *dst0, D *dst1, D *dst2, D* dst3, D *dstEnd,
01683                           long srcWidth, long dstWidth, long lineWidth,
01684                           void (*subMethod)(const S*, const S*, const S*, const S*, D*, D*, D*, D*),
01685                           void (*subSSEMethod)(const S*, const S*, const S*, const S*, D*, D*, D*, D*),
01686                           long step) {
01687         D *dstLEnd   = dst0 + lineWidth;
01688         D *dstSSEEnd = dstLEnd - (step - 1);
01689         long srcOffset = srcWidth - lineWidth;
01690         long dstOffset = dstWidth - lineWidth;
01691 
01692         for (; dst0<dstEnd;) {
01693           if (dst0<dstSSEEnd) {
01694             // convert 'rvalues' values at the same time
01695             (*subSSEMethod)(src0, src1, src2, src3, dst0, dst1, dst2, dst3);
01696 
01697             // increment pointers to the next values
01698             src0 += step;
01699             src1 += step;
01700             src2 += step;
01701             src3 += step;
01702             dst0 += step;
01703             dst1 += step;
01704             dst2 += step;
01705             dst3 += step;
01706           } else {
01707             for (; dst0<dstLEnd; ++src0, ++src1, ++src2, ++src3, ++dst0, ++dst1, ++dst2, ++dst3) {
01708               // convert 1 value
01709               (*subMethod)(src0, src1, src2, src3, dst0, dst1, dst2, dst3);
01710             }
01711 
01712             // move all pointers to the next line
01713             dstLEnd   += dstWidth;
01714             dstSSEEnd += dstWidth;
01715             src0 += srcOffset;
01716             src1 += srcOffset;
01717             src2 += srcOffset;
01718             src3 += srcOffset;
01719             dst0 += dstOffset;
01720             dst1 += dstOffset;
01721             dst2 += dstOffset;
01722             dst3 += dstOffset;
01723           }
01724         }
01725       }
01726 
01727       template<class S, class D>
01728       inline void sse_for(const S *src0, const S *src1, const S *src2, const S *src3, const S *src4,
01729                           D *dst0, D *dstEnd,
01730                           long srcWidth, long dstWidth, long lineWidth,
01731                           void (*subMethod)(const S*, const S*, const S*, const S*, const S*, D*),
01732                           void (*subSSEMethod)(const S*, const S*, const S*, const S*, const S*, D*),
01733                           long step) {
01734         D *dstLEnd   = dst0 + lineWidth;
01735         D *dstSSEEnd = dstLEnd - (step - 1);
01736         long srcOffset = srcWidth - lineWidth;
01737         long dstOffset = dstWidth - lineWidth;
01738 
01739         for (; dst0<dstEnd;) {
01740           if (dst0<dstSSEEnd) {
01741             // convert 'rvalues' values at the same time
01742             (*subSSEMethod)(src0, src1, src2, src3, src4, dst0);
01743 
01744             // increment pointers to the next values
01745             src0 += step;
01746             src1 += step;
01747             src2 += step;
01748             src3 += step;
01749             src4 += step;
01750             dst0 += step;
01751           } else {
01752             for (; dst0<dstLEnd; ++src0, ++src1, ++src2, ++src3, ++src4, ++dst0) {
01753               // convert 1 value
01754               (*subMethod)(src0, src1, src2, src3, src4, dst0);
01755             }
01756 
01757             // move all pointers to the next line
01758             dstLEnd   += dstWidth;
01759             dstSSEEnd += dstWidth;
01760             src0 += srcOffset;
01761             src1 += srcOffset;
01762             src2 += srcOffset;
01763             src3 += srcOffset;
01764             src4 += srcOffset;
01765             dst0 += dstOffset;
01766           }
01767         }
01768       }
01769 
01770       // the sse_for functions can be implemented compact in only one function
01771       // using pointer-to-pointer, but it is slower than the current
01772       // implementation of many versions
01773 
01774       template<class S, class D>
01775       inline void sse_for(const S *src0,
01776                           D *dst0, D *dstEnd,
01777                           long srcWidth, long dstWidth, long lineWidth,
01778                           void (*subMethod)(const S*, D*),
01779                           void (*subSSEMethod)(const S*, D*),
01780                           long srcStep, long dstStep) {
01781         D *dstLEnd   = dst0 + lineWidth;
01782         D *dstSSEEnd = dstLEnd - (dstStep - 1);
01783         long srcOffset = srcWidth - lineWidth;
01784         long dstOffset = dstWidth - lineWidth;
01785         long sStep, dStep;
01786 
01787         if (srcStep < dstStep) {
01788           dStep = dstStep / srcStep;
01789           sStep = 1;
01790         } else {
01791           sStep = srcStep / dstStep;
01792           dStep = 1;
01793         }
01794 
01795         for (; dst0<dstEnd;) {
01796           if (dst0<dstSSEEnd) {
01797             // convert 'rvalues' values at the same time
01798             (*subSSEMethod)(src0, dst0);
01799 
01800             // increment pointers to the next values
01801             src0 += srcStep;
01802             dst0 += dstStep;
01803           } else {
01804             for (; dst0<dstLEnd; src0 += sStep, dst0 += dStep) {
01805               // convert 1 value
01806               (*subMethod)(src0, dst0);
01807             }
01808 
01809             // move all pointers to the next line
01810             dstLEnd   += dstWidth;
01811             dstSSEEnd += dstWidth;
01812             src0 += srcOffset;
01813             dst0 += dstOffset;
01814           }
01815         }
01816       }
01817 
01818       template<class S, class D>
01819       inline void sse_for(const S *src0,
01820                           D *dst0, D *dst1, D *dstEnd,
01821                           long srcWidth, long dstWidth, long lineWidth,
01822                           void (*subMethod)(const S*, D*, D*),
01823                           void (*subSSEMethod)(const S*, D*, D*),
01824                           long srcStep, long dstStep) {
01825         D *dstLEnd   = dst0 + lineWidth;
01826         D *dstSSEEnd = dstLEnd - (dstStep - 1);
01827         long srcOffset = srcWidth - lineWidth;
01828         long dstOffset = dstWidth - lineWidth;
01829         long sStep, dStep;
01830 
01831         if (srcStep < dstStep) {
01832           dStep = dstStep / srcStep;
01833           sStep = 1;
01834         } else {
01835           sStep = srcStep / dstStep;
01836           dStep = 1;
01837         }
01838 
01839         for (; dst0<dstEnd;) {
01840           if (dst0<dstSSEEnd) {
01841             // convert 'rvalues' values at the same time
01842             (*subSSEMethod)(src0, dst0, dst1);
01843 
01844             // increment pointers to the next values
01845             src0 += srcStep;
01846             dst0 += dstStep;
01847             dst1 += dstStep;
01848           } else {
01849             for (; dst0<dstLEnd; src0 += sStep, dst0 += dStep, dst1 += dStep) {
01850               // convert 1 value
01851               (*subMethod)(src0, dst0, dst1);
01852             }
01853 
01854             // move all pointers to the next line
01855             dstLEnd   += dstWidth;
01856             dstSSEEnd += dstWidth;
01857             src0 += srcOffset;
01858             dst0 += dstOffset;
01859             dst1 += dstOffset;
01860           }
01861         }
01862       }
01863 
01864       template<class S, class D>
01865       inline void sse_for(const S *src0,
01866                           D *dst0, D *dst1, D *dst2, D *dstEnd,
01867                           long srcWidth, long dstWidth, long lineWidth,
01868                           void (*subMethod)(const S*, D*, D*, D*),
01869                           void (*subSSEMethod)(const S*, D*, D*, D*),
01870                           long srcStep, long dstStep) {
01871         D *dstLEnd   = dst0 + lineWidth;
01872         D *dstSSEEnd = dstLEnd - (dstStep - 1);
01873         long srcOffset = srcWidth - lineWidth;
01874         long dstOffset = dstWidth - lineWidth;
01875         long sStep, dStep;
01876 
01877         if (srcStep < dstStep) {
01878           dStep = dstStep / srcStep;
01879           sStep = 1;
01880         } else {
01881           sStep = srcStep / dstStep;
01882           dStep = 1;
01883         }
01884 
01885         for (; dst0<dstEnd;) {
01886           if (dst0<dstSSEEnd) {
01887             // convert 'rvalues' values at the same time
01888             (*subSSEMethod)(src0, dst0, dst1, dst2);
01889 
01890             // increment pointers to the next values
01891             src0 += srcStep;
01892             dst0 += dstStep;
01893             dst1 += dstStep;
01894             dst2 += dstStep;
01895           } else {
01896             for (; dst0<dstLEnd; src0 += sStep, dst0 += dStep, dst1 += dStep, dst2 += dStep) {
01897               // convert 1 value
01898               (*subMethod)(src0, dst0, dst1, dst2);
01899             }
01900 
01901             // move all pointers to the next line
01902             dstLEnd   += dstWidth;
01903             dstSSEEnd += dstWidth;
01904             src0 += srcOffset;
01905             dst0 += dstOffset;
01906             dst1 += dstOffset;
01907             dst2 += dstOffset;
01908           }
01909         }
01910       }
01911 
01912       template<class S, class D>
01913       inline void sse_for(const S *src0,
01914                           D *dst0, D *dst1, D *dst2, D *dst3, D *dstEnd,
01915                           long srcWidth, long dstWidth, long lineWidth,
01916                           void (*subMethod)(const S*, D*, D*, D*, D*),
01917                           void (*subSSEMethod)(const S*, D*, D*, D*, D*),
01918                           long srcStep, long dstStep) {
01919         D *dstLEnd   = dst0 + lineWidth;
01920         D *dstSSEEnd = dstLEnd - (dstStep - 1);
01921         long srcOffset = srcWidth - lineWidth;
01922         long dstOffset = dstWidth - lineWidth;
01923         long sStep, dStep;
01924 
01925         if (srcStep < dstStep) {
01926           dStep = dstStep / srcStep;
01927           sStep = 1;
01928         } else {
01929           sStep = srcStep / dstStep;
01930           dStep = 1;
01931         }
01932 
01933         for (; dst0<dstEnd;) {
01934           if (dst0<dstSSEEnd) {
01935             // convert 'rvalues' values at the same time
01936             (*subSSEMethod)(src0, dst0, dst1, dst2, dst3);
01937 
01938             // increment pointers to the next values
01939             src0 += srcStep;
01940             dst0 += dstStep;
01941             dst1 += dstStep;
01942             dst2 += dstStep;
01943             dst3 += dstStep;
01944           } else {
01945             for (; dst0<dstLEnd; src0 += sStep, dst0 += dStep, dst1 += dStep, dst2 += dStep, dst3 += dStep) {
01946               // convert 1 value
01947               (*subMethod)(src0, dst0, dst1, dst2, dst3);
01948             }
01949 
01950             // move all pointers to the next line
01951             dstLEnd   += dstWidth;
01952             dstSSEEnd += dstWidth;
01953             src0 += srcOffset;
01954             dst0 += dstOffset;
01955             dst1 += dstOffset;
01956             dst2 += dstOffset;
01957             dst3 += dstOffset;
01958           }
01959         }
01960       }
01961 
01962       template<class S, class D>
01963       inline void sse_for(const S *src0, const S *src1,
01964                           D *dst0, D *dst1, D *dstEnd,
01965                           long srcWidth, long dstWidth, long lineWidth,
01966                           void (*subMethod)(const S*, const S*, D*, D*),
01967                           void (*subSSEMethod)(const S*, const S*, D*, D*),
01968                           long srcStep, long dstStep) {
01969         D *dstLEnd   = dst0 + lineWidth;
01970         D *dstSSEEnd = dstLEnd - (dstStep - 1);
01971         long srcOffset = srcWidth - lineWidth;
01972         long dstOffset = dstWidth - lineWidth;
01973         long sStep, dStep;
01974 
01975         if (srcStep < dstStep) {
01976           dStep = dstStep / srcStep;
01977           sStep = 1;
01978         } else {
01979           sStep = srcStep / dstStep;
01980           dStep = 1;
01981         }
01982 
01983         for (; dst0<dstEnd;) {
01984           if (dst0<dstSSEEnd) {
01985             // convert 'rvalues' values at the same time
01986             (*subSSEMethod)(src0, src1, dst0, dst1);
01987 
01988             // increment pointers to the next values
01989             src0 += srcStep;
01990             src1 += srcStep;
01991             dst0 += dstStep;
01992             dst1 += dstStep;
01993           } else {
01994             for (; dst0<dstLEnd; src0 += sStep, src1 += sStep, dst0 += dStep, dst1 += dStep) {
01995               // convert 1 value
01996               (*subMethod)(src0, src1, dst0, dst1);
01997             }
01998 
01999             // move all pointers to the next line
02000             dstLEnd   += dstWidth;
02001             dstSSEEnd += dstWidth;
02002             src0 += srcOffset;
02003             src1 += srcOffset;
02004             dst0 += dstOffset;
02005             dst1 += dstOffset;
02006           }
02007         }
02008       }
02009 
02010       template<class S, class D>
02011       inline void sse_for(const S *src0, const S *src1,
02012                           D *dst0, D *dst1, D *dst2, D *dstEnd,
02013                           long srcWidth, long dstWidth, long lineWidth,
02014                           void (*subMethod)(const S*, const S*, D*, D*, D*),
02015                           void (*subSSEMethod)(const S*, const S*, D*, D*, D*),
02016                           long srcStep, long dstStep) {
02017         D *dstLEnd   = dst0 + lineWidth;
02018         D *dstSSEEnd = dstLEnd - (dstStep - 1);
02019         long srcOffset = srcWidth - lineWidth;
02020         long dstOffset = dstWidth - lineWidth;
02021         long sStep, dStep;
02022 
02023         if (srcStep < dstStep) {
02024           dStep = dstStep / srcStep;
02025           sStep = 1;
02026         } else {
02027           sStep = srcStep / dstStep;
02028           dStep = 1;
02029         }
02030 
02031         for (; dst0<dstEnd;) {
02032           if (dst0<dstSSEEnd) {
02033             // convert 'rvalues' values at the same time
02034             (*subSSEMethod)(src0, src1, dst0, dst1, dst2);
02035 
02036             // increment pointers to the next values
02037             src0 += srcStep;
02038             src1 += srcStep;
02039             dst0 += dstStep;
02040             dst1 += dstStep;
02041             dst2 += dstStep;
02042           } else {
02043             for (; dst0<dstLEnd; src0 += sStep, src1 += sStep, dst0 += dStep, dst1 += dStep, dst2 += dStep) {
02044               // convert 1 value
02045               (*subMethod)(src0, src1, dst0, dst1, dst2);
02046             }
02047 
02048             // move all pointers to the next line
02049             dstLEnd   += dstWidth;
02050             dstSSEEnd += dstWidth;
02051             src0 += srcOffset;
02052             src1 += srcOffset;
02053             dst0 += dstOffset;
02054             dst1 += dstOffset;
02055             dst2 += dstOffset;
02056           }
02057         }
02058       }
02059 
02060       template<class S, class D>
02061       inline void sse_for(const S *src0, const S *src1,
02062                           D *dst0, D *dst1, D *dst2, D *dst3, D *dstEnd,
02063                           long srcWidth, long dstWidth, long lineWidth,
02064                           void (*subMethod)(const S*, const S*, D*, D*, D*, D*),
02065                           void (*subSSEMethod)(const S*, const S*, D*, D*, D*, D*),
02066                           long srcStep, long dstStep) {
02067         D *dstLEnd   = dst0 + lineWidth;
02068         D *dstSSEEnd = dstLEnd - (dstStep - 1);
02069         long srcOffset = srcWidth - lineWidth;
02070         long dstOffset = dstWidth - lineWidth;
02071         long sStep, dStep;
02072 
02073         if (srcStep < dstStep) {
02074           dStep = dstStep / srcStep;
02075           sStep = 1;
02076         } else {
02077           sStep = srcStep / dstStep;
02078           dStep = 1;
02079         }
02080 
02081         for (; dst0<dstEnd;) {
02082           if (dst0<dstSSEEnd) {
02083             // convert 'rvalues' values at the same time
02084             (*subSSEMethod)(src0, src1, dst0, dst1, dst2, dst3);
02085 
02086             // increment pointers to the next values
02087             src0 += srcStep;
02088             src1 += srcStep;
02089             dst0 += dstStep;
02090             dst1 += dstStep;
02091             dst2 += dstStep;
02092             dst3 += dstStep;
02093           } else {
02094             for (; dst0<dstLEnd; src0 += sStep, src1 += sStep, dst0 += dStep, dst1 += dStep, dst2 += dStep, dst3 += dStep) {
02095               // convert 1 value
02096               (*subMethod)(src0, src1, dst0, dst1, dst2, dst3);
02097             }
02098 
02099             // move all pointers to the next line
02100             dstLEnd   += dstWidth;
02101             dstSSEEnd += dstWidth;
02102             src0 += srcOffset;
02103             src1 += srcOffset;
02104             dst0 += dstOffset;
02105             dst1 += dstOffset;
02106             dst2 += dstOffset;
02107             dst3 += dstOffset;
02108           }
02109         }
02110       }
02111 
02112       template<class S, class D>
02113       inline void sse_for(const S *src0, const S *src1, const S *src2,
02114                           D *dst0, D *dstEnd,
02115                           long srcWidth, long dstWidth, long lineWidth,
02116                           void (*subMethod)(const S*, const S*, const S*, D*),
02117                           void (*subSSEMethod)(const S*, const S*, const S*, D*),
02118                           long srcStep, long dstStep) {
02119         D *dstLEnd   = dst0 + lineWidth;
02120         D *dstSSEEnd = dstLEnd - (dstStep - 1);
02121         long srcOffset = srcWidth - lineWidth;
02122         long dstOffset = dstWidth - lineWidth;
02123         long sStep, dStep;
02124 
02125         if (srcStep < dstStep) {
02126           dStep = dstStep / srcStep;
02127           sStep = 1;
02128         } else {
02129           sStep = srcStep / dstStep;
02130           dStep = 1;
02131         }
02132 
02133         for (; dst0<dstEnd;) {
02134           if (dst0<dstSSEEnd) {
02135             // convert 'rvalues' values at the same time
02136             (*subSSEMethod)(src0, src1, src2, dst0);
02137 
02138             // increment pointers to the next values
02139             src0 += srcStep;
02140             src1 += srcStep;
02141             src2 += srcStep;
02142             dst0 += dstStep;
02143           } else {
02144             for (; dst0<dstLEnd; src0 += sStep, src1 += sStep, src2 += sStep, dst0 += dStep) {
02145               // convert 1 value
02146               (*subMethod)(src0, src1, src2, dst0);
02147             }
02148 
02149             // move all pointers to the next line
02150             dstLEnd   += dstWidth;
02151             dstSSEEnd += dstWidth;
02152             src0 += srcOffset;
02153             src1 += srcOffset;
02154             src2 += srcOffset;
02155             dst0 += dstOffset;
02156           }
02157         }
02158       }
02159 
02160       template<class S, class D>
02161       inline void sse_for(const S *src0, const S *src1, const S *src2,
02162                           D *dst0, D *dst1, D *dstEnd,
02163                           long srcWidth, long dstWidth, long lineWidth,
02164                           void (*subMethod)(const S*, const S*, const S*, D*, D*),
02165                           void (*subSSEMethod)(const S*, const S*, const S*, D*, D*),
02166                           long srcStep, long dstStep) {
02167         D *dstLEnd   = dst0 + lineWidth;
02168         D *dstSSEEnd = dstLEnd - (dstStep - 1);
02169         long srcOffset = srcWidth - lineWidth;
02170         long dstOffset = dstWidth - lineWidth;
02171         long sStep, dStep;
02172 
02173         if (srcStep < dstStep) {
02174           dStep = dstStep / srcStep;
02175           sStep = 1;
02176         } else {
02177           sStep = srcStep / dstStep;
02178           dStep = 1;
02179         }
02180 
02181         for (; dst0<dstEnd;) {
02182           if (dst0<dstSSEEnd) {
02183             // convert 'rvalues' values at the same time
02184             (*subSSEMethod)(src0, src1, src2, dst0, dst1);
02185 
02186             // increment pointers to the next values
02187             src0 += srcStep;
02188             src1 += srcStep;
02189             src2 += srcStep;
02190             dst0 += dstStep;
02191             dst1 += dstStep;
02192           } else {
02193             for (; dst0<dstLEnd; src0 += sStep, src1 += sStep, src2 += sStep, dst0 += dStep, dst1 += dStep) {
02194               // convert 1 value
02195               (*subMethod)(src0, src1, src2, dst0, dst1);
02196             }
02197 
02198             // move all pointers to the next line
02199             dstLEnd   += dstWidth;
02200             dstSSEEnd += dstWidth;
02201             src0 += srcOffset;
02202             src1 += srcOffset;
02203             src2 += srcOffset;
02204             dst0 += dstOffset;
02205             dst1 += dstOffset;
02206           }
02207         }
02208       }
02209 
02210       template<class S, class D>
02211       inline void sse_for(const S *src0, const S *src1, const S *src2,
02212                           D *dst0, D *dst1, D *dst2, D *dstEnd,
02213                           long srcWidth, long dstWidth, long lineWidth,
02214                           void (*subMethod)(const S*, const S*, const S*, D*, D*, D*),
02215                           void (*subSSEMethod)(const S*, const S*, const S*, D*, D*, D*),
02216                           long srcStep, long dstStep) {
02217         D *dstLEnd   = dst0 + lineWidth;
02218         D *dstSSEEnd = dstLEnd - (dstStep - 1);
02219         long srcOffset = srcWidth - lineWidth;
02220         long dstOffset = dstWidth - lineWidth;
02221         long sStep, dStep;
02222 
02223         if (srcStep < dstStep) {
02224           dStep = dstStep / srcStep;
02225           sStep = 1;
02226         } else {
02227           sStep = srcStep / dstStep;
02228           dStep = 1;
02229         }
02230 
02231         for (; dst0<dstEnd;) {
02232           if (dst0<dstSSEEnd) {
02233             // convert 'rvalues' values at the same time
02234             (*subSSEMethod)(src0, src1, src2, dst0, dst1, dst2);
02235 
02236             // increment pointers to the next values
02237             src0 += srcStep;
02238             src1 += srcStep;
02239             src2 += srcStep;
02240             dst0 += dstStep;
02241             dst1 += dstStep;
02242             dst2 += dstStep;
02243           } else {
02244             for (; dst0<dstLEnd; src0 += sStep, src1 += sStep, src2 += sStep, dst0 += dStep, dst1 += dStep, dst2 += dStep) {
02245               // convert 1 value
02246               (*subMethod)(src0, src1, src2, dst0, dst1, dst2);
02247             }
02248 
02249             // move all pointers to the next line
02250             dstLEnd   += dstWidth;
02251             dstSSEEnd += dstWidth;
02252             src0 += srcOffset;
02253             src1 += srcOffset;
02254             src2 += srcOffset;
02255             dst0 += dstOffset;
02256             dst1 += dstOffset;
02257             dst2 += dstOffset;
02258           }
02259         }
02260       }
02261 
02262       template<class S, class D>
02263       inline void sse_for(const S *src0, const S *src1, const S *src2,
02264                           D *dst0, D *dst1, D *dst2, D* dst3, D *dstEnd,
02265                           long srcWidth, long dstWidth, long lineWidth,
02266                           void (*subMethod)(const S*, const S*, const S*, D*, D*, D*, D*),
02267                           void (*subSSEMethod)(const S*, const S*, const S*, D*, D*, D*, D*),
02268                           long srcStep, long dstStep) {
02269         D *dstLEnd   = dst0 + lineWidth;
02270         D *dstSSEEnd = dstLEnd - (dstStep - 1);
02271         long srcOffset = srcWidth - lineWidth;
02272         long dstOffset = dstWidth - lineWidth;
02273         long sStep, dStep;
02274 
02275         if (srcStep < dstStep) {
02276           dStep = dstStep / srcStep;
02277           sStep = 1;
02278         } else {
02279           sStep = srcStep / dstStep;
02280           dStep = 1;
02281         }
02282 
02283         for (; dst0<dstEnd;) {
02284           if (dst0<dstSSEEnd) {
02285             // convert 'rvalues' values at the same time
02286             (*subSSEMethod)(src0, src1, src2, dst0, dst1, dst2, dst3);
02287 
02288             // increment pointers to the next values
02289             src0 += srcStep;
02290             src1 += srcStep;
02291             src2 += srcStep;
02292             dst0 += dstStep;
02293             dst1 += dstStep;
02294             dst2 += dstStep;
02295             dst3 += dstStep;
02296           } else {
02297             for (; dst0<dstLEnd; src0 += sStep, src1 += sStep, src2 += sStep, dst0 += dStep, dst1 += dStep, dst2 += dStep, dst3 += dStep) {
02298               // convert 1 value
02299               (*subMethod)(src0, src1, src2, dst0, dst1, dst2, dst3);
02300             }
02301 
02302             // move all pointers to the next line
02303             dstLEnd   += dstWidth;
02304             dstSSEEnd += dstWidth;
02305             src0 += srcOffset;
02306             src1 += srcOffset;
02307             src2 += srcOffset;
02308             dst0 += dstOffset;
02309             dst1 += dstOffset;
02310             dst2 += dstOffset;
02311             dst3 += dstOffset;
02312           }
02313         }
02314       }
02315 
02316       template<class S, class D>
02317       inline void sse_for(const S *src0, const S *src1, const S *src2, const S *src3,
02318                           D *dst0, D *dstEnd,
02319                           long srcWidth, long dstWidth, long lineWidth,
02320                           void (*subMethod)(const S*, const S*, const S*, const S*, D*),
02321                           void (*subSSEMethod)(const S*, const S*, const S*, const S*, D*),
02322                           long srcStep, long dstStep) {
02323         D *dstLEnd   = dst0 + lineWidth;
02324         D *dstSSEEnd = dstLEnd - (dstStep - 1);
02325         long srcOffset = srcWidth - lineWidth;
02326         long dstOffset = dstWidth - lineWidth;
02327         long sStep, dStep;
02328 
02329         if (srcStep < dstStep) {
02330           dStep = dstStep / srcStep;
02331           sStep = 1;
02332         } else {
02333           sStep = srcStep / dstStep;
02334           dStep = 1;
02335         }
02336 
02337         for (; dst0<dstEnd;) {
02338           if (dst0<dstSSEEnd) {
02339             // convert 'rvalues' values at the same time
02340             (*subSSEMethod)(src0, src1, src2, src3, dst0);
02341 
02342             // increment pointers to the next values
02343             src0 += srcStep;
02344             src1 += srcStep;
02345             src2 += srcStep;
02346             src3 += srcStep;
02347             dst0 += dstStep;
02348           } else {
02349             for (; dst0<dstLEnd; src0 += sStep, src1 += sStep, src2 += sStep, src3 += sStep, dst0 += dStep) {
02350               // convert 1 value
02351               (*subMethod)(src0, src1, src2, src3, dst0);
02352             }
02353 
02354             // move all pointers to the next line
02355             dstLEnd   += dstWidth;
02356             dstSSEEnd += dstWidth;
02357             src0 += srcOffset;
02358             src1 += srcOffset;
02359             src2 += srcOffset;
02360             src3 += srcOffset;
02361             dst0 += dstOffset;
02362           }
02363         }
02364       }
02365 
02366       template<class S, class D>
02367       inline void sse_for(const S *src0, const S *src1, const S *src2, const S *src3,
02368                           D *dst0, D *dst1, D *dstEnd,
02369                           long srcWidth, long dstWidth, long lineWidth,
02370                           void (*subMethod)(const S*, const S*, const S*, const S*, D*, D*),
02371                           void (*subSSEMethod)(const S*, const S*, const S*, const S*, D*, D*),
02372                           long srcStep, long dstStep) {
02373         D *dstLEnd   = dst0 + lineWidth;
02374         D *dstSSEEnd = dstLEnd - (dstStep - 1);
02375         long srcOffset = srcWidth - lineWidth;
02376         long dstOffset = dstWidth - lineWidth;
02377         long sStep, dStep;
02378 
02379         if (srcStep < dstStep) {
02380           dStep = dstStep / srcStep;
02381           sStep = 1;
02382         } else {
02383           sStep = srcStep / dstStep;
02384           dStep = 1;
02385         }
02386 
02387         for (; dst0<dstEnd;) {
02388           if (dst0<dstSSEEnd) {
02389             // convert 'rvalues' values at the same time
02390             (*subSSEMethod)(src0, src1, src2, src3, dst0, dst1);
02391 
02392             // increment pointers to the next values
02393             src0 += srcStep;
02394             src1 += srcStep;
02395             src2 += srcStep;
02396             src3 += srcStep;
02397             dst0 += dstStep;
02398             dst1 += dstStep;
02399           } else {
02400             for (; dst0<dstLEnd; src0 += sStep, src1 += sStep, src2 += sStep, src3 += sStep, dst0 += dStep, dst1 += dStep) {
02401               // convert 1 value
02402               (*subMethod)(src0, src1, src2, src3, dst0, dst1);
02403             }
02404 
02405             // move all pointers to the next line
02406             dstLEnd   += dstWidth;
02407             dstSSEEnd += dstWidth;
02408             src0 += srcOffset;
02409             src1 += srcOffset;
02410             src2 += srcOffset;
02411             src3 += srcOffset;
02412             dst0 += dstOffset;
02413             dst1 += dstOffset;
02414           }
02415         }
02416       }
02417 
02418       template<class S, class D>
02419       inline void sse_for(const S *src0, const S *src1, const S *src2, const S *src3,
02420                           D *dst0, D *dst1, D *dst2, D *dstEnd,
02421                           long srcWidth, long dstWidth, long lineWidth,
02422                           void (*subMethod)(const S*, const S*, const S*, const S*, D*, D*, D*),
02423                           void (*subSSEMethod)(const S*, const S*, const S*, const S*, D*, D*, D*),
02424                           long srcStep, long dstStep) {
02425         D *dstLEnd   = dst0 + lineWidth;
02426         D *dstSSEEnd = dstLEnd - (dstStep - 1);
02427         long srcOffset = srcWidth - lineWidth;
02428         long dstOffset = dstWidth - lineWidth;
02429         long sStep, dStep;
02430 
02431         if (srcStep < dstStep) {
02432           dStep = dstStep / srcStep;
02433           sStep = 1;
02434         } else {
02435           sStep = srcStep / dstStep;
02436           dStep = 1;
02437         }
02438 
02439         for (; dst0<dstEnd;) {
02440           if (dst0<dstSSEEnd) {
02441             // convert 'rvalues' values at the same time
02442             (*subSSEMethod)(src0, src1, src2, src3, dst0, dst1, dst2);
02443 
02444             // increment pointers to the next values
02445             src0 += srcStep;
02446             src1 += srcStep;
02447             src2 += srcStep;
02448             src3 += srcStep;
02449             dst0 += dstStep;
02450             dst1 += dstStep;
02451             dst2 += dstStep;
02452           } else {
02453             for (; dst0<dstLEnd; src0 += sStep, src1 += sStep, src2 += sStep, src3 += sStep, dst0 += dStep, dst1 += dStep, dst2 += dStep) {
02454               // convert 1 value
02455               (*subMethod)(src0, src1, src2, src3, dst0, dst1, dst2);
02456             }
02457 
02458             // move all pointers to the next line
02459             dstLEnd   += dstWidth;
02460             dstSSEEnd += dstWidth;
02461             src0 += srcOffset;
02462             src1 += srcOffset;
02463             src2 += srcOffset;
02464             src3 += srcOffset;
02465             dst0 += dstOffset;
02466             dst1 += dstOffset;
02467             dst2 += dstOffset;
02468           }
02469         }
02470       }
02471 
02472       template<class S, class D>
02473       inline void sse_for(const S *src0, const S *src1, const S *src2, const S *src3,
02474                           D *dst0, D *dst1, D *dst2, D* dst3, D *dstEnd,
02475                           long srcWidth, long dstWidth, long lineWidth,
02476                           void (*subMethod)(const S*, const S*, const S*, const S*, D*, D*, D*, D*),
02477                           void (*subSSEMethod)(const S*, const S*, const S*, const S*, D*, D*, D*, D*),
02478                           long srcStep, long dstStep) {
02479         D *dstLEnd   = dst0 + lineWidth;
02480         D *dstSSEEnd = dstLEnd - (dstStep - 1);
02481         long srcOffset = srcWidth - lineWidth;
02482         long dstOffset = dstWidth - lineWidth;
02483         long sStep, dStep;
02484 
02485         if (srcStep < dstStep) {
02486           dStep = dstStep / srcStep;
02487           sStep = 1;
02488         } else {
02489           sStep = srcStep / dstStep;
02490           dStep = 1;
02491         }
02492 
02493         for (; dst0<dstEnd;) {
02494           if (dst0<dstSSEEnd) {
02495             // convert 'rvalues' values at the same time
02496             (*subSSEMethod)(src0, src1, src2, src3, dst0, dst1, dst2, dst3);
02497 
02498             // increment pointers to the next values
02499             src0 += srcStep;
02500             src1 += srcStep;
02501             src2 += srcStep;
02502             src3 += srcStep;
02503             dst0 += dstStep;
02504             dst1 += dstStep;
02505             dst2 += dstStep;
02506             dst3 += dstStep;
02507           } else {
02508             for (; dst0<dstLEnd; src0 += sStep, src1 += sStep, src2 += sStep, src3 += sStep, dst0 += dStep, dst1 += dStep, dst2 += dStep, dst3 += dStep) {
02509               // convert 1 value
02510               (*subMethod)(src0, src1, src2, src3, dst0, dst1, dst2, dst3);
02511             }
02512 
02513             // move all pointers to the next line
02514             dstLEnd   += dstWidth;
02515             dstSSEEnd += dstWidth;
02516             src0 += srcOffset;
02517             src1 += srcOffset;
02518             src2 += srcOffset;
02519             src3 += srcOffset;
02520             dst0 += dstOffset;
02521             dst1 += dstOffset;
02522             dst2 += dstOffset;
02523             dst3 += dstOffset;
02524           }
02525         }
02526       }
02527 
02528       template<class S, class D>
02529       inline void sse_for(const S *src0, const S *src1, const S *src2, const S *src3, const S *src4,
02530                           D *dst0, D *dstEnd,
02531                           long srcWidth, long dstWidth, long lineWidth,
02532                           void (*subMethod)(const S*, const S*, const S*, const S*, const S*, D*),
02533                           void (*subSSEMethod)(const S*, const S*, const S*, const S*, const S*, D*),
02534                           long srcStep, long dstStep) {
02535         D *dstLEnd   = dst0 + lineWidth;
02536         D *dstSSEEnd = dstLEnd - (dstStep - 1);
02537         long srcOffset = srcWidth - lineWidth;
02538         long dstOffset = dstWidth - lineWidth;
02539         long sStep, dStep;
02540 
02541         if (srcStep < dstStep) {
02542           dStep = dstStep / srcStep;
02543           sStep = 1;
02544         } else {
02545           sStep = srcStep / dstStep;
02546           dStep = 1;
02547         }
02548 
02549         for (; dst0<dstEnd;) {
02550           if (dst0<dstSSEEnd) {
02551             // convert 'rvalues' values at the same time
02552             (*subSSEMethod)(src0, src1, src2, src3, src4, dst0);
02553 
02554             // increment pointers to the next values
02555             src0 += srcStep;
02556             src1 += srcStep;
02557             src2 += srcStep;
02558             src3 += srcStep;
02559             src4 += srcStep;
02560             dst0 += dstStep;
02561           } else {
02562             for (; dst0<dstLEnd; src0 += sStep, src1 += sStep, src2 += sStep, src3 += sStep, src4 += sStep, dst0 += dStep) {
02563               // convert 1 value
02564               (*subMethod)(src0, src1, src2, src3, src4, dst0);
02565             }
02566 
02567             // move all pointers to the next line
02568             dstLEnd   += dstWidth;
02569             dstSSEEnd += dstWidth;
02570             src0 += srcOffset;
02571             src1 += srcOffset;
02572             src2 += srcOffset;
02573             src3 += srcOffset;
02574             src4 += srcOffset;
02575             dst0 += dstOffset;
02576           }
02577         }
02578       }
02579 
02580       // -- for-loops with ROI -- //
02581 
02582     #endif
02583 
02584   } // namespace utils
02585 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines