GNU Octave
3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
Main Page
Namespaces
Classes
Files
File List
File Members
All
Classes
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Properties
Friends
Macros
Pages
liboctave
operators
mx-op-defs.h
Go to the documentation of this file.
1
/*
2
3
Copyright (C) 1996-2013 John W. Eaton
4
Copyright (C) 2008-2009 Jaroslav Hajek
5
Copyright (C) 2009-2010 VZLU Prague, a.s.
6
7
This file is part of Octave.
8
9
Octave is free software; you can redistribute it and/or modify it
10
under the terms of the GNU General Public License as published by the
11
Free Software Foundation; either version 3 of the License, or (at your
12
option) any later version.
13
14
Octave is distributed in the hope that it will be useful, but WITHOUT
15
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17
for more details.
18
19
You should have received a copy of the GNU General Public License
20
along with Octave; see the file COPYING. If not, see
21
<http://www.gnu.org/licenses/>.
22
23
*/
24
25
#if !defined (octave_mx_op_defs_h)
26
#define octave_mx_op_defs_h 1
27
28
#include "
mx-op-decl.h
"
29
#include "
mx-inlines.cc
"
30
31
#define SNANCHK(s) \
32
if (xisnan (s)) \
33
gripe_nan_to_logical_conversion ()
34
35
#define MNANCHK(m, MT) \
36
if (do_mx_check (m, mx_inline_any_nan<MT>)) \
37
gripe_nan_to_logical_conversion ()
38
39
// vector by scalar operations.
40
41
#define VS_BIN_OP(R, F, OP, V, S) \
42
R \
43
F (const V& v, const S& s) \
44
{ \
45
return do_ms_binary_op<R::element_type, V::element_type, S> (v, s, OP); \
46
}
47
48
#define VS_BIN_OPS(R, V, S) \
49
VS_BIN_OP (R, operator +, mx_inline_add, V, S) \
50
VS_BIN_OP (R, operator -, mx_inline_sub, V, S) \
51
VS_BIN_OP (R, operator *, mx_inline_mul, V, S) \
52
VS_BIN_OP (R, operator /, mx_inline_div, V, S)
53
54
// scalar by vector by operations.
55
56
#define SV_BIN_OP(R, F, OP, S, V) \
57
R \
58
F (const S& s, const V& v) \
59
{ \
60
return do_sm_binary_op<R::element_type, S, V::element_type> (s, v, OP); \
61
}
62
63
#define SV_BIN_OPS(R, S, V) \
64
SV_BIN_OP (R, operator +, mx_inline_add, S, V) \
65
SV_BIN_OP (R, operator -, mx_inline_sub, S, V) \
66
SV_BIN_OP (R, operator *, mx_inline_mul, S, V) \
67
SV_BIN_OP (R, operator /, mx_inline_div, S, V)
68
69
// vector by vector operations.
70
71
#define VV_BIN_OP(R, F, OP, V1, V2) \
72
R \
73
F (const V1& v1, const V2& v2) \
74
{ \
75
return do_mm_binary_op<R::element_type, V1::element_type, V2::element_type> (v1, v2, OP, OP, OP, #F); \
76
}
77
78
#define VV_BIN_OPS(R, V1, V2) \
79
VV_BIN_OP (R, operator +, mx_inline_add, V1, V2) \
80
VV_BIN_OP (R, operator -, mx_inline_sub, V1, V2) \
81
VV_BIN_OP (R, product, mx_inline_mul, V1, V2) \
82
VV_BIN_OP (R, quotient, mx_inline_div, V1, V2)
83
84
// matrix by scalar operations.
85
86
#define MS_BIN_OP(R, OP, M, S, F) \
87
R \
88
OP (const M& m, const S& s) \
89
{ \
90
return do_ms_binary_op<R::element_type, M::element_type, S> (m, s, F); \
91
}
92
93
#define MS_BIN_OPS(R, M, S) \
94
MS_BIN_OP (R, operator +, M, S, mx_inline_add) \
95
MS_BIN_OP (R, operator -, M, S, mx_inline_sub) \
96
MS_BIN_OP (R, operator *, M, S, mx_inline_mul) \
97
MS_BIN_OP (R, operator /, M, S, mx_inline_div)
98
99
#define MS_CMP_OP(F, OP, M, S) \
100
boolMatrix \
101
F (const M& m, const S& s) \
102
{ \
103
return do_ms_binary_op<bool, M::element_type, S> (m, s, OP); \
104
}
105
106
#define MS_CMP_OPS(M, S) \
107
MS_CMP_OP (mx_el_lt, mx_inline_lt, M, S) \
108
MS_CMP_OP (mx_el_le, mx_inline_le, M, S) \
109
MS_CMP_OP (mx_el_ge, mx_inline_ge, M, S) \
110
MS_CMP_OP (mx_el_gt, mx_inline_gt, M, S) \
111
MS_CMP_OP (mx_el_eq, mx_inline_eq, M, S) \
112
MS_CMP_OP (mx_el_ne, mx_inline_ne, M, S)
113
114
#define MS_BOOL_OP(F, OP, M, S) \
115
boolMatrix \
116
F (const M& m, const S& s) \
117
{ \
118
MNANCHK (m, M::element_type); \
119
SNANCHK (s); \
120
return do_ms_binary_op<bool, M::element_type, S> (m, s, OP); \
121
}
122
123
#define MS_BOOL_OPS(M, S) \
124
MS_BOOL_OP (mx_el_and, mx_inline_and, M, S) \
125
MS_BOOL_OP (mx_el_or, mx_inline_or, M, S)
126
127
// scalar by matrix operations.
128
129
#define SM_BIN_OP(R, OP, S, M, F) \
130
R \
131
OP (const S& s, const M& m) \
132
{ \
133
return do_sm_binary_op<R::element_type, S, M::element_type> (s, m, F); \
134
}
135
136
#define SM_BIN_OPS(R, S, M) \
137
SM_BIN_OP (R, operator +, S, M, mx_inline_add) \
138
SM_BIN_OP (R, operator -, S, M, mx_inline_sub) \
139
SM_BIN_OP (R, operator *, S, M, mx_inline_mul) \
140
SM_BIN_OP (R, operator /, S, M, mx_inline_div)
141
142
#define SM_CMP_OP(F, OP, S, M) \
143
boolMatrix \
144
F (const S& s, const M& m) \
145
{ \
146
return do_sm_binary_op<bool, S, M::element_type> (s, m, OP); \
147
}
148
149
#define SM_CMP_OPS(S, M) \
150
SM_CMP_OP (mx_el_lt, mx_inline_lt, S, M) \
151
SM_CMP_OP (mx_el_le, mx_inline_le, S, M) \
152
SM_CMP_OP (mx_el_ge, mx_inline_ge, S, M) \
153
SM_CMP_OP (mx_el_gt, mx_inline_gt, S, M) \
154
SM_CMP_OP (mx_el_eq, mx_inline_eq, S, M) \
155
SM_CMP_OP (mx_el_ne, mx_inline_ne, S, M)
156
157
#define SM_BOOL_OP(F, OP, S, M) \
158
boolMatrix \
159
F (const S& s, const M& m) \
160
{ \
161
SNANCHK (s); \
162
MNANCHK (m, M::element_type); \
163
return do_sm_binary_op<bool, S, M::element_type> (s, m, OP); \
164
}
165
166
#define SM_BOOL_OPS(S, M) \
167
SM_BOOL_OP (mx_el_and, mx_inline_and, S, M) \
168
SM_BOOL_OP (mx_el_or, mx_inline_or, S, M)
169
170
// matrix by matrix operations.
171
172
#define MM_BIN_OP(R, OP, M1, M2, F) \
173
R \
174
OP (const M1& m1, const M2& m2) \
175
{ \
176
return do_mm_binary_op<R::element_type, M1::element_type, M2::element_type> (m1, m2, F, F, F, #OP); \
177
}
178
179
#define MM_BIN_OPS(R, M1, M2) \
180
MM_BIN_OP (R, operator +, M1, M2, mx_inline_add) \
181
MM_BIN_OP (R, operator -, M1, M2, mx_inline_sub) \
182
MM_BIN_OP (R, product, M1, M2, mx_inline_mul) \
183
MM_BIN_OP (R, quotient, M1, M2, mx_inline_div)
184
185
#define MM_CMP_OP(F, OP, M1, M2) \
186
boolMatrix \
187
F (const M1& m1, const M2& m2) \
188
{ \
189
return do_mm_binary_op<bool, M1::element_type, M2::element_type> (m1, m2, OP, OP, OP, #F); \
190
}
191
192
#define MM_CMP_OPS(M1, M2) \
193
MM_CMP_OP (mx_el_lt, mx_inline_lt, M1, M2) \
194
MM_CMP_OP (mx_el_le, mx_inline_le, M1, M2) \
195
MM_CMP_OP (mx_el_ge, mx_inline_ge, M1, M2) \
196
MM_CMP_OP (mx_el_gt, mx_inline_gt, M1, M2) \
197
MM_CMP_OP (mx_el_eq, mx_inline_eq, M1, M2) \
198
MM_CMP_OP (mx_el_ne, mx_inline_ne, M1, M2)
199
200
#define MM_BOOL_OP(F, OP, M1, M2) \
201
boolMatrix \
202
F (const M1& m1, const M2& m2) \
203
{ \
204
MNANCHK (m1, M1::element_type); \
205
MNANCHK (m2, M2::element_type); \
206
return do_mm_binary_op<bool, M1::element_type, M2::element_type> (m1, m2, OP, OP, OP, #F); \
207
}
208
209
#define MM_BOOL_OPS(M1, M2) \
210
MM_BOOL_OP (mx_el_and, mx_inline_and, M1, M2) \
211
MM_BOOL_OP (mx_el_or, mx_inline_or, M1, M2)
212
213
// N-d matrix by scalar operations.
214
215
#define NDS_BIN_OP(R, OP, ND, S, F) \
216
R \
217
OP (const ND& m, const S& s) \
218
{ \
219
return do_ms_binary_op<R::element_type, ND::element_type, S> (m, s, F); \
220
}
221
222
#define NDS_BIN_OPS(R, ND, S) \
223
NDS_BIN_OP (R, operator +, ND, S, mx_inline_add) \
224
NDS_BIN_OP (R, operator -, ND, S, mx_inline_sub) \
225
NDS_BIN_OP (R, operator *, ND, S, mx_inline_mul) \
226
NDS_BIN_OP (R, operator /, ND, S, mx_inline_div)
227
228
#define NDS_CMP_OP(F, OP, ND, S) \
229
boolNDArray \
230
F (const ND& m, const S& s) \
231
{ \
232
return do_ms_binary_op<bool, ND::element_type, S> (m, s, OP); \
233
}
234
235
#define NDS_CMP_OPS(ND, S) \
236
NDS_CMP_OP (mx_el_lt, mx_inline_lt, ND, S) \
237
NDS_CMP_OP (mx_el_le, mx_inline_le, ND, S) \
238
NDS_CMP_OP (mx_el_ge, mx_inline_ge, ND, S) \
239
NDS_CMP_OP (mx_el_gt, mx_inline_gt, ND, S) \
240
NDS_CMP_OP (mx_el_eq, mx_inline_eq, ND, S) \
241
NDS_CMP_OP (mx_el_ne, mx_inline_ne, ND, S)
242
243
#define NDS_BOOL_OP(F, OP, ND, S) \
244
boolNDArray \
245
F (const ND& m, const S& s) \
246
{ \
247
MNANCHK (m, ND::element_type); \
248
SNANCHK (s); \
249
return do_ms_binary_op<bool, ND::element_type, S> (m, s, OP); \
250
}
251
252
#define NDS_BOOL_OPS(ND, S) \
253
NDS_BOOL_OP (mx_el_and, mx_inline_and, ND, S) \
254
NDS_BOOL_OP (mx_el_or, mx_inline_or, ND, S) \
255
NDS_BOOL_OP (mx_el_not_and, mx_inline_not_and, ND, S) \
256
NDS_BOOL_OP (mx_el_not_or, mx_inline_not_or, ND, S) \
257
NDS_BOOL_OP (mx_el_and_not, mx_inline_and_not, ND, S) \
258
NDS_BOOL_OP (mx_el_or_not, mx_inline_or_not, ND, S)
259
260
// scalar by N-d matrix operations.
261
262
#define SND_BIN_OP(R, OP, S, ND, F) \
263
R \
264
OP (const S& s, const ND& m) \
265
{ \
266
return do_sm_binary_op<R::element_type, S, ND::element_type> (s, m, F); \
267
}
268
269
#define SND_BIN_OPS(R, S, ND) \
270
SND_BIN_OP (R, operator +, S, ND, mx_inline_add) \
271
SND_BIN_OP (R, operator -, S, ND, mx_inline_sub) \
272
SND_BIN_OP (R, operator *, S, ND, mx_inline_mul) \
273
SND_BIN_OP (R, operator /, S, ND, mx_inline_div)
274
275
#define SND_CMP_OP(F, OP, S, ND) \
276
boolNDArray \
277
F (const S& s, const ND& m) \
278
{ \
279
return do_sm_binary_op<bool, S, ND::element_type> (s, m, OP); \
280
}
281
282
#define SND_CMP_OPS(S, ND) \
283
SND_CMP_OP (mx_el_lt, mx_inline_lt, S, ND) \
284
SND_CMP_OP (mx_el_le, mx_inline_le, S, ND) \
285
SND_CMP_OP (mx_el_ge, mx_inline_ge, S, ND) \
286
SND_CMP_OP (mx_el_gt, mx_inline_gt, S, ND) \
287
SND_CMP_OP (mx_el_eq, mx_inline_eq, S, ND) \
288
SND_CMP_OP (mx_el_ne, mx_inline_ne, S, ND)
289
290
#define SND_BOOL_OP(F, OP, S, ND) \
291
boolNDArray \
292
F (const S& s, const ND& m) \
293
{ \
294
SNANCHK (s); \
295
MNANCHK (m, ND::element_type); \
296
return do_sm_binary_op<bool, S, ND::element_type> (s, m, OP); \
297
}
298
299
#define SND_BOOL_OPS(S, ND) \
300
SND_BOOL_OP (mx_el_and, mx_inline_and, S, ND) \
301
SND_BOOL_OP (mx_el_or, mx_inline_or, S, ND) \
302
SND_BOOL_OP (mx_el_not_and, mx_inline_not_and, S, ND) \
303
SND_BOOL_OP (mx_el_not_or, mx_inline_not_or, S, ND) \
304
SND_BOOL_OP (mx_el_and_not, mx_inline_and_not, S, ND) \
305
SND_BOOL_OP (mx_el_or_not, mx_inline_or_not, S, ND)
306
307
// N-d matrix by N-d matrix operations.
308
309
#define NDND_BIN_OP(R, OP, ND1, ND2, F) \
310
R \
311
OP (const ND1& m1, const ND2& m2) \
312
{ \
313
return do_mm_binary_op<R::element_type, ND1::element_type, ND2::element_type> (m1, m2, F, F, F, #OP); \
314
}
315
316
#define NDND_BIN_OPS(R, ND1, ND2) \
317
NDND_BIN_OP (R, operator +, ND1, ND2, mx_inline_add) \
318
NDND_BIN_OP (R, operator -, ND1, ND2, mx_inline_sub) \
319
NDND_BIN_OP (R, product, ND1, ND2, mx_inline_mul) \
320
NDND_BIN_OP (R, quotient, ND1, ND2, mx_inline_div)
321
322
#define NDND_CMP_OP(F, OP, ND1, ND2) \
323
boolNDArray \
324
F (const ND1& m1, const ND2& m2) \
325
{ \
326
return do_mm_binary_op<bool, ND1::element_type, ND2::element_type> (m1, m2, OP, OP, OP, #F); \
327
}
328
329
#define NDND_CMP_OPS(ND1, ND2) \
330
NDND_CMP_OP (mx_el_lt, mx_inline_lt, ND1, ND2) \
331
NDND_CMP_OP (mx_el_le, mx_inline_le, ND1, ND2) \
332
NDND_CMP_OP (mx_el_ge, mx_inline_ge, ND1, ND2) \
333
NDND_CMP_OP (mx_el_gt, mx_inline_gt, ND1, ND2) \
334
NDND_CMP_OP (mx_el_eq, mx_inline_eq, ND1, ND2) \
335
NDND_CMP_OP (mx_el_ne, mx_inline_ne, ND1, ND2)
336
337
#define NDND_BOOL_OP(F, OP, ND1, ND2) \
338
boolNDArray \
339
F (const ND1& m1, const ND2& m2) \
340
{ \
341
MNANCHK (m1, ND1::element_type); \
342
MNANCHK (m2, ND2::element_type); \
343
return do_mm_binary_op<bool, ND1::element_type, ND2::element_type> (m1, m2, OP, OP, OP, #F); \
344
}
345
346
#define NDND_BOOL_OPS(ND1, ND2) \
347
NDND_BOOL_OP (mx_el_and, mx_inline_and, ND1, ND2) \
348
NDND_BOOL_OP (mx_el_or, mx_inline_or, ND1, ND2) \
349
NDND_BOOL_OP (mx_el_not_and, mx_inline_not_and, ND1, ND2) \
350
NDND_BOOL_OP (mx_el_not_or, mx_inline_not_or, ND1, ND2) \
351
NDND_BOOL_OP (mx_el_and_not, mx_inline_and_not, ND1, ND2) \
352
NDND_BOOL_OP (mx_el_or_not, mx_inline_or_not, ND1, ND2)
353
354
// scalar by diagonal matrix operations.
355
356
#define SDM_BIN_OP(R, OP, S, DM) \
357
R \
358
operator OP (const S& s, const DM& dm) \
359
{ \
360
R r (dm.rows (), dm.cols ()); \
361
\
362
for (octave_idx_type i = 0; i < dm.length (); i++) \
363
r.dgxelem (i) = s OP dm.dgelem (i); \
364
\
365
return r; \
366
}
367
368
#define SDM_BIN_OPS(R, S, DM) \
369
SDM_BIN_OP (R, *, S, DM)
370
371
// diagonal matrix by scalar operations.
372
373
#define DMS_BIN_OP(R, OP, DM, S) \
374
R \
375
operator OP (const DM& dm, const S& s) \
376
{ \
377
R r (dm.rows (), dm.cols ()); \
378
\
379
for (octave_idx_type i = 0; i < dm.length (); i++) \
380
r.dgxelem (i) = dm.dgelem (i) OP s; \
381
\
382
return r; \
383
}
384
385
#define DMS_BIN_OPS(R, DM, S) \
386
DMS_BIN_OP (R, *, DM, S) \
387
DMS_BIN_OP (R, /, DM, S)
388
389
// matrix by diagonal matrix operations.
390
391
#define MDM_BIN_OP(R, OP, M, DM, OPEQ) \
392
R \
393
OP (const M& m, const DM& dm) \
394
{ \
395
R r; \
396
\
397
octave_idx_type m_nr = m.rows (); \
398
octave_idx_type m_nc = m.cols (); \
399
\
400
octave_idx_type dm_nr = dm.rows (); \
401
octave_idx_type dm_nc = dm.cols (); \
402
\
403
if (m_nr != dm_nr || m_nc != dm_nc) \
404
gripe_nonconformant (#OP, m_nr, m_nc, dm_nr, dm_nc); \
405
else \
406
{ \
407
r.resize (m_nr, m_nc); \
408
\
409
if (m_nr > 0 && m_nc > 0) \
410
{ \
411
r = R (m); \
412
\
413
octave_idx_type len = dm.length (); \
414
\
415
for (octave_idx_type i = 0; i < len; i++) \
416
r.elem (i, i) OPEQ dm.elem (i, i); \
417
} \
418
} \
419
\
420
return r; \
421
}
422
423
#define MDM_MULTIPLY_OP(R, M, DM, R_ZERO) \
424
R \
425
operator * (const M& m, const DM& dm) \
426
{ \
427
R r; \
428
\
429
octave_idx_type m_nr = m.rows (); \
430
octave_idx_type m_nc = m.cols (); \
431
\
432
octave_idx_type dm_nr = dm.rows (); \
433
octave_idx_type dm_nc = dm.cols (); \
434
\
435
if (m_nc != dm_nr) \
436
gripe_nonconformant ("operator *", m_nr, m_nc, dm_nr, dm_nc); \
437
else \
438
{ \
439
r = R (m_nr, dm_nc); \
440
R::element_type *rd = r.fortran_vec (); \
441
const M::element_type *md = m.data (); \
442
const DM::element_type *dd = dm.data (); \
443
\
444
octave_idx_type len = dm.length (); \
445
for (octave_idx_type i = 0; i < len; i++) \
446
{ \
447
mx_inline_mul (m_nr, rd, md, dd[i]); \
448
rd += m_nr; md += m_nr; \
449
} \
450
mx_inline_fill (m_nr * (dm_nc - len), rd, R_ZERO); \
451
} \
452
\
453
return r; \
454
}
455
456
#define MDM_BIN_OPS(R, M, DM, R_ZERO) \
457
MDM_BIN_OP (R, operator +, M, DM, +=) \
458
MDM_BIN_OP (R, operator -, M, DM, -=) \
459
MDM_MULTIPLY_OP (R, M, DM, R_ZERO)
460
461
// diagonal matrix by matrix operations.
462
463
#define DMM_BIN_OP(R, OP, DM, M, OPEQ, PREOP) \
464
R \
465
OP (const DM& dm, const M& m) \
466
{ \
467
R r; \
468
\
469
octave_idx_type dm_nr = dm.rows (); \
470
octave_idx_type dm_nc = dm.cols (); \
471
\
472
octave_idx_type m_nr = m.rows (); \
473
octave_idx_type m_nc = m.cols (); \
474
\
475
if (dm_nr != m_nr || dm_nc != m_nc) \
476
gripe_nonconformant (#OP, dm_nr, dm_nc, m_nr, m_nc); \
477
else \
478
{ \
479
if (m_nr > 0 && m_nc > 0) \
480
{ \
481
r = R (PREOP m); \
482
\
483
octave_idx_type len = dm.length (); \
484
\
485
for (octave_idx_type i = 0; i < len; i++) \
486
r.elem (i, i) OPEQ dm.elem (i, i); \
487
} \
488
else \
489
r.resize (m_nr, m_nc); \
490
} \
491
\
492
return r; \
493
}
494
495
#define DMM_MULTIPLY_OP(R, DM, M, R_ZERO) \
496
R \
497
operator * (const DM& dm, const M& m) \
498
{ \
499
R r; \
500
\
501
octave_idx_type dm_nr = dm.rows (); \
502
octave_idx_type dm_nc = dm.cols (); \
503
\
504
octave_idx_type m_nr = m.rows (); \
505
octave_idx_type m_nc = m.cols (); \
506
\
507
if (dm_nc != m_nr) \
508
gripe_nonconformant ("operator *", dm_nr, dm_nc, m_nr, m_nc); \
509
else \
510
{ \
511
r = R (dm_nr, m_nc); \
512
R::element_type *rd = r.fortran_vec (); \
513
const M::element_type *md = m.data (); \
514
const DM::element_type *dd = dm.data (); \
515
\
516
octave_idx_type len = dm.length (); \
517
for (octave_idx_type i = 0; i < m_nc; i++) \
518
{ \
519
mx_inline_mul (len, rd, md, dd); \
520
rd += len; md += m_nr; \
521
mx_inline_fill (dm_nr - len, rd, R_ZERO); \
522
rd += dm_nr - len; \
523
} \
524
} \
525
\
526
return r; \
527
}
528
529
#define DMM_BIN_OPS(R, DM, M, R_ZERO) \
530
DMM_BIN_OP (R, operator +, DM, M, +=, ) \
531
DMM_BIN_OP (R, operator -, DM, M, +=, -) \
532
DMM_MULTIPLY_OP (R, DM, M, R_ZERO)
533
534
// diagonal matrix by diagonal matrix operations.
535
536
#define DMDM_BIN_OP(R, OP, DM1, DM2, F) \
537
R \
538
OP (const DM1& dm1, const DM2& dm2) \
539
{ \
540
R r; \
541
\
542
octave_idx_type dm1_nr = dm1.rows (); \
543
octave_idx_type dm1_nc = dm1.cols (); \
544
\
545
octave_idx_type dm2_nr = dm2.rows (); \
546
octave_idx_type dm2_nc = dm2.cols (); \
547
\
548
if (dm1_nr != dm2_nr || dm1_nc != dm2_nc) \
549
gripe_nonconformant (#OP, dm1_nr, dm1_nc, dm2_nr, dm2_nc); \
550
else \
551
{ \
552
r.resize (dm1_nr, dm1_nc); \
553
\
554
if (dm1_nr > 0 && dm1_nc > 0) \
555
F (dm1.length (), r.fortran_vec (), dm1.data (), dm2.data ()); \
556
} \
557
\
558
return r; \
559
}
560
561
#define DMDM_BIN_OPS(R, DM1, DM2) \
562
DMDM_BIN_OP (R, operator +, DM1, DM2, mx_inline_add) \
563
DMDM_BIN_OP (R, operator -, DM1, DM2, mx_inline_sub) \
564
DMDM_BIN_OP (R, product, DM1, DM2, mx_inline_mul)
565
566
// scalar by N-d array min/max ops
567
568
#define SND_MINMAX_FCN(FCN, OP, T, S) \
569
T \
570
FCN (S d, const T& m) \
571
{ \
572
return do_sm_binary_op<T::element_type, S, T::element_type> (d, m, mx_inline_x##FCN); \
573
}
574
575
#define NDS_MINMAX_FCN(FCN, OP, T, S) \
576
T \
577
FCN (const T& m, S d) \
578
{ \
579
return do_ms_binary_op<T::element_type, T::element_type, S> (m, d, mx_inline_x##FCN); \
580
}
581
582
#define NDND_MINMAX_FCN(FCN, OP, T, S) \
583
T \
584
FCN (const T& a, const T& b) \
585
{ \
586
return do_mm_binary_op<T::element_type, T::element_type, T::element_type> (a, b, mx_inline_x##FCN, mx_inline_x##FCN, mx_inline_x##FCN, #FCN); \
587
}
588
589
#define MINMAX_FCNS(T, S) \
590
SND_MINMAX_FCN (min, <, T, S) \
591
NDS_MINMAX_FCN (min, <, T, S) \
592
NDND_MINMAX_FCN (min, <, T, S) \
593
SND_MINMAX_FCN (max, >, T, S) \
594
NDS_MINMAX_FCN (max, >, T, S) \
595
NDND_MINMAX_FCN (max, >, T, S)
596
597
// permutation matrix by matrix ops and vice versa
598
599
#define PMM_MULTIPLY_OP(PM, M) \
600
M operator * (const PM& p, const M& x) \
601
{ \
602
octave_idx_type nr = x.rows (), nc = x.columns (); \
603
M result; \
604
if (p.columns () != nr) \
605
gripe_nonconformant ("operator *", p.rows (), p.columns (), nr, nc); \
606
else \
607
{ \
608
if (p.is_col_perm ()) \
609
{ \
610
result = M (nr, nc); \
611
result.assign (p.pvec (), idx_vector::colon, x); \
612
} \
613
else \
614
result = x.index (p.pvec (), idx_vector::colon); \
615
} \
616
\
617
return result; \
618
}
619
620
#define MPM_MULTIPLY_OP(M, PM) \
621
M operator * (const M& x, const PM& p) \
622
{ \
623
octave_idx_type nr = x.rows (), nc = x.columns (); \
624
M result; \
625
if (p.rows () != nc) \
626
gripe_nonconformant ("operator *", nr, nc, p.rows (), p.columns ()); \
627
else \
628
{ \
629
if (p.is_col_perm ()) \
630
result = x.index (idx_vector::colon, p.pvec ()); \
631
else \
632
{ \
633
result = M (nr, nc); \
634
result.assign (idx_vector::colon, p.pvec (), x); \
635
} \
636
} \
637
\
638
return result; \
639
}
640
641
#define PMM_BIN_OPS(R, PM, M) \
642
PMM_MULTIPLY_OP(PM, M);
643
644
#define MPM_BIN_OPS(R, M, PM) \
645
MPM_MULTIPLY_OP(M, PM);
646
647
#define NDND_MAPPER_BODY(R, NAME) \
648
R retval (dims ()); \
649
octave_idx_type n = numel (); \
650
for (octave_idx_type i = 0; i < n; i++) \
651
retval.xelem (i) = NAME (elem (i)); \
652
return retval;
653
654
#endif
Generated on Mon Dec 30 2013 03:04:52 for GNU Octave by
1.8.1.2