// =====================================================================================================================
//  fennec-test, a program to execute unit tests for fennec
//  Copyright © 2025 - 2026  Medusa Slockbower
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================


#ifndef FENNEC_TEST_VECTOR_H
#define FENNEC_TEST_VECTOR_H

#include <iostream>

#include <fennec/math/vector.h>

#include "../../test.h"

namespace fennec::test
{

	inline void fennec_test_math_vector()
	{
		fennec_test_section("component_count");

		fennec_test_spacer(1);

		fennec_test_run((component_count_v<bvec2>        == 2), true);
		fennec_test_run((component_count_v<bvec3>        == 3), true);
		fennec_test_run((component_count_v<bvec4>        == 4), true);
		fennec_test_run((component_count_v<bvec2&>       == 2), true);
		fennec_test_run((component_count_v<bvec3&>       == 3), true);
		fennec_test_run((component_count_v<bvec4&>       == 4), true);
		fennec_test_run((component_count_v<bvec2&&>      == 2), true);
		fennec_test_run((component_count_v<bvec3&&>      == 3), true);
		fennec_test_run((component_count_v<bvec4&&>      == 4), true);
		fennec_test_run((component_count_v<const bvec2&> == 2), true);
		fennec_test_run((component_count_v<const bvec3&> == 3), true);
		fennec_test_run((component_count_v<const bvec4&> == 4), true);

		fennec_test_spacer(1);

		fennec_test_run((component_count_v<ivec2>        == 2), true);
		fennec_test_run((component_count_v<ivec3>        == 3), true);
		fennec_test_run((component_count_v<ivec4>        == 4), true);
		fennec_test_run((component_count_v<ivec2&>       == 2), true);
		fennec_test_run((component_count_v<ivec3&>       == 3), true);
		fennec_test_run((component_count_v<ivec4&>       == 4), true);
		fennec_test_run((component_count_v<ivec2&&>      == 2), true);
		fennec_test_run((component_count_v<ivec3&&>      == 3), true);
		fennec_test_run((component_count_v<ivec4&&>      == 4), true);
		fennec_test_run((component_count_v<const ivec2&> == 2), true);
		fennec_test_run((component_count_v<const ivec3&> == 3), true);
		fennec_test_run((component_count_v<const ivec4&> == 4), true);

		fennec_test_spacer(1);

		fennec_test_run((component_count_v<uvec2>        == 2), true);
		fennec_test_run((component_count_v<uvec3>        == 3), true);
		fennec_test_run((component_count_v<uvec4>        == 4), true);
		fennec_test_run((component_count_v<uvec2&>       == 2), true);
		fennec_test_run((component_count_v<uvec3&>       == 3), true);
		fennec_test_run((component_count_v<uvec4&>       == 4), true);
		fennec_test_run((component_count_v<uvec2&&>      == 2), true);
		fennec_test_run((component_count_v<uvec3&&>      == 3), true);
		fennec_test_run((component_count_v<uvec4&&>      == 4), true);
		fennec_test_run((component_count_v<const uvec2&> == 2), true);
		fennec_test_run((component_count_v<const uvec3&> == 3), true);
		fennec_test_run((component_count_v<const uvec4&> == 4), true);

		fennec_test_spacer(1);

		fennec_test_run((component_count_v<vec2>        == 2), true);
		fennec_test_run((component_count_v<vec3>        == 3), true);
		fennec_test_run((component_count_v<vec4>        == 4), true);
		fennec_test_run((component_count_v<vec2&>       == 2), true);
		fennec_test_run((component_count_v<vec3&>       == 3), true);
		fennec_test_run((component_count_v<vec4&>       == 4), true);
		fennec_test_run((component_count_v<vec2&&>      == 2), true);
		fennec_test_run((component_count_v<vec3&&>      == 3), true);
		fennec_test_run((component_count_v<vec4&&>      == 4), true);
		fennec_test_run((component_count_v<const vec2&> == 2), true);
		fennec_test_run((component_count_v<const vec3&> == 3), true);
		fennec_test_run((component_count_v<const vec4&> == 4), true);

		fennec_test_spacer(1);

		fennec_test_run((component_count_v<dvec2>        == 2), true);
		fennec_test_run((component_count_v<dvec3>        == 3), true);
		fennec_test_run((component_count_v<dvec4>        == 4), true);
		fennec_test_run((component_count_v<dvec2&>       == 2), true);
		fennec_test_run((component_count_v<dvec3&>       == 3), true);
		fennec_test_run((component_count_v<dvec4&>       == 4), true);
		fennec_test_run((component_count_v<dvec2&&>      == 2), true);
		fennec_test_run((component_count_v<dvec3&&>      == 3), true);
		fennec_test_run((component_count_v<dvec4&&>      == 4), true);
		fennec_test_run((component_count_v<const dvec2&> == 2), true);
		fennec_test_run((component_count_v<const dvec3&> == 3), true);
		fennec_test_run((component_count_v<const dvec4&> == 4), true);

		fennec_test_spacer(2);



		fennec_test_section("vec2 equivalency operator");

		fennec_test_spacer(1);

		fennec_test_run((vec2() == vec2()), true);
		fennec_test_run((vec2() != vec2()), false);

		fennec_test_spacer(2);



		fennec_test_section("vec2 constructors");

		fennec_test_spacer(1);

		fennec_test_run(vec2(),                         vec2(0.0f, 0.0f));
		fennec_test_run(vec2(1.0f),                     vec2(1.0f, 1.0f));
		fennec_test_run(vec2(),                         vec2(0.0, 0.0));
		fennec_test_run(vec2(1.0),                      vec2(1.0, 1.0));
		fennec_test_run(vec2(),                         vec2(0, 0));
		fennec_test_run(vec2(1),                        vec2(1, 1));
		fennec_test_run(vec2(fennec::copy(vec2(1.0f))), vec2(1.0f));
		fennec_test_run(vec2(fennec::move(vec2(1.0f))), vec2(1.0f));

		fennec_test_spacer(2);



		fennec_test_section("vec2 swizzles");

		fennec_test_spacer(1);

		fennec_test_run(vec2(vec2(0, 1).xx), vec2(0, 0));
		fennec_test_run(vec2(vec2(0, 1).xy), vec2(0, 1));
		fennec_test_run(vec2(vec2(0, 1).yx), vec2(1, 0));
		fennec_test_run(vec2(vec2(0, 1).yy), vec2(1, 1));

		fennec_test_spacer(2);



		fennec_test_section("vec3 constructors");

		fennec_test_spacer(1);

		fennec_test_run(vec3(),                      vec3(0.0f, 0.0f, 0.0f));
		fennec_test_run(vec3(1.0f),                  vec3(1.0f, 1.0f, 1.0f));
		fennec_test_run(vec3(),                      vec3(0.0, 0.0, 0.0));
		fennec_test_run(vec3(1.0),                   vec3(1.0, 1.0, 1.0));
		fennec_test_run(vec3(),                      vec3(0, 0, 0));
		fennec_test_run(vec3(1),                     vec3(1, 1, 1));
		fennec_test_run(vec3(fennec::copy(vec3(1))), vec3(1));
		fennec_test_run(vec3(fennec::move(vec3(1))), vec3(1));

		fennec_test_spacer(2);



		fennec_test_section("vec3 swizzles");

		fennec_test_spacer(1);

		fennec_test_run(vec3(vec3(0, 1, 2).xxx), vec3(0, 0, 0));
		fennec_test_run(vec3(vec3(0, 1, 2).xxy), vec3(0, 0, 1));
		fennec_test_run(vec3(vec3(0, 1, 2).xxz), vec3(0, 0, 2));

		fennec_test_run(vec3(vec3(0, 1, 2).xyx), vec3(0, 1, 0));
		fennec_test_run(vec3(vec3(0, 1, 2).xyy), vec3(0, 1, 1));
		fennec_test_run(vec3(vec3(0, 1, 2).xyz), vec3(0, 1, 2));

		fennec_test_run(vec3(vec3(0, 1, 2).xzx), vec3(0, 2, 0));
		fennec_test_run(vec3(vec3(0, 1, 2).xzy), vec3(0, 2, 1));
		fennec_test_run(vec3(vec3(0, 1, 2).xzz), vec3(0, 2, 2));

		fennec_test_spacer(1);

		fennec_test_run(vec3(vec3(0, 1, 2).yxx), vec3(1, 0, 0));
		fennec_test_run(vec3(vec3(0, 1, 2).yxy), vec3(1, 0, 1));
		fennec_test_run(vec3(vec3(0, 1, 2).yxz), vec3(1, 0, 2));

		fennec_test_run(vec3(vec3(0, 1, 2).yyx), vec3(1, 1, 0));
		fennec_test_run(vec3(vec3(0, 1, 2).yyy), vec3(1, 1, 1));
		fennec_test_run(vec3(vec3(0, 1, 2).yyz), vec3(1, 1, 2));

		fennec_test_run(vec3(vec3(0, 1, 2).yzx), vec3(1, 2, 0));
		fennec_test_run(vec3(vec3(0, 1, 2).yzy), vec3(1, 2, 1));
		fennec_test_run(vec3(vec3(0, 1, 2).yzz), vec3(1, 2, 2));

		fennec_test_spacer(1);

		fennec_test_run(vec3(vec3(0, 1, 2).zxx), vec3(2, 0, 0));
		fennec_test_run(vec3(vec3(0, 1, 2).zxy), vec3(2, 0, 1));
		fennec_test_run(vec3(vec3(0, 1, 2).zxz), vec3(2, 0, 2));

		fennec_test_run(vec3(vec3(0, 1, 2).zyx), vec3(2, 1, 0));
		fennec_test_run(vec3(vec3(0, 1, 2).zyy), vec3(2, 1, 1));
		fennec_test_run(vec3(vec3(0, 1, 2).zyz), vec3(2, 1, 2));

		fennec_test_run(vec3(vec3(0, 1, 2).zzx), vec3(2, 2, 0));
		fennec_test_run(vec3(vec3(0, 1, 2).zzy), vec3(2, 2, 1));
		fennec_test_run(vec3(vec3(0, 1, 2).zzz), vec3(2, 2, 2));

		fennec_test_spacer(2);



		fennec_test_section("scalar-vector arithmetic operations");

		fennec_test_spacer(1);

		fennec_test_run(2.0 + vec2(1, 2),       vec2(3, 4));
		fennec_test_run(2.0 + vec3(1, 2, 3),    vec3(3, 4, 5));
		fennec_test_run(2.0 + vec4(1, 2, 3, 4), vec4(3, 4, 5, 6));

		fennec_test_spacer(2);

		fennec_test_run(2.0 - vec2(1, 2),       vec2(1, 0));
		fennec_test_run(2.0 - vec3(1, 2, 3),    vec3(1, 0, -1));
		fennec_test_run(2.0 - vec4(1, 2, 3, 4), vec4(1, 0, -1, -2));

		fennec_test_spacer(2);

		fennec_test_run(2.0 * vec2(1, 2),       vec2(2, 4));
		fennec_test_run(2.0 * vec3(1, 2, 3),    vec3(2, 4, 6));
		fennec_test_run(2.0 * vec4(1, 2, 3, 4), vec4(2, 4, 6, 8));

		fennec_test_spacer(2);

		fennec_test_run(2.0 / vec2(1, 2),       vec2(2.0, 1.0));
		fennec_test_run(2.0 / vec3(1, 2, 4),    vec3(2.0, 1.0, 0.5));
		fennec_test_run(2.0 / vec4(1, 2, 4, 8), vec4(2.0, 1.0, 0.5, 0.25));

		fennec_test_run(2 % ivec2(1, 2),       ivec2(0, 0));
		fennec_test_run(2 % ivec3(1, 2, 3),    ivec3(0, 0, 2));
		fennec_test_run(2 % ivec4(1, 2, 3, 4), ivec4(0, 0, 2, 2));

		fennec_test_spacer(2);



		fennec_test_section("vector-scalar arithmetic operations");

		fennec_test_spacer(1);

		fennec_test_run(vec2(1, 2)       + 2.0, vec2(3, 4));
		fennec_test_run(vec3(1, 2, 3)    + 2.0, vec3(3, 4, 5));
		fennec_test_run(vec4(1, 2, 3, 4) + 2.0, vec4(3, 4, 5, 6));

		fennec_test_spacer(2);

		fennec_test_run(vec2(1, 2)       - 2.0, vec2(-1, 0));
		fennec_test_run(vec3(1, 2, 3)    - 2.0, vec3(-1, 0, 1));
		fennec_test_run(vec4(1, 2, 3, 4) - 2.0, vec4(-1, 0, 1, 2));

		fennec_test_spacer(2);

		fennec_test_run(vec2(1, 2)       * 2.0, vec2(2, 4));
		fennec_test_run(vec3(1, 2, 3)    * 2.0, vec3(2, 4, 6));
		fennec_test_run(vec4(1, 2, 3, 4) * 2.0, vec4(2, 4, 6, 8));

		fennec_test_spacer(2);

		fennec_test_run(vec2(1, 2)       / 2.0, vec2(0.5, 1.0));
		fennec_test_run(vec3(1, 2, 4)    / 2.0, vec3(0.5, 1.0, 2.0));
		fennec_test_run(vec4(1, 2, 4, 8) / 2.0, vec4(0.5, 1.0, 2.0, 4.0));

		fennec_test_spacer(2);

		fennec_test_run(ivec2(1, 2)       % 2, ivec2(1, 0));
		fennec_test_run(ivec3(1, 2, 3)    % 2, ivec3(1, 0, 1));
		fennec_test_run(ivec4(1, 2, 3, 4) % 2, ivec4(1, 0, 1, 0));

		fennec_test_spacer(2);



		fennec_test_section("vector-scalar arithmetic assignment operations");

		fennec_test_spacer(1);

		fennec_test_run(([]() -> vec2 { vec2 v{ 1, 2 };       return v += 2.0; }()), vec2(3, 4));
		fennec_test_run(([]() -> vec3 { vec3 v{ 1, 2, 3 };    return v += 2.0; }()), vec3(3, 4, 5));
		fennec_test_run(([]() -> vec4 { vec4 v{ 1, 2, 3, 4 }; return v += 2.0; }()), vec4(3, 4, 5, 6));

		fennec_test_spacer(2);

		fennec_test_run(([]() -> vec2 { vec2 v{ 1, 2 };       return v -= 2.0; }()), vec2(-1, 0));
		fennec_test_run(([]() -> vec3 { vec3 v{ 1, 2, 3 };    return v -= 2.0; }()), vec3(-1, 0, 1));
		fennec_test_run(([]() -> vec4 { vec4 v{ 1, 2, 3, 4 }; return v -= 2.0; }()), vec4(-1, 0, 1, 2));

		fennec_test_spacer(2);

		fennec_test_run(([]() -> vec2 { vec2 v{ 1, 2 };       return v *= 2.0; }()), vec2(2, 4));
		fennec_test_run(([]() -> vec3 { vec3 v{ 1, 2, 3 };    return v *= 2.0; }()), vec3(2, 4, 6));
		fennec_test_run(([]() -> vec4 { vec4 v{ 1, 2, 3, 4 }; return v *= 2.0; }()), vec4(2, 4, 6, 8));

		fennec_test_spacer(2);

		fennec_test_run(([]() -> vec2 { vec2 v{ 1, 2 };       return v /= 2.0; }()), vec2(0.5, 1.0));
		fennec_test_run(([]() -> vec3 { vec3 v{ 1, 2, 3 };    return v /= 2.0; }()), vec3(0.5, 1.0, 1.5));
		fennec_test_run(([]() -> vec4 { vec4 v{ 1, 2, 3, 4 }; return v /= 2.0; }()), vec4(0.5, 1.0, 1.5, 2.0));

		fennec_test_spacer(2);

		fennec_test_run(([]() -> ivec2 { ivec2 v{ 1, 2 };       return v %= 2; }()), ivec2(1, 0));
		fennec_test_run(([]() -> ivec3 { ivec3 v{ 1, 2, 3 };    return v %= 2; }()), ivec3(1, 0, 1));
		fennec_test_run(([]() -> ivec4 { ivec4 v{ 1, 2, 3, 4 }; return v %= 2; }()), ivec4(1, 0, 1, 0));

		fennec_test_spacer(2);



		fennec_test_section("vector-vector arithmetic operations");

		fennec_test_spacer(1);

		fennec_test_run(vec2(1, 2)       + vec2(1, 2),       vec2(2, 4));
		fennec_test_run(vec3(1, 2, 3)    + vec3(1, 2, 3),    vec3(2, 4, 6));
		fennec_test_run(vec4(1, 2, 3, 4) + vec4(1, 2, 3, 4), vec4(2, 4, 6, 8));

		fennec_test_spacer(1);

		fennec_test_run(vec2(1, 2)       - vec2(1, 2),       vec2(0, 0));
		fennec_test_run(vec3(1, 2, 3)    - vec3(1, 2, 3),    vec3(0, 0, 0));
		fennec_test_run(vec4(1, 2, 3, 4) - vec4(1, 2, 3, 4), vec4(0, 0, 0, 0));

		fennec_test_spacer(1);

		fennec_test_run(vec2(1, 2)       * vec2(1, 2),       vec2(1, 4));
		fennec_test_run(vec3(1, 2, 3)    * vec3(1, 2, 3),    vec3(1, 4, 9));
		fennec_test_run(vec4(1, 2, 3, 4) * vec4(1, 2, 3, 4), vec4(1, 4, 9, 16));

		fennec_test_spacer(1);

		fennec_test_run(vec2(1, 2)       / vec2(1, 2),       vec2(1, 1));
		fennec_test_run(vec3(1, 2, 4)    / vec3(1, 2, 4),    vec3(1, 1, 1));
		fennec_test_run(vec4(1, 2, 4, 8) / vec4(1, 2, 4, 8), vec4(1, 1, 1, 1));

		fennec_test_spacer(1);

		fennec_test_run(ivec2(1, 2)       % ivec2(1, 2),       ivec2(0, 0));
		fennec_test_run(ivec3(1, 2, 4)    % ivec3(1, 2, 4),    ivec3(0, 0, 0));
		fennec_test_run(ivec4(1, 2, 4, 8) % ivec4(1, 2, 4, 8), ivec4(0, 0, 0, 0));

		fennec_test_spacer(2);



		fennec_test_section("vector-vector arithmetic assignment operations");

		fennec_test_spacer(1);

		fennec_test_run(([]() -> vec2 { vec2 v(1, 2);       return v += vec2(1, 2);       }()), vec2(2, 4));
		fennec_test_run(([]() -> vec3 { vec3 v(1, 2, 3);    return v += vec3(1, 2, 3);    }()), vec3(2, 4, 6));
		fennec_test_run(([]() -> vec4 { vec4 v(1, 2, 3, 4); return v += vec4(1, 2, 3, 4); }()), vec4(2, 4, 6, 8));

		fennec_test_spacer(1);

		fennec_test_run(([]() -> vec2 { vec2 v(1, 2);       return v -= vec2(1, 2);       }()), vec2(0, 0));
		fennec_test_run(([]() -> vec3 { vec3 v(1, 2, 3);    return v -= vec3(1, 2, 3);    }()), vec3(0, 0, 0));
		fennec_test_run(([]() -> vec4 { vec4 v(1, 2, 3, 4); return v -= vec4(1, 2, 3, 4); }()), vec4(0, 0, 0, 0));

		fennec_test_spacer(1);

		fennec_test_run(([]() -> vec2 { vec2 v(1, 2);       return v *= vec2(1, 2);       }()), vec2(1, 4));
		fennec_test_run(([]() -> vec3 { vec3 v(1, 2, 3);    return v *= vec3(1, 2, 3);    }()), vec3(1, 4, 9));
		fennec_test_run(([]() -> vec4 { vec4 v(1, 2, 3, 4); return v *= vec4(1, 2, 3, 4); }()), vec4(1, 4, 9, 16));

		fennec_test_spacer(1);

		fennec_test_run(([]() -> vec2 { vec2 v(1, 2);       return v /= vec2(1, 2);       }()), vec2(1, 1));
		fennec_test_run(([]() -> vec3 { vec3 v(1, 2, 4);    return v /= vec3(1, 2, 4);    }()), vec3(1, 1, 1));
		fennec_test_run(([]() -> vec4 { vec4 v(1, 2, 4, 8); return v /= vec4(1, 2, 4, 8); }()), vec4(1, 1, 1, 1));

		fennec_test_spacer(1);

		fennec_test_run(([]() -> ivec2 { ivec2 v(1, 2);       return v %= ivec2(1, 2);       }()), ivec2(0, 0));
		fennec_test_run(([]() -> ivec3 { ivec3 v(1, 2, 4);    return v %= ivec3(1, 2, 4);    }()), ivec3(0, 0, 0));
		fennec_test_run(([]() -> ivec4 { ivec4 v(1, 2, 4, 8); return v %= ivec4(1, 2, 4, 8); }()), ivec4(0, 0, 0, 0));

		fennec_test_spacer(2);



		fennec_test_section("boolean operations");

		fennec_test_spacer(1);

		fennec_test_run(not bvec2(false, false),             bvec2(true, true));
		fennec_test_run(not bvec3(false, false, true),       bvec3(true, true, false));
		fennec_test_run(not bvec4(false, false, true, true), bvec4(true, true, false, false));

		fennec_test_spacer(1);

		fennec_test_run(bvec2(false, false)             && true, bvec2(false, false));
		fennec_test_run(bvec3(false, false, true)       && true, bvec3(false, false, true));
		fennec_test_run(bvec4(false, false, true, true) && true, bvec4(false, false, true, true));

		fennec_test_spacer(1);

		fennec_test_run(bvec2(false, false)             && bvec2(false, true),              bvec2(false, false));
		fennec_test_run(bvec3(false, false, true)       && bvec3(false, true, false),       bvec3(false, false, false));
		fennec_test_run(bvec4(false, false, true, true) && bvec4(false, true, false, true), bvec4(false, false, false, true));

		fennec_test_spacer(2);

		fennec_test_run(bvec2(false, false)             || true, bvec2(true, true));
		fennec_test_run(bvec3(false, false, true)       || true, bvec3(true, true, true));
		fennec_test_run(bvec4(false, false, true, true) || true, bvec4(true, true, true, true));

		fennec_test_spacer(1);

		fennec_test_run(bvec2(false, false)             || bvec2(false, true),              bvec2(false, true));
		fennec_test_run(bvec3(false, false, true)       || bvec3(false, true, false),       bvec3(false, true, true));
		fennec_test_run(bvec4(false, false, true, true) || bvec4(false, true, false, true), bvec4(false, true, true, true));

		fennec_test_spacer(2);



		fennec_test_section("bitwise operations");

		fennec_test_spacer(1); // bitwise and ==============================================================================

		fennec_test_run(0b0101 & ivec2(0b0001, 0b0010),                 ivec2(0b0001, 0b0000));
		fennec_test_run(0b0101 & ivec3(0b0001, 0b0010, 0b0011),         ivec3(0b0001, 0b0000, 0b0001));
		fennec_test_run(0b0101 & ivec4(0b0001, 0b0010, 0b0011, 0b0100), ivec4(0b0001, 0b0000, 0b0001, 0b0100));

		fennec_test_spacer(1);

		fennec_test_run(ivec2(0b0001, 0b0010)                 & 0b0101, ivec2(0b0001, 0b0000));
		fennec_test_run(ivec3(0b0001, 0b0010, 0b0011)         & 0b0101, ivec3(0b0001, 0b0000, 0b0001));
		fennec_test_run(ivec4(0b0001, 0b0010, 0b0011, 0b0100) & 0b0101, ivec4(0b0001, 0b0000, 0b0001, 0b0100));

		fennec_test_spacer(1);

		fennec_test_run(([]() -> ivec2 { ivec2 v(0b0001, 0b0010);                 return v &= 0b0101; }()), ivec2(0b0001, 0b0000));
		fennec_test_run(([]() -> ivec3 { ivec3 v(0b0001, 0b0010, 0b0011);         return v &= 0b0101; }()), ivec3(0b0001, 0b0000, 0b0001));
		fennec_test_run(([]() -> ivec4 { ivec4 v(0b0001, 0b0010, 0b0011, 0b0100); return v &= 0b0101; }()), ivec4(0b0001, 0b0000, 0b0001, 0b0100));

		fennec_test_spacer(1);

		fennec_test_run(ivec2(0b0001, 0b0010)                 & ivec2(0b1000, 0b0100),                 ivec2(0b0000));
		fennec_test_run(ivec3(0b0001, 0b0010, 0b0011)         & ivec3(0b1000, 0b0100, 0b1100),         ivec3(0b0000));
		fennec_test_run(ivec4(0b0001, 0b0010, 0b0011, 0b0100) & ivec4(0b1000, 0b0100, 0b1100, 0b0010), ivec4(0b0000));

		fennec_test_spacer(1);

		fennec_test_run(([]() -> ivec2 { ivec2 v(0b0001, 0b0010);                 return v &= ivec2(0b1000, 0b0100);                 }()), ivec2(0b0000));
		fennec_test_run(([]() -> ivec3 { ivec3 v(0b0001, 0b0010, 0b0011);         return v &= ivec3(0b1000, 0b0100, 0b1100);         }()), ivec3(0b0000));
		fennec_test_run(([]() -> ivec4 { ivec4 v(0b0001, 0b0010, 0b0011, 0b0100); return v &= ivec4(0b1000, 0b0100, 0b1100, 0b0010); }()), ivec4(0b0000));


		fennec_test_spacer(2); // bitwise or ===============================================================================


		fennec_test_run(0b0101 | ivec2(0b0001, 0b0010),                 ivec2(0b0101, 0b0111));
		fennec_test_run(0b0101 | ivec3(0b0001, 0b0010, 0b0011),         ivec3(0b0101, 0b0111, 0b0111));
		fennec_test_run(0b0101 | ivec4(0b0001, 0b0010, 0b0011, 0b0100), ivec4(0b0101, 0b0111, 0b0111, 0b0101));

		fennec_test_spacer(1);

		fennec_test_run(ivec2(0b0001, 0b0010)                 | 0b0101, ivec2(0b0101, 0b0111));
		fennec_test_run(ivec3(0b0001, 0b0010, 0b0011)         | 0b0101, ivec3(0b0101, 0b0111, 0b0111));
		fennec_test_run(ivec4(0b0001, 0b0010, 0b0011, 0b0100) | 0b0101, ivec4(0b0101, 0b0111, 0b0111, 0b0101));

		fennec_test_spacer(1);

		fennec_test_run(([]() -> ivec2 { ivec2 v(0b0001, 0b0010);                 return v |= 0b0101; }()), ivec2(0b0101, 0b0111));
		fennec_test_run(([]() -> ivec3 { ivec3 v(0b0001, 0b0010, 0b0011);         return v |= 0b0101; }()), ivec3(0b0101, 0b0111, 0b0111));
		fennec_test_run(([]() -> ivec4 { ivec4 v(0b0001, 0b0010, 0b0011, 0b0100); return v |= 0b0101; }()), ivec4(0b0101, 0b0111, 0b0111, 0b0101));

		fennec_test_spacer(1);

		fennec_test_run(ivec2(0b0001, 0b0010)                 | ivec2(0b1000, 0b0100),                 ivec2(0b1001, 0b0110));
		fennec_test_run(ivec3(0b0001, 0b0010, 0b0011)         | ivec3(0b1000, 0b0100, 0b1100),         ivec3(0b1001, 0b0110, 0b1111));
		fennec_test_run(ivec4(0b0001, 0b0010, 0b0011, 0b0100) | ivec4(0b1000, 0b0100, 0b1100, 0b0010), ivec4(0b1001, 0b0110, 0b1111, 0b0110));

		fennec_test_spacer(1);

		fennec_test_run(([]() -> ivec2 { ivec2 v(0b0001, 0b0010);                 return v |= ivec2(0b1000, 0b0100);                 }()), ivec2(0b1001, 0b0110));
		fennec_test_run(([]() -> ivec3 { ivec3 v(0b0001, 0b0010, 0b0011);         return v |= ivec3(0b1000, 0b0100, 0b1100);         }()), ivec3(0b1001, 0b0110, 0b1111));
		fennec_test_run(([]() -> ivec4 { ivec4 v(0b0001, 0b0010, 0b0011, 0b0100); return v |= ivec4(0b1000, 0b0100, 0b1100, 0b0010); }()), ivec4(0b1001, 0b0110, 0b1111, 0b0110));


		fennec_test_spacer(2); // bitwise xor ==============================================================================


		fennec_test_run(0b0101 ^ ivec2(0b0001, 0b0010),                 ivec2(0b0100, 0b0111));
		fennec_test_run(0b0101 ^ ivec3(0b0001, 0b0010, 0b0011),         ivec3(0b0100, 0b0111, 0b0110));
		fennec_test_run(0b0101 ^ ivec4(0b0001, 0b0010, 0b0011, 0b0100), ivec4(0b0100, 0b0111, 0b0110, 0b0001));

		fennec_test_spacer(1);

		fennec_test_run(ivec2(0b0001, 0b0010)                 ^ 0b0101, ivec2(0b0100, 0b0111));
		fennec_test_run(ivec3(0b0001, 0b0010, 0b0011)         ^ 0b0101, ivec3(0b0100, 0b0111, 0b0110));
		fennec_test_run(ivec4(0b0001, 0b0010, 0b0011, 0b0100) ^ 0b0101, ivec4(0b0100, 0b0111, 0b0110, 0b0001));

		fennec_test_spacer(1);

		fennec_test_run(([]() -> ivec2 { ivec2 v(0b0001, 0b0010);                 return v ^= 0b0101; }()), ivec2(0b0100, 0b0111));
		fennec_test_run(([]() -> ivec3 { ivec3 v(0b0001, 0b0010, 0b0011);         return v ^= 0b0101; }()), ivec3(0b0100, 0b0111, 0b0110));
		fennec_test_run(([]() -> ivec4 { ivec4 v(0b0001, 0b0010, 0b0011, 0b0100); return v ^= 0b0101; }()), ivec4(0b0100, 0b0111, 0b0110, 0b0001));

		fennec_test_spacer(1);

		fennec_test_run(ivec2(0b0001, 0b0010)                 ^ ivec2(0b1000, 0b0100),                 ivec2(0b1001, 0b0110));
		fennec_test_run(ivec3(0b0001, 0b0010, 0b0011)         ^ ivec3(0b1000, 0b0100, 0b1100),         ivec3(0b1001, 0b0110, 0b1111));
		fennec_test_run(ivec4(0b0001, 0b0010, 0b0011, 0b0100) ^ ivec4(0b1000, 0b0100, 0b1100, 0b0010), ivec4(0b1001, 0b0110, 0b1111, 0b0110));

		fennec_test_spacer(1);

		fennec_test_run(([]() -> ivec2 { ivec2 v(0b0001, 0b0010);                 return v ^= ivec2(0b1000, 0b0100);                 }()), ivec2(0b1001, 0b0110));
		fennec_test_run(([]() -> ivec3 { ivec3 v(0b0001, 0b0010, 0b0011);         return v ^= ivec3(0b1000, 0b0100, 0b1100);         }()), ivec3(0b1001, 0b0110, 0b1111));
		fennec_test_run(([]() -> ivec4 { ivec4 v(0b0001, 0b0010, 0b0011, 0b0100); return v ^= ivec4(0b1000, 0b0100, 0b1100, 0b0010); }()), ivec4(0b1001, 0b0110, 0b1111, 0b0110));


		fennec_test_spacer(2); // Left Shift ===============================================================================


		fennec_test_run(0x6D40A3C3 << ivec2(4, 8),         ivec2(0xD40A3C30, 0x40A3C300));
		fennec_test_run(0x6D40A3C3 << ivec3(4, 8, 12),     ivec3(0xD40A3C30, 0x40A3C300, 0x0A3C3000));
		fennec_test_run(0x6D40A3C3 << ivec4(4, 8, 12, 16), ivec4(0xD40A3C30, 0x40A3C300, 0x0A3C3000, 0xA3C30000));

		fennec_test_spacer(1);

		fennec_test_run(ivec2(0x1E, 0xF3)             << 4, ivec2(0x1E0, 0xF30));
		fennec_test_run(ivec3(0x1E, 0xF3, 0x27)       << 4, ivec3(0x1E0, 0xF30, 0x270));
		fennec_test_run(ivec4(0x1E, 0xF3, 0x27, 0x7C) << 4, ivec4(0x1E0, 0xF30, 0x270, 0x7C0));

		fennec_test_spacer(1);

		fennec_test_run(([]() -> ivec2 { ivec2 v(0x1E, 0xF3);             return v <<= 4; }()), ivec2(0x1E0, 0xF30));
		fennec_test_run(([]() -> ivec3 { ivec3 v(0x1E, 0xF3, 0x27);       return v <<= 4; }()), ivec3(0x1E0, 0xF30, 0x270));
		fennec_test_run(([]() -> ivec4 { ivec4 v(0x1E, 0xF3, 0x27, 0x7C); return v <<= 4; }()), ivec4(0x1E0, 0xF30, 0x270, 0x7C0));

		fennec_test_spacer(1);

		fennec_test_run(ivec2(0x1E, 0xF3)             << ivec2(4, 8),         ivec2(0x1E0, 0xF300));
		fennec_test_run(ivec3(0x1E, 0xF3, 0x27)       << ivec3(4, 8, 12),     ivec3(0x1E0, 0xF300, 0x27000));
		fennec_test_run(ivec4(0x1E, 0xF3, 0x27, 0x7C) << ivec4(4, 8, 12, 16), ivec4(0x1E0, 0xF300, 0x27000, 0x7C0000));

		fennec_test_spacer(1);

		fennec_test_run(([]() -> ivec2 { ivec2 v(0x1E, 0xF3);             return v <<= ivec2(4, 8); }()),         ivec2(0x1E0, 0xF300));
		fennec_test_run(([]() -> ivec3 { ivec3 v(0x1E, 0xF3, 0x27);       return v <<= ivec3(4, 8, 12); }()),     ivec3(0x1E0, 0xF300, 0x27000));
		fennec_test_run(([]() -> ivec4 { ivec4 v(0x1E, 0xF3, 0x27, 0x7C); return v <<= ivec4(4, 8, 12, 16); }()), ivec4(0x1E0, 0xF300, 0x27000, 0x7C0000));


		fennec_test_spacer(2); // Right Shift ===============================================================================


		fennec_test_run(0x6D40A3C3 >> ivec2(4, 8),         ivec2(0x06D40A3C, 0x006D40A3));
		fennec_test_run(0x6D40A3C3 >> ivec3(4, 8, 12),     ivec3(0x06D40A3C, 0x006D40A3, 0x0006D40A));
		fennec_test_run(0x6D40A3C3 >> ivec4(4, 8, 12, 16), ivec4(0x06D40A3C, 0x006D40A3, 0x0006D40A, 0x00006D40));

		fennec_test_spacer(1);

		fennec_test_run(ivec2(0x1E, 0xF3)             >> 4, ivec2(0x1, 0xF));
		fennec_test_run(ivec3(0x1E, 0xF3, 0x27)       >> 4, ivec3(0x1, 0xF, 0x2));
		fennec_test_run(ivec4(0x1E, 0xF3, 0x27, 0x7C) >> 4, ivec4(0x1, 0xF, 0x2, 0x7));

		fennec_test_spacer(1);

		fennec_test_run(([]() -> ivec2 { ivec2 v(0x1E, 0xF3);             return v >>= 4; }()), ivec2(0x1, 0xF));
		fennec_test_run(([]() -> ivec3 { ivec3 v(0x1E, 0xF3, 0x27);       return v >>= 4; }()), ivec3(0x1, 0xF, 0x2));
		fennec_test_run(([]() -> ivec4 { ivec4 v(0x1E, 0xF3, 0x27, 0x7C); return v >>= 4; }()), ivec4(0x1, 0xF, 0x2, 0x7));

		fennec_test_spacer(1);

		fennec_test_run(ivec2(0x2A1E, 0x7BF3)                 >> ivec2(4, 8),         ivec2(0x2A1, 0x7B));
		fennec_test_run(ivec3(0x2A1E, 0x7BF3, 0x3927)         >> ivec3(4, 8, 12),     ivec3(0x2A1, 0x7B, 0x3));
		fennec_test_run(ivec4(0x2A1E, 0x7BF3, 0x3927, 0x237C) >> ivec4(4, 8, 12, 16), ivec4(0x2A1, 0x7B, 0x3, 0x0));

		fennec_test_spacer(1);

		fennec_test_run(([]() -> ivec2 { ivec2 v(0x2A1E, 0x7BF3);                 return v >>= ivec2(4, 8); }()),         ivec2(0x2A1, 0x7B));
		fennec_test_run(([]() -> ivec3 { ivec3 v(0x2A1E, 0x7BF3, 0x3927);         return v >>= ivec3(4, 8, 12); }()),     ivec3(0x2A1, 0x7B, 0x3));
		fennec_test_run(([]() -> ivec4 { ivec4 v(0x2A1E, 0x7BF3, 0x3927, 0x237C); return v >>= ivec4(4, 8, 12, 16); }()), ivec4(0x2A1, 0x7B, 0x3, 0x0));
	}

}

#endif // FENNEC_TEST_VECTOR_H
