Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/multiply.cs @ 9407

Last change on this file since 9407 was 9102, checked in by gkronber, 12 years ago

#1967: ILNumerics source for experimentation

File size: 20.9 KB
Line 
1///
2///    This file is part of ILNumerics Community Edition.
3///
4///    ILNumerics Community Edition - high performance computing for applications.
5///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
6///
7///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
8///    it under the terms of the GNU General Public License version 3 as published by
9///    the Free Software Foundation.
10///
11///    ILNumerics Community Edition is distributed in the hope that it will be useful,
12///    but WITHOUT ANY WARRANTY; without even the implied warranty of
13///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14///    GNU General Public License for more details.
15///
16///    You should have received a copy of the GNU General Public License
17///    along with ILNumerics Community Edition. See the file License.txt in the root
18///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
19///
20///    In addition this software uses the following components and/or licenses:
21///
22///    =================================================================================
23///    The Open Toolkit Library License
24///   
25///    Copyright (c) 2006 - 2009 the Open Toolkit library.
26///   
27///    Permission is hereby granted, free of charge, to any person obtaining a copy
28///    of this software and associated documentation files (the "Software"), to deal
29///    in the Software without restriction, including without limitation the rights to
30///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
31///    the Software, and to permit persons to whom the Software is furnished to do
32///    so, subject to the following conditions:
33///
34///    The above copyright notice and this permission notice shall be included in all
35///    copies or substantial portions of the Software.
36///
37///    =================================================================================
38///   
39
40using System;
41using System.Collections.Generic;
42using System.Text;
43using System.Runtime.InteropServices;
44using ILNumerics.Storage;
45using ILNumerics.Misc;
46using ILNumerics.Native;
47using ILNumerics.Exceptions;
48
49
50
51namespace ILNumerics {
52
53  public partial class ILMath {
54
55        private static readonly uint ALIGN = 1024 * 4;
56        [DllImport("matmulttestASM.dll", SetLastError = false, CallingConvention = CallingConvention.Cdecl, ExactSpelling= true, EntryPoint = "?inner_k_loop@@YAXHHHHHHHPAN0000HH@Z")]
57        unsafe static extern void inner_k_loop(int m, int n, int k, int kc, int mc, int mr, int nr,
58                                            IntPtr pAArr, IntPtr pBArr, IntPtr pCArr, IntPtr pBpack, IntPtr pApack,
59                                            int n_start, int n_end);
60        internal struct MatMultArguments {
61            public IntPtr pArr;
62            public IntPtr pBrr;
63            public IntPtr pCrr;
64            public IntPtr pAPack;
65            public IntPtr pBPack;
66            public int m_start;
67            public int m_end;
68            public int n_start;
69            public int n_end;
70        }
71
72
73        /// <summary>
74        /// Multiplicate an arbitrary number of matrices from left to right
75        /// </summary>
76        /// <param name="matrices">Input matrices </param>
77        /// <returns>Result of matrix multiplication for all matrices</returns>
78        public static ILRetArray< double> multiply(params ILInArray< double>[] matrices) {
79            if (matrices == null || matrices.Length < 2)
80                throw new ILArgumentException("the number of matching parameters for multiply must be at least 2");
81            using (ILScope.Enter(matrices)) {
82                ILArray< double> ret = multiply(matrices[0], matrices[1]);
83                for (int i = 2; i < matrices.Length; i++) {
84                    ret.a = multiply(ret, matrices[i]);
85                }
86                return ret;
87            }
88        }
89
90        /// <summary>
91        /// General matrix multiply this array
92        /// </summary>
93        /// <param name="A">Input matrix A</param>
94        /// <param name="B">Input matrix B</param>
95        /// <returns>Matrix with result of matrix multiplication</returns>
96        /// <remarks>Both arrays must be matrices with matching dimension length. Therefore the number of rows
97        /// of B must equal the number of columns of A. An ILArgumentSizeException will be thrown otherwise.
98        /// The multiplication will be carried out inside optimized BLAS libraries if availiable. If not it
99        /// will be done in managed code.
100        /// </remarks>
101        /// <exception cref="ILNumerics.Exceptions.ILArgumentSizeException">If at least one arrays is not a matrix</exception>
102        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If the size of both matrices do not match</exception>
103        public static ILRetArray< double > multiply(ILInArray< double > A, ILInArray< double > B) {
104            using (ILScope.Enter(A,B)) {
105                ILArray< double> ret = null;
106                //if (A.Dimensions.NumberOfDimensions != 2
107                //    || B.Dimensions.NumberOfDimensions != 2)
108                //    throw new ILArgumentSizeException("input arguments must be matrices");
109                if (A.Size[1] != B.Size[0])
110                    throw new ILDimensionMismatchException("inner matrix dimensions must match");
111               
112                double[] retArr = null;
113                if (A.Size.NumberOfElements > ILAtlasMinimumElementSize ||
114                    B.Size.NumberOfElements > ILAtlasMinimumElementSize) {
115                    // do BLAS GEMM
116                    ret = zeros< double>(new ILSize(A.Size[0], B.Size[1]));  // todo: change to use uninitialized memory!
117                    retArr = ret.GetArrayForWrite();
118                    unsafe {
119                        fixed ( double* ptrC = retArr)
120                        fixed ( double* pA = A.GetArrayForRead())
121                        fixed ( double* pB = B.GetArrayForRead()) {
122                           
123                            Lapack.dgemm(TRANS_NONE, TRANS_NONE,
124                                A.Size[0], B.Size[1],
125                                A.Size[1], ( double)1.0,
126                                (IntPtr)pA, A.Size[0],
127                                (IntPtr)pB, B.Size[0], ( double)1.0,
128                                retArr, ret.Size[0]);
129                        }
130                    }
131                } else {
132                    // do GEMM by hand
133                    retArr = new  double[A.Size[0] * B.Size[1]];
134                    ret = array< double>(retArr, A.Size[0], B.Size[1]);
135                    unsafe {
136                        int in2Len1 = B.Size[1];
137                        int in1Len0 = A.Size[0];
138                        int in1Len1 = A.Size[1];
139                        fixed ( double* ptrC = retArr) {
140                           
141                            double* pC = ptrC;
142                            for (int c = 0; c < in2Len1; c++) {
143                                for (int r = 0; r < in1Len0; r++) {
144                                    for (int n = 0; n < in1Len1; n++) {
145                                        *pC += A.GetValue(r, n) * B.GetValue(n, c);
146                                    }
147                                    pC++;
148                                }
149                            }
150                        }
151                    }
152                }
153                return ret;
154            }
155        }
156
157
158#region HYCALPER AUTO GENERATED CODE
159
160        /// <summary>
161        /// Multiplicate an arbitrary number of matrices from left to right
162        /// </summary>
163        /// <param name="matrices">Input matrices </param>
164        /// <returns>Result of matrix multiplication for all matrices</returns>
165        public static ILRetArray< float> multiply(params ILInArray< float>[] matrices) {
166            if (matrices == null || matrices.Length < 2)
167                throw new ILArgumentException("the number of matching parameters for multiply must be at least 2");
168            using (ILScope.Enter(matrices)) {
169                ILArray< float> ret = multiply(matrices[0], matrices[1]);
170                for (int i = 2; i < matrices.Length; i++) {
171                    ret.a = multiply(ret, matrices[i]);
172                }
173                return ret;
174            }
175        }
176
177        /// <summary>
178        /// General matrix multiply this array
179        /// </summary>
180        /// <param name="A">Input matrix A</param>
181        /// <param name="B">Input matrix B</param>
182        /// <returns>Matrix with result of matrix multiplication</returns>
183        /// <remarks>Both arrays must be matrices with matching dimension length. Therefore the number of rows
184        /// of B must equal the number of columns of A. An ILArgumentSizeException will be thrown otherwise.
185        /// The multiplication will be carried out inside optimized BLAS libraries if availiable. If not it
186        /// will be done in managed code.
187        /// </remarks>
188        /// <exception cref="ILNumerics.Exceptions.ILArgumentSizeException">If at least one arrays is not a matrix</exception>
189        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If the size of both matrices do not match</exception>
190        public static ILRetArray< float > multiply(ILInArray< float > A, ILInArray< float > B) {
191            using (ILScope.Enter(A,B)) {
192                ILArray< float> ret = null;
193                //if (A.Dimensions.NumberOfDimensions != 2
194                //    || B.Dimensions.NumberOfDimensions != 2)
195                //    throw new ILArgumentSizeException("input arguments must be matrices");
196                if (A.Size[1] != B.Size[0])
197                    throw new ILDimensionMismatchException("inner matrix dimensions must match");
198               
199                float[] retArr = null;
200                if (A.Size.NumberOfElements > ILAtlasMinimumElementSize ||
201                    B.Size.NumberOfElements > ILAtlasMinimumElementSize) {
202                    // do BLAS GEMM
203                    ret = zeros< float>(new ILSize(A.Size[0], B.Size[1]));  // todo: change to use uninitialized memory!
204                    retArr = ret.GetArrayForWrite();
205                    unsafe {
206                        fixed ( float* ptrC = retArr)
207                        fixed ( float* pA = A.GetArrayForRead())
208                        fixed ( float* pB = B.GetArrayForRead()) {
209                           
210                            Lapack.sgemm(TRANS_NONE, TRANS_NONE,
211                                A.Size[0], B.Size[1],
212                                A.Size[1], ( float)1.0,
213                                (IntPtr)pA, A.Size[0],
214                                (IntPtr)pB, B.Size[0], ( float)1.0,
215                                retArr, ret.Size[0]);
216                        }
217                    }
218                } else {
219                    // do GEMM by hand
220                    retArr = new  float[A.Size[0] * B.Size[1]];
221                    ret = array< float>(retArr, A.Size[0], B.Size[1]);
222                    unsafe {
223                        int in2Len1 = B.Size[1];
224                        int in1Len0 = A.Size[0];
225                        int in1Len1 = A.Size[1];
226                        fixed ( float* ptrC = retArr) {
227                           
228                            float* pC = ptrC;
229                            for (int c = 0; c < in2Len1; c++) {
230                                for (int r = 0; r < in1Len0; r++) {
231                                    for (int n = 0; n < in1Len1; n++) {
232                                        *pC += A.GetValue(r, n) * B.GetValue(n, c);
233                                    }
234                                    pC++;
235                                }
236                            }
237                        }
238                    }
239                }
240                return ret;
241            }
242        }
243
244        /// <summary>
245        /// Multiplicate an arbitrary number of matrices from left to right
246        /// </summary>
247        /// <param name="matrices">Input matrices </param>
248        /// <returns>Result of matrix multiplication for all matrices</returns>
249        public static ILRetArray< fcomplex> multiply(params ILInArray< fcomplex>[] matrices) {
250            if (matrices == null || matrices.Length < 2)
251                throw new ILArgumentException("the number of matching parameters for multiply must be at least 2");
252            using (ILScope.Enter(matrices)) {
253                ILArray< fcomplex> ret = multiply(matrices[0], matrices[1]);
254                for (int i = 2; i < matrices.Length; i++) {
255                    ret.a = multiply(ret, matrices[i]);
256                }
257                return ret;
258            }
259        }
260
261        /// <summary>
262        /// General matrix multiply this array
263        /// </summary>
264        /// <param name="A">Input matrix A</param>
265        /// <param name="B">Input matrix B</param>
266        /// <returns>Matrix with result of matrix multiplication</returns>
267        /// <remarks>Both arrays must be matrices with matching dimension length. Therefore the number of rows
268        /// of B must equal the number of columns of A. An ILArgumentSizeException will be thrown otherwise.
269        /// The multiplication will be carried out inside optimized BLAS libraries if availiable. If not it
270        /// will be done in managed code.
271        /// </remarks>
272        /// <exception cref="ILNumerics.Exceptions.ILArgumentSizeException">If at least one arrays is not a matrix</exception>
273        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If the size of both matrices do not match</exception>
274        public static ILRetArray< fcomplex > multiply(ILInArray< fcomplex > A, ILInArray< fcomplex > B) {
275            using (ILScope.Enter(A,B)) {
276                ILArray< fcomplex> ret = null;
277                //if (A.Dimensions.NumberOfDimensions != 2
278                //    || B.Dimensions.NumberOfDimensions != 2)
279                //    throw new ILArgumentSizeException("input arguments must be matrices");
280                if (A.Size[1] != B.Size[0])
281                    throw new ILDimensionMismatchException("inner matrix dimensions must match");
282               
283                fcomplex[] retArr = null;
284                if (A.Size.NumberOfElements > ILAtlasMinimumElementSize ||
285                    B.Size.NumberOfElements > ILAtlasMinimumElementSize) {
286                    // do BLAS GEMM
287                    ret = zeros< fcomplex>(new ILSize(A.Size[0], B.Size[1]));  // todo: change to use uninitialized memory!
288                    retArr = ret.GetArrayForWrite();
289                    unsafe {
290                        fixed ( fcomplex* ptrC = retArr)
291                        fixed ( fcomplex* pA = A.GetArrayForRead())
292                        fixed ( fcomplex* pB = B.GetArrayForRead()) {
293                           
294                            Lapack.cgemm(TRANS_NONE, TRANS_NONE,
295                                A.Size[0], B.Size[1],
296                                A.Size[1], ( fcomplex)1.0,
297                                (IntPtr)pA, A.Size[0],
298                                (IntPtr)pB, B.Size[0], ( fcomplex)1.0,
299                                retArr, ret.Size[0]);
300                        }
301                    }
302                } else {
303                    // do GEMM by hand
304                    retArr = new  fcomplex[A.Size[0] * B.Size[1]];
305                    ret = array< fcomplex>(retArr, A.Size[0], B.Size[1]);
306                    unsafe {
307                        int in2Len1 = B.Size[1];
308                        int in1Len0 = A.Size[0];
309                        int in1Len1 = A.Size[1];
310                        fixed ( fcomplex* ptrC = retArr) {
311                           
312                            fcomplex* pC = ptrC;
313                            for (int c = 0; c < in2Len1; c++) {
314                                for (int r = 0; r < in1Len0; r++) {
315                                    for (int n = 0; n < in1Len1; n++) {
316                                        *pC += A.GetValue(r, n) * B.GetValue(n, c);
317                                    }
318                                    pC++;
319                                }
320                            }
321                        }
322                    }
323                }
324                return ret;
325            }
326        }
327
328        /// <summary>
329        /// Multiplicate an arbitrary number of matrices from left to right
330        /// </summary>
331        /// <param name="matrices">Input matrices </param>
332        /// <returns>Result of matrix multiplication for all matrices</returns>
333        public static ILRetArray< complex> multiply(params ILInArray< complex>[] matrices) {
334            if (matrices == null || matrices.Length < 2)
335                throw new ILArgumentException("the number of matching parameters for multiply must be at least 2");
336            using (ILScope.Enter(matrices)) {
337                ILArray< complex> ret = multiply(matrices[0], matrices[1]);
338                for (int i = 2; i < matrices.Length; i++) {
339                    ret.a = multiply(ret, matrices[i]);
340                }
341                return ret;
342            }
343        }
344
345        /// <summary>
346        /// General matrix multiply this array
347        /// </summary>
348        /// <param name="A">Input matrix A</param>
349        /// <param name="B">Input matrix B</param>
350        /// <returns>Matrix with result of matrix multiplication</returns>
351        /// <remarks>Both arrays must be matrices with matching dimension length. Therefore the number of rows
352        /// of B must equal the number of columns of A. An ILArgumentSizeException will be thrown otherwise.
353        /// The multiplication will be carried out inside optimized BLAS libraries if availiable. If not it
354        /// will be done in managed code.
355        /// </remarks>
356        /// <exception cref="ILNumerics.Exceptions.ILArgumentSizeException">If at least one arrays is not a matrix</exception>
357        /// <exception cref="ILNumerics.Exceptions.ILDimensionMismatchException">If the size of both matrices do not match</exception>
358        public static ILRetArray< complex > multiply(ILInArray< complex > A, ILInArray< complex > B) {
359            using (ILScope.Enter(A,B)) {
360                ILArray< complex> ret = null;
361                //if (A.Dimensions.NumberOfDimensions != 2
362                //    || B.Dimensions.NumberOfDimensions != 2)
363                //    throw new ILArgumentSizeException("input arguments must be matrices");
364                if (A.Size[1] != B.Size[0])
365                    throw new ILDimensionMismatchException("inner matrix dimensions must match");
366               
367                complex[] retArr = null;
368                if (A.Size.NumberOfElements > ILAtlasMinimumElementSize ||
369                    B.Size.NumberOfElements > ILAtlasMinimumElementSize) {
370                    // do BLAS GEMM
371                    ret = zeros< complex>(new ILSize(A.Size[0], B.Size[1]));  // todo: change to use uninitialized memory!
372                    retArr = ret.GetArrayForWrite();
373                    unsafe {
374                        fixed ( complex* ptrC = retArr)
375                        fixed ( complex* pA = A.GetArrayForRead())
376                        fixed ( complex* pB = B.GetArrayForRead()) {
377                           
378                            Lapack.zgemm(TRANS_NONE, TRANS_NONE,
379                                A.Size[0], B.Size[1],
380                                A.Size[1], ( complex)1.0,
381                                (IntPtr)pA, A.Size[0],
382                                (IntPtr)pB, B.Size[0], ( complex)1.0,
383                                retArr, ret.Size[0]);
384                        }
385                    }
386                } else {
387                    // do GEMM by hand
388                    retArr = new  complex[A.Size[0] * B.Size[1]];
389                    ret = array< complex>(retArr, A.Size[0], B.Size[1]);
390                    unsafe {
391                        int in2Len1 = B.Size[1];
392                        int in1Len0 = A.Size[0];
393                        int in1Len1 = A.Size[1];
394                        fixed ( complex* ptrC = retArr) {
395                           
396                            complex* pC = ptrC;
397                            for (int c = 0; c < in2Len1; c++) {
398                                for (int r = 0; r < in1Len0; r++) {
399                                    for (int n = 0; n < in1Len1; n++) {
400                                        *pC += A.GetValue(r, n) * B.GetValue(n, c);
401                                    }
402                                    pC++;
403                                }
404                            }
405                        }
406                    }
407                }
408                return ret;
409            }
410        }
411
412
413#endregion HYCALPER AUTO GENERATED CODE
414
415    }
416}
Note: See TracBrowser for help on using the repository browser.