Skip to content
GitLab
Explore
Sign in
Hide whitespace changes
Inline
Side-by-side
Some changes are not shown.
For a faster browsing experience, only
7 of 167+
files are shown. Download one of the files below to see all changes.
external/eigen3/Eigen/src/Core/arch/ZVector/PacketMath.h
0 → 100755
View file @
a394b22a
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2016 Konstantinos Margaritis <markos@freevec.org>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_PACKET_MATH_ZVECTOR_H
#define EIGEN_PACKET_MATH_ZVECTOR_H
#include
<stdint.h>
namespace
Eigen
{
namespace
internal
{
#ifndef EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
#define EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD 4
#endif
#ifndef EIGEN_HAS_SINGLE_INSTRUCTION_MADD
#define EIGEN_HAS_SINGLE_INSTRUCTION_MADD
#endif
#ifndef EIGEN_HAS_SINGLE_INSTRUCTION_CJMADD
#define EIGEN_HAS_SINGLE_INSTRUCTION_CJMADD
#endif
#ifndef EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS
#define EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS 16
#endif
typedef
__vector
int
Packet4i
;
typedef
__vector
unsigned
int
Packet4ui
;
typedef
__vector
__bool
int
Packet4bi
;
typedef
__vector
short
int
Packet8i
;
typedef
__vector
unsigned
char
Packet16uc
;
typedef
__vector
double
Packet2d
;
typedef
__vector
unsigned
long
long
Packet2ul
;
typedef
__vector
long
long
Packet2l
;
typedef
struct
{
Packet2d
v4f
[
2
];
}
Packet4f
;
typedef
union
{
int32_t
i
[
4
];
uint32_t
ui
[
4
];
int64_t
l
[
2
];
uint64_t
ul
[
2
];
double
d
[
2
];
Packet4i
v4i
;
Packet4ui
v4ui
;
Packet2l
v2l
;
Packet2ul
v2ul
;
Packet2d
v2d
;
}
Packet
;
// We don't want to write the same code all the time, but we need to reuse the constants
// and it doesn't really work to declare them global, so we define macros instead
#define _EIGEN_DECLARE_CONST_FAST_Packet4i(NAME,X) \
Packet4i p4i_##NAME = reinterpret_cast<Packet4i>(vec_splat_s32(X))
#define _EIGEN_DECLARE_CONST_FAST_Packet2d(NAME,X) \
Packet2d p2d_##NAME = reinterpret_cast<Packet2d>(vec_splat_s64(X))
#define _EIGEN_DECLARE_CONST_FAST_Packet2l(NAME,X) \
Packet2l p2l_##NAME = reinterpret_cast<Packet2l>(vec_splat_s64(X))
#define _EIGEN_DECLARE_CONST_Packet4i(NAME,X) \
Packet4i p4i_##NAME = pset1<Packet4i>(X)
#define _EIGEN_DECLARE_CONST_Packet2d(NAME,X) \
Packet2d p2d_##NAME = pset1<Packet2d>(X)
#define _EIGEN_DECLARE_CONST_Packet2l(NAME,X) \
Packet2l p2l_##NAME = pset1<Packet2l>(X)
// These constants are endian-agnostic
//static _EIGEN_DECLARE_CONST_FAST_Packet4i(ZERO, 0); //{ 0, 0, 0, 0,}
static
_EIGEN_DECLARE_CONST_FAST_Packet4i
(
ONE
,
1
);
//{ 1, 1, 1, 1}
static
_EIGEN_DECLARE_CONST_FAST_Packet2d
(
ZERO
,
0
);
static
_EIGEN_DECLARE_CONST_FAST_Packet2l
(
ZERO
,
0
);
static
_EIGEN_DECLARE_CONST_FAST_Packet2l
(
ONE
,
1
);
static
Packet2d
p2d_ONE
=
{
1.0
,
1.0
};
static
Packet2d
p2d_ZERO_
=
{
-
0.0
,
-
0.0
};
static
Packet4i
p4i_COUNTDOWN
=
{
0
,
1
,
2
,
3
};
static
Packet4f
p4f_COUNTDOWN
=
{
0.0
,
1.0
,
2.0
,
3.0
};
static
Packet2d
p2d_COUNTDOWN
=
reinterpret_cast
<
Packet2d
>
(
vec_sld
(
reinterpret_cast
<
Packet16uc
>
(
p2d_ZERO
),
reinterpret_cast
<
Packet16uc
>
(
p2d_ONE
),
8
));
static
Packet16uc
p16uc_PSET64_HI
=
{
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
};
static
Packet16uc
p16uc_DUPLICATE32_HI
=
{
0
,
1
,
2
,
3
,
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
4
,
5
,
6
,
7
};
// Mask alignment
#define _EIGEN_MASK_ALIGNMENT 0xfffffffffffffff0
#define _EIGEN_ALIGNED_PTR(x) ((std::ptrdiff_t)(x) & _EIGEN_MASK_ALIGNMENT)
// Handle endianness properly while loading constants
// Define global static constants:
static
Packet16uc
p16uc_FORWARD
=
{
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
,
11
,
12
,
13
,
14
,
15
};
static
Packet16uc
p16uc_REVERSE32
=
{
12
,
13
,
14
,
15
,
8
,
9
,
10
,
11
,
4
,
5
,
6
,
7
,
0
,
1
,
2
,
3
};
static
Packet16uc
p16uc_REVERSE64
=
{
8
,
9
,
10
,
11
,
12
,
13
,
14
,
15
,
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
};
static
Packet16uc
p16uc_PSET32_WODD
=
vec_sld
((
Packet16uc
)
vec_splat
((
Packet4ui
)
p16uc_FORWARD
,
0
),
(
Packet16uc
)
vec_splat
((
Packet4ui
)
p16uc_FORWARD
,
2
),
8
);
//{ 0,1,2,3, 0,1,2,3, 8,9,10,11, 8,9,10,11 };
static
Packet16uc
p16uc_PSET32_WEVEN
=
vec_sld
(
p16uc_DUPLICATE32_HI
,
(
Packet16uc
)
vec_splat
((
Packet4ui
)
p16uc_FORWARD
,
3
),
8
);
//{ 4,5,6,7, 4,5,6,7, 12,13,14,15, 12,13,14,15 };
/*static Packet16uc p16uc_HALF64_0_16 = vec_sld((Packet16uc)p4i_ZERO, vec_splat((Packet16uc) vec_abs(p4i_MINUS16), 3), 8); //{ 0,0,0,0, 0,0,0,0, 16,16,16,16, 16,16,16,16};
static Packet16uc p16uc_PSET64_HI = (Packet16uc) vec_mergeh((Packet4ui)p16uc_PSET32_WODD, (Packet4ui)p16uc_PSET32_WEVEN); //{ 0,1,2,3, 4,5,6,7, 0,1,2,3, 4,5,6,7 };*/
static
Packet16uc
p16uc_PSET64_LO
=
(
Packet16uc
)
vec_mergel
((
Packet4ui
)
p16uc_PSET32_WODD
,
(
Packet4ui
)
p16uc_PSET32_WEVEN
);
//{ 8,9,10,11, 12,13,14,15, 8,9,10,11, 12,13,14,15 };
/*static Packet16uc p16uc_TRANSPOSE64_HI = vec_add(p16uc_PSET64_HI, p16uc_HALF64_0_16); //{ 0,1,2,3, 4,5,6,7, 16,17,18,19, 20,21,22,23};
static Packet16uc p16uc_TRANSPOSE64_LO = vec_add(p16uc_PSET64_LO, p16uc_HALF64_0_16); //{ 8,9,10,11, 12,13,14,15, 24,25,26,27, 28,29,30,31};*/
static
Packet16uc
p16uc_TRANSPOSE64_HI
=
{
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
16
,
17
,
18
,
19
,
20
,
21
,
22
,
23
};
static
Packet16uc
p16uc_TRANSPOSE64_LO
=
{
8
,
9
,
10
,
11
,
12
,
13
,
14
,
15
,
24
,
25
,
26
,
27
,
28
,
29
,
30
,
31
};
//static Packet16uc p16uc_COMPLEX32_REV = vec_sld(p16uc_REVERSE32, p16uc_REVERSE32, 8); //{ 4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11 };
//static Packet16uc p16uc_COMPLEX32_REV2 = vec_sld(p16uc_FORWARD, p16uc_FORWARD, 8); //{ 8,9,10,11, 12,13,14,15, 0,1,2,3, 4,5,6,7 };
#if EIGEN_HAS_BUILTIN(__builtin_prefetch) || EIGEN_COMP_GNUC
#define EIGEN_ZVECTOR_PREFETCH(ADDR) __builtin_prefetch(ADDR);
#else
#define EIGEN_ZVECTOR_PREFETCH(ADDR) asm( " pfd [%[addr]]\n" :: [addr] "r" (ADDR) : "cc" );
#endif
template
<
>
struct
packet_traits
<
int
>
:
default_packet_traits
{
typedef
Packet4i
type
;
typedef
Packet4i
half
;
enum
{
Vectorizable
=
1
,
AlignedOnScalar
=
1
,
size
=
4
,
HasHalfPacket
=
0
,
HasAdd
=
1
,
HasSub
=
1
,
HasMul
=
1
,
HasDiv
=
1
,
HasBlend
=
1
};
};
template
<
>
struct
packet_traits
<
float
>
:
default_packet_traits
{
typedef
Packet4f
type
;
typedef
Packet4f
half
;
enum
{
Vectorizable
=
1
,
AlignedOnScalar
=
1
,
size
=
4
,
HasHalfPacket
=
0
,
HasAdd
=
1
,
HasSub
=
1
,
HasMul
=
1
,
HasDiv
=
1
,
HasMin
=
1
,
HasMax
=
1
,
HasAbs
=
1
,
HasSin
=
0
,
HasCos
=
0
,
HasLog
=
0
,
HasExp
=
1
,
HasSqrt
=
1
,
HasRsqrt
=
1
,
HasRound
=
1
,
HasFloor
=
1
,
HasCeil
=
1
,
HasNegate
=
1
,
HasBlend
=
1
};
};
template
<
>
struct
packet_traits
<
double
>
:
default_packet_traits
{
typedef
Packet2d
type
;
typedef
Packet2d
half
;
enum
{
Vectorizable
=
1
,
AlignedOnScalar
=
1
,
size
=
2
,
HasHalfPacket
=
1
,
HasAdd
=
1
,
HasSub
=
1
,
HasMul
=
1
,
HasDiv
=
1
,
HasMin
=
1
,
HasMax
=
1
,
HasAbs
=
1
,
HasSin
=
0
,
HasCos
=
0
,
HasLog
=
0
,
HasExp
=
1
,
HasSqrt
=
1
,
HasRsqrt
=
1
,
HasRound
=
1
,
HasFloor
=
1
,
HasCeil
=
1
,
HasNegate
=
1
,
HasBlend
=
1
};
};
template
<
>
struct
unpacket_traits
<
Packet4i
>
{
typedef
int
type
;
enum
{
size
=
4
,
alignment
=
Aligned16
};
typedef
Packet4i
half
;
};
template
<
>
struct
unpacket_traits
<
Packet4f
>
{
typedef
float
type
;
enum
{
size
=
4
,
alignment
=
Aligned16
};
typedef
Packet4f
half
;
};
template
<
>
struct
unpacket_traits
<
Packet2d
>
{
typedef
double
type
;
enum
{
size
=
2
,
alignment
=
Aligned16
};
typedef
Packet2d
half
;
};
/* Forward declaration */
EIGEN_DEVICE_FUNC
inline
void
ptranspose
(
PacketBlock
<
Packet4f
,
4
>&
kernel
);
inline
std
::
ostream
&
operator
<<
(
std
::
ostream
&
s
,
const
Packet4i
&
v
)
{
Packet
vt
;
vt
.
v4i
=
v
;
s
<<
vt
.
i
[
0
]
<<
", "
<<
vt
.
i
[
1
]
<<
", "
<<
vt
.
i
[
2
]
<<
", "
<<
vt
.
i
[
3
];
return
s
;
}
inline
std
::
ostream
&
operator
<<
(
std
::
ostream
&
s
,
const
Packet4ui
&
v
)
{
Packet
vt
;
vt
.
v4ui
=
v
;
s
<<
vt
.
ui
[
0
]
<<
", "
<<
vt
.
ui
[
1
]
<<
", "
<<
vt
.
ui
[
2
]
<<
", "
<<
vt
.
ui
[
3
];
return
s
;
}
inline
std
::
ostream
&
operator
<<
(
std
::
ostream
&
s
,
const
Packet2l
&
v
)
{
Packet
vt
;
vt
.
v2l
=
v
;
s
<<
vt
.
l
[
0
]
<<
", "
<<
vt
.
l
[
1
];
return
s
;
}
inline
std
::
ostream
&
operator
<<
(
std
::
ostream
&
s
,
const
Packet2ul
&
v
)
{
Packet
vt
;
vt
.
v2ul
=
v
;
s
<<
vt
.
ul
[
0
]
<<
", "
<<
vt
.
ul
[
1
]
;
return
s
;
}
inline
std
::
ostream
&
operator
<<
(
std
::
ostream
&
s
,
const
Packet2d
&
v
)
{
Packet
vt
;
vt
.
v2d
=
v
;
s
<<
vt
.
d
[
0
]
<<
", "
<<
vt
.
d
[
1
];
return
s
;
}
/* Helper function to simulate a vec_splat_packet4f
*/
template
<
int
element
>
EIGEN_STRONG_INLINE
Packet4f
vec_splat_packet4f
(
const
Packet4f
&
from
)
{
Packet4f
splat
;
switch
(
element
)
{
case
0
:
splat
.
v4f
[
0
]
=
vec_splat
(
from
.
v4f
[
0
],
0
);
splat
.
v4f
[
1
]
=
splat
.
v4f
[
0
];
break
;
case
1
:
splat
.
v4f
[
0
]
=
vec_splat
(
from
.
v4f
[
0
],
1
);
splat
.
v4f
[
1
]
=
splat
.
v4f
[
0
];
break
;
case
2
:
splat
.
v4f
[
0
]
=
vec_splat
(
from
.
v4f
[
1
],
0
);
splat
.
v4f
[
1
]
=
splat
.
v4f
[
0
];
break
;
case
3
:
splat
.
v4f
[
0
]
=
vec_splat
(
from
.
v4f
[
1
],
1
);
splat
.
v4f
[
1
]
=
splat
.
v4f
[
0
];
break
;
}
return
splat
;
}
template
<
int
Offset
>
struct
palign_impl
<
Offset
,
Packet4i
>
{
static
EIGEN_STRONG_INLINE
void
run
(
Packet4i
&
first
,
const
Packet4i
&
second
)
{
switch
(
Offset
%
4
)
{
case
1
:
first
=
vec_sld
(
first
,
second
,
4
);
break
;
case
2
:
first
=
vec_sld
(
first
,
second
,
8
);
break
;
case
3
:
first
=
vec_sld
(
first
,
second
,
12
);
break
;
}
}
};
/* This is a tricky one, we have to translate float alignment to vector elements of sizeof double
*/
template
<
int
Offset
>
struct
palign_impl
<
Offset
,
Packet4f
>
{
static
EIGEN_STRONG_INLINE
void
run
(
Packet4f
&
first
,
const
Packet4f
&
second
)
{
switch
(
Offset
%
4
)
{
case
1
:
first
.
v4f
[
0
]
=
vec_sld
(
first
.
v4f
[
0
],
first
.
v4f
[
1
],
8
);
first
.
v4f
[
1
]
=
vec_sld
(
first
.
v4f
[
1
],
second
.
v4f
[
0
],
8
);
break
;
case
2
:
first
.
v4f
[
0
]
=
first
.
v4f
[
1
];
first
.
v4f
[
1
]
=
second
.
v4f
[
0
];
break
;
case
3
:
first
.
v4f
[
0
]
=
vec_sld
(
first
.
v4f
[
1
],
second
.
v4f
[
0
],
8
);
first
.
v4f
[
1
]
=
vec_sld
(
second
.
v4f
[
0
],
second
.
v4f
[
1
],
8
);
break
;
}
}
};
template
<
int
Offset
>
struct
palign_impl
<
Offset
,
Packet2d
>
{
static
EIGEN_STRONG_INLINE
void
run
(
Packet2d
&
first
,
const
Packet2d
&
second
)
{
if
(
Offset
==
1
)
first
=
reinterpret_cast
<
Packet2d
>
(
vec_sld
(
reinterpret_cast
<
Packet4i
>
(
first
),
reinterpret_cast
<
Packet4i
>
(
second
),
8
));
}
};
template
<
>
EIGEN_STRONG_INLINE
Packet4i
pload
<
Packet4i
>
(
const
int
*
from
)
{
// FIXME: No intrinsic yet
EIGEN_DEBUG_ALIGNED_LOAD
Packet
*
vfrom
;
vfrom
=
(
Packet
*
)
from
;
return
vfrom
->
v4i
;
}
template
<
>
EIGEN_STRONG_INLINE
Packet4f
pload
<
Packet4f
>
(
const
float
*
from
)
{
// FIXME: No intrinsic yet
EIGEN_DEBUG_ALIGNED_LOAD
Packet4f
vfrom
;
vfrom
.
v4f
[
0
]
=
vec_ld2f
(
&
from
[
0
]);
vfrom
.
v4f
[
1
]
=
vec_ld2f
(
&
from
[
2
]);
return
vfrom
;
}
template
<
>
EIGEN_STRONG_INLINE
Packet2d
pload
<
Packet2d
>
(
const
double
*
from
)
{
// FIXME: No intrinsic yet
EIGEN_DEBUG_ALIGNED_LOAD
Packet
*
vfrom
;
vfrom
=
(
Packet
*
)
from
;
return
vfrom
->
v2d
;
}
template
<
>
EIGEN_STRONG_INLINE
void
pstore
<
int
>
(
int
*
to
,
const
Packet4i
&
from
)
{
// FIXME: No intrinsic yet
EIGEN_DEBUG_ALIGNED_STORE
Packet
*
vto
;
vto
=
(
Packet
*
)
to
;
vto
->
v4i
=
from
;
}
template
<
>
EIGEN_STRONG_INLINE
void
pstore
<
float
>
(
float
*
to
,
const
Packet4f
&
from
)
{
// FIXME: No intrinsic yet
EIGEN_DEBUG_ALIGNED_STORE
vec_st2f
(
from
.
v4f
[
0
],
&
to
[
0
]);
vec_st2f
(
from
.
v4f
[
1
],
&
to
[
2
]);
}
template
<
>
EIGEN_STRONG_INLINE
void
pstore
<
double
>
(
double
*
to
,
const
Packet2d
&
from
)
{
// FIXME: No intrinsic yet
EIGEN_DEBUG_ALIGNED_STORE
Packet
*
vto
;
vto
=
(
Packet
*
)
to
;
vto
->
v2d
=
from
;
}
template
<
>
EIGEN_STRONG_INLINE
Packet4i
pset1
<
Packet4i
>
(
const
int
&
from
)
{
return
vec_splats
(
from
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet2d
pset1
<
Packet2d
>
(
const
double
&
from
)
{
return
vec_splats
(
from
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet4f
pset1
<
Packet4f
>
(
const
float
&
from
)
{
Packet4f
to
;
to
.
v4f
[
0
]
=
pset1
<
Packet2d
>
(
static_cast
<
const
double
&>
(
from
));
to
.
v4f
[
1
]
=
to
.
v4f
[
0
];
return
to
;
}
template
<
>
EIGEN_STRONG_INLINE
void
pbroadcast4
<
Packet4i
>
(
const
int
*
a
,
Packet4i
&
a0
,
Packet4i
&
a1
,
Packet4i
&
a2
,
Packet4i
&
a3
)
{
a3
=
pload
<
Packet4i
>
(
a
);
a0
=
vec_splat
(
a3
,
0
);
a1
=
vec_splat
(
a3
,
1
);
a2
=
vec_splat
(
a3
,
2
);
a3
=
vec_splat
(
a3
,
3
);
}
template
<
>
EIGEN_STRONG_INLINE
void
pbroadcast4
<
Packet4f
>
(
const
float
*
a
,
Packet4f
&
a0
,
Packet4f
&
a1
,
Packet4f
&
a2
,
Packet4f
&
a3
)
{
a3
=
pload
<
Packet4f
>
(
a
);
a0
=
vec_splat_packet4f
<
0
>
(
a3
);
a1
=
vec_splat_packet4f
<
1
>
(
a3
);
a2
=
vec_splat_packet4f
<
2
>
(
a3
);
a3
=
vec_splat_packet4f
<
3
>
(
a3
);
}
template
<
>
EIGEN_STRONG_INLINE
void
pbroadcast4
<
Packet2d
>
(
const
double
*
a
,
Packet2d
&
a0
,
Packet2d
&
a1
,
Packet2d
&
a2
,
Packet2d
&
a3
)
{
a1
=
pload
<
Packet2d
>
(
a
);
a0
=
vec_splat
(
a1
,
0
);
a1
=
vec_splat
(
a1
,
1
);
a3
=
pload
<
Packet2d
>
(
a
+
2
);
a2
=
vec_splat
(
a3
,
0
);
a3
=
vec_splat
(
a3
,
1
);
}
template
<
>
EIGEN_DEVICE_FUNC
inline
Packet4i
pgather
<
int
,
Packet4i
>
(
const
int
*
from
,
Index
stride
)
{
int
EIGEN_ALIGN16
ai
[
4
];
ai
[
0
]
=
from
[
0
*
stride
];
ai
[
1
]
=
from
[
1
*
stride
];
ai
[
2
]
=
from
[
2
*
stride
];
ai
[
3
]
=
from
[
3
*
stride
];
return
pload
<
Packet4i
>
(
ai
);
}
template
<
>
EIGEN_DEVICE_FUNC
inline
Packet4f
pgather
<
float
,
Packet4f
>
(
const
float
*
from
,
Index
stride
)
{
float
EIGEN_ALIGN16
ai
[
4
];
ai
[
0
]
=
from
[
0
*
stride
];
ai
[
1
]
=
from
[
1
*
stride
];
ai
[
2
]
=
from
[
2
*
stride
];
ai
[
3
]
=
from
[
3
*
stride
];
return
pload
<
Packet4f
>
(
ai
);
}
template
<
>
EIGEN_DEVICE_FUNC
inline
Packet2d
pgather
<
double
,
Packet2d
>
(
const
double
*
from
,
Index
stride
)
{
double
EIGEN_ALIGN16
af
[
2
];
af
[
0
]
=
from
[
0
*
stride
];
af
[
1
]
=
from
[
1
*
stride
];
return
pload
<
Packet2d
>
(
af
);
}
template
<
>
EIGEN_DEVICE_FUNC
inline
void
pscatter
<
int
,
Packet4i
>
(
int
*
to
,
const
Packet4i
&
from
,
Index
stride
)
{
int
EIGEN_ALIGN16
ai
[
4
];
pstore
<
int
>
((
int
*
)
ai
,
from
);
to
[
0
*
stride
]
=
ai
[
0
];
to
[
1
*
stride
]
=
ai
[
1
];
to
[
2
*
stride
]
=
ai
[
2
];
to
[
3
*
stride
]
=
ai
[
3
];
}
template
<
>
EIGEN_DEVICE_FUNC
inline
void
pscatter
<
float
,
Packet4f
>
(
float
*
to
,
const
Packet4f
&
from
,
Index
stride
)
{
float
EIGEN_ALIGN16
ai
[
4
];
pstore
<
float
>
((
float
*
)
ai
,
from
);
to
[
0
*
stride
]
=
ai
[
0
];
to
[
1
*
stride
]
=
ai
[
1
];
to
[
2
*
stride
]
=
ai
[
2
];
to
[
3
*
stride
]
=
ai
[
3
];
}
template
<
>
EIGEN_DEVICE_FUNC
inline
void
pscatter
<
double
,
Packet2d
>
(
double
*
to
,
const
Packet2d
&
from
,
Index
stride
)
{
double
EIGEN_ALIGN16
af
[
2
];
pstore
<
double
>
(
af
,
from
);
to
[
0
*
stride
]
=
af
[
0
];
to
[
1
*
stride
]
=
af
[
1
];
}
template
<
>
EIGEN_STRONG_INLINE
Packet4i
padd
<
Packet4i
>
(
const
Packet4i
&
a
,
const
Packet4i
&
b
)
{
return
(
a
+
b
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet4f
padd
<
Packet4f
>
(
const
Packet4f
&
a
,
const
Packet4f
&
b
)
{
Packet4f
c
;
c
.
v4f
[
0
]
=
a
.
v4f
[
0
]
+
b
.
v4f
[
0
];
c
.
v4f
[
1
]
=
a
.
v4f
[
1
]
+
b
.
v4f
[
1
];
return
c
;
}
template
<
>
EIGEN_STRONG_INLINE
Packet2d
padd
<
Packet2d
>
(
const
Packet2d
&
a
,
const
Packet2d
&
b
)
{
return
(
a
+
b
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet4i
psub
<
Packet4i
>
(
const
Packet4i
&
a
,
const
Packet4i
&
b
)
{
return
(
a
-
b
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet4f
psub
<
Packet4f
>
(
const
Packet4f
&
a
,
const
Packet4f
&
b
)
{
Packet4f
c
;
c
.
v4f
[
0
]
=
a
.
v4f
[
0
]
-
b
.
v4f
[
0
];
c
.
v4f
[
1
]
=
a
.
v4f
[
1
]
-
b
.
v4f
[
1
];
return
c
;
}
template
<
>
EIGEN_STRONG_INLINE
Packet2d
psub
<
Packet2d
>
(
const
Packet2d
&
a
,
const
Packet2d
&
b
)
{
return
(
a
-
b
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet4i
pmul
<
Packet4i
>
(
const
Packet4i
&
a
,
const
Packet4i
&
b
)
{
return
(
a
*
b
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet4f
pmul
<
Packet4f
>
(
const
Packet4f
&
a
,
const
Packet4f
&
b
)
{
Packet4f
c
;
c
.
v4f
[
0
]
=
a
.
v4f
[
0
]
*
b
.
v4f
[
0
];
c
.
v4f
[
1
]
=
a
.
v4f
[
1
]
*
b
.
v4f
[
1
];
return
c
;
}
template
<
>
EIGEN_STRONG_INLINE
Packet2d
pmul
<
Packet2d
>
(
const
Packet2d
&
a
,
const
Packet2d
&
b
)
{
return
(
a
*
b
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet4i
pdiv
<
Packet4i
>
(
const
Packet4i
&
a
,
const
Packet4i
&
b
)
{
return
(
a
/
b
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet4f
pdiv
<
Packet4f
>
(
const
Packet4f
&
a
,
const
Packet4f
&
b
)
{
Packet4f
c
;
c
.
v4f
[
0
]
=
a
.
v4f
[
0
]
/
b
.
v4f
[
0
];
c
.
v4f
[
1
]
=
a
.
v4f
[
1
]
/
b
.
v4f
[
1
];
return
c
;
}
template
<
>
EIGEN_STRONG_INLINE
Packet2d
pdiv
<
Packet2d
>
(
const
Packet2d
&
a
,
const
Packet2d
&
b
)
{
return
(
a
/
b
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet4i
pnegate
(
const
Packet4i
&
a
)
{
return
(
-
a
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet4f
pnegate
(
const
Packet4f
&
a
)
{
Packet4f
c
;
c
.
v4f
[
0
]
=
-
a
.
v4f
[
0
];
c
.
v4f
[
1
]
=
-
a
.
v4f
[
1
];
return
c
;
}
template
<
>
EIGEN_STRONG_INLINE
Packet2d
pnegate
(
const
Packet2d
&
a
)
{
return
(
-
a
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet4i
pconj
(
const
Packet4i
&
a
)
{
return
a
;
}
template
<
>
EIGEN_STRONG_INLINE
Packet4f
pconj
(
const
Packet4f
&
a
)
{
return
a
;
}
template
<
>
EIGEN_STRONG_INLINE
Packet2d
pconj
(
const
Packet2d
&
a
)
{
return
a
;
}
template
<
>
EIGEN_STRONG_INLINE
Packet4i
pmadd
(
const
Packet4i
&
a
,
const
Packet4i
&
b
,
const
Packet4i
&
c
)
{
return
padd
<
Packet4i
>
(
pmul
<
Packet4i
>
(
a
,
b
),
c
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet4f
pmadd
(
const
Packet4f
&
a
,
const
Packet4f
&
b
,
const
Packet4f
&
c
)
{
Packet4f
res
;
res
.
v4f
[
0
]
=
vec_madd
(
a
.
v4f
[
0
],
b
.
v4f
[
0
],
c
.
v4f
[
0
]);
res
.
v4f
[
1
]
=
vec_madd
(
a
.
v4f
[
1
],
b
.
v4f
[
1
],
c
.
v4f
[
1
]);
return
res
;
}
template
<
>
EIGEN_STRONG_INLINE
Packet2d
pmadd
(
const
Packet2d
&
a
,
const
Packet2d
&
b
,
const
Packet2d
&
c
)
{
return
vec_madd
(
a
,
b
,
c
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet4i
plset
<
Packet4i
>
(
const
int
&
a
)
{
return
padd
<
Packet4i
>
(
pset1
<
Packet4i
>
(
a
),
p4i_COUNTDOWN
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet4f
plset
<
Packet4f
>
(
const
float
&
a
)
{
return
padd
<
Packet4f
>
(
pset1
<
Packet4f
>
(
a
),
p4f_COUNTDOWN
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet2d
plset
<
Packet2d
>
(
const
double
&
a
)
{
return
padd
<
Packet2d
>
(
pset1
<
Packet2d
>
(
a
),
p2d_COUNTDOWN
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet4i
pmin
<
Packet4i
>
(
const
Packet4i
&
a
,
const
Packet4i
&
b
)
{
return
vec_min
(
a
,
b
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet2d
pmin
<
Packet2d
>
(
const
Packet2d
&
a
,
const
Packet2d
&
b
)
{
return
vec_min
(
a
,
b
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet4f
pmin
<
Packet4f
>
(
const
Packet4f
&
a
,
const
Packet4f
&
b
)
{
Packet4f
res
;
res
.
v4f
[
0
]
=
pmin
(
a
.
v4f
[
0
],
b
.
v4f
[
0
]);
res
.
v4f
[
1
]
=
pmin
(
a
.
v4f
[
1
],
b
.
v4f
[
1
]);
return
res
;
}
template
<
>
EIGEN_STRONG_INLINE
Packet4i
pmax
<
Packet4i
>
(
const
Packet4i
&
a
,
const
Packet4i
&
b
)
{
return
vec_max
(
a
,
b
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet2d
pmax
<
Packet2d
>
(
const
Packet2d
&
a
,
const
Packet2d
&
b
)
{
return
vec_max
(
a
,
b
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet4f
pmax
<
Packet4f
>
(
const
Packet4f
&
a
,
const
Packet4f
&
b
)
{
Packet4f
res
;
res
.
v4f
[
0
]
=
pmax
(
a
.
v4f
[
0
],
b
.
v4f
[
0
]);
res
.
v4f
[
1
]
=
pmax
(
a
.
v4f
[
1
],
b
.
v4f
[
1
]);
return
res
;
}
template
<
>
EIGEN_STRONG_INLINE
Packet4i
pand
<
Packet4i
>
(
const
Packet4i
&
a
,
const
Packet4i
&
b
)
{
return
vec_and
(
a
,
b
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet2d
pand
<
Packet2d
>
(
const
Packet2d
&
a
,
const
Packet2d
&
b
)
{
return
vec_and
(
a
,
b
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet4f
pand
<
Packet4f
>
(
const
Packet4f
&
a
,
const
Packet4f
&
b
)
{
Packet4f
res
;
res
.
v4f
[
0
]
=
pand
(
a
.
v4f
[
0
],
b
.
v4f
[
0
]);
res
.
v4f
[
1
]
=
pand
(
a
.
v4f
[
1
],
b
.
v4f
[
1
]);
return
res
;
}
template
<
>
EIGEN_STRONG_INLINE
Packet4i
por
<
Packet4i
>
(
const
Packet4i
&
a
,
const
Packet4i
&
b
)
{
return
vec_or
(
a
,
b
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet2d
por
<
Packet2d
>
(
const
Packet2d
&
a
,
const
Packet2d
&
b
)
{
return
vec_or
(
a
,
b
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet4f
por
<
Packet4f
>
(
const
Packet4f
&
a
,
const
Packet4f
&
b
)
{
Packet4f
res
;
res
.
v4f
[
0
]
=
pand
(
a
.
v4f
[
0
],
b
.
v4f
[
0
]);
res
.
v4f
[
1
]
=
pand
(
a
.
v4f
[
1
],
b
.
v4f
[
1
]);
return
res
;
}
template
<
>
EIGEN_STRONG_INLINE
Packet4i
pxor
<
Packet4i
>
(
const
Packet4i
&
a
,
const
Packet4i
&
b
)
{
return
vec_xor
(
a
,
b
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet2d
pxor
<
Packet2d
>
(
const
Packet2d
&
a
,
const
Packet2d
&
b
)
{
return
vec_xor
(
a
,
b
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet4f
pxor
<
Packet4f
>
(
const
Packet4f
&
a
,
const
Packet4f
&
b
)
{
Packet4f
res
;
res
.
v4f
[
0
]
=
pand
(
a
.
v4f
[
0
],
b
.
v4f
[
0
]);
res
.
v4f
[
1
]
=
pand
(
a
.
v4f
[
1
],
b
.
v4f
[
1
]);
return
res
;
}
template
<
>
EIGEN_STRONG_INLINE
Packet4i
pandnot
<
Packet4i
>
(
const
Packet4i
&
a
,
const
Packet4i
&
b
)
{
return
pand
<
Packet4i
>
(
a
,
vec_nor
(
b
,
b
));
}
template
<
>
EIGEN_STRONG_INLINE
Packet2d
pandnot
<
Packet2d
>
(
const
Packet2d
&
a
,
const
Packet2d
&
b
)
{
return
vec_and
(
a
,
vec_nor
(
b
,
b
));
}
template
<
>
EIGEN_STRONG_INLINE
Packet4f
pandnot
<
Packet4f
>
(
const
Packet4f
&
a
,
const
Packet4f
&
b
)
{
Packet4f
res
;
res
.
v4f
[
0
]
=
pandnot
(
a
.
v4f
[
0
],
b
.
v4f
[
0
]);
res
.
v4f
[
1
]
=
pandnot
(
a
.
v4f
[
1
],
b
.
v4f
[
1
]);
return
res
;
}
template
<
>
EIGEN_STRONG_INLINE
Packet4f
pround
<
Packet4f
>
(
const
Packet4f
&
a
)
{
Packet4f
res
;
res
.
v4f
[
0
]
=
vec_round
(
a
.
v4f
[
0
]);
res
.
v4f
[
1
]
=
vec_round
(
a
.
v4f
[
1
]);
return
res
;
}
template
<
>
EIGEN_STRONG_INLINE
Packet2d
pround
<
Packet2d
>
(
const
Packet2d
&
a
)
{
return
vec_round
(
a
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet4f
pceil
<
Packet4f
>
(
const
Packet4f
&
a
)
{
Packet4f
res
;
res
.
v4f
[
0
]
=
vec_ceil
(
a
.
v4f
[
0
]);
res
.
v4f
[
1
]
=
vec_ceil
(
a
.
v4f
[
1
]);
return
res
;
}
template
<
>
EIGEN_STRONG_INLINE
Packet2d
pceil
<
Packet2d
>
(
const
Packet2d
&
a
)
{
return
vec_ceil
(
a
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet4f
pfloor
<
Packet4f
>
(
const
Packet4f
&
a
)
{
Packet4f
res
;
res
.
v4f
[
0
]
=
vec_floor
(
a
.
v4f
[
0
]);
res
.
v4f
[
1
]
=
vec_floor
(
a
.
v4f
[
1
]);
return
res
;
}
template
<
>
EIGEN_STRONG_INLINE
Packet2d
pfloor
<
Packet2d
>
(
const
Packet2d
&
a
)
{
return
vec_floor
(
a
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet4i
ploadu
<
Packet4i
>
(
const
int
*
from
)
{
return
pload
<
Packet4i
>
(
from
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet4f
ploadu
<
Packet4f
>
(
const
float
*
from
)
{
return
pload
<
Packet4f
>
(
from
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet2d
ploadu
<
Packet2d
>
(
const
double
*
from
)
{
return
pload
<
Packet2d
>
(
from
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet4i
ploaddup
<
Packet4i
>
(
const
int
*
from
)
{
Packet4i
p
=
pload
<
Packet4i
>
(
from
);
return
vec_perm
(
p
,
p
,
p16uc_DUPLICATE32_HI
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet4f
ploaddup
<
Packet4f
>
(
const
float
*
from
)
{
Packet4f
p
=
pload
<
Packet4f
>
(
from
);
p
.
v4f
[
1
]
=
vec_splat
(
p
.
v4f
[
0
],
1
);
p
.
v4f
[
0
]
=
vec_splat
(
p
.
v4f
[
0
],
0
);
return
p
;
}
template
<
>
EIGEN_STRONG_INLINE
Packet2d
ploaddup
<
Packet2d
>
(
const
double
*
from
)
{
Packet2d
p
=
pload
<
Packet2d
>
(
from
);
return
vec_perm
(
p
,
p
,
p16uc_PSET64_HI
);
}
template
<
>
EIGEN_STRONG_INLINE
void
pstoreu
<
int
>
(
int
*
to
,
const
Packet4i
&
from
)
{
pstore
<
int
>
(
to
,
from
);
}
template
<
>
EIGEN_STRONG_INLINE
void
pstoreu
<
float
>
(
float
*
to
,
const
Packet4f
&
from
)
{
pstore
<
float
>
(
to
,
from
);
}
template
<
>
EIGEN_STRONG_INLINE
void
pstoreu
<
double
>
(
double
*
to
,
const
Packet2d
&
from
)
{
pstore
<
double
>
(
to
,
from
);
}
template
<
>
EIGEN_STRONG_INLINE
void
prefetch
<
int
>
(
const
int
*
addr
)
{
EIGEN_ZVECTOR_PREFETCH
(
addr
);
}
template
<
>
EIGEN_STRONG_INLINE
void
prefetch
<
float
>
(
const
float
*
addr
)
{
EIGEN_ZVECTOR_PREFETCH
(
addr
);
}
template
<
>
EIGEN_STRONG_INLINE
void
prefetch
<
double
>
(
const
double
*
addr
)
{
EIGEN_ZVECTOR_PREFETCH
(
addr
);
}
template
<
>
EIGEN_STRONG_INLINE
int
pfirst
<
Packet4i
>
(
const
Packet4i
&
a
)
{
int
EIGEN_ALIGN16
x
[
4
];
pstore
(
x
,
a
);
return
x
[
0
];
}
template
<
>
EIGEN_STRONG_INLINE
float
pfirst
<
Packet4f
>
(
const
Packet4f
&
a
)
{
float
EIGEN_ALIGN16
x
[
2
];
vec_st2f
(
a
.
v4f
[
0
],
&
x
[
0
]);
return
x
[
0
];
}
template
<
>
EIGEN_STRONG_INLINE
double
pfirst
<
Packet2d
>
(
const
Packet2d
&
a
)
{
double
EIGEN_ALIGN16
x
[
2
];
pstore
(
x
,
a
);
return
x
[
0
];
}
template
<
>
EIGEN_STRONG_INLINE
Packet4i
preverse
(
const
Packet4i
&
a
)
{
return
reinterpret_cast
<
Packet4i
>
(
vec_perm
(
reinterpret_cast
<
Packet16uc
>
(
a
),
reinterpret_cast
<
Packet16uc
>
(
a
),
p16uc_REVERSE32
));
}
template
<
>
EIGEN_STRONG_INLINE
Packet2d
preverse
(
const
Packet2d
&
a
)
{
return
reinterpret_cast
<
Packet2d
>
(
vec_perm
(
reinterpret_cast
<
Packet16uc
>
(
a
),
reinterpret_cast
<
Packet16uc
>
(
a
),
p16uc_REVERSE64
));
}
template
<
>
EIGEN_STRONG_INLINE
Packet4f
preverse
(
const
Packet4f
&
a
)
{
Packet4f
rev
;
rev
.
v4f
[
0
]
=
preverse
<
Packet2d
>
(
a
.
v4f
[
1
]);
rev
.
v4f
[
1
]
=
preverse
<
Packet2d
>
(
a
.
v4f
[
0
]);
return
rev
;
}
template
<
>
EIGEN_STRONG_INLINE
Packet4i
pabs
<
Packet4i
>
(
const
Packet4i
&
a
)
{
return
vec_abs
(
a
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet2d
pabs
<
Packet2d
>
(
const
Packet2d
&
a
)
{
return
vec_abs
(
a
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet4f
pabs
<
Packet4f
>
(
const
Packet4f
&
a
)
{
Packet4f
res
;
res
.
v4f
[
0
]
=
pabs
(
a
.
v4f
[
0
]);
res
.
v4f
[
1
]
=
pabs
(
a
.
v4f
[
1
]);
return
res
;
}
template
<
>
EIGEN_STRONG_INLINE
int
predux
<
Packet4i
>
(
const
Packet4i
&
a
)
{
Packet4i
b
,
sum
;
b
=
vec_sld
(
a
,
a
,
8
);
sum
=
padd
<
Packet4i
>
(
a
,
b
);
b
=
vec_sld
(
sum
,
sum
,
4
);
sum
=
padd
<
Packet4i
>
(
sum
,
b
);
return
pfirst
(
sum
);
}
template
<
>
EIGEN_STRONG_INLINE
double
predux
<
Packet2d
>
(
const
Packet2d
&
a
)
{
Packet2d
b
,
sum
;
b
=
reinterpret_cast
<
Packet2d
>
(
vec_sld
(
reinterpret_cast
<
Packet4i
>
(
a
),
reinterpret_cast
<
Packet4i
>
(
a
),
8
));
sum
=
padd
<
Packet2d
>
(
a
,
b
);
return
pfirst
(
sum
);
}
template
<
>
EIGEN_STRONG_INLINE
float
predux
<
Packet4f
>
(
const
Packet4f
&
a
)
{
Packet2d
sum
;
sum
=
padd
<
Packet2d
>
(
a
.
v4f
[
0
],
a
.
v4f
[
1
]);
double
first
=
predux
<
Packet2d
>
(
sum
);
return
static_cast
<
float
>
(
first
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet4i
preduxp
<
Packet4i
>
(
const
Packet4i
*
vecs
)
{
Packet4i
v
[
4
],
sum
[
4
];
// It's easier and faster to transpose then add as columns
// Check: http://www.freevec.org/function/matrix_4x4_transpose_floats for explanation
// Do the transpose, first set of moves
v
[
0
]
=
vec_mergeh
(
vecs
[
0
],
vecs
[
2
]);
v
[
1
]
=
vec_mergel
(
vecs
[
0
],
vecs
[
2
]);
v
[
2
]
=
vec_mergeh
(
vecs
[
1
],
vecs
[
3
]);
v
[
3
]
=
vec_mergel
(
vecs
[
1
],
vecs
[
3
]);
// Get the resulting vectors
sum
[
0
]
=
vec_mergeh
(
v
[
0
],
v
[
2
]);
sum
[
1
]
=
vec_mergel
(
v
[
0
],
v
[
2
]);
sum
[
2
]
=
vec_mergeh
(
v
[
1
],
v
[
3
]);
sum
[
3
]
=
vec_mergel
(
v
[
1
],
v
[
3
]);
// Now do the summation:
// Lines 0+1
sum
[
0
]
=
padd
<
Packet4i
>
(
sum
[
0
],
sum
[
1
]);
// Lines 2+3
sum
[
1
]
=
padd
<
Packet4i
>
(
sum
[
2
],
sum
[
3
]);
// Add the results
sum
[
0
]
=
padd
<
Packet4i
>
(
sum
[
0
],
sum
[
1
]);
return
sum
[
0
];
}
template
<
>
EIGEN_STRONG_INLINE
Packet2d
preduxp
<
Packet2d
>
(
const
Packet2d
*
vecs
)
{
Packet2d
v
[
2
],
sum
;
v
[
0
]
=
padd
<
Packet2d
>
(
vecs
[
0
],
reinterpret_cast
<
Packet2d
>
(
vec_sld
(
reinterpret_cast
<
Packet4ui
>
(
vecs
[
0
]),
reinterpret_cast
<
Packet4ui
>
(
vecs
[
0
]),
8
)));
v
[
1
]
=
padd
<
Packet2d
>
(
vecs
[
1
],
reinterpret_cast
<
Packet2d
>
(
vec_sld
(
reinterpret_cast
<
Packet4ui
>
(
vecs
[
1
]),
reinterpret_cast
<
Packet4ui
>
(
vecs
[
1
]),
8
)));
sum
=
reinterpret_cast
<
Packet2d
>
(
vec_sld
(
reinterpret_cast
<
Packet4ui
>
(
v
[
0
]),
reinterpret_cast
<
Packet4ui
>
(
v
[
1
]),
8
));
return
sum
;
}
template
<
>
EIGEN_STRONG_INLINE
Packet4f
preduxp
<
Packet4f
>
(
const
Packet4f
*
vecs
)
{
PacketBlock
<
Packet4f
,
4
>
transpose
;
transpose
.
packet
[
0
]
=
vecs
[
0
];
transpose
.
packet
[
1
]
=
vecs
[
1
];
transpose
.
packet
[
2
]
=
vecs
[
2
];
transpose
.
packet
[
3
]
=
vecs
[
3
];
ptranspose
(
transpose
);
Packet4f
sum
=
padd
(
transpose
.
packet
[
0
],
transpose
.
packet
[
1
]);
sum
=
padd
(
sum
,
transpose
.
packet
[
2
]);
sum
=
padd
(
sum
,
transpose
.
packet
[
3
]);
return
sum
;
}
// Other reduction functions:
// mul
template
<
>
EIGEN_STRONG_INLINE
int
predux_mul
<
Packet4i
>
(
const
Packet4i
&
a
)
{
EIGEN_ALIGN16
int
aux
[
4
];
pstore
(
aux
,
a
);
return
aux
[
0
]
*
aux
[
1
]
*
aux
[
2
]
*
aux
[
3
];
}
template
<
>
EIGEN_STRONG_INLINE
double
predux_mul
<
Packet2d
>
(
const
Packet2d
&
a
)
{
return
pfirst
(
pmul
(
a
,
reinterpret_cast
<
Packet2d
>
(
vec_sld
(
reinterpret_cast
<
Packet4i
>
(
a
),
reinterpret_cast
<
Packet4i
>
(
a
),
8
))));
}
template
<
>
EIGEN_STRONG_INLINE
float
predux_mul
<
Packet4f
>
(
const
Packet4f
&
a
)
{
// Return predux_mul<Packet2d> of the subvectors product
return
static_cast
<
float
>
(
pfirst
(
predux_mul
(
pmul
(
a
.
v4f
[
0
],
a
.
v4f
[
1
]))));
}
// min
template
<
>
EIGEN_STRONG_INLINE
int
predux_min
<
Packet4i
>
(
const
Packet4i
&
a
)
{
Packet4i
b
,
res
;
b
=
pmin
<
Packet4i
>
(
a
,
vec_sld
(
a
,
a
,
8
));
res
=
pmin
<
Packet4i
>
(
b
,
vec_sld
(
b
,
b
,
4
));
return
pfirst
(
res
);
}
template
<
>
EIGEN_STRONG_INLINE
double
predux_min
<
Packet2d
>
(
const
Packet2d
&
a
)
{
return
pfirst
(
pmin
<
Packet2d
>
(
a
,
reinterpret_cast
<
Packet2d
>
(
vec_sld
(
reinterpret_cast
<
Packet4i
>
(
a
),
reinterpret_cast
<
Packet4i
>
(
a
),
8
))));
}
template
<
>
EIGEN_STRONG_INLINE
float
predux_min
<
Packet4f
>
(
const
Packet4f
&
a
)
{
Packet2d
b
,
res
;
b
=
pmin
<
Packet2d
>
(
a
.
v4f
[
0
],
a
.
v4f
[
1
]);
res
=
pmin
<
Packet2d
>
(
b
,
reinterpret_cast
<
Packet2d
>
(
vec_sld
(
reinterpret_cast
<
Packet4i
>
(
b
),
reinterpret_cast
<
Packet4i
>
(
b
),
8
)));
return
static_cast
<
float
>
(
pfirst
(
res
));
}
// max
template
<
>
EIGEN_STRONG_INLINE
int
predux_max
<
Packet4i
>
(
const
Packet4i
&
a
)
{
Packet4i
b
,
res
;
b
=
pmax
<
Packet4i
>
(
a
,
vec_sld
(
a
,
a
,
8
));
res
=
pmax
<
Packet4i
>
(
b
,
vec_sld
(
b
,
b
,
4
));
return
pfirst
(
res
);
}
// max
template
<
>
EIGEN_STRONG_INLINE
double
predux_max
<
Packet2d
>
(
const
Packet2d
&
a
)
{
return
pfirst
(
pmax
<
Packet2d
>
(
a
,
reinterpret_cast
<
Packet2d
>
(
vec_sld
(
reinterpret_cast
<
Packet4i
>
(
a
),
reinterpret_cast
<
Packet4i
>
(
a
),
8
))));
}
template
<
>
EIGEN_STRONG_INLINE
float
predux_max
<
Packet4f
>
(
const
Packet4f
&
a
)
{
Packet2d
b
,
res
;
b
=
pmax
<
Packet2d
>
(
a
.
v4f
[
0
],
a
.
v4f
[
1
]);
res
=
pmax
<
Packet2d
>
(
b
,
reinterpret_cast
<
Packet2d
>
(
vec_sld
(
reinterpret_cast
<
Packet4i
>
(
b
),
reinterpret_cast
<
Packet4i
>
(
b
),
8
)));
return
static_cast
<
float
>
(
pfirst
(
res
));
}
EIGEN_DEVICE_FUNC
inline
void
ptranspose
(
PacketBlock
<
Packet4i
,
4
>&
kernel
)
{
Packet4i
t0
=
vec_mergeh
(
kernel
.
packet
[
0
],
kernel
.
packet
[
2
]);
Packet4i
t1
=
vec_mergel
(
kernel
.
packet
[
0
],
kernel
.
packet
[
2
]);
Packet4i
t2
=
vec_mergeh
(
kernel
.
packet
[
1
],
kernel
.
packet
[
3
]);
Packet4i
t3
=
vec_mergel
(
kernel
.
packet
[
1
],
kernel
.
packet
[
3
]);
kernel
.
packet
[
0
]
=
vec_mergeh
(
t0
,
t2
);
kernel
.
packet
[
1
]
=
vec_mergel
(
t0
,
t2
);
kernel
.
packet
[
2
]
=
vec_mergeh
(
t1
,
t3
);
kernel
.
packet
[
3
]
=
vec_mergel
(
t1
,
t3
);
}
EIGEN_DEVICE_FUNC
inline
void
ptranspose
(
PacketBlock
<
Packet2d
,
2
>&
kernel
)
{
Packet2d
t0
=
vec_perm
(
kernel
.
packet
[
0
],
kernel
.
packet
[
1
],
p16uc_TRANSPOSE64_HI
);
Packet2d
t1
=
vec_perm
(
kernel
.
packet
[
0
],
kernel
.
packet
[
1
],
p16uc_TRANSPOSE64_LO
);
kernel
.
packet
[
0
]
=
t0
;
kernel
.
packet
[
1
]
=
t1
;
}
/* Split the Packet4f PacketBlock into 4 Packet2d PacketBlocks and transpose each one
*/
EIGEN_DEVICE_FUNC
inline
void
ptranspose
(
PacketBlock
<
Packet4f
,
4
>&
kernel
)
{
PacketBlock
<
Packet2d
,
2
>
t0
,
t1
,
t2
,
t3
;
// copy top-left 2x2 Packet2d block
t0
.
packet
[
0
]
=
kernel
.
packet
[
0
].
v4f
[
0
];
t0
.
packet
[
1
]
=
kernel
.
packet
[
1
].
v4f
[
0
];
// copy top-right 2x2 Packet2d block
t1
.
packet
[
0
]
=
kernel
.
packet
[
0
].
v4f
[
1
];
t1
.
packet
[
1
]
=
kernel
.
packet
[
1
].
v4f
[
1
];
// copy bottom-left 2x2 Packet2d block
t2
.
packet
[
0
]
=
kernel
.
packet
[
2
].
v4f
[
0
];
t2
.
packet
[
1
]
=
kernel
.
packet
[
3
].
v4f
[
0
];
// copy bottom-right 2x2 Packet2d block
t3
.
packet
[
0
]
=
kernel
.
packet
[
2
].
v4f
[
1
];
t3
.
packet
[
1
]
=
kernel
.
packet
[
3
].
v4f
[
1
];
// Transpose all 2x2 blocks
ptranspose
(
t0
);
ptranspose
(
t1
);
ptranspose
(
t2
);
ptranspose
(
t3
);
// Copy back transposed blocks, but exchange t1 and t2 due to transposition
kernel
.
packet
[
0
].
v4f
[
0
]
=
t0
.
packet
[
0
];
kernel
.
packet
[
0
].
v4f
[
1
]
=
t2
.
packet
[
0
];
kernel
.
packet
[
1
].
v4f
[
0
]
=
t0
.
packet
[
1
];
kernel
.
packet
[
1
].
v4f
[
1
]
=
t2
.
packet
[
1
];
kernel
.
packet
[
2
].
v4f
[
0
]
=
t1
.
packet
[
0
];
kernel
.
packet
[
2
].
v4f
[
1
]
=
t3
.
packet
[
0
];
kernel
.
packet
[
3
].
v4f
[
0
]
=
t1
.
packet
[
1
];
kernel
.
packet
[
3
].
v4f
[
1
]
=
t3
.
packet
[
1
];
}
template
<
>
EIGEN_STRONG_INLINE
Packet4i
pblend
(
const
Selector
<
4
>&
ifPacket
,
const
Packet4i
&
thenPacket
,
const
Packet4i
&
elsePacket
)
{
Packet4ui
select
=
{
ifPacket
.
select
[
0
],
ifPacket
.
select
[
1
],
ifPacket
.
select
[
2
],
ifPacket
.
select
[
3
]
};
Packet4ui
mask
=
vec_cmpeq
(
select
,
reinterpret_cast
<
Packet4ui
>
(
p4i_ONE
));
return
vec_sel
(
elsePacket
,
thenPacket
,
mask
);
}
template
<
>
EIGEN_STRONG_INLINE
Packet4f
pblend
(
const
Selector
<
4
>&
ifPacket
,
const
Packet4f
&
thenPacket
,
const
Packet4f
&
elsePacket
)
{
Packet2ul
select_hi
=
{
ifPacket
.
select
[
0
],
ifPacket
.
select
[
1
]
};
Packet2ul
select_lo
=
{
ifPacket
.
select
[
2
],
ifPacket
.
select
[
3
]
};
Packet2ul
mask_hi
=
vec_cmpeq
(
select_hi
,
reinterpret_cast
<
Packet2ul
>
(
p2l_ONE
));
Packet2ul
mask_lo
=
vec_cmpeq
(
select_lo
,
reinterpret_cast
<
Packet2ul
>
(
p2l_ONE
));
Packet4f
result
;
result
.
v4f
[
0
]
=
vec_sel
(
elsePacket
.
v4f
[
0
],
thenPacket
.
v4f
[
0
],
mask_hi
);
result
.
v4f
[
1
]
=
vec_sel
(
elsePacket
.
v4f
[
1
],
thenPacket
.
v4f
[
1
],
mask_lo
);
return
result
;
}
template
<
>
EIGEN_STRONG_INLINE
Packet2d
pblend
(
const
Selector
<
2
>&
ifPacket
,
const
Packet2d
&
thenPacket
,
const
Packet2d
&
elsePacket
)
{
Packet2ul
select
=
{
ifPacket
.
select
[
0
],
ifPacket
.
select
[
1
]
};
Packet2ul
mask
=
vec_cmpeq
(
select
,
reinterpret_cast
<
Packet2ul
>
(
p2l_ONE
));
return
vec_sel
(
elsePacket
,
thenPacket
,
mask
);
}
}
// end namespace internal
}
// end namespace Eigen
#endif // EIGEN_PACKET_MATH_ZVECTOR_H
external/eigen3/Eigen/src/Core/functors/AssignmentFunctors.h
0 → 100644
View file @
a394b22a
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_ASSIGNMENT_FUNCTORS_H
#define EIGEN_ASSIGNMENT_FUNCTORS_H
namespace
Eigen
{
namespace
internal
{
/** \internal
* \brief Template functor for scalar/packet assignment
*
*/
template
<
typename
DstScalar
,
typename
SrcScalar
>
struct
assign_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
assign_op
)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
void
assignCoeff
(
DstScalar
&
a
,
const
SrcScalar
&
b
)
const
{
a
=
b
;
}
template
<
int
Alignment
,
typename
Packet
>
EIGEN_STRONG_INLINE
void
assignPacket
(
DstScalar
*
a
,
const
Packet
&
b
)
const
{
internal
::
pstoret
<
DstScalar
,
Packet
,
Alignment
>
(
a
,
b
);
}
};
// Empty overload for void type (used by PermutationMatrix)
template
<
typename
DstScalar
>
struct
assign_op
<
DstScalar
,
void
>
{};
template
<
typename
DstScalar
,
typename
SrcScalar
>
struct
functor_traits
<
assign_op
<
DstScalar
,
SrcScalar
>
>
{
enum
{
Cost
=
NumTraits
<
DstScalar
>::
ReadCost
,
PacketAccess
=
is_same
<
DstScalar
,
SrcScalar
>::
value
&&
packet_traits
<
DstScalar
>::
Vectorizable
&&
packet_traits
<
SrcScalar
>::
Vectorizable
};
};
/** \internal
* \brief Template functor for scalar/packet assignment with addition
*
*/
template
<
typename
DstScalar
,
typename
SrcScalar
>
struct
add_assign_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
add_assign_op
)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
void
assignCoeff
(
DstScalar
&
a
,
const
SrcScalar
&
b
)
const
{
a
+=
b
;
}
template
<
int
Alignment
,
typename
Packet
>
EIGEN_STRONG_INLINE
void
assignPacket
(
DstScalar
*
a
,
const
Packet
&
b
)
const
{
internal
::
pstoret
<
DstScalar
,
Packet
,
Alignment
>
(
a
,
internal
::
padd
(
internal
::
ploadt
<
Packet
,
Alignment
>
(
a
),
b
));
}
};
template
<
typename
DstScalar
,
typename
SrcScalar
>
struct
functor_traits
<
add_assign_op
<
DstScalar
,
SrcScalar
>
>
{
enum
{
Cost
=
NumTraits
<
DstScalar
>::
ReadCost
+
NumTraits
<
DstScalar
>::
AddCost
,
PacketAccess
=
is_same
<
DstScalar
,
SrcScalar
>::
value
&&
packet_traits
<
DstScalar
>::
HasAdd
};
};
/** \internal
* \brief Template functor for scalar/packet assignment with subtraction
*
*/
template
<
typename
DstScalar
,
typename
SrcScalar
>
struct
sub_assign_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
sub_assign_op
)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
void
assignCoeff
(
DstScalar
&
a
,
const
SrcScalar
&
b
)
const
{
a
-=
b
;
}
template
<
int
Alignment
,
typename
Packet
>
EIGEN_STRONG_INLINE
void
assignPacket
(
DstScalar
*
a
,
const
Packet
&
b
)
const
{
internal
::
pstoret
<
DstScalar
,
Packet
,
Alignment
>
(
a
,
internal
::
psub
(
internal
::
ploadt
<
Packet
,
Alignment
>
(
a
),
b
));
}
};
template
<
typename
DstScalar
,
typename
SrcScalar
>
struct
functor_traits
<
sub_assign_op
<
DstScalar
,
SrcScalar
>
>
{
enum
{
Cost
=
NumTraits
<
DstScalar
>::
ReadCost
+
NumTraits
<
DstScalar
>::
AddCost
,
PacketAccess
=
is_same
<
DstScalar
,
SrcScalar
>::
value
&&
packet_traits
<
DstScalar
>::
HasSub
};
};
/** \internal
* \brief Template functor for scalar/packet assignment with multiplication
*
*/
template
<
typename
DstScalar
,
typename
SrcScalar
=
DstScalar
>
struct
mul_assign_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
mul_assign_op
)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
void
assignCoeff
(
DstScalar
&
a
,
const
SrcScalar
&
b
)
const
{
a
*=
b
;
}
template
<
int
Alignment
,
typename
Packet
>
EIGEN_STRONG_INLINE
void
assignPacket
(
DstScalar
*
a
,
const
Packet
&
b
)
const
{
internal
::
pstoret
<
DstScalar
,
Packet
,
Alignment
>
(
a
,
internal
::
pmul
(
internal
::
ploadt
<
Packet
,
Alignment
>
(
a
),
b
));
}
};
template
<
typename
DstScalar
,
typename
SrcScalar
>
struct
functor_traits
<
mul_assign_op
<
DstScalar
,
SrcScalar
>
>
{
enum
{
Cost
=
NumTraits
<
DstScalar
>::
ReadCost
+
NumTraits
<
DstScalar
>::
MulCost
,
PacketAccess
=
is_same
<
DstScalar
,
SrcScalar
>::
value
&&
packet_traits
<
DstScalar
>::
HasMul
};
};
/** \internal
* \brief Template functor for scalar/packet assignment with diviving
*
*/
template
<
typename
DstScalar
,
typename
SrcScalar
=
DstScalar
>
struct
div_assign_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
div_assign_op
)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
void
assignCoeff
(
DstScalar
&
a
,
const
SrcScalar
&
b
)
const
{
a
/=
b
;
}
template
<
int
Alignment
,
typename
Packet
>
EIGEN_STRONG_INLINE
void
assignPacket
(
DstScalar
*
a
,
const
Packet
&
b
)
const
{
internal
::
pstoret
<
DstScalar
,
Packet
,
Alignment
>
(
a
,
internal
::
pdiv
(
internal
::
ploadt
<
Packet
,
Alignment
>
(
a
),
b
));
}
};
template
<
typename
DstScalar
,
typename
SrcScalar
>
struct
functor_traits
<
div_assign_op
<
DstScalar
,
SrcScalar
>
>
{
enum
{
Cost
=
NumTraits
<
DstScalar
>::
ReadCost
+
NumTraits
<
DstScalar
>::
MulCost
,
PacketAccess
=
is_same
<
DstScalar
,
SrcScalar
>::
value
&&
packet_traits
<
DstScalar
>::
HasDiv
};
};
/** \internal
* \brief Template functor for scalar/packet assignment with swapping
*
* It works as follow. For a non-vectorized evaluation loop, we have:
* for(i) func(A.coeffRef(i), B.coeff(i));
* where B is a SwapWrapper expression. The trick is to make SwapWrapper::coeff behaves like a non-const coeffRef.
* Actually, SwapWrapper might not even be needed since even if B is a plain expression, since it has to be writable
* B.coeff already returns a const reference to the underlying scalar value.
*
* The case of a vectorized loop is more tricky:
* for(i,j) func.assignPacket<A_Align>(&A.coeffRef(i,j), B.packet<B_Align>(i,j));
* Here, B must be a SwapWrapper whose packet function actually returns a proxy object holding a Scalar*,
* the actual alignment and Packet type.
*
*/
template
<
typename
Scalar
>
struct
swap_assign_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
swap_assign_op
)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
void
assignCoeff
(
Scalar
&
a
,
const
Scalar
&
b
)
const
{
#ifdef __CUDACC__
// FIXME is there some kind of cuda::swap?
Scalar
t
=
b
;
const_cast
<
Scalar
&>
(
b
)
=
a
;
a
=
t
;
#else
using
std
::
swap
;
swap
(
a
,
const_cast
<
Scalar
&>
(
b
));
#endif
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
swap_assign_op
<
Scalar
>
>
{
enum
{
Cost
=
3
*
NumTraits
<
Scalar
>::
ReadCost
,
PacketAccess
=
packet_traits
<
Scalar
>::
Vectorizable
};
};
}
// namespace internal
}
// namespace Eigen
#endif // EIGEN_ASSIGNMENT_FUNCTORS_H
external/eigen3/Eigen/src/Core/functors/BinaryFunctors.h
0 → 100644
View file @
a394b22a
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_BINARY_FUNCTORS_H
#define EIGEN_BINARY_FUNCTORS_H
namespace
Eigen
{
namespace
internal
{
//---------- associative binary functors ----------
template
<
typename
Arg1
,
typename
Arg2
>
struct
binary_op_base
{
typedef
Arg1
first_argument_type
;
typedef
Arg2
second_argument_type
;
};
/** \internal
* \brief Template functor to compute the sum of two scalars
*
* \sa class CwiseBinaryOp, MatrixBase::operator+, class VectorwiseOp, DenseBase::sum()
*/
template
<
typename
LhsScalar
,
typename
RhsScalar
>
struct
scalar_sum_op
:
binary_op_base
<
LhsScalar
,
RhsScalar
>
{
typedef
typename
ScalarBinaryOpTraits
<
LhsScalar
,
RhsScalar
,
scalar_sum_op
>::
ReturnType
result_type
;
#ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_sum_op
)
#else
scalar_sum_op
()
{
EIGEN_SCALAR_BINARY_OP_PLUGIN
}
#endif
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
result_type
operator
()
(
const
LhsScalar
&
a
,
const
RhsScalar
&
b
)
const
{
return
a
+
b
;
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
Packet
packetOp
(
const
Packet
&
a
,
const
Packet
&
b
)
const
{
return
internal
::
padd
(
a
,
b
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
result_type
predux
(
const
Packet
&
a
)
const
{
return
internal
::
predux
(
a
);
}
};
template
<
typename
LhsScalar
,
typename
RhsScalar
>
struct
functor_traits
<
scalar_sum_op
<
LhsScalar
,
RhsScalar
>
>
{
enum
{
Cost
=
(
NumTraits
<
LhsScalar
>::
AddCost
+
NumTraits
<
RhsScalar
>::
AddCost
)
/
2
,
// rough estimate!
PacketAccess
=
is_same
<
LhsScalar
,
RhsScalar
>::
value
&&
packet_traits
<
LhsScalar
>::
HasAdd
&&
packet_traits
<
RhsScalar
>::
HasAdd
// TODO vectorize mixed sum
};
};
/** \internal
* \brief Template specialization to deprecate the summation of boolean expressions.
* This is required to solve Bug 426.
* \sa DenseBase::count(), DenseBase::any(), ArrayBase::cast(), MatrixBase::cast()
*/
template
<
>
struct
scalar_sum_op
<
bool
,
bool
>
:
scalar_sum_op
<
int
,
int
>
{
EIGEN_DEPRECATED
scalar_sum_op
()
{}
};
/** \internal
* \brief Template functor to compute the product of two scalars
*
* \sa class CwiseBinaryOp, Cwise::operator*(), class VectorwiseOp, MatrixBase::redux()
*/
template
<
typename
LhsScalar
,
typename
RhsScalar
>
struct
scalar_product_op
:
binary_op_base
<
LhsScalar
,
RhsScalar
>
{
typedef
typename
ScalarBinaryOpTraits
<
LhsScalar
,
RhsScalar
,
scalar_product_op
>::
ReturnType
result_type
;
#ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_product_op
)
#else
scalar_product_op
()
{
EIGEN_SCALAR_BINARY_OP_PLUGIN
}
#endif
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
result_type
operator
()
(
const
LhsScalar
&
a
,
const
RhsScalar
&
b
)
const
{
return
a
*
b
;
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
Packet
packetOp
(
const
Packet
&
a
,
const
Packet
&
b
)
const
{
return
internal
::
pmul
(
a
,
b
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
result_type
predux
(
const
Packet
&
a
)
const
{
return
internal
::
predux_mul
(
a
);
}
};
template
<
typename
LhsScalar
,
typename
RhsScalar
>
struct
functor_traits
<
scalar_product_op
<
LhsScalar
,
RhsScalar
>
>
{
enum
{
Cost
=
(
NumTraits
<
LhsScalar
>::
MulCost
+
NumTraits
<
RhsScalar
>::
MulCost
)
/
2
,
// rough estimate!
PacketAccess
=
is_same
<
LhsScalar
,
RhsScalar
>::
value
&&
packet_traits
<
LhsScalar
>::
HasMul
&&
packet_traits
<
RhsScalar
>::
HasMul
// TODO vectorize mixed product
};
};
/** \internal
* \brief Template functor to compute the conjugate product of two scalars
*
* This is a short cut for conj(x) * y which is needed for optimization purpose; in Eigen2 support mode, this becomes x * conj(y)
*/
template
<
typename
LhsScalar
,
typename
RhsScalar
>
struct
scalar_conj_product_op
:
binary_op_base
<
LhsScalar
,
RhsScalar
>
{
enum
{
Conj
=
NumTraits
<
LhsScalar
>::
IsComplex
};
typedef
typename
ScalarBinaryOpTraits
<
LhsScalar
,
RhsScalar
,
scalar_conj_product_op
>::
ReturnType
result_type
;
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_conj_product_op
)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
result_type
operator
()
(
const
LhsScalar
&
a
,
const
RhsScalar
&
b
)
const
{
return
conj_helper
<
LhsScalar
,
RhsScalar
,
Conj
,
false
>
().
pmul
(
a
,
b
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
Packet
packetOp
(
const
Packet
&
a
,
const
Packet
&
b
)
const
{
return
conj_helper
<
Packet
,
Packet
,
Conj
,
false
>
().
pmul
(
a
,
b
);
}
};
template
<
typename
LhsScalar
,
typename
RhsScalar
>
struct
functor_traits
<
scalar_conj_product_op
<
LhsScalar
,
RhsScalar
>
>
{
enum
{
Cost
=
NumTraits
<
LhsScalar
>::
MulCost
,
PacketAccess
=
internal
::
is_same
<
LhsScalar
,
RhsScalar
>::
value
&&
packet_traits
<
LhsScalar
>::
HasMul
};
};
/** \internal
* \brief Template functor to compute the min of two scalars
*
* \sa class CwiseBinaryOp, MatrixBase::cwiseMin, class VectorwiseOp, MatrixBase::minCoeff()
*/
template
<
typename
LhsScalar
,
typename
RhsScalar
>
struct
scalar_min_op
:
binary_op_base
<
LhsScalar
,
RhsScalar
>
{
typedef
typename
ScalarBinaryOpTraits
<
LhsScalar
,
RhsScalar
,
scalar_min_op
>::
ReturnType
result_type
;
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_min_op
)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
result_type
operator
()
(
const
LhsScalar
&
a
,
const
RhsScalar
&
b
)
const
{
return
numext
::
mini
(
a
,
b
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
Packet
packetOp
(
const
Packet
&
a
,
const
Packet
&
b
)
const
{
return
internal
::
pmin
(
a
,
b
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
result_type
predux
(
const
Packet
&
a
)
const
{
return
internal
::
predux_min
(
a
);
}
};
template
<
typename
LhsScalar
,
typename
RhsScalar
>
struct
functor_traits
<
scalar_min_op
<
LhsScalar
,
RhsScalar
>
>
{
enum
{
Cost
=
(
NumTraits
<
LhsScalar
>::
AddCost
+
NumTraits
<
RhsScalar
>::
AddCost
)
/
2
,
PacketAccess
=
internal
::
is_same
<
LhsScalar
,
RhsScalar
>::
value
&&
packet_traits
<
LhsScalar
>::
HasMin
};
};
/** \internal
* \brief Template functor to compute the max of two scalars
*
* \sa class CwiseBinaryOp, MatrixBase::cwiseMax, class VectorwiseOp, MatrixBase::maxCoeff()
*/
template
<
typename
LhsScalar
,
typename
RhsScalar
>
struct
scalar_max_op
:
binary_op_base
<
LhsScalar
,
RhsScalar
>
{
typedef
typename
ScalarBinaryOpTraits
<
LhsScalar
,
RhsScalar
,
scalar_max_op
>::
ReturnType
result_type
;
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_max_op
)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
result_type
operator
()
(
const
LhsScalar
&
a
,
const
RhsScalar
&
b
)
const
{
return
numext
::
maxi
(
a
,
b
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
Packet
packetOp
(
const
Packet
&
a
,
const
Packet
&
b
)
const
{
return
internal
::
pmax
(
a
,
b
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
result_type
predux
(
const
Packet
&
a
)
const
{
return
internal
::
predux_max
(
a
);
}
};
template
<
typename
LhsScalar
,
typename
RhsScalar
>
struct
functor_traits
<
scalar_max_op
<
LhsScalar
,
RhsScalar
>
>
{
enum
{
Cost
=
(
NumTraits
<
LhsScalar
>::
AddCost
+
NumTraits
<
RhsScalar
>::
AddCost
)
/
2
,
PacketAccess
=
internal
::
is_same
<
LhsScalar
,
RhsScalar
>::
value
&&
packet_traits
<
LhsScalar
>::
HasMax
};
};
/** \internal
* \brief Template functors for comparison of two scalars
* \todo Implement packet-comparisons
*/
template
<
typename
LhsScalar
,
typename
RhsScalar
,
ComparisonName
cmp
>
struct
scalar_cmp_op
;
template
<
typename
LhsScalar
,
typename
RhsScalar
,
ComparisonName
cmp
>
struct
functor_traits
<
scalar_cmp_op
<
LhsScalar
,
RhsScalar
,
cmp
>
>
{
enum
{
Cost
=
(
NumTraits
<
LhsScalar
>::
AddCost
+
NumTraits
<
RhsScalar
>::
AddCost
)
/
2
,
PacketAccess
=
false
};
};
template
<
ComparisonName
Cmp
,
typename
LhsScalar
,
typename
RhsScalar
>
struct
result_of
<
scalar_cmp_op
<
LhsScalar
,
RhsScalar
,
Cmp
>
(
LhsScalar
,
RhsScalar
)
>
{
typedef
bool
type
;
};
template
<
typename
LhsScalar
,
typename
RhsScalar
>
struct
scalar_cmp_op
<
LhsScalar
,
RhsScalar
,
cmp_EQ
>
:
binary_op_base
<
LhsScalar
,
RhsScalar
>
{
typedef
bool
result_type
;
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_cmp_op
)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
bool
operator
()(
const
LhsScalar
&
a
,
const
RhsScalar
&
b
)
const
{
return
a
==
b
;}
};
template
<
typename
LhsScalar
,
typename
RhsScalar
>
struct
scalar_cmp_op
<
LhsScalar
,
RhsScalar
,
cmp_LT
>
:
binary_op_base
<
LhsScalar
,
RhsScalar
>
{
typedef
bool
result_type
;
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_cmp_op
)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
bool
operator
()(
const
LhsScalar
&
a
,
const
RhsScalar
&
b
)
const
{
return
a
<
b
;}
};
template
<
typename
LhsScalar
,
typename
RhsScalar
>
struct
scalar_cmp_op
<
LhsScalar
,
RhsScalar
,
cmp_LE
>
:
binary_op_base
<
LhsScalar
,
RhsScalar
>
{
typedef
bool
result_type
;
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_cmp_op
)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
bool
operator
()(
const
LhsScalar
&
a
,
const
RhsScalar
&
b
)
const
{
return
a
<=
b
;}
};
template
<
typename
LhsScalar
,
typename
RhsScalar
>
struct
scalar_cmp_op
<
LhsScalar
,
RhsScalar
,
cmp_GT
>
:
binary_op_base
<
LhsScalar
,
RhsScalar
>
{
typedef
bool
result_type
;
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_cmp_op
)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
bool
operator
()(
const
LhsScalar
&
a
,
const
RhsScalar
&
b
)
const
{
return
a
>
b
;}
};
template
<
typename
LhsScalar
,
typename
RhsScalar
>
struct
scalar_cmp_op
<
LhsScalar
,
RhsScalar
,
cmp_GE
>
:
binary_op_base
<
LhsScalar
,
RhsScalar
>
{
typedef
bool
result_type
;
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_cmp_op
)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
bool
operator
()(
const
LhsScalar
&
a
,
const
RhsScalar
&
b
)
const
{
return
a
>=
b
;}
};
template
<
typename
LhsScalar
,
typename
RhsScalar
>
struct
scalar_cmp_op
<
LhsScalar
,
RhsScalar
,
cmp_UNORD
>
:
binary_op_base
<
LhsScalar
,
RhsScalar
>
{
typedef
bool
result_type
;
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_cmp_op
)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
bool
operator
()(
const
LhsScalar
&
a
,
const
RhsScalar
&
b
)
const
{
return
!
(
a
<=
b
||
b
<=
a
);}
};
template
<
typename
LhsScalar
,
typename
RhsScalar
>
struct
scalar_cmp_op
<
LhsScalar
,
RhsScalar
,
cmp_NEQ
>
:
binary_op_base
<
LhsScalar
,
RhsScalar
>
{
typedef
bool
result_type
;
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_cmp_op
)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
bool
operator
()(
const
LhsScalar
&
a
,
const
RhsScalar
&
b
)
const
{
return
a
!=
b
;}
};
/** \internal
* \brief Template functor to compute the hypot of two scalars
*
* \sa MatrixBase::stableNorm(), class Redux
*/
template
<
typename
Scalar
>
struct
scalar_hypot_op
<
Scalar
,
Scalar
>
:
binary_op_base
<
Scalar
,
Scalar
>
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_hypot_op
)
// typedef typename NumTraits<Scalar>::Real result_type;
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
Scalar
operator
()
(
const
Scalar
&
_x
,
const
Scalar
&
_y
)
const
{
EIGEN_USING_STD_MATH
(
sqrt
)
Scalar
p
,
qp
;
if
(
_x
>
_y
)
{
p
=
_x
;
qp
=
_y
/
p
;
}
else
{
p
=
_y
;
qp
=
_x
/
p
;
}
return
p
*
sqrt
(
Scalar
(
1
)
+
qp
*
qp
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_hypot_op
<
Scalar
,
Scalar
>
>
{
enum
{
Cost
=
3
*
NumTraits
<
Scalar
>::
AddCost
+
2
*
NumTraits
<
Scalar
>::
MulCost
+
2
*
scalar_div_cost
<
Scalar
,
false
>::
value
,
PacketAccess
=
false
};
};
/** \internal
* \brief Template functor to compute the pow of two scalars
*/
template
<
typename
Scalar
,
typename
Exponent
>
struct
scalar_pow_op
:
binary_op_base
<
Scalar
,
Exponent
>
{
typedef
typename
ScalarBinaryOpTraits
<
Scalar
,
Exponent
,
scalar_pow_op
>::
ReturnType
result_type
;
#ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_pow_op
)
#else
scalar_pow_op
()
{
typedef
Scalar
LhsScalar
;
typedef
Exponent
RhsScalar
;
EIGEN_SCALAR_BINARY_OP_PLUGIN
}
#endif
EIGEN_DEVICE_FUNC
inline
result_type
operator
()
(
const
Scalar
&
a
,
const
Exponent
&
b
)
const
{
return
numext
::
pow
(
a
,
b
);
}
};
template
<
typename
Scalar
,
typename
Exponent
>
struct
functor_traits
<
scalar_pow_op
<
Scalar
,
Exponent
>
>
{
enum
{
Cost
=
5
*
NumTraits
<
Scalar
>::
MulCost
,
PacketAccess
=
false
};
};
//---------- non associative binary functors ----------
/** \internal
* \brief Template functor to compute the difference of two scalars
*
* \sa class CwiseBinaryOp, MatrixBase::operator-
*/
template
<
typename
LhsScalar
,
typename
RhsScalar
>
struct
scalar_difference_op
:
binary_op_base
<
LhsScalar
,
RhsScalar
>
{
typedef
typename
ScalarBinaryOpTraits
<
LhsScalar
,
RhsScalar
,
scalar_difference_op
>::
ReturnType
result_type
;
#ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_difference_op
)
#else
scalar_difference_op
()
{
EIGEN_SCALAR_BINARY_OP_PLUGIN
}
#endif
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
result_type
operator
()
(
const
LhsScalar
&
a
,
const
RhsScalar
&
b
)
const
{
return
a
-
b
;
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
Packet
packetOp
(
const
Packet
&
a
,
const
Packet
&
b
)
const
{
return
internal
::
psub
(
a
,
b
);
}
};
template
<
typename
LhsScalar
,
typename
RhsScalar
>
struct
functor_traits
<
scalar_difference_op
<
LhsScalar
,
RhsScalar
>
>
{
enum
{
Cost
=
(
NumTraits
<
LhsScalar
>::
AddCost
+
NumTraits
<
RhsScalar
>::
AddCost
)
/
2
,
PacketAccess
=
is_same
<
LhsScalar
,
RhsScalar
>::
value
&&
packet_traits
<
LhsScalar
>::
HasSub
&&
packet_traits
<
RhsScalar
>::
HasSub
};
};
/** \internal
* \brief Template functor to compute the quotient of two scalars
*
* \sa class CwiseBinaryOp, Cwise::operator/()
*/
template
<
typename
LhsScalar
,
typename
RhsScalar
>
struct
scalar_quotient_op
:
binary_op_base
<
LhsScalar
,
RhsScalar
>
{
typedef
typename
ScalarBinaryOpTraits
<
LhsScalar
,
RhsScalar
,
scalar_quotient_op
>::
ReturnType
result_type
;
#ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_quotient_op
)
#else
scalar_quotient_op
()
{
EIGEN_SCALAR_BINARY_OP_PLUGIN
}
#endif
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
result_type
operator
()
(
const
LhsScalar
&
a
,
const
RhsScalar
&
b
)
const
{
return
a
/
b
;
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
Packet
packetOp
(
const
Packet
&
a
,
const
Packet
&
b
)
const
{
return
internal
::
pdiv
(
a
,
b
);
}
};
template
<
typename
LhsScalar
,
typename
RhsScalar
>
struct
functor_traits
<
scalar_quotient_op
<
LhsScalar
,
RhsScalar
>
>
{
typedef
typename
scalar_quotient_op
<
LhsScalar
,
RhsScalar
>::
result_type
result_type
;
enum
{
PacketAccess
=
is_same
<
LhsScalar
,
RhsScalar
>::
value
&&
packet_traits
<
LhsScalar
>::
HasDiv
&&
packet_traits
<
RhsScalar
>::
HasDiv
,
Cost
=
scalar_div_cost
<
result_type
,
PacketAccess
>::
value
};
};
/** \internal
* \brief Template functor to compute the and of two booleans
*
* \sa class CwiseBinaryOp, ArrayBase::operator&&
*/
struct
scalar_boolean_and_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_boolean_and_op
)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
bool
operator
()
(
const
bool
&
a
,
const
bool
&
b
)
const
{
return
a
&&
b
;
}
};
template
<
>
struct
functor_traits
<
scalar_boolean_and_op
>
{
enum
{
Cost
=
NumTraits
<
bool
>::
AddCost
,
PacketAccess
=
false
};
};
/** \internal
* \brief Template functor to compute the or of two booleans
*
* \sa class CwiseBinaryOp, ArrayBase::operator||
*/
struct
scalar_boolean_or_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_boolean_or_op
)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
bool
operator
()
(
const
bool
&
a
,
const
bool
&
b
)
const
{
return
a
||
b
;
}
};
template
<
>
struct
functor_traits
<
scalar_boolean_or_op
>
{
enum
{
Cost
=
NumTraits
<
bool
>::
AddCost
,
PacketAccess
=
false
};
};
/** \internal
* \brief Template functor to compute the xor of two booleans
*
* \sa class CwiseBinaryOp, ArrayBase::operator^
*/
struct
scalar_boolean_xor_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_boolean_xor_op
)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
bool
operator
()
(
const
bool
&
a
,
const
bool
&
b
)
const
{
return
a
^
b
;
}
};
template
<
>
struct
functor_traits
<
scalar_boolean_xor_op
>
{
enum
{
Cost
=
NumTraits
<
bool
>::
AddCost
,
PacketAccess
=
false
};
};
//---------- binary functors bound to a constant, thus appearing as a unary functor ----------
// The following two classes permits to turn any binary functor into a unary one with one argument bound to a constant value.
// They are analogues to std::binder1st/binder2nd but with the following differences:
// - they are compatible with packetOp
// - they are portable across C++ versions (the std::binder* are deprecated in C++11)
template
<
typename
BinaryOp
>
struct
bind1st_op
:
BinaryOp
{
typedef
typename
BinaryOp
::
first_argument_type
first_argument_type
;
typedef
typename
BinaryOp
::
second_argument_type
second_argument_type
;
typedef
typename
BinaryOp
::
result_type
result_type
;
bind1st_op
(
const
first_argument_type
&
val
)
:
m_value
(
val
)
{}
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
result_type
operator
()
(
const
second_argument_type
&
b
)
const
{
return
BinaryOp
::
operator
()(
m_value
,
b
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
Packet
packetOp
(
const
Packet
&
b
)
const
{
return
BinaryOp
::
packetOp
(
internal
::
pset1
<
Packet
>
(
m_value
),
b
);
}
first_argument_type
m_value
;
};
template
<
typename
BinaryOp
>
struct
functor_traits
<
bind1st_op
<
BinaryOp
>
>
:
functor_traits
<
BinaryOp
>
{};
template
<
typename
BinaryOp
>
struct
bind2nd_op
:
BinaryOp
{
typedef
typename
BinaryOp
::
first_argument_type
first_argument_type
;
typedef
typename
BinaryOp
::
second_argument_type
second_argument_type
;
typedef
typename
BinaryOp
::
result_type
result_type
;
bind2nd_op
(
const
second_argument_type
&
val
)
:
m_value
(
val
)
{}
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
result_type
operator
()
(
const
first_argument_type
&
a
)
const
{
return
BinaryOp
::
operator
()(
a
,
m_value
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
Packet
packetOp
(
const
Packet
&
a
)
const
{
return
BinaryOp
::
packetOp
(
a
,
internal
::
pset1
<
Packet
>
(
m_value
));
}
second_argument_type
m_value
;
};
template
<
typename
BinaryOp
>
struct
functor_traits
<
bind2nd_op
<
BinaryOp
>
>
:
functor_traits
<
BinaryOp
>
{};
}
// end namespace internal
}
// end namespace Eigen
#endif // EIGEN_BINARY_FUNCTORS_H
external/eigen3/Eigen/src/Core/functors/NullaryFunctors.h
0 → 100644
View file @
a394b22a
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2016 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_NULLARY_FUNCTORS_H
#define EIGEN_NULLARY_FUNCTORS_H
namespace
Eigen
{
namespace
internal
{
template
<
typename
Scalar
>
struct
scalar_constant_op
{
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
scalar_constant_op
(
const
scalar_constant_op
&
other
)
:
m_other
(
other
.
m_other
)
{
}
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
scalar_constant_op
(
const
Scalar
&
other
)
:
m_other
(
other
)
{
}
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
Scalar
operator
()
()
const
{
return
m_other
;
}
template
<
typename
PacketType
>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
PacketType
packetOp
()
const
{
return
internal
::
pset1
<
PacketType
>
(
m_other
);
}
const
Scalar
m_other
;
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_constant_op
<
Scalar
>
>
{
enum
{
Cost
=
0
/* as the constant value should be loaded in register only once for the whole expression */
,
PacketAccess
=
packet_traits
<
Scalar
>::
Vectorizable
,
IsRepeatable
=
true
};
};
template
<
typename
Scalar
>
struct
scalar_identity_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_identity_op
)
template
<
typename
IndexType
>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
Scalar
operator
()
(
IndexType
row
,
IndexType
col
)
const
{
return
row
==
col
?
Scalar
(
1
)
:
Scalar
(
0
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_identity_op
<
Scalar
>
>
{
enum
{
Cost
=
NumTraits
<
Scalar
>::
AddCost
,
PacketAccess
=
false
,
IsRepeatable
=
true
};
};
template
<
typename
Scalar
,
typename
Packet
,
bool
IsInteger
>
struct
linspaced_op_impl
;
template
<
typename
Scalar
,
typename
Packet
>
struct
linspaced_op_impl
<
Scalar
,
Packet
,
/*IsInteger*/
false
>
{
linspaced_op_impl
(
const
Scalar
&
low
,
const
Scalar
&
high
,
Index
num_steps
)
:
m_low
(
low
),
m_high
(
high
),
m_size1
(
num_steps
==
1
?
1
:
num_steps
-
1
),
m_step
(
num_steps
==
1
?
Scalar
()
:
(
high
-
low
)
/
Scalar
(
num_steps
-
1
)),
m_flip
(
numext
::
abs
(
high
)
<
numext
::
abs
(
low
))
{}
template
<
typename
IndexType
>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
Scalar
operator
()
(
IndexType
i
)
const
{
typedef
typename
NumTraits
<
Scalar
>::
Real
RealScalar
;
if
(
m_flip
)
return
(
i
==
0
)
?
m_low
:
(
m_high
-
RealScalar
(
m_size1
-
i
)
*
m_step
);
else
return
(
i
==
m_size1
)
?
m_high
:
(
m_low
+
RealScalar
(
i
)
*
m_step
);
}
template
<
typename
IndexType
>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
Packet
packetOp
(
IndexType
i
)
const
{
// Principle:
// [low, ..., low] + ( [step, ..., step] * ( [i, ..., i] + [0, ..., size] ) )
if
(
m_flip
)
{
Packet
pi
=
plset
<
Packet
>
(
Scalar
(
i
-
m_size1
));
Packet
res
=
padd
(
pset1
<
Packet
>
(
m_high
),
pmul
(
pset1
<
Packet
>
(
m_step
),
pi
));
if
(
i
==
0
)
res
=
pinsertfirst
(
res
,
m_low
);
return
res
;
}
else
{
Packet
pi
=
plset
<
Packet
>
(
Scalar
(
i
));
Packet
res
=
padd
(
pset1
<
Packet
>
(
m_low
),
pmul
(
pset1
<
Packet
>
(
m_step
),
pi
));
if
(
i
==
m_size1
-
unpacket_traits
<
Packet
>::
size
+
1
)
res
=
pinsertlast
(
res
,
m_high
);
return
res
;
}
}
const
Scalar
m_low
;
const
Scalar
m_high
;
const
Index
m_size1
;
const
Scalar
m_step
;
const
bool
m_flip
;
};
template
<
typename
Scalar
,
typename
Packet
>
struct
linspaced_op_impl
<
Scalar
,
Packet
,
/*IsInteger*/
true
>
{
linspaced_op_impl
(
const
Scalar
&
low
,
const
Scalar
&
high
,
Index
num_steps
)
:
m_low
(
low
),
m_multiplier
((
high
-
low
)
/
convert_index
<
Scalar
>
(
num_steps
<=
1
?
1
:
num_steps
-
1
)),
m_divisor
(
convert_index
<
Scalar
>
((
high
>=
low
?
num_steps
:-
num_steps
)
+
(
high
-
low
))
/
((
numext
::
abs
(
high
-
low
)
+
1
)
==
0
?
1
:
(
numext
::
abs
(
high
-
low
)
+
1
))),
m_use_divisor
(
num_steps
>
1
&&
(
numext
::
abs
(
high
-
low
)
+
1
)
<
num_steps
)
{}
template
<
typename
IndexType
>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
Scalar
operator
()
(
IndexType
i
)
const
{
if
(
m_use_divisor
)
return
m_low
+
convert_index
<
Scalar
>
(
i
)
/
m_divisor
;
else
return
m_low
+
convert_index
<
Scalar
>
(
i
)
*
m_multiplier
;
}
const
Scalar
m_low
;
const
Scalar
m_multiplier
;
const
Scalar
m_divisor
;
const
bool
m_use_divisor
;
};
// ----- Linspace functor ----------------------------------------------------------------
// Forward declaration (we default to random access which does not really give
// us a speed gain when using packet access but it allows to use the functor in
// nested expressions).
template
<
typename
Scalar
,
typename
PacketType
>
struct
linspaced_op
;
template
<
typename
Scalar
,
typename
PacketType
>
struct
functor_traits
<
linspaced_op
<
Scalar
,
PacketType
>
>
{
enum
{
Cost
=
1
,
PacketAccess
=
(
!
NumTraits
<
Scalar
>::
IsInteger
)
&&
packet_traits
<
Scalar
>::
HasSetLinear
&&
packet_traits
<
Scalar
>::
HasBlend
,
/*&& ((!NumTraits<Scalar>::IsInteger) || packet_traits<Scalar>::HasDiv),*/
// <- vectorization for integer is currently disabled
IsRepeatable
=
true
};
};
template
<
typename
Scalar
,
typename
PacketType
>
struct
linspaced_op
{
linspaced_op
(
const
Scalar
&
low
,
const
Scalar
&
high
,
Index
num_steps
)
:
impl
((
num_steps
==
1
?
high
:
low
),
high
,
num_steps
)
{}
template
<
typename
IndexType
>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
Scalar
operator
()
(
IndexType
i
)
const
{
return
impl
(
i
);
}
template
<
typename
Packet
,
typename
IndexType
>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
Packet
packetOp
(
IndexType
i
)
const
{
return
impl
.
packetOp
(
i
);
}
// This proxy object handles the actual required temporaries and the different
// implementations (integer vs. floating point).
const
linspaced_op_impl
<
Scalar
,
PacketType
,
NumTraits
<
Scalar
>::
IsInteger
>
impl
;
};
// Linear access is automatically determined from the operator() prototypes available for the given functor.
// If it exposes an operator()(i,j), then we assume the i and j coefficients are required independently
// and linear access is not possible. In all other cases, linear access is enabled.
// Users should not have to deal with this structure.
template
<
typename
Functor
>
struct
functor_has_linear_access
{
enum
{
ret
=
!
has_binary_operator
<
Functor
>::
value
};
};
// For unreliable compilers, let's specialize the has_*ary_operator
// helpers so that at least built-in nullary functors work fine.
#if !( (EIGEN_COMP_MSVC>1600) || (EIGEN_GNUC_AT_LEAST(4,8)) || (EIGEN_COMP_ICC>=1600))
template
<
typename
Scalar
,
typename
IndexType
>
struct
has_nullary_operator
<
scalar_constant_op
<
Scalar
>
,
IndexType
>
{
enum
{
value
=
1
};
};
template
<
typename
Scalar
,
typename
IndexType
>
struct
has_unary_operator
<
scalar_constant_op
<
Scalar
>
,
IndexType
>
{
enum
{
value
=
0
};
};
template
<
typename
Scalar
,
typename
IndexType
>
struct
has_binary_operator
<
scalar_constant_op
<
Scalar
>
,
IndexType
>
{
enum
{
value
=
0
};
};
template
<
typename
Scalar
,
typename
IndexType
>
struct
has_nullary_operator
<
scalar_identity_op
<
Scalar
>
,
IndexType
>
{
enum
{
value
=
0
};
};
template
<
typename
Scalar
,
typename
IndexType
>
struct
has_unary_operator
<
scalar_identity_op
<
Scalar
>
,
IndexType
>
{
enum
{
value
=
0
};
};
template
<
typename
Scalar
,
typename
IndexType
>
struct
has_binary_operator
<
scalar_identity_op
<
Scalar
>
,
IndexType
>
{
enum
{
value
=
1
};
};
template
<
typename
Scalar
,
typename
PacketType
,
typename
IndexType
>
struct
has_nullary_operator
<
linspaced_op
<
Scalar
,
PacketType
>
,
IndexType
>
{
enum
{
value
=
0
};
};
template
<
typename
Scalar
,
typename
PacketType
,
typename
IndexType
>
struct
has_unary_operator
<
linspaced_op
<
Scalar
,
PacketType
>
,
IndexType
>
{
enum
{
value
=
1
};
};
template
<
typename
Scalar
,
typename
PacketType
,
typename
IndexType
>
struct
has_binary_operator
<
linspaced_op
<
Scalar
,
PacketType
>
,
IndexType
>
{
enum
{
value
=
0
};
};
template
<
typename
Scalar
,
typename
IndexType
>
struct
has_nullary_operator
<
scalar_random_op
<
Scalar
>
,
IndexType
>
{
enum
{
value
=
1
};
};
template
<
typename
Scalar
,
typename
IndexType
>
struct
has_unary_operator
<
scalar_random_op
<
Scalar
>
,
IndexType
>
{
enum
{
value
=
0
};
};
template
<
typename
Scalar
,
typename
IndexType
>
struct
has_binary_operator
<
scalar_random_op
<
Scalar
>
,
IndexType
>
{
enum
{
value
=
0
};
};
#endif
}
// end namespace internal
}
// end namespace Eigen
#endif // EIGEN_NULLARY_FUNCTORS_H
external/eigen3/Eigen/src/Core/functors/StlFunctors.h
0 → 100644
View file @
a394b22a
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_STL_FUNCTORS_H
#define EIGEN_STL_FUNCTORS_H
namespace
Eigen
{
namespace
internal
{
// default functor traits for STL functors:
template
<
typename
T
>
struct
functor_traits
<
std
::
multiplies
<
T
>
>
{
enum
{
Cost
=
NumTraits
<
T
>::
MulCost
,
PacketAccess
=
false
};
};
template
<
typename
T
>
struct
functor_traits
<
std
::
divides
<
T
>
>
{
enum
{
Cost
=
NumTraits
<
T
>::
MulCost
,
PacketAccess
=
false
};
};
template
<
typename
T
>
struct
functor_traits
<
std
::
plus
<
T
>
>
{
enum
{
Cost
=
NumTraits
<
T
>::
AddCost
,
PacketAccess
=
false
};
};
template
<
typename
T
>
struct
functor_traits
<
std
::
minus
<
T
>
>
{
enum
{
Cost
=
NumTraits
<
T
>::
AddCost
,
PacketAccess
=
false
};
};
template
<
typename
T
>
struct
functor_traits
<
std
::
negate
<
T
>
>
{
enum
{
Cost
=
NumTraits
<
T
>::
AddCost
,
PacketAccess
=
false
};
};
template
<
typename
T
>
struct
functor_traits
<
std
::
logical_or
<
T
>
>
{
enum
{
Cost
=
1
,
PacketAccess
=
false
};
};
template
<
typename
T
>
struct
functor_traits
<
std
::
logical_and
<
T
>
>
{
enum
{
Cost
=
1
,
PacketAccess
=
false
};
};
template
<
typename
T
>
struct
functor_traits
<
std
::
logical_not
<
T
>
>
{
enum
{
Cost
=
1
,
PacketAccess
=
false
};
};
template
<
typename
T
>
struct
functor_traits
<
std
::
greater
<
T
>
>
{
enum
{
Cost
=
1
,
PacketAccess
=
false
};
};
template
<
typename
T
>
struct
functor_traits
<
std
::
less
<
T
>
>
{
enum
{
Cost
=
1
,
PacketAccess
=
false
};
};
template
<
typename
T
>
struct
functor_traits
<
std
::
greater_equal
<
T
>
>
{
enum
{
Cost
=
1
,
PacketAccess
=
false
};
};
template
<
typename
T
>
struct
functor_traits
<
std
::
less_equal
<
T
>
>
{
enum
{
Cost
=
1
,
PacketAccess
=
false
};
};
template
<
typename
T
>
struct
functor_traits
<
std
::
equal_to
<
T
>
>
{
enum
{
Cost
=
1
,
PacketAccess
=
false
};
};
template
<
typename
T
>
struct
functor_traits
<
std
::
not_equal_to
<
T
>
>
{
enum
{
Cost
=
1
,
PacketAccess
=
false
};
};
#if (__cplusplus < 201103L) && (EIGEN_COMP_MSVC <= 1900)
// std::binder* are deprecated since c++11 and will be removed in c++17
template
<
typename
T
>
struct
functor_traits
<
std
::
binder2nd
<
T
>
>
{
enum
{
Cost
=
functor_traits
<
T
>::
Cost
,
PacketAccess
=
false
};
};
template
<
typename
T
>
struct
functor_traits
<
std
::
binder1st
<
T
>
>
{
enum
{
Cost
=
functor_traits
<
T
>::
Cost
,
PacketAccess
=
false
};
};
#endif
template
<
typename
T
>
struct
functor_traits
<
std
::
unary_negate
<
T
>
>
{
enum
{
Cost
=
1
+
functor_traits
<
T
>::
Cost
,
PacketAccess
=
false
};
};
template
<
typename
T
>
struct
functor_traits
<
std
::
binary_negate
<
T
>
>
{
enum
{
Cost
=
1
+
functor_traits
<
T
>::
Cost
,
PacketAccess
=
false
};
};
#ifdef EIGEN_STDEXT_SUPPORT
template
<
typename
T0
,
typename
T1
>
struct
functor_traits
<
std
::
project1st
<
T0
,
T1
>
>
{
enum
{
Cost
=
0
,
PacketAccess
=
false
};
};
template
<
typename
T0
,
typename
T1
>
struct
functor_traits
<
std
::
project2nd
<
T0
,
T1
>
>
{
enum
{
Cost
=
0
,
PacketAccess
=
false
};
};
template
<
typename
T0
,
typename
T1
>
struct
functor_traits
<
std
::
select2nd
<
std
::
pair
<
T0
,
T1
>
>
>
{
enum
{
Cost
=
0
,
PacketAccess
=
false
};
};
template
<
typename
T0
,
typename
T1
>
struct
functor_traits
<
std
::
select1st
<
std
::
pair
<
T0
,
T1
>
>
>
{
enum
{
Cost
=
0
,
PacketAccess
=
false
};
};
template
<
typename
T0
,
typename
T1
>
struct
functor_traits
<
std
::
unary_compose
<
T0
,
T1
>
>
{
enum
{
Cost
=
functor_traits
<
T0
>::
Cost
+
functor_traits
<
T1
>::
Cost
,
PacketAccess
=
false
};
};
template
<
typename
T0
,
typename
T1
,
typename
T2
>
struct
functor_traits
<
std
::
binary_compose
<
T0
,
T1
,
T2
>
>
{
enum
{
Cost
=
functor_traits
<
T0
>::
Cost
+
functor_traits
<
T1
>::
Cost
+
functor_traits
<
T2
>::
Cost
,
PacketAccess
=
false
};
};
#endif // EIGEN_STDEXT_SUPPORT
// allow to add new functors and specializations of functor_traits from outside Eigen.
// this macro is really needed because functor_traits must be specialized after it is declared but before it is used...
#ifdef EIGEN_FUNCTORS_PLUGIN
#include EIGEN_FUNCTORS_PLUGIN
#endif
}
// end namespace internal
}
// end namespace Eigen
#endif // EIGEN_STL_FUNCTORS_H
external/eigen3/Eigen/src/Core/functors/TernaryFunctors.h
0 → 100644
View file @
a394b22a
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2016 Eugene Brevdo <ebrevdo@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_TERNARY_FUNCTORS_H
#define EIGEN_TERNARY_FUNCTORS_H
namespace
Eigen
{
namespace
internal
{
//---------- associative ternary functors ----------
}
// end namespace internal
}
// end namespace Eigen
#endif // EIGEN_TERNARY_FUNCTORS_H
external/eigen3/Eigen/src/Core/functors/UnaryFunctors.h
0 → 100644
View file @
a394b22a
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2016 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_UNARY_FUNCTORS_H
#define EIGEN_UNARY_FUNCTORS_H
namespace
Eigen
{
namespace
internal
{
/** \internal
* \brief Template functor to compute the opposite of a scalar
*
* \sa class CwiseUnaryOp, MatrixBase::operator-
*/
template
<
typename
Scalar
>
struct
scalar_opposite_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_opposite_op
)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
Scalar
operator
()
(
const
Scalar
&
a
)
const
{
return
-
a
;
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
Packet
packetOp
(
const
Packet
&
a
)
const
{
return
internal
::
pnegate
(
a
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_opposite_op
<
Scalar
>
>
{
enum
{
Cost
=
NumTraits
<
Scalar
>::
AddCost
,
PacketAccess
=
packet_traits
<
Scalar
>::
HasNegate
};
};
/** \internal
* \brief Template functor to compute the absolute value of a scalar
*
* \sa class CwiseUnaryOp, Cwise::abs
*/
template
<
typename
Scalar
>
struct
scalar_abs_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_abs_op
)
typedef
typename
NumTraits
<
Scalar
>::
Real
result_type
;
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
result_type
operator
()
(
const
Scalar
&
a
)
const
{
return
numext
::
abs
(
a
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
Packet
packetOp
(
const
Packet
&
a
)
const
{
return
internal
::
pabs
(
a
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_abs_op
<
Scalar
>
>
{
enum
{
Cost
=
NumTraits
<
Scalar
>::
AddCost
,
PacketAccess
=
packet_traits
<
Scalar
>::
HasAbs
};
};
/** \internal
* \brief Template functor to compute the score of a scalar, to chose a pivot
*
* \sa class CwiseUnaryOp
*/
template
<
typename
Scalar
>
struct
scalar_score_coeff_op
:
scalar_abs_op
<
Scalar
>
{
typedef
void
Score_is_abs
;
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_score_coeff_op
<
Scalar
>
>
:
functor_traits
<
scalar_abs_op
<
Scalar
>
>
{};
/* Avoid recomputing abs when we know the score and they are the same. Not a true Eigen functor. */
template
<
typename
Scalar
,
typename
=
void
>
struct
abs_knowing_score
{
EIGEN_EMPTY_STRUCT_CTOR
(
abs_knowing_score
)
typedef
typename
NumTraits
<
Scalar
>::
Real
result_type
;
template
<
typename
Score
>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
result_type
operator
()
(
const
Scalar
&
a
,
const
Score
&
)
const
{
return
numext
::
abs
(
a
);
}
};
template
<
typename
Scalar
>
struct
abs_knowing_score
<
Scalar
,
typename
scalar_score_coeff_op
<
Scalar
>::
Score_is_abs
>
{
EIGEN_EMPTY_STRUCT_CTOR
(
abs_knowing_score
)
typedef
typename
NumTraits
<
Scalar
>::
Real
result_type
;
template
<
typename
Scal
>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
result_type
operator
()
(
const
Scal
&
,
const
result_type
&
a
)
const
{
return
a
;
}
};
/** \internal
* \brief Template functor to compute the squared absolute value of a scalar
*
* \sa class CwiseUnaryOp, Cwise::abs2
*/
template
<
typename
Scalar
>
struct
scalar_abs2_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_abs2_op
)
typedef
typename
NumTraits
<
Scalar
>::
Real
result_type
;
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
result_type
operator
()
(
const
Scalar
&
a
)
const
{
return
numext
::
abs2
(
a
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
Packet
packetOp
(
const
Packet
&
a
)
const
{
return
internal
::
pmul
(
a
,
a
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_abs2_op
<
Scalar
>
>
{
enum
{
Cost
=
NumTraits
<
Scalar
>::
MulCost
,
PacketAccess
=
packet_traits
<
Scalar
>::
HasAbs2
};
};
/** \internal
* \brief Template functor to compute the conjugate of a complex value
*
* \sa class CwiseUnaryOp, MatrixBase::conjugate()
*/
template
<
typename
Scalar
>
struct
scalar_conjugate_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_conjugate_op
)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
Scalar
operator
()
(
const
Scalar
&
a
)
const
{
using
numext
::
conj
;
return
conj
(
a
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
Packet
packetOp
(
const
Packet
&
a
)
const
{
return
internal
::
pconj
(
a
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_conjugate_op
<
Scalar
>
>
{
enum
{
Cost
=
NumTraits
<
Scalar
>::
IsComplex
?
NumTraits
<
Scalar
>::
AddCost
:
0
,
PacketAccess
=
packet_traits
<
Scalar
>::
HasConj
};
};
/** \internal
* \brief Template functor to compute the phase angle of a complex
*
* \sa class CwiseUnaryOp, Cwise::arg
*/
template
<
typename
Scalar
>
struct
scalar_arg_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_arg_op
)
typedef
typename
NumTraits
<
Scalar
>::
Real
result_type
;
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
result_type
operator
()
(
const
Scalar
&
a
)
const
{
using
numext
::
arg
;
return
arg
(
a
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
Packet
packetOp
(
const
Packet
&
a
)
const
{
return
internal
::
parg
(
a
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_arg_op
<
Scalar
>
>
{
enum
{
Cost
=
NumTraits
<
Scalar
>::
IsComplex
?
5
*
NumTraits
<
Scalar
>::
MulCost
:
NumTraits
<
Scalar
>::
AddCost
,
PacketAccess
=
packet_traits
<
Scalar
>::
HasArg
};
};
/** \internal
* \brief Template functor to cast a scalar to another type
*
* \sa class CwiseUnaryOp, MatrixBase::cast()
*/
template
<
typename
Scalar
,
typename
NewType
>
struct
scalar_cast_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_cast_op
)
typedef
NewType
result_type
;
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
NewType
operator
()
(
const
Scalar
&
a
)
const
{
return
cast
<
Scalar
,
NewType
>
(
a
);
}
};
template
<
typename
Scalar
,
typename
NewType
>
struct
functor_traits
<
scalar_cast_op
<
Scalar
,
NewType
>
>
{
enum
{
Cost
=
is_same
<
Scalar
,
NewType
>::
value
?
0
:
NumTraits
<
NewType
>::
AddCost
,
PacketAccess
=
false
};
};
/** \internal
* \brief Template functor to extract the real part of a complex
*
* \sa class CwiseUnaryOp, MatrixBase::real()
*/
template
<
typename
Scalar
>
struct
scalar_real_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_real_op
)
typedef
typename
NumTraits
<
Scalar
>::
Real
result_type
;
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
result_type
operator
()
(
const
Scalar
&
a
)
const
{
return
numext
::
real
(
a
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_real_op
<
Scalar
>
>
{
enum
{
Cost
=
0
,
PacketAccess
=
false
};
};
/** \internal
* \brief Template functor to extract the imaginary part of a complex
*
* \sa class CwiseUnaryOp, MatrixBase::imag()
*/
template
<
typename
Scalar
>
struct
scalar_imag_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_imag_op
)
typedef
typename
NumTraits
<
Scalar
>::
Real
result_type
;
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
result_type
operator
()
(
const
Scalar
&
a
)
const
{
return
numext
::
imag
(
a
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_imag_op
<
Scalar
>
>
{
enum
{
Cost
=
0
,
PacketAccess
=
false
};
};
/** \internal
* \brief Template functor to extract the real part of a complex as a reference
*
* \sa class CwiseUnaryOp, MatrixBase::real()
*/
template
<
typename
Scalar
>
struct
scalar_real_ref_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_real_ref_op
)
typedef
typename
NumTraits
<
Scalar
>::
Real
result_type
;
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
result_type
&
operator
()
(
const
Scalar
&
a
)
const
{
return
numext
::
real_ref
(
*
const_cast
<
Scalar
*>
(
&
a
));
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_real_ref_op
<
Scalar
>
>
{
enum
{
Cost
=
0
,
PacketAccess
=
false
};
};
/** \internal
* \brief Template functor to extract the imaginary part of a complex as a reference
*
* \sa class CwiseUnaryOp, MatrixBase::imag()
*/
template
<
typename
Scalar
>
struct
scalar_imag_ref_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_imag_ref_op
)
typedef
typename
NumTraits
<
Scalar
>::
Real
result_type
;
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
result_type
&
operator
()
(
const
Scalar
&
a
)
const
{
return
numext
::
imag_ref
(
*
const_cast
<
Scalar
*>
(
&
a
));
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_imag_ref_op
<
Scalar
>
>
{
enum
{
Cost
=
0
,
PacketAccess
=
false
};
};
/** \internal
*
* \brief Template functor to compute the exponential of a scalar
*
* \sa class CwiseUnaryOp, Cwise::exp()
*/
template
<
typename
Scalar
>
struct
scalar_exp_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_exp_op
)
EIGEN_DEVICE_FUNC
inline
const
Scalar
operator
()
(
const
Scalar
&
a
)
const
{
return
numext
::
exp
(
a
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
inline
Packet
packetOp
(
const
Packet
&
a
)
const
{
return
internal
::
pexp
(
a
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_exp_op
<
Scalar
>
>
{
enum
{
PacketAccess
=
packet_traits
<
Scalar
>::
HasExp
,
// The following numbers are based on the AVX implementation.
#ifdef EIGEN_VECTORIZE_FMA
// Haswell can issue 2 add/mul/madd per cycle.
Cost
=
(
sizeof
(
Scalar
)
==
4
// float: 8 pmadd, 4 pmul, 2 padd/psub, 6 other
?
(
8
*
NumTraits
<
Scalar
>::
AddCost
+
6
*
NumTraits
<
Scalar
>::
MulCost
)
// double: 7 pmadd, 5 pmul, 3 padd/psub, 1 div, 13 other
:
(
14
*
NumTraits
<
Scalar
>::
AddCost
+
6
*
NumTraits
<
Scalar
>::
MulCost
+
scalar_div_cost
<
Scalar
,
packet_traits
<
Scalar
>::
HasDiv
>::
value
))
#else
Cost
=
(
sizeof
(
Scalar
)
==
4
// float: 7 pmadd, 6 pmul, 4 padd/psub, 10 other
?
(
21
*
NumTraits
<
Scalar
>::
AddCost
+
13
*
NumTraits
<
Scalar
>::
MulCost
)
// double: 7 pmadd, 5 pmul, 3 padd/psub, 1 div, 13 other
:
(
23
*
NumTraits
<
Scalar
>::
AddCost
+
12
*
NumTraits
<
Scalar
>::
MulCost
+
scalar_div_cost
<
Scalar
,
packet_traits
<
Scalar
>::
HasDiv
>::
value
))
#endif
};
};
/** \internal
*
* \brief Template functor to compute the logarithm of a scalar
*
* \sa class CwiseUnaryOp, ArrayBase::log()
*/
template
<
typename
Scalar
>
struct
scalar_log_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_log_op
)
EIGEN_DEVICE_FUNC
inline
const
Scalar
operator
()
(
const
Scalar
&
a
)
const
{
return
numext
::
log
(
a
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
inline
Packet
packetOp
(
const
Packet
&
a
)
const
{
return
internal
::
plog
(
a
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_log_op
<
Scalar
>
>
{
enum
{
PacketAccess
=
packet_traits
<
Scalar
>::
HasLog
,
Cost
=
(
PacketAccess
// The following numbers are based on the AVX implementation.
#ifdef EIGEN_VECTORIZE_FMA
// 8 pmadd, 6 pmul, 8 padd/psub, 16 other, can issue 2 add/mul/madd per cycle.
?
(
20
*
NumTraits
<
Scalar
>::
AddCost
+
7
*
NumTraits
<
Scalar
>::
MulCost
)
#else
// 8 pmadd, 6 pmul, 8 padd/psub, 20 other
?
(
36
*
NumTraits
<
Scalar
>::
AddCost
+
14
*
NumTraits
<
Scalar
>::
MulCost
)
#endif
// Measured cost of std::log.
:
sizeof
(
Scalar
)
==
4
?
40
:
85
)
};
};
/** \internal
*
* \brief Template functor to compute the logarithm of 1 plus a scalar value
*
* \sa class CwiseUnaryOp, ArrayBase::log1p()
*/
template
<
typename
Scalar
>
struct
scalar_log1p_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_log1p_op
)
EIGEN_DEVICE_FUNC
inline
const
Scalar
operator
()
(
const
Scalar
&
a
)
const
{
return
numext
::
log1p
(
a
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
inline
Packet
packetOp
(
const
Packet
&
a
)
const
{
return
internal
::
plog1p
(
a
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_log1p_op
<
Scalar
>
>
{
enum
{
PacketAccess
=
packet_traits
<
Scalar
>::
HasLog1p
,
Cost
=
functor_traits
<
scalar_log_op
<
Scalar
>
>::
Cost
// TODO measure cost of log1p
};
};
/** \internal
*
* \brief Template functor to compute the base-10 logarithm of a scalar
*
* \sa class CwiseUnaryOp, Cwise::log10()
*/
template
<
typename
Scalar
>
struct
scalar_log10_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_log10_op
)
EIGEN_DEVICE_FUNC
inline
const
Scalar
operator
()
(
const
Scalar
&
a
)
const
{
EIGEN_USING_STD_MATH
(
log10
)
return
log10
(
a
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
inline
Packet
packetOp
(
const
Packet
&
a
)
const
{
return
internal
::
plog10
(
a
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_log10_op
<
Scalar
>
>
{
enum
{
Cost
=
5
*
NumTraits
<
Scalar
>::
MulCost
,
PacketAccess
=
packet_traits
<
Scalar
>::
HasLog10
};
};
/** \internal
* \brief Template functor to compute the square root of a scalar
* \sa class CwiseUnaryOp, Cwise::sqrt()
*/
template
<
typename
Scalar
>
struct
scalar_sqrt_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_sqrt_op
)
EIGEN_DEVICE_FUNC
inline
const
Scalar
operator
()
(
const
Scalar
&
a
)
const
{
return
numext
::
sqrt
(
a
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
inline
Packet
packetOp
(
const
Packet
&
a
)
const
{
return
internal
::
psqrt
(
a
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_sqrt_op
<
Scalar
>
>
{
enum
{
#if EIGEN_FAST_MATH
// The following numbers are based on the AVX implementation.
Cost
=
(
sizeof
(
Scalar
)
==
8
?
28
// 4 pmul, 1 pmadd, 3 other
:
(
3
*
NumTraits
<
Scalar
>::
AddCost
+
5
*
NumTraits
<
Scalar
>::
MulCost
)),
#else
// The following numbers are based on min VSQRT throughput on Haswell.
Cost
=
(
sizeof
(
Scalar
)
==
8
?
28
:
14
),
#endif
PacketAccess
=
packet_traits
<
Scalar
>::
HasSqrt
};
};
/** \internal
* \brief Template functor to compute the reciprocal square root of a scalar
* \sa class CwiseUnaryOp, Cwise::rsqrt()
*/
template
<
typename
Scalar
>
struct
scalar_rsqrt_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_rsqrt_op
)
EIGEN_DEVICE_FUNC
inline
const
Scalar
operator
()
(
const
Scalar
&
a
)
const
{
return
Scalar
(
1
)
/
numext
::
sqrt
(
a
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
inline
Packet
packetOp
(
const
Packet
&
a
)
const
{
return
internal
::
prsqrt
(
a
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_rsqrt_op
<
Scalar
>
>
{
enum
{
Cost
=
5
*
NumTraits
<
Scalar
>::
MulCost
,
PacketAccess
=
packet_traits
<
Scalar
>::
HasRsqrt
};
};
/** \internal
* \brief Template functor to compute the cosine of a scalar
* \sa class CwiseUnaryOp, ArrayBase::cos()
*/
template
<
typename
Scalar
>
struct
scalar_cos_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_cos_op
)
EIGEN_DEVICE_FUNC
inline
Scalar
operator
()
(
const
Scalar
&
a
)
const
{
return
numext
::
cos
(
a
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
inline
Packet
packetOp
(
const
Packet
&
a
)
const
{
return
internal
::
pcos
(
a
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_cos_op
<
Scalar
>
>
{
enum
{
Cost
=
5
*
NumTraits
<
Scalar
>::
MulCost
,
PacketAccess
=
packet_traits
<
Scalar
>::
HasCos
};
};
/** \internal
* \brief Template functor to compute the sine of a scalar
* \sa class CwiseUnaryOp, ArrayBase::sin()
*/
template
<
typename
Scalar
>
struct
scalar_sin_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_sin_op
)
EIGEN_DEVICE_FUNC
inline
const
Scalar
operator
()
(
const
Scalar
&
a
)
const
{
return
numext
::
sin
(
a
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
inline
Packet
packetOp
(
const
Packet
&
a
)
const
{
return
internal
::
psin
(
a
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_sin_op
<
Scalar
>
>
{
enum
{
Cost
=
5
*
NumTraits
<
Scalar
>::
MulCost
,
PacketAccess
=
packet_traits
<
Scalar
>::
HasSin
};
};
/** \internal
* \brief Template functor to compute the tan of a scalar
* \sa class CwiseUnaryOp, ArrayBase::tan()
*/
template
<
typename
Scalar
>
struct
scalar_tan_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_tan_op
)
EIGEN_DEVICE_FUNC
inline
const
Scalar
operator
()
(
const
Scalar
&
a
)
const
{
return
numext
::
tan
(
a
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
inline
Packet
packetOp
(
const
Packet
&
a
)
const
{
return
internal
::
ptan
(
a
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_tan_op
<
Scalar
>
>
{
enum
{
Cost
=
5
*
NumTraits
<
Scalar
>::
MulCost
,
PacketAccess
=
packet_traits
<
Scalar
>::
HasTan
};
};
/** \internal
* \brief Template functor to compute the arc cosine of a scalar
* \sa class CwiseUnaryOp, ArrayBase::acos()
*/
template
<
typename
Scalar
>
struct
scalar_acos_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_acos_op
)
EIGEN_DEVICE_FUNC
inline
const
Scalar
operator
()
(
const
Scalar
&
a
)
const
{
return
numext
::
acos
(
a
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
inline
Packet
packetOp
(
const
Packet
&
a
)
const
{
return
internal
::
pacos
(
a
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_acos_op
<
Scalar
>
>
{
enum
{
Cost
=
5
*
NumTraits
<
Scalar
>::
MulCost
,
PacketAccess
=
packet_traits
<
Scalar
>::
HasACos
};
};
/** \internal
* \brief Template functor to compute the arc sine of a scalar
* \sa class CwiseUnaryOp, ArrayBase::asin()
*/
template
<
typename
Scalar
>
struct
scalar_asin_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_asin_op
)
EIGEN_DEVICE_FUNC
inline
const
Scalar
operator
()
(
const
Scalar
&
a
)
const
{
return
numext
::
asin
(
a
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
inline
Packet
packetOp
(
const
Packet
&
a
)
const
{
return
internal
::
pasin
(
a
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_asin_op
<
Scalar
>
>
{
enum
{
Cost
=
5
*
NumTraits
<
Scalar
>::
MulCost
,
PacketAccess
=
packet_traits
<
Scalar
>::
HasASin
};
};
/** \internal
* \brief Template functor to compute the atan of a scalar
* \sa class CwiseUnaryOp, ArrayBase::atan()
*/
template
<
typename
Scalar
>
struct
scalar_atan_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_atan_op
)
EIGEN_DEVICE_FUNC
inline
const
Scalar
operator
()
(
const
Scalar
&
a
)
const
{
return
numext
::
atan
(
a
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
inline
Packet
packetOp
(
const
Packet
&
a
)
const
{
return
internal
::
patan
(
a
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_atan_op
<
Scalar
>
>
{
enum
{
Cost
=
5
*
NumTraits
<
Scalar
>::
MulCost
,
PacketAccess
=
packet_traits
<
Scalar
>::
HasATan
};
};
/** \internal
* \brief Template functor to compute the tanh of a scalar
* \sa class CwiseUnaryOp, ArrayBase::tanh()
*/
template
<
typename
Scalar
>
struct
scalar_tanh_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_tanh_op
)
EIGEN_DEVICE_FUNC
inline
const
Scalar
operator
()(
const
Scalar
&
a
)
const
{
return
numext
::
tanh
(
a
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
inline
Packet
packetOp
(
const
Packet
&
x
)
const
{
return
ptanh
(
x
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_tanh_op
<
Scalar
>
>
{
enum
{
PacketAccess
=
packet_traits
<
Scalar
>::
HasTanh
,
Cost
=
(
(
EIGEN_FAST_MATH
&&
is_same
<
Scalar
,
float
>::
value
)
// The following numbers are based on the AVX implementation,
#ifdef EIGEN_VECTORIZE_FMA
// Haswell can issue 2 add/mul/madd per cycle.
// 9 pmadd, 2 pmul, 1 div, 2 other
?
(
2
*
NumTraits
<
Scalar
>::
AddCost
+
6
*
NumTraits
<
Scalar
>::
MulCost
+
scalar_div_cost
<
Scalar
,
packet_traits
<
Scalar
>::
HasDiv
>::
value
)
#else
?
(
11
*
NumTraits
<
Scalar
>::
AddCost
+
11
*
NumTraits
<
Scalar
>::
MulCost
+
scalar_div_cost
<
Scalar
,
packet_traits
<
Scalar
>::
HasDiv
>::
value
)
#endif
// This number assumes a naive implementation of tanh
:
(
6
*
NumTraits
<
Scalar
>::
AddCost
+
3
*
NumTraits
<
Scalar
>::
MulCost
+
2
*
scalar_div_cost
<
Scalar
,
packet_traits
<
Scalar
>::
HasDiv
>::
value
+
functor_traits
<
scalar_exp_op
<
Scalar
>
>::
Cost
))
};
};
/** \internal
* \brief Template functor to compute the sinh of a scalar
* \sa class CwiseUnaryOp, ArrayBase::sinh()
*/
template
<
typename
Scalar
>
struct
scalar_sinh_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_sinh_op
)
EIGEN_DEVICE_FUNC
inline
const
Scalar
operator
()
(
const
Scalar
&
a
)
const
{
return
numext
::
sinh
(
a
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
inline
Packet
packetOp
(
const
Packet
&
a
)
const
{
return
internal
::
psinh
(
a
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_sinh_op
<
Scalar
>
>
{
enum
{
Cost
=
5
*
NumTraits
<
Scalar
>::
MulCost
,
PacketAccess
=
packet_traits
<
Scalar
>::
HasSinh
};
};
/** \internal
* \brief Template functor to compute the cosh of a scalar
* \sa class CwiseUnaryOp, ArrayBase::cosh()
*/
template
<
typename
Scalar
>
struct
scalar_cosh_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_cosh_op
)
EIGEN_DEVICE_FUNC
inline
const
Scalar
operator
()
(
const
Scalar
&
a
)
const
{
return
numext
::
cosh
(
a
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
inline
Packet
packetOp
(
const
Packet
&
a
)
const
{
return
internal
::
pcosh
(
a
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_cosh_op
<
Scalar
>
>
{
enum
{
Cost
=
5
*
NumTraits
<
Scalar
>::
MulCost
,
PacketAccess
=
packet_traits
<
Scalar
>::
HasCosh
};
};
/** \internal
* \brief Template functor to compute the inverse of a scalar
* \sa class CwiseUnaryOp, Cwise::inverse()
*/
template
<
typename
Scalar
>
struct
scalar_inverse_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_inverse_op
)
EIGEN_DEVICE_FUNC
inline
Scalar
operator
()
(
const
Scalar
&
a
)
const
{
return
Scalar
(
1
)
/
a
;
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
inline
const
Packet
packetOp
(
const
Packet
&
a
)
const
{
return
internal
::
pdiv
(
pset1
<
Packet
>
(
Scalar
(
1
)),
a
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_inverse_op
<
Scalar
>
>
{
enum
{
Cost
=
NumTraits
<
Scalar
>::
MulCost
,
PacketAccess
=
packet_traits
<
Scalar
>::
HasDiv
};
};
/** \internal
* \brief Template functor to compute the square of a scalar
* \sa class CwiseUnaryOp, Cwise::square()
*/
template
<
typename
Scalar
>
struct
scalar_square_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_square_op
)
EIGEN_DEVICE_FUNC
inline
Scalar
operator
()
(
const
Scalar
&
a
)
const
{
return
a
*
a
;
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
inline
const
Packet
packetOp
(
const
Packet
&
a
)
const
{
return
internal
::
pmul
(
a
,
a
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_square_op
<
Scalar
>
>
{
enum
{
Cost
=
NumTraits
<
Scalar
>::
MulCost
,
PacketAccess
=
packet_traits
<
Scalar
>::
HasMul
};
};
/** \internal
* \brief Template functor to compute the cube of a scalar
* \sa class CwiseUnaryOp, Cwise::cube()
*/
template
<
typename
Scalar
>
struct
scalar_cube_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_cube_op
)
EIGEN_DEVICE_FUNC
inline
Scalar
operator
()
(
const
Scalar
&
a
)
const
{
return
a
*
a
*
a
;
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
inline
const
Packet
packetOp
(
const
Packet
&
a
)
const
{
return
internal
::
pmul
(
a
,
pmul
(
a
,
a
));
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_cube_op
<
Scalar
>
>
{
enum
{
Cost
=
2
*
NumTraits
<
Scalar
>::
MulCost
,
PacketAccess
=
packet_traits
<
Scalar
>::
HasMul
};
};
/** \internal
* \brief Template functor to compute the rounded value of a scalar
* \sa class CwiseUnaryOp, ArrayBase::round()
*/
template
<
typename
Scalar
>
struct
scalar_round_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_round_op
)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
Scalar
operator
()
(
const
Scalar
&
a
)
const
{
return
numext
::
round
(
a
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
inline
Packet
packetOp
(
const
Packet
&
a
)
const
{
return
internal
::
pround
(
a
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_round_op
<
Scalar
>
>
{
enum
{
Cost
=
NumTraits
<
Scalar
>::
MulCost
,
PacketAccess
=
packet_traits
<
Scalar
>::
HasRound
};
};
/** \internal
* \brief Template functor to compute the floor of a scalar
* \sa class CwiseUnaryOp, ArrayBase::floor()
*/
template
<
typename
Scalar
>
struct
scalar_floor_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_floor_op
)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
Scalar
operator
()
(
const
Scalar
&
a
)
const
{
return
numext
::
floor
(
a
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
inline
Packet
packetOp
(
const
Packet
&
a
)
const
{
return
internal
::
pfloor
(
a
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_floor_op
<
Scalar
>
>
{
enum
{
Cost
=
NumTraits
<
Scalar
>::
MulCost
,
PacketAccess
=
packet_traits
<
Scalar
>::
HasFloor
};
};
/** \internal
* \brief Template functor to compute the ceil of a scalar
* \sa class CwiseUnaryOp, ArrayBase::ceil()
*/
template
<
typename
Scalar
>
struct
scalar_ceil_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_ceil_op
)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
const
Scalar
operator
()
(
const
Scalar
&
a
)
const
{
return
numext
::
ceil
(
a
);
}
template
<
typename
Packet
>
EIGEN_DEVICE_FUNC
inline
Packet
packetOp
(
const
Packet
&
a
)
const
{
return
internal
::
pceil
(
a
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_ceil_op
<
Scalar
>
>
{
enum
{
Cost
=
NumTraits
<
Scalar
>::
MulCost
,
PacketAccess
=
packet_traits
<
Scalar
>::
HasCeil
};
};
/** \internal
* \brief Template functor to compute whether a scalar is NaN
* \sa class CwiseUnaryOp, ArrayBase::isnan()
*/
template
<
typename
Scalar
>
struct
scalar_isnan_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_isnan_op
)
typedef
bool
result_type
;
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
result_type
operator
()
(
const
Scalar
&
a
)
const
{
return
(
numext
::
isnan
)(
a
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_isnan_op
<
Scalar
>
>
{
enum
{
Cost
=
NumTraits
<
Scalar
>::
MulCost
,
PacketAccess
=
false
};
};
/** \internal
* \brief Template functor to check whether a scalar is +/-inf
* \sa class CwiseUnaryOp, ArrayBase::isinf()
*/
template
<
typename
Scalar
>
struct
scalar_isinf_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_isinf_op
)
typedef
bool
result_type
;
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
result_type
operator
()
(
const
Scalar
&
a
)
const
{
return
(
numext
::
isinf
)(
a
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_isinf_op
<
Scalar
>
>
{
enum
{
Cost
=
NumTraits
<
Scalar
>::
MulCost
,
PacketAccess
=
false
};
};
/** \internal
* \brief Template functor to check whether a scalar has a finite value
* \sa class CwiseUnaryOp, ArrayBase::isfinite()
*/
template
<
typename
Scalar
>
struct
scalar_isfinite_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_isfinite_op
)
typedef
bool
result_type
;
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
result_type
operator
()
(
const
Scalar
&
a
)
const
{
return
(
numext
::
isfinite
)(
a
);
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_isfinite_op
<
Scalar
>
>
{
enum
{
Cost
=
NumTraits
<
Scalar
>::
MulCost
,
PacketAccess
=
false
};
};
/** \internal
* \brief Template functor to compute the logical not of a boolean
*
* \sa class CwiseUnaryOp, ArrayBase::operator!
*/
template
<
typename
Scalar
>
struct
scalar_boolean_not_op
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_boolean_not_op
)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
bool
operator
()
(
const
bool
&
a
)
const
{
return
!
a
;
}
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_boolean_not_op
<
Scalar
>
>
{
enum
{
Cost
=
NumTraits
<
bool
>::
AddCost
,
PacketAccess
=
false
};
};
/** \internal
* \brief Template functor to compute the signum of a scalar
* \sa class CwiseUnaryOp, Cwise::sign()
*/
template
<
typename
Scalar
,
bool
iscpx
=
(
NumTraits
<
Scalar
>
::
IsComplex
!=
0
)
>
struct
scalar_sign_op
;
template
<
typename
Scalar
>
struct
scalar_sign_op
<
Scalar
,
false
>
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_sign_op
)
EIGEN_DEVICE_FUNC
inline
const
Scalar
operator
()
(
const
Scalar
&
a
)
const
{
return
Scalar
(
(
a
>
Scalar
(
0
))
-
(
a
<
Scalar
(
0
))
);
}
//TODO
//template <typename Packet>
//EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::psign(a); }
};
template
<
typename
Scalar
>
struct
scalar_sign_op
<
Scalar
,
true
>
{
EIGEN_EMPTY_STRUCT_CTOR
(
scalar_sign_op
)
EIGEN_DEVICE_FUNC
inline
const
Scalar
operator
()
(
const
Scalar
&
a
)
const
{
typedef
typename
NumTraits
<
Scalar
>::
Real
real_type
;
real_type
aa
=
numext
::
abs
(
a
);
if
(
aa
==
real_type
(
0
))
return
Scalar
(
0
);
aa
=
real_type
(
1
)
/
aa
;
return
Scalar
(
real
(
a
)
*
aa
,
imag
(
a
)
*
aa
);
}
//TODO
//template <typename Packet>
//EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::psign(a); }
};
template
<
typename
Scalar
>
struct
functor_traits
<
scalar_sign_op
<
Scalar
>
>
{
enum
{
Cost
=
NumTraits
<
Scalar
>::
IsComplex
?
(
8
*
NumTraits
<
Scalar
>::
MulCost
)
// roughly
:
(
3
*
NumTraits
<
Scalar
>::
AddCost
),
PacketAccess
=
packet_traits
<
Scalar
>::
HasSign
};
};
}
// end namespace internal
}
// end namespace Eigen
#endif // EIGEN_FUNCTORS_H
Prev
1
…
5
6
7
8
9
Next