My Marlin configs for Fabrikator Mini and CTC i3 Pro B
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

types.h 58KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763
  1. /**
  2. * Marlin 3D Printer Firmware
  3. * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
  4. *
  5. * Based on Sprinter and grbl.
  6. * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  20. *
  21. */
  22. #pragma once
  23. #include <math.h>
  24. #include <stddef.h>
  25. #include "../inc/MarlinConfigPre.h"
  26. //
  27. // Conditional type assignment magic. For example...
  28. //
  29. // typename IF<(MYOPT==12), int, float>::type myvar;
  30. //
  31. template <bool, class L, class R>
  32. struct IF { typedef R type; };
  33. template <class L, class R>
  34. struct IF<true, L, R> { typedef L type; };
  35. #define NUM_AXIS_GANG(V...) GANG_N(NUM_AXES, V)
  36. #define NUM_AXIS_CODE(V...) CODE_N(NUM_AXES, V)
  37. #define NUM_AXIS_LIST(V...) LIST_N(NUM_AXES, V)
  38. #define NUM_AXIS_LIST_1(V) LIST_N_1(NUM_AXES, V)
  39. #define NUM_AXIS_ARRAY(V...) { NUM_AXIS_LIST(V) }
  40. #define NUM_AXIS_ARRAY_1(V) { NUM_AXIS_LIST_1(V) }
  41. #define NUM_AXIS_ARGS(T...) NUM_AXIS_LIST(T x, T y, T z, T i, T j, T k, T u, T v, T w)
  42. #define NUM_AXIS_ELEM(O) NUM_AXIS_LIST(O.x, O.y, O.z, O.i, O.j, O.k, O.u, O.v, O.w)
  43. #define NUM_AXIS_DEFS(T,V) NUM_AXIS_LIST(T x=V, T y=V, T z=V, T i=V, T j=V, T k=V, T u=V, T v=V, T w=V)
  44. #define MAIN_AXIS_NAMES NUM_AXIS_LIST(X, Y, Z, I, J, K, U, V, W)
  45. #define MAIN_AXIS_MAP(F) MAP(F, MAIN_AXIS_NAMES)
  46. #define STR_AXES_MAIN NUM_AXIS_GANG("X", "Y", "Z", STR_I, STR_J, STR_K, STR_U, STR_V, STR_W)
  47. #define LOGICAL_AXIS_GANG(E,V...) NUM_AXIS_GANG(V) GANG_ITEM_E(E)
  48. #define LOGICAL_AXIS_CODE(E,V...) NUM_AXIS_CODE(V) CODE_ITEM_E(E)
  49. #define LOGICAL_AXIS_LIST(E,V...) NUM_AXIS_LIST(V) LIST_ITEM_E(E)
  50. #define LOGICAL_AXIS_LIST_1(V) NUM_AXIS_LIST_1(V) LIST_ITEM_E(V)
  51. #define LOGICAL_AXIS_ARRAY(E,V...) { LOGICAL_AXIS_LIST(E,V) }
  52. #define LOGICAL_AXIS_ARRAY_1(V) { LOGICAL_AXIS_LIST_1(V) }
  53. #define LOGICAL_AXIS_ARGS(T...) LOGICAL_AXIS_LIST(T e, T x, T y, T z, T i, T j, T k, T u, T v, T w)
  54. #define LOGICAL_AXIS_ELEM(O) LOGICAL_AXIS_LIST(O.e, O.x, O.y, O.z, O.i, O.j, O.k, O.u, O.v, O.w)
  55. #define LOGICAL_AXIS_DECL(T,V) LOGICAL_AXIS_LIST(T e=V, T x=V, T y=V, T z=V, T i=V, T j=V, T k=V, T u=V, T v=V, T w=V)
  56. #define LOGICAL_AXIS_NAMES LOGICAL_AXIS_LIST(E, X, Y, Z, I, J, K, U, V, W)
  57. #define LOGICAL_AXIS_MAP(F) MAP(F, LOGICAL_AXIS_NAMES)
  58. #define STR_AXES_LOGICAL LOGICAL_AXIS_GANG("E", "X", "Y", "Z", STR_I, STR_J, STR_K, STR_U, STR_V, STR_W)
  59. #define XYZ_GANG(V...) GANG_N(PRIMARY_LINEAR_AXES, V)
  60. #define XYZ_CODE(V...) CODE_N(PRIMARY_LINEAR_AXES, V)
  61. #define SECONDARY_AXIS_GANG(V...) GANG_N(SECONDARY_AXES, V)
  62. #define SECONDARY_AXIS_CODE(V...) CODE_N(SECONDARY_AXES, V)
  63. #if HAS_ROTATIONAL_AXES
  64. #define ROTATIONAL_AXIS_GANG(V...) GANG_N(ROTATIONAL_AXES, V)
  65. #endif
  66. #if HAS_EXTRUDERS
  67. #define LIST_ITEM_E(N) , N
  68. #define CODE_ITEM_E(N) ; N
  69. #define GANG_ITEM_E(N) N
  70. #else
  71. #define LIST_ITEM_E(N)
  72. #define CODE_ITEM_E(N)
  73. #define GANG_ITEM_E(N)
  74. #endif
  75. #define AXIS_COLLISION(L) (AXIS4_NAME == L || AXIS5_NAME == L || AXIS6_NAME == L || AXIS7_NAME == L || AXIS8_NAME == L || AXIS9_NAME == L)
  76. // General Flags for some number of states
  77. template<size_t N>
  78. struct Flags {
  79. typedef typename IF<(N>8), uint16_t, uint8_t>::type bits_t;
  80. typedef struct { bool b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1; } N8;
  81. typedef struct { bool b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1, b8:1, b9:1, b10:1, b11:1, b12:1, b13:1, b14:1, b15:1; } N16;
  82. union {
  83. bits_t b;
  84. typename IF<(N>8), N16, N8>::type flag;
  85. };
  86. void reset() { b = 0; }
  87. void set(const int n, const bool onoff) { onoff ? set(n) : clear(n); }
  88. void set(const int n) { b |= (bits_t)_BV(n); }
  89. void clear(const int n) { b &= ~(bits_t)_BV(n); }
  90. bool test(const int n) const { return TEST(b, n); }
  91. const bool operator[](const int n) { return test(n); }
  92. const bool operator[](const int n) const { return test(n); }
  93. int size() const { return sizeof(b); }
  94. };
  95. // Specialization for a single bool flag
  96. template<>
  97. struct Flags<1> {
  98. bool b;
  99. void reset() { b = false; }
  100. void set(const int n, const bool onoff) { onoff ? set(n) : clear(n); }
  101. void set(const int) { b = true; }
  102. void clear(const int) { b = false; }
  103. bool test(const int) const { return b; }
  104. bool& operator[](const int) { return b; }
  105. bool operator[](const int) const { return b; }
  106. int size() const { return sizeof(b); }
  107. };
  108. typedef Flags<8> flags_8_t;
  109. typedef Flags<16> flags_16_t;
  110. // Flags for some axis states, with per-axis aliases xyzijkuvwe
  111. typedef struct AxisFlags {
  112. union {
  113. struct Flags<LOGICAL_AXES> flags;
  114. struct { bool LOGICAL_AXIS_LIST(e:1, x:1, y:1, z:1, i:1, j:1, k:1, u:1, v:1, w:1); };
  115. };
  116. void reset() { flags.reset(); }
  117. void set(const int n) { flags.set(n); }
  118. void set(const int n, const bool onoff) { flags.set(n, onoff); }
  119. void clear(const int n) { flags.clear(n); }
  120. bool test(const int n) const { return flags.test(n); }
  121. bool operator[](const int n) { return flags[n]; }
  122. bool operator[](const int n) const { return flags[n]; }
  123. int size() const { return sizeof(flags); }
  124. } axis_flags_t;
  125. //
  126. // Enumerated axis indices
  127. //
  128. // - X_AXIS, Y_AXIS, and Z_AXIS should be used for axes in Cartesian space
  129. // - A_AXIS, B_AXIS, and C_AXIS should be used for Steppers, corresponding to XYZ on Cartesians
  130. // - X_HEAD, Y_HEAD, and Z_HEAD should be used for Steppers on Core kinematics
  131. //
  132. enum AxisEnum : uint8_t {
  133. // Linear axes may be controlled directly or indirectly
  134. NUM_AXIS_LIST(X_AXIS, Y_AXIS, Z_AXIS, I_AXIS, J_AXIS, K_AXIS, U_AXIS, V_AXIS, W_AXIS)
  135. // Extruder axes may be considered distinctly
  136. #define _EN_ITEM(N) , E##N##_AXIS
  137. REPEAT(EXTRUDERS, _EN_ITEM)
  138. #undef _EN_ITEM
  139. // Core also keeps toolhead directions
  140. #if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX)
  141. , X_HEAD, Y_HEAD, Z_HEAD
  142. #endif
  143. // Distinct axes, including all E and Core
  144. , NUM_AXIS_ENUMS
  145. // Most of the time we refer only to the single E_AXIS
  146. #if HAS_EXTRUDERS
  147. , E_AXIS = E0_AXIS
  148. #endif
  149. // A, B, and C are for DELTA, SCARA, etc.
  150. , A_AXIS = X_AXIS
  151. #if HAS_Y_AXIS
  152. , B_AXIS = Y_AXIS
  153. #endif
  154. #if HAS_Z_AXIS
  155. , C_AXIS = Z_AXIS
  156. #endif
  157. // To refer to all or none
  158. , ALL_AXES_ENUM = 0xFE, NO_AXIS_ENUM = 0xFF
  159. };
  160. typedef IF<(NUM_AXIS_ENUMS > 8), uint16_t, uint8_t>::type axis_bits_t;
  161. //
  162. // Loop over axes
  163. //
  164. #define LOOP_ABC(VAR) LOOP_S_LE_N(VAR, A_AXIS, C_AXIS)
  165. #define LOOP_NUM_AXES(VAR) LOOP_S_L_N(VAR, X_AXIS, NUM_AXES)
  166. #define LOOP_LOGICAL_AXES(VAR) LOOP_S_L_N(VAR, X_AXIS, LOGICAL_AXES)
  167. #define LOOP_DISTINCT_AXES(VAR) LOOP_S_L_N(VAR, X_AXIS, DISTINCT_AXES)
  168. #define LOOP_DISTINCT_E(VAR) LOOP_L_N(VAR, DISTINCT_E)
  169. //
  170. // feedRate_t is just a humble float
  171. //
  172. typedef float feedRate_t;
  173. //
  174. // celsius_t is the native unit of temperature. Signed to handle a disconnected thermistor value (-14).
  175. // For more resolition (e.g., for a chocolate printer) this may later be changed to Celsius x 100
  176. //
  177. typedef uint16_t raw_adc_t;
  178. typedef int16_t celsius_t;
  179. typedef float celsius_float_t;
  180. //
  181. // On AVR pointers are only 2 bytes so use 'const float &' for 'const float'
  182. //
  183. #ifdef __AVR__
  184. typedef const float & const_float_t;
  185. #else
  186. typedef const float const_float_t;
  187. #endif
  188. typedef const_float_t const_feedRate_t;
  189. typedef const_float_t const_celsius_float_t;
  190. // Conversion macros
  191. #define MMM_TO_MMS(MM_M) feedRate_t(static_cast<float>(MM_M) / 60.0f)
  192. #define MMS_TO_MMM(MM_S) (static_cast<float>(MM_S) * 60.0f)
  193. //
  194. // Coordinates structures for XY, XYZ, XYZE...
  195. //
  196. // Helpers
  197. #define _RECIP(N) ((N) ? 1.0f / static_cast<float>(N) : 0.0f)
  198. #define _ABS(N) ((N) < 0 ? -(N) : (N))
  199. #define _LS(N) (N = (T)(uint32_t(N) << v))
  200. #define _RS(N) (N = (T)(uint32_t(N) >> v))
  201. #define FI FORCE_INLINE
  202. // Forward declarations
  203. template<typename T> struct XYval;
  204. template<typename T> struct XYZval;
  205. template<typename T> struct XYZEval;
  206. typedef struct XYval<bool> xy_bool_t;
  207. typedef struct XYZval<bool> xyz_bool_t;
  208. typedef struct XYZEval<bool> xyze_bool_t;
  209. typedef struct XYval<char> xy_char_t;
  210. typedef struct XYZval<char> xyz_char_t;
  211. typedef struct XYZEval<char> xyze_char_t;
  212. typedef struct XYval<unsigned char> xy_uchar_t;
  213. typedef struct XYZval<unsigned char> xyz_uchar_t;
  214. typedef struct XYZEval<unsigned char> xyze_uchar_t;
  215. typedef struct XYval<int8_t> xy_int8_t;
  216. typedef struct XYZval<int8_t> xyz_int8_t;
  217. typedef struct XYZEval<int8_t> xyze_int8_t;
  218. typedef struct XYval<uint8_t> xy_uint8_t;
  219. typedef struct XYZval<uint8_t> xyz_uint8_t;
  220. typedef struct XYZEval<uint8_t> xyze_uint8_t;
  221. typedef struct XYval<int16_t> xy_int_t;
  222. typedef struct XYZval<int16_t> xyz_int_t;
  223. typedef struct XYZEval<int16_t> xyze_int_t;
  224. typedef struct XYval<uint16_t> xy_uint_t;
  225. typedef struct XYZval<uint16_t> xyz_uint_t;
  226. typedef struct XYZEval<uint16_t> xyze_uint_t;
  227. typedef struct XYval<int32_t> xy_long_t;
  228. typedef struct XYZval<int32_t> xyz_long_t;
  229. typedef struct XYZEval<int32_t> xyze_long_t;
  230. typedef struct XYval<uint32_t> xy_ulong_t;
  231. typedef struct XYZval<uint32_t> xyz_ulong_t;
  232. typedef struct XYZEval<uint32_t> xyze_ulong_t;
  233. typedef struct XYZval<volatile int32_t> xyz_vlong_t;
  234. typedef struct XYZEval<volatile int32_t> xyze_vlong_t;
  235. typedef struct XYval<float> xy_float_t;
  236. typedef struct XYZval<float> xyz_float_t;
  237. typedef struct XYZEval<float> xyze_float_t;
  238. typedef struct XYval<feedRate_t> xy_feedrate_t;
  239. typedef struct XYZval<feedRate_t> xyz_feedrate_t;
  240. typedef struct XYZEval<feedRate_t> xyze_feedrate_t;
  241. typedef xy_uint8_t xy_byte_t;
  242. typedef xyz_uint8_t xyz_byte_t;
  243. typedef xyze_uint8_t xyze_byte_t;
  244. typedef xyz_long_t abc_long_t;
  245. typedef xyze_long_t abce_long_t;
  246. typedef xyz_ulong_t abc_ulong_t;
  247. typedef xyze_ulong_t abce_ulong_t;
  248. typedef xy_float_t xy_pos_t;
  249. typedef xyz_float_t xyz_pos_t;
  250. typedef xyze_float_t xyze_pos_t;
  251. typedef xy_float_t ab_float_t;
  252. typedef xyz_float_t abc_float_t;
  253. typedef xyze_float_t abce_float_t;
  254. typedef ab_float_t ab_pos_t;
  255. typedef abc_float_t abc_pos_t;
  256. typedef abce_float_t abce_pos_t;
  257. // External conversion methods
  258. void toLogical(xy_pos_t &raw);
  259. void toLogical(xyz_pos_t &raw);
  260. void toLogical(xyze_pos_t &raw);
  261. void toNative(xy_pos_t &raw);
  262. void toNative(xyz_pos_t &raw);
  263. void toNative(xyze_pos_t &raw);
  264. //
  265. // Paired XY coordinates, counters, flags, etc.
  266. //
  267. template<typename T>
  268. struct XYval {
  269. union {
  270. struct { T x, y; };
  271. struct { T a, b; };
  272. T pos[2];
  273. };
  274. // Set all to 0
  275. FI void reset() { x = y = 0; }
  276. // Setters taking struct types and arrays
  277. FI void set(const T px) { x = px; }
  278. #if HAS_Y_AXIS
  279. FI void set(const T px, const T py) { x = px; y = py; }
  280. FI void set(const T (&arr)[XY]) { x = arr[0]; y = arr[1]; }
  281. #endif
  282. #if NUM_AXES > XY
  283. FI void set(const T (&arr)[NUM_AXES]) { x = arr[0]; y = arr[1]; }
  284. #endif
  285. #if LOGICAL_AXES > NUM_AXES
  286. FI void set(const T (&arr)[LOGICAL_AXES]) { x = arr[0]; y = arr[1]; }
  287. #if DISTINCT_AXES > LOGICAL_AXES
  288. FI void set(const T (&arr)[DISTINCT_AXES]) { x = arr[0]; y = arr[1]; }
  289. #endif
  290. #endif
  291. // Length reduced to one dimension
  292. FI T magnitude() const { return (T)sqrtf(x*x + y*y); }
  293. // Pointer to the data as a simple array
  294. FI operator T* () { return pos; }
  295. // If any element is true then it's true
  296. FI operator bool() { return x || y; }
  297. // Explicit copy and copies with conversion
  298. FI XYval<T> copy() const { return *this; }
  299. FI XYval<T> ABS() const { return { T(_ABS(x)), T(_ABS(y)) }; }
  300. FI XYval<int16_t> asInt() { return { int16_t(x), int16_t(y) }; }
  301. FI XYval<int16_t> asInt() const { return { int16_t(x), int16_t(y) }; }
  302. FI XYval<int32_t> asLong() { return { int32_t(x), int32_t(y) }; }
  303. FI XYval<int32_t> asLong() const { return { int32_t(x), int32_t(y) }; }
  304. FI XYval<int32_t> ROUNDL() { return { int32_t(LROUND(x)), int32_t(LROUND(y)) }; }
  305. FI XYval<int32_t> ROUNDL() const { return { int32_t(LROUND(x)), int32_t(LROUND(y)) }; }
  306. FI XYval<float> asFloat() { return { static_cast<float>(x), static_cast<float>(y) }; }
  307. FI XYval<float> asFloat() const { return { static_cast<float>(x), static_cast<float>(y) }; }
  308. FI XYval<float> reciprocal() const { return { _RECIP(x), _RECIP(y) }; }
  309. // Marlin workspace shifting is done with G92 and M206
  310. FI XYval<float> asLogical() const { XYval<float> o = asFloat(); toLogical(o); return o; }
  311. FI XYval<float> asNative() const { XYval<float> o = asFloat(); toNative(o); return o; }
  312. // Cast to a type with more fields by making a new object
  313. FI operator XYZval<T>() { return { x, y }; }
  314. FI operator XYZval<T>() const { return { x, y }; }
  315. FI operator XYZEval<T>() { return { x, y }; }
  316. FI operator XYZEval<T>() const { return { x, y }; }
  317. // Accessor via an AxisEnum (or any integer) [index]
  318. FI T& operator[](const int n) { return pos[n]; }
  319. FI const T& operator[](const int n) const { return pos[n]; }
  320. // Assignment operator overrides do the expected thing
  321. FI XYval<T>& operator= (const T v) { set(v, v ); return *this; }
  322. FI XYval<T>& operator= (const XYZval<T> &rs) { set(rs.x, rs.y); return *this; }
  323. FI XYval<T>& operator= (const XYZEval<T> &rs) { set(rs.x, rs.y); return *this; }
  324. // Override other operators to get intuitive behaviors
  325. FI XYval<T> operator+ (const XYval<T> &rs) const { XYval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; return ls; }
  326. FI XYval<T> operator+ (const XYval<T> &rs) { XYval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; return ls; }
  327. FI XYval<T> operator- (const XYval<T> &rs) const { XYval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; return ls; }
  328. FI XYval<T> operator- (const XYval<T> &rs) { XYval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; return ls; }
  329. FI XYval<T> operator* (const XYval<T> &rs) const { XYval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; return ls; }
  330. FI XYval<T> operator* (const XYval<T> &rs) { XYval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; return ls; }
  331. FI XYval<T> operator/ (const XYval<T> &rs) const { XYval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; }
  332. FI XYval<T> operator/ (const XYval<T> &rs) { XYval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; }
  333. FI XYval<T> operator+ (const XYZval<T> &rs) const { XYval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; return ls; }
  334. FI XYval<T> operator+ (const XYZval<T> &rs) { XYval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; return ls; }
  335. FI XYval<T> operator- (const XYZval<T> &rs) const { XYval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; return ls; }
  336. FI XYval<T> operator- (const XYZval<T> &rs) { XYval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; return ls; }
  337. FI XYval<T> operator* (const XYZval<T> &rs) const { XYval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; return ls; }
  338. FI XYval<T> operator* (const XYZval<T> &rs) { XYval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; return ls; }
  339. FI XYval<T> operator/ (const XYZval<T> &rs) const { XYval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; }
  340. FI XYval<T> operator/ (const XYZval<T> &rs) { XYval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; }
  341. FI XYval<T> operator+ (const XYZEval<T> &rs) const { XYval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; return ls; }
  342. FI XYval<T> operator+ (const XYZEval<T> &rs) { XYval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; return ls; }
  343. FI XYval<T> operator- (const XYZEval<T> &rs) const { XYval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; return ls; }
  344. FI XYval<T> operator- (const XYZEval<T> &rs) { XYval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; return ls; }
  345. FI XYval<T> operator* (const XYZEval<T> &rs) const { XYval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; return ls; }
  346. FI XYval<T> operator* (const XYZEval<T> &rs) { XYval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; return ls; }
  347. FI XYval<T> operator/ (const XYZEval<T> &rs) const { XYval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; }
  348. FI XYval<T> operator/ (const XYZEval<T> &rs) { XYval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; }
  349. FI XYval<T> operator* (const float &v) const { XYval<T> ls = *this; ls.x *= v; ls.y *= v; return ls; }
  350. FI XYval<T> operator* (const float &v) { XYval<T> ls = *this; ls.x *= v; ls.y *= v; return ls; }
  351. FI XYval<T> operator* (const int &v) const { XYval<T> ls = *this; ls.x *= v; ls.y *= v; return ls; }
  352. FI XYval<T> operator* (const int &v) { XYval<T> ls = *this; ls.x *= v; ls.y *= v; return ls; }
  353. FI XYval<T> operator/ (const float &v) const { XYval<T> ls = *this; ls.x /= v; ls.y /= v; return ls; }
  354. FI XYval<T> operator/ (const float &v) { XYval<T> ls = *this; ls.x /= v; ls.y /= v; return ls; }
  355. FI XYval<T> operator/ (const int &v) const { XYval<T> ls = *this; ls.x /= v; ls.y /= v; return ls; }
  356. FI XYval<T> operator/ (const int &v) { XYval<T> ls = *this; ls.x /= v; ls.y /= v; return ls; }
  357. FI XYval<T> operator>>(const int &v) const { XYval<T> ls = *this; _RS(ls.x); _RS(ls.y); return ls; }
  358. FI XYval<T> operator>>(const int &v) { XYval<T> ls = *this; _RS(ls.x); _RS(ls.y); return ls; }
  359. FI XYval<T> operator<<(const int &v) const { XYval<T> ls = *this; _LS(ls.x); _LS(ls.y); return ls; }
  360. FI XYval<T> operator<<(const int &v) { XYval<T> ls = *this; _LS(ls.x); _LS(ls.y); return ls; }
  361. FI const XYval<T> operator-() const { XYval<T> o = *this; o.x = -x; o.y = -y; return o; }
  362. FI XYval<T> operator-() { XYval<T> o = *this; o.x = -x; o.y = -y; return o; }
  363. // Modifier operators
  364. FI XYval<T>& operator+=(const XYval<T> &rs) { x += rs.x; y += rs.y; return *this; }
  365. FI XYval<T>& operator-=(const XYval<T> &rs) { x -= rs.x; y -= rs.y; return *this; }
  366. FI XYval<T>& operator*=(const XYval<T> &rs) { x *= rs.x; y *= rs.y; return *this; }
  367. FI XYval<T>& operator+=(const XYZval<T> &rs) { x += rs.x; y += rs.y; return *this; }
  368. FI XYval<T>& operator-=(const XYZval<T> &rs) { x -= rs.x; y -= rs.y; return *this; }
  369. FI XYval<T>& operator*=(const XYZval<T> &rs) { x *= rs.x; y *= rs.y; return *this; }
  370. FI XYval<T>& operator+=(const XYZEval<T> &rs) { x += rs.x; y += rs.y; return *this; }
  371. FI XYval<T>& operator-=(const XYZEval<T> &rs) { x -= rs.x; y -= rs.y; return *this; }
  372. FI XYval<T>& operator*=(const XYZEval<T> &rs) { x *= rs.x; y *= rs.y; return *this; }
  373. FI XYval<T>& operator*=(const float &v) { x *= v; y *= v; return *this; }
  374. FI XYval<T>& operator*=(const int &v) { x *= v; y *= v; return *this; }
  375. FI XYval<T>& operator>>=(const int &v) { _RS(x); _RS(y); return *this; }
  376. FI XYval<T>& operator<<=(const int &v) { _LS(x); _LS(y); return *this; }
  377. // Exact comparisons. For floats a "NEAR" operation may be better.
  378. FI bool operator==(const XYval<T> &rs) { return x == rs.x && y == rs.y; }
  379. FI bool operator==(const XYZval<T> &rs) { return x == rs.x && y == rs.y; }
  380. FI bool operator==(const XYZEval<T> &rs) { return x == rs.x && y == rs.y; }
  381. FI bool operator==(const XYval<T> &rs) const { return x == rs.x && y == rs.y; }
  382. FI bool operator==(const XYZval<T> &rs) const { return x == rs.x && y == rs.y; }
  383. FI bool operator==(const XYZEval<T> &rs) const { return x == rs.x && y == rs.y; }
  384. FI bool operator!=(const XYval<T> &rs) { return !operator==(rs); }
  385. FI bool operator!=(const XYZval<T> &rs) { return !operator==(rs); }
  386. FI bool operator!=(const XYZEval<T> &rs) { return !operator==(rs); }
  387. FI bool operator!=(const XYval<T> &rs) const { return !operator==(rs); }
  388. FI bool operator!=(const XYZval<T> &rs) const { return !operator==(rs); }
  389. FI bool operator!=(const XYZEval<T> &rs) const { return !operator==(rs); }
  390. };
  391. //
  392. // Linear Axes coordinates, counters, flags, etc.
  393. //
  394. template<typename T>
  395. struct XYZval {
  396. union {
  397. struct { T NUM_AXIS_ARGS(); };
  398. struct { T NUM_AXIS_LIST(a, b, c, _i, _j, _k, _u, _v, _w); };
  399. T pos[NUM_AXES];
  400. };
  401. // Set all to 0
  402. FI void reset() { NUM_AXIS_GANG(x =, y =, z =, i =, j =, k =, u =, v =, w =) 0; }
  403. // Setters taking struct types and arrays
  404. FI void set(const T px) { x = px; }
  405. FI void set(const T px, const T py) { x = px; y = py; }
  406. FI void set(const XYval<T> pxy) { x = pxy.x; y = pxy.y; }
  407. FI void set(const XYval<T> pxy, const T pz) { NUM_AXIS_CODE(x = pxy.x, y = pxy.y, z = pz, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP); }
  408. FI void set(const T (&arr)[XY]) { x = arr[0]; y = arr[1]; }
  409. #if HAS_Z_AXIS
  410. FI void set(const T (&arr)[NUM_AXES]) { NUM_AXIS_CODE(x = arr[0], y = arr[1], z = arr[2], i = arr[3], j = arr[4], k = arr[5], u = arr[6], v = arr[7], w = arr[8]); }
  411. FI void set(NUM_AXIS_ARGS(const T)) { NUM_AXIS_CODE(a = x, b = y, c = z, _i = i, _j = j, _k = k, _u = u, _v = v, _w = w ); }
  412. #endif
  413. #if LOGICAL_AXES > NUM_AXES
  414. FI void set(const T (&arr)[LOGICAL_AXES]) { NUM_AXIS_CODE(x = arr[0], y = arr[1], z = arr[2], i = arr[3], j = arr[4], k = arr[5], u = arr[6], v = arr[7], w = arr[8]); }
  415. FI void set(LOGICAL_AXIS_ARGS(const T)) { NUM_AXIS_CODE(a = x, b = y, c = z, _i = i, _j = j, _k = k, _u = u, _v = v, _w = w ); }
  416. #if DISTINCT_AXES > LOGICAL_AXES
  417. FI void set(const T (&arr)[DISTINCT_AXES]) { NUM_AXIS_CODE(x = arr[0], y = arr[1], z = arr[2], i = arr[3], j = arr[4], k = arr[5], u = arr[6], v = arr[7], w = arr[8]); }
  418. #endif
  419. #endif
  420. #if HAS_I_AXIS
  421. FI void set(const T px, const T py, const T pz) { x = px; y = py; z = pz; }
  422. #endif
  423. #if HAS_J_AXIS
  424. FI void set(const T px, const T py, const T pz, const T pi) { x = px; y = py; z = pz; i = pi; }
  425. #endif
  426. #if HAS_K_AXIS
  427. FI void set(const T px, const T py, const T pz, const T pi, const T pj) { x = px; y = py; z = pz; i = pi; j = pj; }
  428. #endif
  429. #if HAS_U_AXIS
  430. FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; }
  431. #endif
  432. #if HAS_V_AXIS
  433. FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pm) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; u = pu; }
  434. #endif
  435. #if HAS_W_AXIS
  436. FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pm, const T po) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; u = pu; v = pv; }
  437. #endif
  438. // Length reduced to one dimension
  439. FI T magnitude() const { return (T)sqrtf(NUM_AXIS_GANG(x*x, + y*y, + z*z, + i*i, + j*j, + k*k, + u*u, + v*v, + w*w)); }
  440. // Pointer to the data as a simple array
  441. FI operator T* () { return pos; }
  442. // If any element is true then it's true
  443. FI operator bool() { return NUM_AXIS_GANG(x, || y, || z, || i, || j, || k, || u, || v, || w); }
  444. // Explicit copy and copies with conversion
  445. FI XYZval<T> copy() const { XYZval<T> o = *this; return o; }
  446. FI XYZval<T> ABS() const { return NUM_AXIS_ARRAY(T(_ABS(x)), T(_ABS(y)), T(_ABS(z)), T(_ABS(i)), T(_ABS(j)), T(_ABS(k)), T(_ABS(u)), T(_ABS(v)), T(_ABS(w))); }
  447. FI XYZval<int16_t> asInt() { return NUM_AXIS_ARRAY(int16_t(x), int16_t(y), int16_t(z), int16_t(i), int16_t(j), int16_t(k), int16_t(u), int16_t(v), int16_t(w)); }
  448. FI XYZval<int16_t> asInt() const { return NUM_AXIS_ARRAY(int16_t(x), int16_t(y), int16_t(z), int16_t(i), int16_t(j), int16_t(k), int16_t(u), int16_t(v), int16_t(w)); }
  449. FI XYZval<int32_t> asLong() { return NUM_AXIS_ARRAY(int32_t(x), int32_t(y), int32_t(z), int32_t(i), int32_t(j), int32_t(k), int32_t(u), int32_t(v), int32_t(w)); }
  450. FI XYZval<int32_t> asLong() const { return NUM_AXIS_ARRAY(int32_t(x), int32_t(y), int32_t(z), int32_t(i), int32_t(j), int32_t(k), int32_t(u), int32_t(v), int32_t(w)); }
  451. FI XYZval<int32_t> ROUNDL() { return NUM_AXIS_ARRAY(int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(i)), int32_t(LROUND(j)), int32_t(LROUND(k)), int32_t(LROUND(u)), int32_t(LROUND(v)), int32_t(LROUND(w))); }
  452. FI XYZval<int32_t> ROUNDL() const { return NUM_AXIS_ARRAY(int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(i)), int32_t(LROUND(j)), int32_t(LROUND(k)), int32_t(LROUND(u)), int32_t(LROUND(v)), int32_t(LROUND(w))); }
  453. FI XYZval<float> asFloat() { return NUM_AXIS_ARRAY(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(i), static_cast<float>(j), static_cast<float>(k), static_cast<float>(u), static_cast<float>(v), static_cast<float>(w)); }
  454. FI XYZval<float> asFloat() const { return NUM_AXIS_ARRAY(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(i), static_cast<float>(j), static_cast<float>(k), static_cast<float>(u), static_cast<float>(v), static_cast<float>(w)); }
  455. FI XYZval<float> reciprocal() const { return NUM_AXIS_ARRAY(_RECIP(x), _RECIP(y), _RECIP(z), _RECIP(i), _RECIP(j), _RECIP(k), _RECIP(u), _RECIP(v), _RECIP(w)); }
  456. // Marlin workspace shifting is done with G92 and M206
  457. FI XYZval<float> asLogical() const { XYZval<float> o = asFloat(); toLogical(o); return o; }
  458. FI XYZval<float> asNative() const { XYZval<float> o = asFloat(); toNative(o); return o; }
  459. // In-place cast to types having fewer fields
  460. FI operator XYval<T>&() { return *(XYval<T>*)this; }
  461. FI operator const XYval<T>&() const { return *(const XYval<T>*)this; }
  462. // Cast to a type with more fields by making a new object
  463. FI operator XYZEval<T>() const { return NUM_AXIS_ARRAY(x, y, z, i, j, k, u, v, w); }
  464. // Accessor via an AxisEnum (or any integer) [index]
  465. FI T& operator[](const int n) { return pos[n]; }
  466. FI const T& operator[](const int n) const { return pos[n]; }
  467. // Assignment operator overrides do the expected thing
  468. FI XYZval<T>& operator= (const T v) { set(ARRAY_N_1(NUM_AXES, v)); return *this; }
  469. FI XYZval<T>& operator= (const XYval<T> &rs) { set(rs.x, rs.y ); return *this; }
  470. FI XYZval<T>& operator= (const XYZEval<T> &rs) { set(NUM_AXIS_ELEM(rs)); return *this; }
  471. // Override other operators to get intuitive behaviors
  472. FI XYZval<T> operator+ (const XYval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; }
  473. FI XYZval<T> operator+ (const XYval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; }
  474. FI XYZval<T> operator- (const XYval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; }
  475. FI XYZval<T> operator- (const XYval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; }
  476. FI XYZval<T> operator* (const XYval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; }
  477. FI XYZval<T> operator* (const XYval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; }
  478. FI XYZval<T> operator/ (const XYval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; }
  479. FI XYZval<T> operator/ (const XYval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; }
  480. FI XYZval<T> operator+ (const XYZval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; }
  481. FI XYZval<T> operator+ (const XYZval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; }
  482. FI XYZval<T> operator- (const XYZval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; }
  483. FI XYZval<T> operator- (const XYZval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; }
  484. FI XYZval<T> operator* (const XYZval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; }
  485. FI XYZval<T> operator* (const XYZval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; }
  486. FI XYZval<T> operator/ (const XYZval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; }
  487. FI XYZval<T> operator/ (const XYZval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; }
  488. FI XYZval<T> operator+ (const XYZEval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; }
  489. FI XYZval<T> operator+ (const XYZEval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; }
  490. FI XYZval<T> operator- (const XYZEval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; }
  491. FI XYZval<T> operator- (const XYZEval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; }
  492. FI XYZval<T> operator* (const XYZEval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; }
  493. FI XYZval<T> operator* (const XYZEval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; }
  494. FI XYZval<T> operator/ (const XYZEval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; }
  495. FI XYZval<T> operator/ (const XYZEval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; }
  496. FI XYZval<T> operator* (const float &v) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; }
  497. FI XYZval<T> operator* (const float &v) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; }
  498. FI XYZval<T> operator* (const int &v) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; }
  499. FI XYZval<T> operator* (const int &v) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; }
  500. FI XYZval<T> operator/ (const float &v) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; }
  501. FI XYZval<T> operator/ (const float &v) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; }
  502. FI XYZval<T> operator/ (const int &v) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; }
  503. FI XYZval<T> operator/ (const int &v) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; }
  504. FI XYZval<T> operator>>(const int &v) const { XYZval<T> ls = *this; NUM_AXIS_CODE(_RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k), _RS(ls.u), _RS(ls.v), _RS(ls.w) ); return ls; }
  505. FI XYZval<T> operator>>(const int &v) { XYZval<T> ls = *this; NUM_AXIS_CODE(_RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k), _RS(ls.u), _RS(ls.v), _RS(ls.w) ); return ls; }
  506. FI XYZval<T> operator<<(const int &v) const { XYZval<T> ls = *this; NUM_AXIS_CODE(_LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k), _LS(ls.u), _LS(ls.v), _LS(ls.w) ); return ls; }
  507. FI XYZval<T> operator<<(const int &v) { XYZval<T> ls = *this; NUM_AXIS_CODE(_LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k), _LS(ls.u), _LS(ls.v), _LS(ls.w) ); return ls; }
  508. FI const XYZval<T> operator-() const { XYZval<T> o = *this; NUM_AXIS_CODE(o.x = -x, o.y = -y, o.z = -z, o.i = -i, o.j = -j, o.k = -k, o.u = -u, o.v = -v, o.w = -w); return o; }
  509. FI XYZval<T> operator-() { XYZval<T> o = *this; NUM_AXIS_CODE(o.x = -x, o.y = -y, o.z = -z, o.i = -i, o.j = -j, o.k = -k, o.u = -u, o.v = -v, o.w = -w); return o; }
  510. // Modifier operators
  511. FI XYZval<T>& operator+=(const XYval<T> &rs) { NUM_AXIS_CODE(x += rs.x, y += rs.y, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP ); return *this; }
  512. FI XYZval<T>& operator-=(const XYval<T> &rs) { NUM_AXIS_CODE(x -= rs.x, y -= rs.y, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP ); return *this; }
  513. FI XYZval<T>& operator*=(const XYval<T> &rs) { NUM_AXIS_CODE(x *= rs.x, y *= rs.y, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP ); return *this; }
  514. FI XYZval<T>& operator/=(const XYval<T> &rs) { NUM_AXIS_CODE(x /= rs.x, y /= rs.y, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP ); return *this; }
  515. FI XYZval<T>& operator+=(const XYZval<T> &rs) { NUM_AXIS_CODE(x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k, u += rs.u, v += rs.v, w += rs.w); return *this; }
  516. FI XYZval<T>& operator-=(const XYZval<T> &rs) { NUM_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k, u -= rs.u, v -= rs.v, w -= rs.w); return *this; }
  517. FI XYZval<T>& operator*=(const XYZval<T> &rs) { NUM_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k, u *= rs.u, v *= rs.v, w *= rs.w); return *this; }
  518. FI XYZval<T>& operator/=(const XYZval<T> &rs) { NUM_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k, u /= rs.u, v /= rs.v, w /= rs.w); return *this; }
  519. FI XYZval<T>& operator+=(const XYZEval<T> &rs) { NUM_AXIS_CODE(x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k, u += rs.u, v += rs.v, w += rs.w); return *this; }
  520. FI XYZval<T>& operator-=(const XYZEval<T> &rs) { NUM_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k, u -= rs.u, v -= rs.v, w -= rs.w); return *this; }
  521. FI XYZval<T>& operator*=(const XYZEval<T> &rs) { NUM_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k, u *= rs.u, v *= rs.v, w *= rs.w); return *this; }
  522. FI XYZval<T>& operator/=(const XYZEval<T> &rs) { NUM_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k, u /= rs.u, v /= rs.v, w /= rs.w); return *this; }
  523. FI XYZval<T>& operator*=(const float &v) { NUM_AXIS_CODE(x *= v, y *= v, z *= v, i *= v, j *= v, k *= v, u *= v, v *= v, w *= v); return *this; }
  524. FI XYZval<T>& operator*=(const int &v) { NUM_AXIS_CODE(x *= v, y *= v, z *= v, i *= v, j *= v, k *= v, u *= v, v *= v, w *= v); return *this; }
  525. FI XYZval<T>& operator>>=(const int &v) { NUM_AXIS_CODE(_RS(x), _RS(y), _RS(z), _RS(i), _RS(j), _RS(k), _RS(u), _RS(v), _RS(w)); return *this; }
  526. FI XYZval<T>& operator<<=(const int &v) { NUM_AXIS_CODE(_LS(x), _LS(y), _LS(z), _LS(i), _LS(j), _LS(k), _LS(u), _LS(v), _LS(w)); return *this; }
  527. // Exact comparisons. For floats a "NEAR" operation may be better.
  528. FI bool operator==(const XYZEval<T> &rs) { return true NUM_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); }
  529. FI bool operator==(const XYZEval<T> &rs) const { return true NUM_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); }
  530. FI bool operator!=(const XYZEval<T> &rs) { return !operator==(rs); }
  531. FI bool operator!=(const XYZEval<T> &rs) const { return !operator==(rs); }
  532. };
  533. //
  534. // Logical Axes coordinates, counters, etc.
  535. //
  536. template<typename T>
  537. struct XYZEval {
  538. union {
  539. struct { T LOGICAL_AXIS_ARGS(); };
  540. struct { T LOGICAL_AXIS_LIST(_e, a, b, c, _i, _j, _k, _u, _v, _w); };
  541. T pos[LOGICAL_AXES];
  542. };
  543. // Reset all to 0
  544. FI void reset() { LOGICAL_AXIS_GANG(e =, x =, y =, z =, i =, j =, k =, u =, v =, w =) 0; }
  545. // Setters for some number of linear axes, not all
  546. FI void set(const T px) { x = px; }
  547. FI void set(const T px, const T py) { x = px; y = py; }
  548. #if HAS_I_AXIS
  549. FI void set(const T px, const T py, const T pz) { x = px; y = py; z = pz; }
  550. #endif
  551. #if HAS_J_AXIS
  552. FI void set(const T px, const T py, const T pz, const T pi) { x = px; y = py; z = pz; i = pi; }
  553. #endif
  554. #if HAS_K_AXIS
  555. FI void set(const T px, const T py, const T pz, const T pi, const T pj) { x = px; y = py; z = pz; i = pi; j = pj; }
  556. #endif
  557. #if HAS_U_AXIS
  558. FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; }
  559. #endif
  560. #if HAS_V_AXIS
  561. FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pm) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; u = pu; }
  562. #endif
  563. #if HAS_W_AXIS
  564. FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pm, const T po) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; u = pm; v = pv; }
  565. #endif
  566. // Setters taking struct types and arrays
  567. FI void set(const XYval<T> pxy) { x = pxy.x; y = pxy.y; }
  568. FI void set(const XYZval<T> pxyz) { set(NUM_AXIS_ELEM(pxyz)); }
  569. #if HAS_Z_AXIS
  570. FI void set(NUM_AXIS_ARGS(const T)) { NUM_AXIS_CODE(a = x, b = y, c = z, _i = i, _j = j, _k = k, _u = u, _v = v, _w = w); }
  571. #endif
  572. FI void set(const XYval<T> pxy, const T pz) { set(pxy); TERN_(HAS_Z_AXIS, z = pz); }
  573. #if LOGICAL_AXES > NUM_AXES
  574. FI void set(const XYval<T> pxy, const T pz, const T pe) { set(pxy, pz); e = pe; }
  575. FI void set(const XYZval<T> pxyz, const T pe) { set(pxyz); e = pe; }
  576. FI void set(LOGICAL_AXIS_ARGS(const T)) { LOGICAL_AXIS_CODE(_e = e, a = x, b = y, c = z, _i = i, _j = j, _k = k, _u = u, _v = v, _w = w); }
  577. #endif
  578. // Length reduced to one dimension
  579. FI T magnitude() const { return (T)sqrtf(LOGICAL_AXIS_GANG(+ e*e, + x*x, + y*y, + z*z, + i*i, + j*j, + k*k, + u*u, + v*v, + w*w)); }
  580. // Pointer to the data as a simple array
  581. FI operator T* () { return pos; }
  582. // If any element is true then it's true
  583. FI operator bool() { return 0 LOGICAL_AXIS_GANG(|| e, || x, || y, || z, || i, || j, || k, || u, || v, || w); }
  584. // Explicit copy and copies with conversion
  585. FI XYZEval<T> copy() const { XYZEval<T> v = *this; return v; }
  586. FI XYZEval<T> ABS() const { return LOGICAL_AXIS_ARRAY(T(_ABS(e)), T(_ABS(x)), T(_ABS(y)), T(_ABS(z)), T(_ABS(i)), T(_ABS(j)), T(_ABS(k)), T(_ABS(u)), T(_ABS(v)), T(_ABS(w))); }
  587. FI XYZEval<int16_t> asInt() { return LOGICAL_AXIS_ARRAY(int16_t(e), int16_t(x), int16_t(y), int16_t(z), int16_t(i), int16_t(j), int16_t(k), int16_t(u), int16_t(v), int16_t(w)); }
  588. FI XYZEval<int16_t> asInt() const { return LOGICAL_AXIS_ARRAY(int16_t(e), int16_t(x), int16_t(y), int16_t(z), int16_t(i), int16_t(j), int16_t(k), int16_t(u), int16_t(v), int16_t(w)); }
  589. FI XYZEval<int32_t> asLong() { return LOGICAL_AXIS_ARRAY(int32_t(e), int32_t(x), int32_t(y), int32_t(z), int32_t(i), int32_t(j), int32_t(k), int32_t(u), int32_t(v), int32_t(w)); }
  590. FI XYZEval<int32_t> asLong() const { return LOGICAL_AXIS_ARRAY(int32_t(e), int32_t(x), int32_t(y), int32_t(z), int32_t(i), int32_t(j), int32_t(k), int32_t(u), int32_t(v), int32_t(w)); }
  591. FI XYZEval<int32_t> ROUNDL() { return LOGICAL_AXIS_ARRAY(int32_t(LROUND(e)), int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(i)), int32_t(LROUND(j)), int32_t(LROUND(k)), int32_t(LROUND(u)), int32_t(LROUND(v)), int32_t(LROUND(w))); }
  592. FI XYZEval<int32_t> ROUNDL() const { return LOGICAL_AXIS_ARRAY(int32_t(LROUND(e)), int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(i)), int32_t(LROUND(j)), int32_t(LROUND(k)), int32_t(LROUND(u)), int32_t(LROUND(v)), int32_t(LROUND(w))); }
  593. FI XYZEval<float> asFloat() { return LOGICAL_AXIS_ARRAY(static_cast<float>(e), static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(i), static_cast<float>(j), static_cast<float>(k), static_cast<float>(u), static_cast<float>(v), static_cast<float>(w)); }
  594. FI XYZEval<float> asFloat() const { return LOGICAL_AXIS_ARRAY(static_cast<float>(e), static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(i), static_cast<float>(j), static_cast<float>(k), static_cast<float>(u), static_cast<float>(v), static_cast<float>(w)); }
  595. FI XYZEval<float> reciprocal() const { return LOGICAL_AXIS_ARRAY(_RECIP(e), _RECIP(x), _RECIP(y), _RECIP(z), _RECIP(i), _RECIP(j), _RECIP(k), _RECIP(u), _RECIP(v), _RECIP(w)); }
  596. // Marlin workspace shifting is done with G92 and M206
  597. FI XYZEval<float> asLogical() const { XYZEval<float> o = asFloat(); toLogical(o); return o; }
  598. FI XYZEval<float> asNative() const { XYZEval<float> o = asFloat(); toNative(o); return o; }
  599. // In-place cast to types having fewer fields
  600. FI operator XYval<T>&() { return *(XYval<T>*)this; }
  601. FI operator const XYval<T>&() const { return *(const XYval<T>*)this; }
  602. FI operator XYZval<T>&() { return *(XYZval<T>*)this; }
  603. FI operator const XYZval<T>&() const { return *(const XYZval<T>*)this; }
  604. // Accessor via an AxisEnum (or any integer) [index]
  605. FI T& operator[](const int n) { return pos[n]; }
  606. FI const T& operator[](const int n) const { return pos[n]; }
  607. // Assignment operator overrides do the expected thing
  608. FI XYZEval<T>& operator= (const T v) { set(LOGICAL_AXIS_LIST_1(v)); return *this; }
  609. FI XYZEval<T>& operator= (const XYval<T> &rs) { set(rs.x, rs.y); return *this; }
  610. FI XYZEval<T>& operator= (const XYZval<T> &rs) { set(NUM_AXIS_ELEM(rs)); return *this; }
  611. // Override other operators to get intuitive behaviors
  612. FI XYZEval<T> operator+ (const XYval<T> &rs) const { XYZEval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; return ls; }
  613. FI XYZEval<T> operator+ (const XYval<T> &rs) { XYZEval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; return ls; }
  614. FI XYZEval<T> operator- (const XYval<T> &rs) const { XYZEval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; return ls; }
  615. FI XYZEval<T> operator- (const XYval<T> &rs) { XYZEval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; return ls; }
  616. FI XYZEval<T> operator* (const XYval<T> &rs) const { XYZEval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; return ls; }
  617. FI XYZEval<T> operator* (const XYval<T> &rs) { XYZEval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; return ls; }
  618. FI XYZEval<T> operator/ (const XYval<T> &rs) const { XYZEval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; }
  619. FI XYZEval<T> operator/ (const XYval<T> &rs) { XYZEval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; }
  620. FI XYZEval<T> operator+ (const XYZval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; }
  621. FI XYZEval<T> operator+ (const XYZval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; }
  622. FI XYZEval<T> operator- (const XYZval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; }
  623. FI XYZEval<T> operator- (const XYZval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; }
  624. FI XYZEval<T> operator* (const XYZval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; }
  625. FI XYZEval<T> operator* (const XYZval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; }
  626. FI XYZEval<T> operator/ (const XYZval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; }
  627. FI XYZEval<T> operator/ (const XYZval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; }
  628. FI XYZEval<T> operator+ (const XYZEval<T> &rs) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e += rs.e, ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; }
  629. FI XYZEval<T> operator+ (const XYZEval<T> &rs) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e += rs.e, ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; }
  630. FI XYZEval<T> operator- (const XYZEval<T> &rs) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e -= rs.e, ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; }
  631. FI XYZEval<T> operator- (const XYZEval<T> &rs) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e -= rs.e, ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; }
  632. FI XYZEval<T> operator* (const XYZEval<T> &rs) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= rs.e, ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; }
  633. FI XYZEval<T> operator* (const XYZEval<T> &rs) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= rs.e, ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; }
  634. FI XYZEval<T> operator/ (const XYZEval<T> &rs) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= rs.e, ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; }
  635. FI XYZEval<T> operator/ (const XYZEval<T> &rs) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= rs.e, ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; }
  636. FI XYZEval<T> operator* (const float &v) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= v, ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; }
  637. FI XYZEval<T> operator* (const float &v) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= v, ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; }
  638. FI XYZEval<T> operator* (const int &v) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= v, ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; }
  639. FI XYZEval<T> operator* (const int &v) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= v, ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; }
  640. FI XYZEval<T> operator/ (const float &v) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= v, ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; }
  641. FI XYZEval<T> operator/ (const float &v) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= v, ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; }
  642. FI XYZEval<T> operator/ (const int &v) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= v, ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; }
  643. FI XYZEval<T> operator/ (const int &v) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= v, ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; }
  644. FI XYZEval<T> operator>>(const int &v) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(_RS(ls.e), _RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k), _RS(ls.u), _RS(ls.v), _RS(ls.w) ); return ls; }
  645. FI XYZEval<T> operator>>(const int &v) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(_RS(ls.e), _RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k), _RS(ls.u), _RS(ls.v), _RS(ls.w) ); return ls; }
  646. FI XYZEval<T> operator<<(const int &v) const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(_LS(ls.e), _LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k), _LS(ls.u), _LS(ls.v), _LS(ls.w) ); return ls; }
  647. FI XYZEval<T> operator<<(const int &v) { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(_LS(ls.e), _LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k), _LS(ls.u), _LS(ls.v), _LS(ls.w) ); return ls; }
  648. FI const XYZEval<T> operator-() const { return LOGICAL_AXIS_ARRAY(-e, -x, -y, -z, -i, -j, -k, -u, -v, -w); }
  649. FI XYZEval<T> operator-() { return LOGICAL_AXIS_ARRAY(-e, -x, -y, -z, -i, -j, -k, -u, -v, -w); }
  650. // Modifier operators
  651. FI XYZEval<T>& operator+=(const XYval<T> &rs) { x += rs.x; y += rs.y; return *this; }
  652. FI XYZEval<T>& operator-=(const XYval<T> &rs) { x -= rs.x; y -= rs.y; return *this; }
  653. FI XYZEval<T>& operator*=(const XYval<T> &rs) { x *= rs.x; y *= rs.y; return *this; }
  654. FI XYZEval<T>& operator/=(const XYval<T> &rs) { x /= rs.x; y /= rs.y; return *this; }
  655. FI XYZEval<T>& operator+=(const XYZval<T> &rs) { NUM_AXIS_CODE(x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k, u += rs.u, v += rs.v, w += rs.w); return *this; }
  656. FI XYZEval<T>& operator-=(const XYZval<T> &rs) { NUM_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k, u -= rs.u, v -= rs.v, w -= rs.w); return *this; }
  657. FI XYZEval<T>& operator*=(const XYZval<T> &rs) { NUM_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k, u *= rs.u, v *= rs.v, w *= rs.w); return *this; }
  658. FI XYZEval<T>& operator/=(const XYZval<T> &rs) { NUM_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k, u /= rs.u, v /= rs.v, w /= rs.w); return *this; }
  659. FI XYZEval<T>& operator+=(const XYZEval<T> &rs) { LOGICAL_AXIS_CODE(e += rs.e, x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k, u += rs.u, v += rs.v, w += rs.w); return *this; }
  660. FI XYZEval<T>& operator-=(const XYZEval<T> &rs) { LOGICAL_AXIS_CODE(e -= rs.e, x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k, u -= rs.u, v -= rs.v, w -= rs.w); return *this; }
  661. FI XYZEval<T>& operator*=(const XYZEval<T> &rs) { LOGICAL_AXIS_CODE(e *= rs.e, x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k, u *= rs.u, v *= rs.v, w *= rs.w); return *this; }
  662. FI XYZEval<T>& operator/=(const XYZEval<T> &rs) { LOGICAL_AXIS_CODE(e /= rs.e, x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k, u /= rs.u, v /= rs.v, w /= rs.w); return *this; }
  663. FI XYZEval<T>& operator*=(const T &v) { LOGICAL_AXIS_CODE(e *= v, x *= v, y *= v, z *= v, i *= v, j *= v, k *= v, u *= v, v *= v, w *= v); return *this; }
  664. FI XYZEval<T>& operator>>=(const int &v) { LOGICAL_AXIS_CODE(_RS(e), _RS(x), _RS(y), _RS(z), _RS(i), _RS(j), _RS(k), _RS(u), _RS(v), _RS(w)); return *this; }
  665. FI XYZEval<T>& operator<<=(const int &v) { LOGICAL_AXIS_CODE(_LS(e), _LS(x), _LS(y), _LS(z), _LS(i), _LS(j), _LS(k), _LS(u), _LS(v), _LS(w)); return *this; }
  666. // Exact comparisons. For floats a "NEAR" operation may be better.
  667. FI bool operator==(const XYZval<T> &rs) { return true NUM_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); }
  668. FI bool operator==(const XYZval<T> &rs) const { return true NUM_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); }
  669. FI bool operator!=(const XYZval<T> &rs) { return !operator==(rs); }
  670. FI bool operator!=(const XYZval<T> &rs) const { return !operator==(rs); }
  671. };
  672. #undef _RECIP
  673. #undef _ABS
  674. #undef _LS
  675. #undef _RS
  676. #undef FI