Argon 0.1.0
Loading...
Searching...
No Matches
lane.hpp
1#pragma once
2#include "arm_simd.hpp"
3#include "arm_simd/helpers/scalar.hpp"
4#include "arm_simd/helpers/vec64.hpp"
5#include "features.h"
6#include "helpers/argon_for.hpp"
7
8#ifdef __ARM_FEATURE_MVE
9#define simd mve
10#else
11#define simd neon
12#endif
13
14#ifdef ARGON_PLATFORM_SIMDE
15#define ace
16#elifdef __clang__
17#define ace [[gnu::always_inline]] constexpr
18#else
19#define ace [[gnu::always_inline]] inline
20#endif
21
22namespace argon {
23template <typename T>
24class Vector;
25
26#ifdef ARGON_PLATFORM_MVE
27
28// MVE does not support lane manipulators, so we use the scalar type directly
29// for the lane type.
30
31template <size_t, typename VectorType>
32using ConstLane = simd::Scalar_t<VectorType>;
33
34template <typename VectorType>
35using Lane = simd::Scalar_t<VectorType>;
36
37#else
38
43template <size_t LaneIndex, typename VectorType>
44class ConstLane {
45 using scalar_type = simd::Scalar_t<VectorType>;
46 using type = ConstLane<LaneIndex, VectorType>;
47 using argon_type = helpers::ArgonFor_t<VectorType>;
48
49 public:
50 ace ConstLane(VectorType& vec) : vec_{vec} {}
51 ace operator scalar_type() const { return Get(); }
52 ace argon_type operator=(const scalar_type b) { return vec_ = Set(b); }
53 ace argon_type Load(const scalar_type* ptr) {
54#ifdef ARGON_PLATFORM_MVE
55 Set(*ptr);
56#else
57 if constexpr (simd::is_quadword_v<VectorType>) {
58 return simd::load1_lane_quad<LaneIndex>(ptr, vec_);
59 } else {
60 return simd::load1_lane<LaneIndex>(ptr, vec_);
61 }
62#endif
63 }
64 ace argon_type Set(const scalar_type b) { return simd::set_lane<LaneIndex>(vec_, b); }
65 ace scalar_type Get() const { return simd::get_lane<LaneIndex>(vec_); }
66
67#if __ARM_ARCH >= 8
68 ace VectorType vec() { return vec_; }
69 ace const int lane() { return LaneIndex; }
70#else
71 ace neon::Vec64_t<scalar_type> vec() {
72 if constexpr (simd::is_doubleword_v<VectorType>) {
73 return vec_;
74 } else if constexpr (simd::is_quadword_v<VectorType>) {
75 if constexpr (LaneIndex >= ArgonHalf<scalar_type>::lanes) {
76 return simd::get_high(vec_);
77 } else {
78 return simd::get_low(vec_);
79 }
80 }
81 }
82 ace int lane() {
83 if constexpr (simd::is_doubleword_v<VectorType>) {
84 return LaneIndex;
85 } else if constexpr (simd::is_quadword_v<VectorType>) {
86 if (LaneIndex >= ArgonHalf<scalar_type>::lanes) {
87 return (LaneIndex - ArgonHalf<scalar_type>::lanes);
88 } else {
89 return LaneIndex;
90 }
91 }
92 }
93#endif
94 private:
95 VectorType& vec_;
96};
97
101template <typename VectorType>
102class Lane {
103 using scalar_type = simd::Scalar_t<VectorType>;
104 using type = Lane<VectorType>;
105 using argon_type = helpers::ArgonFor_t<VectorType>;
106
107 public:
108 ace Lane(VectorType& vec, const int lane) : vec_{vec}, lane_{lane} {}
109 ace argon_type operator=(const scalar_type b) { return vec_ = Set(b); }
110 [[nodiscard]] ace argon_type Load(const scalar_type* ptr) {
111#ifdef ARGON_PLATFORM_MVE
112 return Set(*ptr);
113#else
114 return simd::load1_lane(vec_, lane_, ptr);
115#endif
116 }
117 ace argon_type Set(const scalar_type b) { return simd::set_lane(vec_, lane_, b); }
118 ace scalar_type Get() const { return simd::get_lane(vec_, lane_); }
119 ace operator scalar_type() const { return Get(); }
120
121#if __ARM_ARCH >= 8
122 ace VectorType vec() { return vec_; }
123 ace const int lane() { return lane_; }
124#else
125 ace neon::Vec64_t<scalar_type> vec() {
126 if constexpr (simd::is_doubleword_v<VectorType>) {
127 return vec_;
128 } else if constexpr (simd::is_quadword_v<VectorType>) {
129 if (lane_ >= ArgonHalf<scalar_type>::lanes) {
130 return simd::get_high(vec_);
131 } else {
132 return simd::get_low(vec_);
133 }
134 }
135 }
136 ace int lane() {
137 if constexpr (simd::is_doubleword_v<VectorType>) {
138 return lane_;
139 } else if constexpr (simd::is_quadword_v<VectorType>) {
140 if (lane_ >= ArgonHalf<scalar_type>::lanes) {
141 return (lane_ - ArgonHalf<scalar_type>::lanes);
142 } else {
143 return lane_;
144 }
145 }
146 }
147#endif
148
149 private:
150 VectorType& vec_;
151 int lane_;
152
153 // friend class Vector<VectorType>;
154};
155#endif
156} // namespace argon
Definition argon_half.hpp:11
Represents a single lane of a SIMD vector, where the lane's index is known at compile time.
Definition lane.hpp:44
Represents a single lane of a SIMD vector.
Definition lane.hpp:102
Represents a SIMD vector with various operations.
Definition vector.hpp:50
Header file for SIMD features and platform detection.
typename ArgonFor< std::remove_cv_t< T > >::type ArgonFor_t
Helper alias to get the Argon type for a given vector type.
Definition argon_for.hpp:45