PLearn 0.1
convolutions.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 // convolutions.cc
00003 
00004 // PLearn (A C++ Machine Learning Library)
00005 // Copyright (C) 1998 Pascal Vincent
00006 // Copyright (C) 1999-2002 Pascal Vincent, Yoshua Bengio and University of
00007 // Montreal
00008 //
00009 
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are met:
00012 //
00013 //  1. Redistributions of source code must retain the above copyright
00014 //     notice, this list of conditions and the following disclaimer.
00015 //
00016 //  2. Redistributions in binary form must reproduce the above copyright
00017 //     notice, this list of conditions and the following disclaimer in the
00018 //     documentation and/or other materials provided with the distribution.
00019 //
00020 //  3. The name of the authors may not be used to endorse or promote
00021 //     products derived from this software without specific prior written
00022 //     permission.
00023 //
00024 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
00025 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00026 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
00027 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00028 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00029 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00030 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00031 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00032 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00033 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034 //
00035 // This file is part of the PLearn library. For more information on the PLearn
00036 // library, go to the PLearn Web site at www.plearn.org
00037 
00038 
00039 /* *******************************************************
00040  * $Id$
00041  * This file is part of the PLearn library.
00042  ******************************************************* */
00043 
00047 #include "convolutions.h"
00048 
00049 namespace PLearn {
00050 using namespace std;
00051 
00052 void convolve1D(const Vec& source_signal, const Vec& kernel,
00053                 const Vec& dest_signal, int step, bool accumulate)
00054 {
00055     int nk=kernel.length();
00056     int nd=dest_signal.length();
00057 #ifdef BOUNDCHECK
00058     int ns=source_signal.length();
00059     if (step<1)
00060         PLERROR("convolve1D: step (%d) should be a positive integer\n",step);
00061     if (ns!=step*(nd-1)+nk)
00062         PLERROR("convolve1D: source_signal.length() (%d) should equal %d:\n"
00063                 "step (%d) * (dest_signal.length() (%d) - 1) + kernel.length()"
00064                 " (%d)\n",
00065                 ns,step*(nd-1)+nk,step,nd,nk);
00066 #endif
00067     if (!accumulate)
00068         dest_signal.clear();
00069     real* s=source_signal.data();
00070     real* k=kernel.data();
00071     real* d=dest_signal.data();
00072     for (int i=0;i<nd;i++,s+=step)
00073     {
00074         real somme=0;
00075         for (int j=0;j<nk;j++)
00076             somme += s[j]*k[j];
00077         d[i]+=somme;
00078     }
00079 }
00080 
00081 void backConvolve1D(const Vec& source_signal, const Vec& kernel,
00082                     const Vec& dest_signal, int step, bool accumulate)
00083 {
00084     int nk=kernel.length();
00085     int nd=dest_signal.length();
00086 #ifdef BOUNDCHECK
00087     int ns=source_signal.length();
00088     if (step<1)
00089         PLERROR("backConvolve1D: step (%d) should be a positive integer\n",
00090                 step);
00091     if (ns!=step*(nd-1)+nk)
00092         PLERROR("backConvolve1D: source_signal.length() (%d) should equal %d:\n"
00093                 "step (%d) * (dest_signal.length() (%d) - 1) + kernel.length()"
00094                 " (%d)\n",
00095                 ns,step*(nd-1)+nk,step,nd,nk);
00096 #endif
00097     if (!accumulate)
00098         source_signal.clear();
00099     real* s=source_signal.data();
00100     real* k=kernel.data();
00101     real* d=dest_signal.data();
00102     for (int i=0;i<nd;i++,s+=step)
00103     {
00107         real di=d[i];
00108         for (int j=0;j<nk;j++)
00109             s[j] += di*k[j];
00110     }
00111 }
00112 
00113 
00114 void convolve1Dbackprop(const Vec& source_signal, const Vec& kernel,
00115                         const Vec& dC_ddest_signal,
00116                         const Vec& dC_dsource_signal, const Vec& dC_dkernel,
00117                         int step, bool accumulate)
00118 {
00119     int nk=kernel.length();
00120     int nd=dC_ddest_signal.length();
00121 #ifdef BOUNDCHECK
00122     int ns=source_signal.length();
00123     if (step<1)
00124         PLERROR("convolve1Dbackprop: step (%d) should be a positive integer\n",
00125                 step);
00126     if (ns!=step*(nd-1)+nk)
00127         PLERROR("convolve1Dbackprop: source_signal.length() (%d) should"
00128                 " equal %d:\n"
00129                 "step (%d) * (dC_ddest_signal.length() (%d) - 1) +"
00130                 " kernel.length() (%d)\n",
00131                 ns,step*(nd-1)+nk,step,nd,nk);
00132     if (dC_dsource_signal.length()!=ns)
00133         PLERROR("convolve1Dbackprop: source_signal.length() (%d) should"
00134                 " equal:\n"
00135                 "dC_dsource_signal.length() (%d)\n",
00136                 ns,dC_dsource_signal.length());
00137     if (dC_dkernel.length()!=nk)
00138         PLERROR("convolve1Dbackprop: kernel.length() (%d) should equal:\n"
00139                 " dC_dkernel.length() (%d)\n",
00140                 nk,dC_dkernel.length());
00141 #endif
00142     if (!accumulate)
00143     {
00144         dC_dsource_signal.clear();
00145         dC_dkernel.clear();
00146     }
00147     real* s=source_signal.data();
00148     real* dCds=dC_dsource_signal.data();
00149     real* k=kernel.data();
00150     real* dCdk=dC_dkernel.data();
00151     real* dCdd=dC_ddest_signal.data();
00152 
00157     for (int i=0;i<nd;i++,dCds+=step,s+=step)
00158     {
00159         real di=dCdd[i];
00160         for (int j=0;j<nk;j++)
00161         {
00162             dCds[j] += di*k[j];
00163             dCdk[j] += di*s[j];
00164         }
00165     }
00166 }
00167 
00168 void convolve1Dbackprop(const Vec& source_signal,
00169                         const Vec& dC_ddest_signal,
00170                         const Vec& dC_dkernel,
00171                         int step, bool accumulate)
00172 {
00173     int nk=dC_dkernel.length();
00174     int nd=dC_ddest_signal.length();
00175 #ifdef BOUNDCHECK
00176     int ns=source_signal.length();
00177     if (step<1)
00178         PLERROR("convolve1Dbackprop: step (%d) should be a positive integer\n",
00179                 step);
00180     if (ns!=step*(nd-1)+nk)
00181         PLERROR("convolve1Dbackprop: source_signal.length() (%d) should"
00182                 " equal %d:\n"
00183                 "step (%d) * (dC_ddest_signal.length() (%d) - 1) +"
00184                 " dC_dkernel.length() (%d)\n",
00185                 ns,step*(nd-1)+nk,step,nd,nk);
00186 #endif
00187     if (!accumulate)
00188         dC_dkernel.clear();
00189 
00190     real* s=source_signal.data();
00191     real* dCdk=dC_dkernel.data();
00192     real* dCdd=dC_ddest_signal.data();
00193 
00197     for (int i=0;i<nd;i++,s+=step)
00198     {
00199         real di=dCdd[i];
00200         for (int j=0;j<nk;j++)
00201             dCdk[j] += di*s[j];
00202     }
00203 }
00204 
00205 
00206 void backConvolve1Dbackprop(const Vec& kernel, const Vec& dest_signal,
00207                             const Vec& dC_ddest_signal,
00208                             const Vec& dC_dsource_signal,
00209                             const Vec& dC_dkernel,
00210                             int step, bool accumulate)
00211 {
00212     int nk=kernel.length();
00213     int nd=dest_signal.length();
00214 #ifdef BOUNDCHECK
00215     int ns=dC_dsource_signal.length();
00216     if (step<1)
00217         PLERROR("backConvolve1Dbackprop: step (%d) should be a positive"
00218                 " integer\n",
00219                 step);
00220     if (ns!=step*(nd-1)+nk)
00221         PLERROR("backConvolve1Dbackprop: dC_dsource_signal.length() (%d)\n"
00222                 "should equal %d:\n"
00223                 "step (%d) * (dest_signal.length() (%d) - 1) + kernel.length()"
00224                 " (%d)\n",
00225                 ns,step*(nd-1)+nk,step,nd,nk);
00226     if (dC_ddest_signal.length()!=nd)
00227         PLERROR("backConvolve1Dbackprop: dest_signal.length() (%d) should"
00228                 " equal:\n"
00229                 "dC_ddest_signal.length() (%d)\n",
00230                 nd,dC_ddest_signal.length());
00231     if (dC_dkernel.length()!=nk)
00232         PLERROR("backConvolve1Dbackprop: kernel.length() (%d) should equal:\n"
00233                 " dC_dkernel.length() (%d)\n",
00234                 nk,dC_dkernel.length());
00235 #endif
00236     if (!accumulate)
00237     {
00238         dC_ddest_signal.clear();
00239         dC_dkernel.clear();
00240     }
00241     real* k=kernel.data();
00242     real* dCdk=dC_dkernel.data();
00243     real* dCdd=dC_ddest_signal.data();
00244     real* d=dest_signal.data();
00245     real* dCds=dC_dsource_signal.data();
00246 
00251     for (int i=0;i<nd;i++,dCds+=step)
00252     {
00253         real di = d[i];
00254         real dCdd_i_sum = 0;
00255         for (int j=0;j<nk;j++)
00256         {
00257             dCdd_i_sum += dCds[j]*k[j];
00258             dCdk[j] += dCds[j]*di;
00259         }
00260         dCdd[i] += dCdd_i_sum;
00261     }
00262 }
00263 
00264 
00265 void backConvolve1Dbackprop(const Vec& dest_signal,
00266                             const Vec& dC_dsource_signal,
00267                             const Vec& dC_dkernel,
00268                             int step, bool accumulate)
00269 {
00270     int nk=dC_dkernel.length();
00271     int nd=dest_signal.length();
00272 #ifdef BOUNDCHECK
00273     int ns=dC_dsource_signal.length();
00274     if (step<1)
00275         PLERROR("backConvolve1Dbackprop: step (%d) should be a positive"
00276                 " integer\n",
00277                 step);
00278     if (ns!=step*(nd-1)+nk)
00279         PLERROR("backConvolve1Dbackprop: dC_dsource_signal.length() (%d)\n"
00280                 "should equal %d:\n"
00281                 "step (%d) * (dest_signal.length() (%d) - 1) + dC_dkernel.length()"
00282                 " (%d)\n",
00283                 ns,step*(nd-1)+nk,step,nd,nk);
00284 #endif
00285     if (!accumulate)
00286         dC_dkernel.clear();
00287 
00288     real* dCdk=dC_dkernel.data();
00289     real* d=dest_signal.data();
00290     real* dCds=dC_dsource_signal.data();
00291 
00295     for (int i=0;i<nd;i++,dCds+=step)
00296     {
00297         real di = d[i];
00298         for (int j=0;j<nk;j++)
00299             dCdk[j] += dCds[j]*di;
00300     }
00301 }
00302 
00303 
00304 void convolve2D(const Mat& source_image, const Mat& kernel,
00305                 const Mat& dest_image,
00306                 int step1, int step2, bool accumulate)
00307 {
00308     int kl = kernel.length();
00309     int kw = kernel.width();
00310     int dl = dest_image.length();
00311     int dw = dest_image.width();
00312 
00313 #ifdef BOUNDCHECK
00314     int sl = source_image.length();
00315     int sw = source_image.width();
00316 
00317     if (step1<1)
00318         PLERROR("convolve2D: step1 (%d) should be a positive integer\n",step1);
00319     if (sl != step1*(dl-1)+kl)
00320         PLERROR("convolve2D: source_image.length() (%d) should equal %d:\n"
00321                 "step1 (%d) * (dest_image.length() (%d) - 1) + kernel.length()"
00322                 " (%d)\n",
00323                 sl, step1*(dl-1)+kl, step1, dl, kl);
00324 
00325     if (step2<1)
00326         PLERROR("convolve2D: step2 (%d) should be a positive integer\n",step2);
00327     if (sw != step2*(dw-1)+kw)
00328         PLERROR("convolve2D: source_image.width() (%d) should equal %d:\n"
00329                 "step2 (%d) * (dest_image.width() (%d) - 1) + kernel.width()"
00330                 " (%d)\n",
00331                 sw, step2*(dw-1)+kw, step2, dw, kw);
00332 #endif
00333     if (!accumulate)
00334         dest_image.clear();
00335     int sm = source_image.mod();
00336     int dm = dest_image.mod();
00337     int km = kernel.mod();
00338     real* source_i = source_image.data(); // source_image[i*step1]
00339     real* dest_i = dest_image.data(); // dest_image[i]
00340     for (int i=0; i<dl; i++, source_i+=sm*step1, dest_i+=dm)
00341     {
00342         real* source_i_j = source_i; // source_image[i*step1][j*step2]
00343         for (int j=0; j<dw; j++, source_i_j+=step2)
00344         {
00345             real sum = 0;
00346             real* kernel_k = kernel.data(); // kernel[k]
00347             real* source_ik_j = source_i_j; // source_image[i*step1+k][j*step2]
00348             for (int k=0; k<kl; k++, source_ik_j+=sm, kernel_k+=km)
00349                 for (int l=0; l<kw; l++)
00350                     sum += source_ik_j[l] * kernel_k[l];
00351             dest_i[j] += sum;
00352         }
00353     }
00354 }
00355 
00356 void backConvolve2D(const Mat& source_image, const Mat& kernel,
00357                     const Mat& dest_image,
00358                     int step1, int step2, bool accumulate)
00359 {
00360     int n1k=kernel.length();
00361     int n2k=kernel.width();
00362     int n1d=dest_image.length();
00363     int n2d=dest_image.width();
00364 #ifdef BOUNDCHECK
00365     int n1s=source_image.length();
00366     int n2s=source_image.width();
00367     if (step1<1)
00368         PLERROR("backConvolve2D: step1 (%d) should be a positive integer\n",
00369                 step1);
00370     if (n1s!=step1*(n1d-1)+n1k)
00371         PLERROR("backConvolve2D: source_image.length() (%d) should equal %d:\n"
00372                 "step1 (%d) * (dest_image.length() (%d) - 1) + kernel.length()"
00373                 " (%d)\n",
00374                 n1s,step1*(n1d-1)+n1k,step1,n1d,n1k);
00375 
00376     if (step2<1)
00377         PLERROR("backConvolve2D: step2 (%d) should be a positive integer\n",
00378                 step2);
00379     if (n2s!=step2*(n2d-1)+n2k)
00380         PLERROR("backConvolve2D: source_image.width() (%d) should equal %d:\n"
00381                 "step2 (%d) * (dest_image.width() (%d) - 1) + kernel.width()"
00382                 " (%d)\n",
00383                 n2s,step2*(n2d-1)+n2k,step2,n2d,n2k);
00384 #endif
00385     if (!accumulate)
00386         source_image.clear();
00387     int sm = source_image.mod();
00388     int dm = dest_image.mod();
00389     int km = kernel.mod();
00390     real* s = source_image.data();
00391     real* d = dest_image.data();
00392     for (int i=0;i<n1d;i++,s+=sm*step1,d+=dm)
00393     {
00394         real* s1 = s; // copy to iterate over columns
00395         for (int j=0;j<n2d;j++,s1+=step2)
00396         {
00397             real* k = kernel.data();
00398             real* ss = s1; // copy to iterate over sub-rows
00399             real d_ij=d[j];
00400             for (int l=0;l<n1k;l++,ss+=sm,k+=km)
00401             {
00402                 for (int m=0;m<n2k;m++)
00403                     ss[m] += d_ij * k[m];
00404             }
00405         }
00406     }
00407 }
00408 
00409 void convolve2Dbackprop(const Mat& source_image, const Mat& kernel,
00410                         const Mat& dC_ddest_image,
00411                         const Mat& dC_dsource_image, const Mat& dC_dkernel,
00412                         int step1, int step2, bool accumulate)
00413 {
00414     int n1k=kernel.length();
00415     int n2k=kernel.width();
00416     int n1d=dC_ddest_image.length();
00417     int n2d=dC_ddest_image.width();
00418 #ifdef BOUNDCHECK
00419     int n1s=source_image.length();
00420     int n2s=source_image.width();
00421     if (step1<1)
00422         PLERROR("convolve2Dbackprop: step1 (%d) should be a positive integer\n",
00423                 step1);
00424     if (n1s!=step1*(n1d-1)+n1k)
00425         PLERROR("convolve2Dbackprop: source_image.length() (%d) should equal"
00426                 " %d:\n"
00427                 "step1 (%d) * (dest_image.length() (%d) - 1) + kernel.length()"
00428                 " (%d)\n",
00429                 n1s,step1*(n1d-1)+n1k,step1,n1d,n1k);
00430     if (dC_dsource_image.length()!=n1s)
00431         PLERROR("convolve2Dbackprop: source_image.length() (%d) should"
00432                 " equal:\n"
00433                 "dC_dsource_image.length() (%d)\n",
00434                 n1s,dC_dsource_image.length());
00435     if (dC_dkernel.length()!=n1k)
00436         PLERROR("convolve2Dbackprop: kernel.length() (%d) should equal:\n"
00437                 " dC_dkernel.length() (%d)\n",
00438                 n1k,dC_dkernel.length());
00439 
00440     if (step2<1)
00441         PLERROR("convolve2Dbackprop: step2 (%d) should be a positive integer\n",
00442                 step2);
00443     if (n2s!=step2*(n2d-1)+n2k)
00444         PLERROR("convolve2Dbackprop: source_image.width() (%d) should equal"
00445                 " %d:\n"
00446                 "step2 (%d) * (dest_image.width() (%d) - 1) + kernel.width()"
00447                 " (%d)\n",
00448                 n2s,step2*(n2d-1)+n2k,step2,n2d,n2k);
00449     if (dC_dsource_image.width()!=n2s)
00450         PLERROR("convolve2Dbackprop: source_image.width() (%d) should"
00451                 " equal:\n"
00452                 "dC_dsource_image.width() (%d)\n",
00453                 n2s,dC_dsource_image.width());
00454     if (dC_dkernel.width()!=n2k)
00455         PLERROR("convolve2Dbackprop: kernel.width() (%d) should equal:\n"
00456                 " dC_dkernel.width() (%d)\n",
00457                 n2k,dC_dkernel.width());
00458 #endif
00459     if (!accumulate)
00460     {
00461         dC_dsource_image.clear();
00462         dC_dkernel.clear();
00463     }
00464     int sm = source_image.mod();
00465     int dCdsm = dC_dsource_image.mod();
00466     int km = kernel.mod();
00467     int dCdkm = dC_dkernel.mod();
00468     int dCddm = dC_ddest_image.mod();
00469 
00470     real* s = source_image.data();
00471     real* dCds = dC_dsource_image.data();
00472     real* dCdd = dC_ddest_image.data();
00473 
00474     for (int i=0;i<n1d;i++,s+=sm*step1,dCds+=dCdsm*step1,dCdd+=dCddm)
00475     {
00476         real* s1 = s; // copy to iterate over columns
00477         real* dCds1 = dCds;
00478         for (int j=0;j<n2d;j++,s1+=step2,dCds1+=step2)
00479         {
00480             real* k = kernel.data();
00481             real* dCdk = dC_dkernel.data();
00482             real* ss = s1; // copy to iterate over sub-rows
00483             real* dCdss = dCds1;
00484             real dCdd_ij=dCdd[j];
00485             for (int l=0;l<n1k;l++,ss+=sm,dCdss+=dCdsm,k+=km,dCdk+=dCdkm)
00486             {
00487                 for (int m=0;m<n2k;m++)
00488                 {
00489                     dCdss[m] += dCdd_ij * k[m];
00490                     dCdk[m] += dCdd_ij * ss[m];
00491                 }
00492             }
00493         }
00494     }
00495 }
00496 
00497 
00498 void convolve2Dbackprop(const Mat& source_image,
00499                         const Mat& dC_ddest_image,
00500                         const Mat& dC_dkernel,
00501                         int step1, int step2, bool accumulate)
00502 {
00503     int n1k=dC_dkernel.length();
00504     int n2k=dC_dkernel.width();
00505     int n1d=dC_ddest_image.length();
00506     int n2d=dC_ddest_image.width();
00507 #ifdef BOUNDCHECK
00508     int n1s=source_image.length();
00509     int n2s=source_image.width();
00510     if (step1<1)
00511         PLERROR("convolve2Dbackprop: step1 (%d) should be a positive integer\n",
00512                 step1);
00513     if (n1s!=step1*(n1d-1)+n1k)
00514         PLERROR("convolve2Dbackprop: source_image.length() (%d) should equal"
00515                 " %d:\n"
00516                 "step1 (%d) * (dest_image.length() (%d) - 1) +"
00517                 " dC_dkernel.length() (%d)\n",
00518                 n1s,step1*(n1d-1)+n1k,step1,n1d,n1k);
00519 
00520     if (step2<1)
00521         PLERROR("convolve2Dbackprop: step2 (%d) should be a positive integer\n",
00522                 step2);
00523     if (n2s!=step2*(n2d-1)+n2k)
00524         PLERROR("convolve2Dbackprop: source_image.width() (%d) should equal"
00525                 " %d:\n"
00526                 "step2 (%d) * (dest_image.width() (%d) - 1) +"
00527                 " dC_dkernel.width() (%d)\n",
00528                 n2s,step2*(n2d-1)+n2k,step2,n2d,n2k);
00529 #endif
00530     if (!accumulate)
00531         dC_dkernel.clear();
00532 
00533     int sm = source_image.mod();
00534     int dCdkm = dC_dkernel.mod();
00535     int dCddm = dC_ddest_image.mod();
00536 
00537     real* s = source_image.data();
00538     real* dCdd = dC_ddest_image.data();
00539 
00540     for (int i=0;i<n1d;i++,s+=sm*step1,dCdd+=dCddm)
00541     {
00542         real* s1 = s; // copy to iterate over columns
00543         for (int j=0;j<n2d;j++,s1+=step2)
00544         {
00545             real* dCdk = dC_dkernel.data();
00546             real* ss = s1; // copy to iterate over sub-rows
00547             real dCdd_ij=dCdd[j];
00548             for (int l=0;l<n1k;l++,ss+=sm,dCdk+=dCdkm)
00549                 for (int m=0;m<n2k;m++)
00550                     dCdk[m] += dCdd_ij * ss[m];
00551         }
00552     }
00553 }
00554 
00555 
00556 void backConvolve2Dbackprop(const Mat& kernel, const Mat& dest_image,
00557                             const Mat& dC_ddest_image,
00558                             const Mat& dC_dsource_image, const Mat& dC_dkernel,
00559                             int step1, int step2, bool accumulate)
00560 {
00561     int n1k=kernel.length();
00562     int n2k=kernel.width();
00563     int n1d=dest_image.length();
00564     int n2d=dest_image.width();
00565 #ifdef BOUNDCHECK
00566     int n1s=dC_dsource_image.length();
00567     int n2s=dC_dsource_image.width();
00568     if (step1<1)
00569         PLERROR("backConvolve2Dbackprop: step1 (%d) should be a positive"
00570                 " integer\n",
00571                 step1);
00572     if (n1s!=step1*(n1d-1)+n1k)
00573         PLERROR("backConvolve2Dbackprop: dC_dsource_image.length() (%d)\n"
00574                 "should equal %d:\n"
00575                 "step1 (%d) * (dest_image.length() (%d) - 1) + kernel.length()"
00576                 " (%d)\n",
00577                 n1s,step1*(n1d-1)+n1k,step1,n1d,n1k);
00578     if (dC_ddest_image.length()!=n1d)
00579         PLERROR("backConvolve2Dbackprop: dest_image.length() (%d) should"
00580                 " equal:\n"
00581                 "dC_ddest_image.length() (%d)\n",
00582                 n1d,dC_ddest_image.length());
00583     if (dC_dkernel.length()!=n1k)
00584         PLERROR("backConvolve2Dbackprop: kernel.length() (%d) should equal:\n"
00585                 " dC_dkernel.length() (%d)\n",
00586                 n1k,dC_dkernel.length());
00587 
00588     if (step2<1)
00589         PLERROR("backConvolve2Dbackprop: step2 (%d) should be a positive"
00590                 " integer\n",
00591                 step2);
00592     if (n2s!=step2*(n2d-1)+n2k)
00593         PLERROR("backConvolve2Dbackprop: source_image.width() (%d)\n"
00594                 "should equal %d:\n"
00595                 "step2 (%d) * (dest_image.width() (%d) - 1) + kernel.width()"
00596                 " (%d)\n",
00597                 n2s,step2*(n2d-1)+n2k,step2,n2d,n2k);
00598     if (dC_ddest_image.width()!=n2d)
00599         PLERROR("backConvolve2Dbackprop: dest_image.width() (%d) should"
00600                 " equal:\n"
00601                 "dC_ddest_image.width() (%d)\n",
00602                 n2d,dC_ddest_image.width());
00603     if (dC_dkernel.length()!=n2k)
00604         PLERROR("backConvolve2Dbackprop: kernel.width() (%d) should equal:\n"
00605                 " dC_dkernel.width() (%d)\n",
00606                 n2k,dC_dkernel.width());
00607 #endif
00608     if (!accumulate)
00609     {
00610         dC_ddest_image.clear();
00611         dC_dkernel.clear();
00612     }
00613     int km = kernel.mod();
00614     int dCdkm = dC_dkernel.mod();
00615     int dm = dest_image.mod();
00616     int dCddm = dC_ddest_image.mod();
00617     int dCdsm = dC_dsource_image.mod();
00618 
00619     real* d = dest_image.data();
00620     real* dCdd = dC_ddest_image.data();
00621     real* dCds = dC_dsource_image.data();
00622 
00623     for (int i=0;i<n1d;i++,d+=dm,dCdd+=dCddm,dCds+=dCdsm*step1)
00624     {
00625         real* dCds1 = dCds; // copy to iterate over columns
00626         for (int j=0;j<n2d;j++,dCds1+=step2)
00627         {
00628             real* k = kernel.data();
00629             real* dCdk = dC_dkernel.data();
00630             real* dCdss = dCds1; // copy to iterate over sub-rows
00631             real d_ij=d[j];
00632             real dCdd_ij_sum = 0;
00633             for (int l=0;l<n1k;l++,dCdss+=dCdsm,k+=km,dCdk+=dCdkm)
00634             {
00635                 for (int m=0;m<n2k;m++)
00636                 {
00637                     dCdd_ij_sum += dCdss[m]*k[m];
00638                     dCdk[m] += dCdss[m]*d_ij;
00639                 }
00640             }
00641             dCdd[j] += dCdd_ij_sum;
00642         }
00643     }
00644 }
00645 
00646 void backConvolve2Dbackprop(const Mat& dest_image,
00647                             const Mat& dC_dsource_image,
00648                             const Mat& dC_dkernel,
00649                             int step1, int step2, bool accumulate)
00650 {
00651     int n1k=dC_dkernel.length();
00652     int n2k=dC_dkernel.width();
00653     int n1d=dest_image.length();
00654     int n2d=dest_image.width();
00655 #ifdef BOUNDCHECK
00656     int n1s=dC_dsource_image.length();
00657     int n2s=dC_dsource_image.width();
00658     if (step1<1)
00659         PLERROR("backConvolve2Dbackprop: step1 (%d) should be a positive"
00660                 " integer\n",
00661                 step1);
00662     if (n1s!=step1*(n1d-1)+n1k)
00663         PLERROR("backConvolve2Dbackprop: dC_dsource_image.length() (%d)\n"
00664                 "should equal %d:\n"
00665                 "step1 (%d) * (dest_image.length() (%d) - 1) +"
00666                 " dC_dkernel.length() (%d)\n",
00667                 n1s,step1*(n1d-1)+n1k,step1,n1d,n1k);
00668 
00669     if (step2<1)
00670         PLERROR("backConvolve2Dbackprop: step2 (%d) should be a positive"
00671                 " integer\n",
00672                 step2);
00673     if (n2s!=step2*(n2d-1)+n2k)
00674         PLERROR("backConvolve2Dbackprop: source_image.width() (%d)\n"
00675                 "should equal %d:\n"
00676                 "step2 (%d) * (dest_image.width() (%d) - 1) +"
00677                 " dC_dkernel.width() (%d)\n",
00678                 n2s,step2*(n2d-1)+n2k,step2,n2d,n2k);
00679 #endif
00680     if (!accumulate)
00681         dC_dkernel.clear();
00682 
00683     int dCdkm = dC_dkernel.mod();
00684     int dm = dest_image.mod();
00685     int dCdsm = dC_dsource_image.mod();
00686 
00687     real* d = dest_image.data();
00688     real* dCds = dC_dsource_image.data();
00689 
00690     for (int i=0;i<n1d;i++,d+=dm,dCds+=dCdsm*step1)
00691     {
00692         real* dCds1 = dCds; // copy to iterate over columns
00693         for (int j=0;j<n2d;j++,dCds1+=step2)
00694         {
00695             real* dCdk = dC_dkernel.data();
00696             real* dCdss = dCds1; // copy to iterate over sub-rows
00697             real d_ij=d[j];
00698             for (int l=0;l<n1k;l++,dCdss+=dCdsm,dCdk+=dCdkm)
00699                 for (int m=0;m<n2k;m++)
00700                     dCdk[m] += dCdss[m]*d_ij;
00701         }
00702     }
00703 }
00704 
00705 } // end of namespace PLearn
00706 
00707 
00708 /*
00709   Local Variables:
00710   mode:c++
00711   c-basic-offset:4
00712   c-file-style:"stroustrup"
00713   c-file-offsets:((innamespace . 0)(inline-open . 0))
00714   indent-tabs-mode:nil
00715   fill-column:79
00716   End:
00717 */
00718 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines