Vector3
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © RicardoSantos

//@version=5

// @description Representation of 3D vectors and points.
// This structure is used to pass 3D positions and directions around. It also contains functions for doing common vector operations.
// Besides the functions listed below, other classes can be used to manipulate vectors and points as well. 
// For example the Quaternion and the Matrix4x4 classes are useful for rotating or transforming vectors and points.
// ___
// **Reference:**
// - https://github.com/phoboslab/q1k3/blob/master/source/math_utils.js
// - https://github.com/lauripiispanen/vectorz/blob/master/3d.js
// - https://github.com/thormeier/vanilla-vectors-3d/blob/master/src/Vector.js
// - http://www.movable-type.co.uk/scripts/geodesy/docs/vector3d.js.html
// - https://docs.unity3d.com/ScriptReference/Vector3.html
// - https://referencesource.microsoft.com/#System.Numerics/System/Numerics/Vector3.cs
// - https://github.com/Unity-Technologies/UnityCsReference/blob/master/Runtime/Export/Math/Vector3.cs
// \
library(title = 'Vector3')

// <--	101 Character spaces.																	 -->|
// 3456789 123456789 123456789 123456789 123456789|123456789 123456789 123456789 123456789 123456789|
//		|	|		|		|	|		|		|	|		|		|			|		|	|		|

//#region	0: Pre loading and module dependencies.													
//#region	0.0: Imports:                                              								

import RicardoSantos/CommonTypesMath/1 as TMath
import RicardoSantos/Vector2/1 as V2
import RicardoSantos/Vector2DrawLine/1 as DrawLine
import RicardoSantos/DebugConsole/12 as console

//#endregion	0.0
//#region	0.1: Constants:                                            								

console.Console logger = console.new()

//#endregion	0.1
//#region	0.2: Helpers:                                              								
//#endregion	0.2
//#endregion	0
//#region	1: Constructor.																			
// > - Methods to Initialize the structure of a `Vector3` 
//#region	1.1: Basic Constructor:																	
//#region	1.1.1: new							()													

// @function Create a new `Vector3`.
// @param x `float` Property `x` value, (optional, default=na).
// @param y `float` Property `y` value, (optional, default=na).
// @param z `float` Property `z` value, (optional, default=na).
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// .new(1.1, 1, 1)
// ```
export new (float x = na, float y = na, float z = na) =>
	TMath.Vector3.new(x, y, z)

//#endregion	1.1.1
//#region	1.1.2: from							()													

// @function Create a new `Vector3` from a single value.
// @param value `float` Properties positional value, (optional, default=na).
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// .from(1.1)
// ```
export from (float value = na) =>
	TMath.Vector3.new(value, value, value)

//#endregion	1.1.2
//#region	1.1.3: from_Array					()													

// @function Create a new `Vector3` from a list of values, only reads up to the third item.
// @param values  `array<float>` Vector property values.
// @param fill_na `float`        Parameter value to replace missing indexes, (optional, defualt=na).
// @returns `Vector3` Generated new vector.
// ___
// **Notes:**
// - Supports any size of array, fills non available fields with `na`.
// ___
// **Usage:**
// ```
// .from_Array(array.from(1.1, fill_na=33))
// .from_Array(array.from(1.1, 2, 3))
// ```
export from_Array (array<float> values, float fill_na=na) =>
	switch values.size()
		00 => TMath.Vector3.new(fill_na      , fill_na      , fill_na      )
		01 => TMath.Vector3.new(values.get(0), fill_na      , fill_na      )
		02 => TMath.Vector3.new(values.get(0), values.get(1), fill_na      )
		=>    TMath.Vector3.new(values.get(0), values.get(1), values.get(2))

// TEST 20230512 OK RS
// if barstate.islast
// 	_tmp0 = from_Array(array.new<float>(), 123)
// 	_tmp1 = from_Array(array.from(1.0))
// 	_tmp2 = from_Array(array.from(1.0, 2.0))
// 	_tmp3 = from_Array(array.from(1.0, 2.0, 3.0))
// 	logger.queue_one('x: ' + str.tostring(_tmp0.x) + ' y: ' + str.tostring(_tmp0.y) + ' z: ' + str.tostring(_tmp0.z))
// 	logger.queue_one('x: ' + str.tostring(_tmp1.x) + ' y: ' + str.tostring(_tmp1.y) + ' z: ' + str.tostring(_tmp1.z))
// 	logger.queue_one('x: ' + str.tostring(_tmp2.x) + ' y: ' + str.tostring(_tmp2.y) + ' z: ' + str.tostring(_tmp2.z))
// 	logger.queue_one('x: ' + str.tostring(_tmp3.x) + ' y: ' + str.tostring(_tmp3.y) + ' z: ' + str.tostring(_tmp3.z))

//#endregion	1.1.3
//#region	1.1.4: from_Vector2					()													

// @function Create a new `Vector3` from a `Vector2`.
// @param values `Vector2` Vector property values.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// .from:Vector2(.Vector2.new(1, 2.0))
// ```
// ___
// **Notes:**
// - Type `Vector2` from CommonTypesMath library.
export from_Vector2 (TMath.Vector2 values) =>
	TMath.Vector3.new(values.x, values.y, float(na))

//#endregion	1.1.4
//#region	1.1.5: from_Quaternion				()													

// @function Create a new `Vector3` from a `Quaternion`'s `x, y, z` properties.
// @param values `Quaternion` Vector property values.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// .from_Quaternion(.Quaternion.new(1, 2, 3, 4))
// ```
// ___
// **Notes:**
// - Type `Quaternion` from CommonTypesMath library.
export from_Quaternion (TMath.Quaternion values) =>
	TMath.Vector3.new(values.x, values.y, values.z)

//#endregion	1.1.5
//#region	1.1.6: from_String					()													


// @function Create a new `Vector3` from a list of values in a formated string.
// @param expression	`array<float>`	String with the list of vector properties.
// @param separator		`string`		Separator between entries, (optional, default=`","`).
// @param fill_na 		`float`			Parameter value to replace missing indexes, (optional, defualt=na).
// @returns `Vector3` Generated new vector.
// ___
// **Notes:**
// - Supports any size of array, fills non available fields with `na`.
// - `",,"` Empty fields will be ignored.
// ___
// **Usage:**
// ```
// .from_String("1.1", fill_na=33))
// .from_String("(1.1,, 3)") // 1.1 , 3.0, NaN // empty field will be ignored!!
// ```
export from_String (string expression, string separator=',', float fill_na=na) =>
	array<string> _values = str.split(expression, separator)
	switch _values.size()
		00 => TMath.Vector3.new(fill_na      , fill_na      , fill_na)
		01 => TMath.Vector3.new(str.tonumber(_values.get(0)), fill_na                     , fill_na)
		02 => TMath.Vector3.new(str.tonumber(_values.get(0)), str.tonumber(_values.get(1)), fill_na)
		=>    TMath.Vector3.new(str.tonumber(_values.get(0)), str.tonumber(_values.get(1)), str.tonumber(_values.get(2)))

// if barstate.islast
// 	_v = from_String('1.0, , 3')
// 	logger.queue(str.format('x: {0}, y: {1}, z: {2}', _v.x, _v.y, _v.z))

//#endregion	1.1.6
//#endregion	1.1
//#region	1.2: Static Properties:																	
//#region	1.2.01: back						()													

// @function Create a new `Vector3` object in the form `(0, 0, -1)`.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// .back()
// ```
export back () =>
	TMath.Vector3.new(0.0, 0.0, -1.0)

//#endregion	1.2.1
//#region	1.2.02: front						()													

// @function Create a new `Vector3` object in the form `(0, 0, 1)`.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// .front()
// ```
export front () =>
	TMath.Vector3.new(0.0, 0.0, 1.0)

//#endregion	1.2.2
//#region	1.2.03: up							()													

// @function Create a new `Vector3` object in the form `(0, 1, 0)`.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// .up()
// ```
export up () =>
	TMath.Vector3.new(0.0, 1.0, 0.0)

//#endregion	1.2.3
//#region	1.2.04: down						()													

// @function Create a new `Vector3` object in the form `(0, -1, 0)`.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// .down()
// ```
export down () =>
	TMath.Vector3.new(0.0, -1.0, 0.0)

//#endregion	1.2.4
//#region	1.2.05: left						()													

// @function Create a new `Vector3` object in the form `(-1, 0, 0)`.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// .left()
// ```
export left () =>
	TMath.Vector3.new(-1.0, 0.0, 0.0)

//#endregion	1.2.5
//#region	1.2.06: right						()													

// @function Create a new `Vector3` object in the form `(1, 0, 0)`.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// .right()
// ```
export right () =>
	TMath.Vector3.new(1.0, 0.0, 0.0)

//#endregion	1.2.6
//#region	1.2.07: zero						()													

// @function Create a new `Vector3` object in the form `(0, 0, 0)`.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// .zero()
// ```
export zero () =>
	TMath.Vector3.new(0.0, 0.0, 0.0)

//#endregion	1.2.7
//#region	1.2.08: one							()													

// @function Create a new `Vector3` object in the form `(1, 1, 1)`.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// .one()
// ```
export one () =>
	TMath.Vector3.new(1.0, 1.0, 1.0)

//#endregion	1.2.8
//#region	1.2.09: minus_one					()													

// @function Create a new `Vector3` object in the form `(-1, -1, -1)`.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// .minus_one()
// ```
export minus_one () =>
	TMath.Vector3.new(-1.0, -1.0, -1.0)

//#endregion	1.2.9
//#region	1.2.10: unit_x						()													

// @function Create a new `Vector3` object in the form `(1, 0, 0)`.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// .unit_x()
// ```
export unit_x () =>
	TMath.Vector3.new(1.0, 0.0, 0.0)

//#endregion	1.2.10
//#region	1.2.11: unit_y						()													

// @function Create a new `Vector3` object in the form `(0, 1, 0)`.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// .unit_y()
// ```
export unit_y () =>
	TMath.Vector3.new(0.0, 1.0, 0.0)

//#endregion	1.2.11
//#region	1.2.12: unit_z						()													

// @function Create a new `Vector3` object in the form `(0, 0, 1)`.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// .unit_z()
// ```
export unit_z () =>
	TMath.Vector3.new(0.0, 0.0, 1.0)

//#endregion	1.2.12
//#region	1.2.13: nan							()													

// @function Create a new `Vector3` object in the form `(na, na, na)`.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// .nan()
// ```
export nan () =>
	TMath.Vector3.new(float(na), float(na), float(na))

//#endregion	1.2.13
//#endregion	1.2
//#region	1.3: Random Generation:																	
//#region	1.3.1: random						() min, max											

// @function Generate a vector with random properties.
// @param max	`Vector3`	Maximum defined range of the vector properties.
// @param min	`Vector3`	Minimum defined range of the vector properties.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// .random(.from(math.pi), .from(-math.pi))
// ```
export random (TMath.Vector3 max, TMath.Vector3 min) =>
	TMath.Vector3.new(math.random(min.x, max.x), math.random(min.y, max.y), math.random(min.z, max.z))

//#endregion	1.3.1
//#region	1.3.2: random						() max												

// @function Generate a vector with random properties (min set to 0.0).
// @param max	`Vector3`	Maximum defined range of the vector properties.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// .random(.from(math.pi))
// ```
export random (TMath.Vector3 max) =>
	TMath.Vector3.new(math.random(0.0, max.x), math.random(0.0, max.y), math.random(0.0, max.z))

//#endregion	1.3.2
//#region	1.3.3: random						() min, max, seed								*NI*
// *NI*: Not Implemented

// // @function Generate a vector with random properties with a specified seed.
// // @param max	`Vector3`	Maximum defined range of the vector properties.
// // @param min	`Vector3`	Minimum defined range of the vector properties.
// // @param seed	`int`		Seed parameter for reproduction of values.
// // @returns `Vector3`.
// export random (TMath.Vector3 max, TMath.Vector3 min, int seed) =>
// 	TMath.Vector3.new(math.random(min.x, max.x, seed), math.random(min.y, max.y, seed), math.random(min.z, max.z, seed))

//#endregion	1.3.3
//#region	1.3.4: random						() max, seed									*NI*
// *NI*: Not Implemented

// // @function Generate a vector with random properties (min set to 0.0) with a specified seed.
// // @param max	`Vector3`	Maximum defined range of the vector properties.
// // @param seed	`int`		Seed parameter for reproduction of values.
// // @returns `Vector3`.
// export random (TMath.Vector3 max, simple int seed) =>
// 	TMath.Vector3.new(math.random(0.0, max.x, seed), math.random(0.0, max.y, seed), math.random(0.0, max.z, seed))

//#endregion	1.3.4
//#endregion	1.3
//#endregion	1
//#region	2: Class Methods.                                           							
// > - Methods that pass its class in the first argument (not exactly the same as other languages), 
//	and are callable from the namespace of its class.
//	ex:. `method fun(vector3 this) => this.x` , `a = vector3.new()` , `a.fun()`
//#region	2.1: Instance:																			
//#region	2.1.1: copy							()													

// @function Copy a existing `Vector3` 
// @param this	`Vector3`	Source vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .one().copy()
// ```
export method copy (TMath.Vector3 this) =>
	TMath.Vector3.copy(this)

//#endregion	2.1.1
//#region	2.1.2: Inplace Operators:																
// > - A set of operators that manipulate the source vector.
//#region	2.1.2.1: i_add						()													
//#region	2.1.2.1.1: Vector3 + Vector3															

// @function Modify a instance of a vector by adding a vector to it.
// @param this	`Vector3`	Source vector.
// @param other	`Vector3`	Other Vector.
// @returns `Vector3` Updated source vector.
// ___
// **Usage:**
// ```
// a = .from(1)		, a.i_add(.up())
// ```
export method i_add (TMath.Vector3 this, TMath.Vector3 other) =>
	this.x += other.x
	this.y += other.y
	this.z += other.z
	this

// TEST 20230515 RS
// if barstate.islast
// 	_v = from(1), logger.queue_one('origin: ' + str.tostring(_v.x) + ' ' + str.tostring(_v.y) + ' ' + str.tostring(_v.z))
// 	_v.i_add(_v), logger.queue_one('added : ' + str.tostring(_v.x) + ' ' + str.tostring(_v.y) + ' ' + str.tostring(_v.z))

//#endregion	2.1.2.1.1
//#region	2.1.2.1.2: Vector3 + float																

// @function Modify a instance of a vector by adding a vector to it.
// @param this	`Vector3`	Source vector.
// @param value	`float`		Value.
// @returns `Vector3` Updated source vector.
// ___
// **Usage:**
// ```
// a = .from(1)		, a.i_add(3.2)
// ```
export method i_add (TMath.Vector3 this, float value) =>
	this.x += value
	this.y += value
	this.z += value
	this

//#endregion	2.1.2.1.2
//#endregion	2.1.2.1
//#region	2.1.2.2: i_subtract					()													
//#region	2.1.2.2.1: Vector3 - Vector3															

// @function Modify a instance of a vector by subtracting a vector to it.
// @param this	`Vector3`	Source vector.
// @param other	`Vector3`	Other Vector.
// @returns `Vector3` Updated source vector.
// ___
// **Usage:**
// ```
// a = .from(1)		, a.i_subtract(.down())
// ```
export method i_subtract (TMath.Vector3 this, TMath.Vector3 other) =>
	this.x -= other.x
	this.y -= other.y
	this.z -= other.z
	this

//#endregion	2.1.2.2.1
//#region	2.1.2.2.2: Vector3 - float																

// @function Modify a instance of a vector by subtracting a vector to it.
// @param this	`Vector3`	Source vector.
// @param value	`float`		Value.
// @returns `Vector3` Updated source vector.
// ___
// **Usage:**
// ```
// a = .from(1)		, a.i_subtract(3)
// ```
export method i_subtract (TMath.Vector3 this, float value) =>
	this.x -= value
	this.y -= value
	this.z -= value
	this

//#endregion	2.1.2.2.2
//#endregion	2.1.2.2
//#region	2.1.2.3: i_multiply					()													
//#region	2.1.2.3.1: Vector3 * Vector3															

// @function Modify a instance of a vector by multiplying a vector with it.
// @param this	`Vector3`	Source vector.
// @param other	`Vector3`	Other Vector.
// @returns `Vector3` Updated source vector.
// ___
// **Usage:**
// ```
// a = .from(1)		, a.i_multiply(.left())
// ```
export method i_multiply (TMath.Vector3 this, TMath.Vector3 other) =>
	this.x *= other.x
	this.y *= other.y
	this.z *= other.z
	this

//#endregion	2.1.2.3.1
//#region	2.1.2.3.2: Vector3 * float																

// @function Modify a instance of a vector by multiplying a vector with it.
// @param this	`Vector3`	Source vector.
// @param value	`float`	value.
// @returns `Vector3` Updated source vector.
// ___
// **Usage:**
// ```
// a = .from(1)		, a.i_multiply(3)
// ```
export method i_multiply (TMath.Vector3 this, float value) =>
	this.x *= value
	this.y *= value
	this.z *= value
	this

//#endregion	2.1.2.3.2
//#endregion	2.1.2.3
//#region	2.1.2.4: i_divide					()													
//#region	2.1.2.4.1: Vector3 / Vector3															

// @function Modify a instance of a vector by dividing it by another vector.
// @param this	`Vector3`	Source vector.
// @param other	`Vector3`	Other Vector.
// @returns `Vector3` Updated source vector.
// ___
// **Usage:**
// ```
// a = .from(1)		, a.i_divide(.forward())
// ```
export method i_divide (TMath.Vector3 this, TMath.Vector3 other) =>
	this.x /= other.x
	this.y /= other.y
	this.z /= other.z
	this

//#endregion	2.1.2.4.1
//#region	2.1.2.4.2: Vector3 / float																

// @function Modify a instance of a vector by dividing it by another vector.
// @param this	`Vector3`	Source vector.
// @param value	`float`	Value.
// @returns `Vector3` Updated source vector.
// ___
// **Usage:**
// ```
// a = .from(1)		, a.i_divide(3)
// ```
export method i_divide (TMath.Vector3 this, float value) =>
	this.x /= value
	this.y /= value
	this.z /= value
	this

//#endregion	2.1.2.4.2
//#endregion	2.1.2.4
//#region	2.1.2.5: i_mod						()													
//#region	2.1.2.5.1: Vector3 % Vector3															

// @function Modify a instance of a vector by modulo assignment with another vector.
// @param this	`Vector3`	Source vector.
// @param other	`Vector3`	Other Vector.
// @returns `Vector3` Updated source vector.
// ___
// **Usage:**
// ```
// a = .from(1)		, a.i_mod(.back())
// ```
export method i_mod (TMath.Vector3 this, TMath.Vector3 other) =>
	this.x %= other.x
	this.y %= other.y
	this.z %= other.z
	this

// TEST 20230515 RS
// if barstate.islast
// 	_v = from(12)		, logger.queue_one('origin: ' + str.tostring(_v.x) + ' ' + str.tostring(_v.y) + ' ' + str.tostring(_v.z))
// 	//_v.i_mod(from(3))	, logger.queue_one('mod3 : ' + str.tostring(_v.x) + ' ' + str.tostring(_v.y) + ' ' + str.tostring(_v.z))
// 	_v.i_mod(from(5))	, logger.queue_one('mod5 : ' + str.tostring(_v.x) + ' ' + str.tostring(_v.y) + ' ' + str.tostring(_v.z))

//#endregion	2.1.2.5.1
//#region	2.1.2.5.2: Vector3 % float																

// @function Modify a instance of a vector by modulo assignment with another vector.
// @param this	`Vector3`	Source vector.
// @param value	`float`		Value.
// @returns `Vector3` Updated source vector.
// ___
// **Usage:**
// ```
// a = .from(1)		, a.i_mod(3)
// ```
export method i_mod (TMath.Vector3 this, float value) =>
	this.x %= value
	this.y %= value
	this.z %= value
	this

//#endregion	2.1.2.5.2
//#endregion	2.1.2.5
//#region	2.1.2.6: i_pow						()													
//#region	2.1.2.6.1: Vector3 ^ Vector3															

// @function Modify a instance of a vector by modulo assignment with another vector.
// @param this		`Vector3`	Source vector.
// @param exponent	`Vector3`	Exponent Vector.
// @returns `Vector3` Updated source vector.
// ___
// **Usage:**
// ```
// a = .from(1)		, a.i_pow(.up())
// ```
export method i_pow (TMath.Vector3 this, TMath.Vector3 exponent) =>
	this.x := math.pow(this.x, exponent.x)
	this.y := math.pow(this.y, exponent.y)
	this.z := math.pow(this.z, exponent.z)
	this

//#endregion	2.1.2.6.1
//#region	2.1.2.6.2: Vector3 ^ float																

// @function Modify a instance of a vector by modulo assignment with another vector.
// @param this		`Vector3`	Source vector.
// @param exponent	`float`		Exponent Value.
// @returns `Vector3` Updated source vector.
// ___
// **Usage:**
// ```
// a = .from(1)		, a.i_pow(2)
// ```
export method i_pow (TMath.Vector3 this, float exponent) =>
	this.x := math.pow(this.x, exponent)
	this.y := math.pow(this.y, exponent)
	this.z := math.pow(this.z, exponent)
	this

//#endregion	2.1.2.6.2
//#endregion	2.1.2.6
//#endregion	2.1.2
//#endregion	2.1
//#region	2.2: Properties:																		
//#region	2.2.1: length_squared				()													

// @function Squared length of the vector.
// @param a `Vector3` Source vector.
// @returns `float` The squared length of this vector.
// ___
// **Usage:**
// ```
// a = .one().length_squared()
// ```
export method length_squared (TMath.Vector3 this) =>
	(this.x * this.x) + (this.y * this.y) + (this.z * this.z)

//#endregion	2.2.1
//#region	2.2.2: magnitude_squared			()													

// @function Squared magnitude of the vector.
// @param this `Vector3` Source vector.
// @returns `float` The length squared of this vector.
// ___
// **Usage:**
// ```
// a = .one().magnitude_squared()
// ```
export method magnitude_squared (TMath.Vector3 this) =>
	(this.x * this.x) + (this.y * this.y) + (this.z * this.z)

//#endregion	2.2.2
//#region	2.2.3: length						()													

// @function Length of the vector.
// @param this `Vector3` Source vector.
// @returns `float` The length of this vector.
// ___
// **Usage:**
// ```
// a = .one().length()
// ```
export method length (TMath.Vector3 this) =>
	math.sqrt((this.x * this.x) + (this.y * this.y) + (this.z * this.z))

//#endregion	2.2.3
//#region	2.2.4: magnitude					()													

// @function Magnitude of the vector.
// @param this `Vector3` Source vector.
// @returns `float` The Length of this vector.
// ___
// **Usage:**
// ```
// a = .one().magnitude()
// ```
export method magnitude (TMath.Vector3 this) =>
	math.sqrt((this.x * this.x) + (this.y * this.y) + (this.z * this.z))

//#endregion	2.2.4
//#region	2.2.5: normalize					()													

// @function Normalize a vector with a magnitude of 1(optional).
// @param this		`Vector3`	Source vector.
// @param magnitude	`float`		Value to manipulate the magnitude of normalization, (optional, default=1.0).
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .new(33, 50, 100).normalize()	// (x=0.283, y=0.429, z=0.858)
// a = .new(33, 50, 100).normalize(2)	// (x=0.142, y=0.214, z=0.429)
// ```
export method normalize (TMath.Vector3 this, float magnitude = 1.0, float eps = 0.000001) =>
	float _magnitude = this.length() * magnitude
	if _magnitude > eps
		float _m = 1.0 / _magnitude
		TMath.Vector3.new(this.x * _m, this.y * _m, this.z * _m)
	else
		zero()

// if barstate.islast
// 	a = new(33, 50, 100).normalize()
// 	b = new(33, 50, 100).normalize(2)
// 	logger.queue(str.format('a: {0}, {1}, {2}', a.x, a.y, a.z))
// 	logger.queue(str.format('b: {0}, {1}, {2}', b.x, b.y, b.z))

//#endregion	2.2.1
//#endregion	2.2
//#region	2.3: Type Conversion:																	
//#region	2.3.1: to_String					()													

// @function Converts source vector to a string format, in the form `"(x, y, z)"`.
// @param this      `Vector3` Source vector. 
// @param precision `string`  Precision format to apply to values (optional, default='').
// @returns `string` Formated string in a `"(x, y, z)"` format.
// ___
// **Usage:**
// ```
// a = .one().to_String("#.###")
// ```
export method to_String (TMath.Vector3 this, string precision = '') =>
	switch precision
		'' => str.format('({0}, {1}, {2})', this.x, this.y, this.z)
		=>    str.format(
		 '({0,number,' + precision + '}, {0,number,' + precision + '}, {0,number,' + precision + '})', 
		 this.x, this.y, this.z                                                                      )

//#endregion	2.3.1
//#region	2.3.2: to_Array						()													

// @function Converts source vector to a array format.
// @param this `Vector3` Source vector. 
// @returns `array<float>` List of the vector properties.
// ___
// **Usage:**
// ```
// a = .new(1, 2, 3).to_Array()
// ```
export method to_Array (TMath.Vector3 this) =>
	array<float> _return = array.from(float(this.x), float(this.y), float(this.z))

//#endregion	2.3.2
//#region	2.3.3: to_Vector2					()													

// @function Converts source vector to a Vector2 in the form `x, y`.
// @param this `Vector3` Source vector.
// @returns `Vector2` Generated new vector.
// ___
// **Usage:**
// ```
// a = .from(1).to_Vector2()
// ```
export method to_Vector2 (TMath.Vector3 this) =>
	TMath.Vector2.new(this.x, this.y)

//#endregion	2.3.3
//#region	2.3.4: to_Quaternion				()													

// @function Converts source vector to a Quaternion in the form `x, y, z, w`.
// @param this `Vector3` Sorce vector.
// @param w    `float`   Property of `w` new value.
// @returns `Quaternion` Generated new vector.
// ___
// **Usage:**
// ```
// a = .from(1).to_Quaternion(w=1)
// ```
export method to_Quaternion (TMath.Vector3 this, float w = na) =>
	TMath.Quaternion.new(this.x, this.y, this.z, w)

//#endregion	2.3.4
//#endregion	2.3
//#region	2.4: Operators:																			
//#region	2.4.01: add							()													
//#region	2.4.01.1: Vector3 + Vector3																

// @function Add a vector to source vector.
// @param this  `Vector3` Source vector.
// @param other `Vector3` Other vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .from(1).add(.unit_z())
// ```
export method add (TMath.Vector3 this, TMath.Vector3 other) =>
	TMath.Vector3.new(this.x + other.x, this.y + other.y, this.z + other.z)

//#endregion	2.4.01.1
//#region	2.4.01.2: Vector3 + float																

// @function Add a value to each property of the vector.
// @param this  `Vector3` Source vector.
// @param value `float`   Value.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .from(1).add(2.0)
// ```
export method add (TMath.Vector3 this, float value) =>
	TMath.Vector3.new(this.x + value, this.y + value, this.z + value)

//#endregion	2.4.01.2
//#region	2.4.01.3: float   + Vector3																

// @function Add each property of a vector to a base value as a new vector.
// @param value `float`   Value.
// @param other `Vector3` Vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .from(2)		, b = .add(1.0, a)
// ```
export add (float value, TMath.Vector3 other) =>
	TMath.Vector3.new(value + other.x, value + other.y, value + other.z)

//#endregion	2.4.01.3
//#endregion	2.4.01
//#region	2.4.02: subtract					()													
//#region	2.4.02.1: Vector3 - Vector3																

// @function Subtract vector from source vector.
// @param this  `Vector3` Source vector.
// @param other `Vector3` Other vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .from(1).subtract(.left())
// ```
export method subtract (TMath.Vector3 this, TMath.Vector3 other) =>
	TMath.Vector3.new(this.x - other.x, this.y - other.y, this.z - other.z)

//#endregion	2.4.02.1
//#region	2.4.02.2: Vector3 - float																

// @function Subtract a value from each property in source vector.
// @param this  `Vector3` Source vector.
// @param value `float`   Value.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .from(1).subtract(2.0)
// ```
export method subtract (TMath.Vector3 this, float value) =>
	TMath.Vector3.new(this.x - value, this.y - value, this.z - value)

//#endregion	2.4.02.2
//#region	2.4.02.3: float   - Vector3																

// @function Subtract each property in a vector from a base value and create a new vector.
// @param value `float`   Value.
// @param other `Vector3` Vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .subtract(1.0, .right())
// ```
export subtract (float value, TMath.Vector3 other) =>
	TMath.Vector3.new(value - other.x, value - other.y, value - other.z)

//#endregion	2.4.02.3
//#endregion	2.4.02
//#region	2.4.03: multiply					()													
//#region	2.4.03.1: Vector3 * Vector3																

// @function Multiply a vector by another.
// @param this  `Vector3` Source vector.
// @param other `Vector3` Other vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .from(1).multiply(.up())
// ```
export method multiply (TMath.Vector3 this, TMath.Vector3 other) =>
	TMath.Vector3.new(this.x * other.x, this.y * other.y, this.z * other.z)

//#endregion	2.4.03.1
//#region	2.4.03.2: Vector3 * float																

// @function Multiply each element in source vector with a value.
// @param this  `Vector3` Source vector.
// @param value `float`   Value.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .from(1).multiply(2.0)
// ```
export method multiply (TMath.Vector3 this, float value) =>
	TMath.Vector3.new(this.x * value, this.y * value, this.z * value)

//#endregion	2.4.03.2
//#region	2.4.03.3: float   * Vector3																

// @function Multiply a value with each property in a vector and create a new vector.
// @param value `float`   Value.
// @param other `Vector3` Vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .multiply(1.0, .new(1, 2, 1))
// ```
export multiply (float value, TMath.Vector3 other) =>
	TMath.Vector3.new(value * other.x, value * other.y, value * other.z)

//#endregion	2.4.03.3
//#endregion	2.4.03
//#region	2.4.04: divide						()													
//#region	2.4.04.1: Vector3 / Vector3																

// @function Divide a vector by another.
// @param this  `Vector3` Source vector.
// @param other `Vector3` Other vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .from(1).divide(.from(2))
// ```
export method divide (TMath.Vector3 this, TMath.Vector3 other) =>
	TMath.Vector3.new(this.x / other.x, this.y / other.y, this.z / other.z)

//#endregion	2.4.04.1
//#region	2.4.04.2: Vector3 / float																

// @function Divide each property in a vector by a value.
// @param this  `Vector3` Source vector.
// @param value `float`   Value.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .from(1).divide(2.0)
// ```
export method divide (TMath.Vector3 this, float value) =>
	TMath.Vector3.new(this.x / value, this.y / value, this.z / value)

//#endregion	2.4.04.2
//#region	2.4.04.3: float   / Vector3																

// @function Divide a base value by each property in a vector and create a new vector.
// @param value `float`   Value.
// @param other `Vector3` Vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .divide(1.0, .from(2))
// ```
export divide (float value, TMath.Vector3 other) =>
	TMath.Vector3.new(value / other.x, value / other.y, value / other.z)

//#endregion	2.4.04.3
//#endregion	2.4.04
//#region	2.4.05: mod							()													
//#region	2.4.05.1: Vector3 / Vector3																

// @function Modulo a vector by another.
// @param this  `Vector3` Source vector.
// @param other `Vector3` Other vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .from(1).mod(.from(2))
// ```
export method mod (TMath.Vector3 this, TMath.Vector3 other) =>
	TMath.Vector3.new(this.x % other.x, this.y % other.y, this.z % other.z)

//#endregion	2.4.05.1
//#region	2.4.05.2: Vector3 / float																

// @function Modulo each property in a vector by a value.
// @param this  `Vector3` Source vector.
// @param value `float`   Value.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .from(1).mod(2.0)
// ```
export method mod (TMath.Vector3 this, float value) =>
	TMath.Vector3.new(this.x % value, this.y % value, this.z % value)

//#endregion	2.4.05.2
//#region	2.4.05.3: float   / Vector3																

// @function Modulo a base value by each property in a vector and create a new vector.
// @param value `float`   Value.
// @param other `Vector3` Vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .mod(1.0, .from(2))
// ```
export mod (float value, TMath.Vector3 other) =>
	TMath.Vector3.new(value % other.x, value % other.y, value % other.z)

//#endregion	2.4.05.3
//#endregion	2.4.05
//#region	2.4.06: negate						()													

// @function Negate a vector in the form `(zero - this)`.
// @param this `Vector3` Source vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .one().negate()
// ```
export method negate (TMath.Vector3 this) =>
	TMath.Vector3.new(0.0 - this.x, 0.0 - this.y, 0.0 - this.z)

//#endregion	2.4.6
//#region	2.4.07: pow							()													
//#region	2.4.07.1: Vector3 ^ Vector3																

// @function Modulo a vector by another.
// @param this  `Vector3` Source vector.
// @param other `Vector3` Other vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .from(2).pow(.from(3))
// ```
export method pow (TMath.Vector3 this, TMath.Vector3 other) =>
	TMath.Vector3.new(math.pow(this.x, other.x), math.pow(this.y, other.y), math.pow(this.z, other.z))

//#endregion	2.4.07.1
//#region	2.4.07.2: Vector3 ^ float																

// @function Raise the vector elements by a exponent.
// @param this     `Vector3` Source vector.
// @param exponent `float`   The exponent to raise the vector by.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .from(1).pow(2.0)
// ```
export method pow (TMath.Vector3 this, float exponent) =>
	TMath.Vector3.new(math.pow(this.x, exponent), math.pow(this.y, exponent), math.pow(this.z, exponent))

//#endregion	2.4.07.2
//#region	2.4.07.3: float   ^ Vector3																

// @function Raise value into a vector raised by the elements in exponent vector.
// @param value    `float`   Base value.
// @param exponent `Vector3` The exponent to raise the vector of base value by.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .pow(1.0, .from(2))
// ```
export pow (float value, TMath.Vector3 exponent) =>
	TMath.Vector3.new(math.pow(value, exponent.x), math.pow(value, exponent.y), math.pow(value, exponent.z))

//#endregion	2.4.07.3
//#endregion	2.4.07
//#region	2.4.08: sqrt						()													

// @function Square root of the elements in a vector.
// @param this `Vector3` Source vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .from(1).sqrt()
// ```
export method sqrt (TMath.Vector3 this) =>
	TMath.Vector3.new(math.sqrt(this.x), math.sqrt(this.y), math.sqrt(this.z))

//#endregion	2.4.08
//#region	2.4.09: abs							()													

// @function Absolute properties of the vector.
// @param this `Vector3` Source vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .from(1).abs()
// ```
export method abs (TMath.Vector3 this) =>
	TMath.Vector3.new(math.abs(this.x), math.abs(this.y), math.abs(this.z))

//#endregion	2.4.09
//#region	2.4.10: max							()													

// @function Highest property of the vector.
// @param this `Vector3` Source vector.
// @returns `float` Highest value amongst the vector properties.
// ___
// **Usage:**
// ```
// a = .new(1, 2, 3).max()
// ```
export method max (TMath.Vector3 this) =>
	math.max(this.x, this.y, this.z)

//#endregion	2.4.10
//#region	2.4.11: min							()													

// @function Lowest element of the vector.
// @param this `Vector3` Source vector.
// @returns `float` Lowest values amongst the vector properties.
// ___
// **Usage:**
// ```
// a = .new(1, 2, 3).min()
// ```
export method min (TMath.Vector3 this) =>
	math.min(this.x, this.y, this.z)

//#endregion	2.4.11
//#region	2.4.12: floor						()													

// @function Floor of vector a.
// @param this `Vector3` Source vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .new(1.33, 1.66, 1.99).floor()
// ```
export method floor (TMath.Vector3 this) =>
	TMath.Vector3.new(math.floor(this.x), math.floor(this.y), math.floor(this.z))

//#endregion	2.4.12
//#region	2.4.13: ceil						()													

// @function Ceil of vector a.
// @param this `Vector3` Source vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .new(1.33, 1.66, 1.99).ceil()
// ```
export method ceil (TMath.Vector3 this) =>
	TMath.Vector3.new(math.ceil(this.x), math.ceil(this.y), math.ceil(this.z))

//#endregion	2.4.13
//#region	2.4.14: round						()													
//#region	2.4.14.1: with out precision.															

// @function Round of vector elements.
// @param this `Vector3` Source vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .new(1.33, 1.66, 1.99).round()
// ```
export method round (TMath.Vector3 this) =>
	TMath.Vector3.new(math.round(this.x), math.round(this.y), math.round(this.z))

//#endregion	2.4.14.1
//#region	2.4.14.2: with precision.																

// @function Round of vector elements to n digits.
// @param this 		`Vector3` 	Source vector.
// @param precision `int`		Number of digits to round the vector elements.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .new(1.33, 1.66, 1.99).round(1)	// 1.3, 1.7, 2
// ```
export method round (TMath.Vector3 this, int precision) =>
	int _d = math.max(0, precision)
	TMath.Vector3.new(math.round(this.x, _d), math.round(this.y, _d), math.round(this.z, _d))

//#endregion	2.4.14.2
//#endregion	2.4.14
//#region	2.4.15: fractional					()													

// @function Fractional parts of vector.
// @param this	`Vector3`	Source vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .from(1.337).fractional()	// 0.337
// ```
export method fractional (TMath.Vector3 this) =>
	TMath.Vector3.new(this.x - math.floor(this.x), this.y - math.floor(this.y), this.z - math.floor(this.z))

//#endregion	2.4.15
//#region	2.4.16: dot_product					()													

// @function Dot product of two vectors.
// @param this	`Vector3`	Source vector.
// @param other `Vector3`	Other vector.
// @returns `float` Dot product.
// ___
// **Usage:**
// ```
// a = .from(2).dot_product(.left())
// ```
export method dot_product (TMath.Vector3 this, TMath.Vector3 other) =>
	this.x * other.x + this.y * other.y + this.z * other.z

//#endregion	2.4.16
//#region	2.4.17: cross_product				()													

// @function Cross product of two vectors.
// @param this	`Vector3`	Source vector.
// @param other	`Vector3`	Other vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .from(1).cross_produc(.right())
// ```
export method cross_product (TMath.Vector3 this, TMath.Vector3 other) =>
	TMath.Vector3.new(
	 this.y * other.z - this.z * other.y, 
	 this.z * other.x - this.x * other.z, 
	 this.x * other.y - this.y * other.x
	 )

//#endregion	2.4.17
//#region	2.4.18: scale						()													

// @function Scale vector by a scalar value.
// @param this 		`Vector3` 	Source vector.
// @param scalar	`float`		Value to scale the the vector by.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .from(1).scale(2)
// ```
export method scale (TMath.Vector3 this, float scalar) =>
	TMath.Vector3.new(this.x * scalar, this.y * scalar, this.z * scalar)

//#endregion	2.4.18
//#region	2.4.19: rescale						()													

// @function Rescale a vector to a new magnitude.
// @param this		`Vector3`	Source vector.
// @param magnitude	`float`		Value to manipulate the magnitude of normalization.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .from(20).rescale(1)
// ```
export method rescale (TMath.Vector3 this, float magnitude) =>
	float _scalar = magnitude / this.length()
	multiply(this, _scalar)

//#endregion	2.4.19
//#region	2.4.20: equals						()													

// @function Compares two vectors.
// @param this	`Vector3`	Source vector.
// @param other	`Vector3`	Other vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .from(1).equals(.one())
// ```
export method equals (TMath.Vector3 this, TMath.Vector3 other) =>
	this.x == other.x and this.y == other.y and this.z == other.z

//#endregion	2.4.20
//#endregion	2.4
//#region	2.5: Trigonometry:																		
//#region	2.5.1: sin							()													

// @function Sine of vector.
// @param this	`Vector3`	Source vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .from(1).sin()
// ```
export method sin (TMath.Vector3 this) =>
	TMath.Vector3.new(math.sin(this.x), math.sin(this.y), math.sin(this.z))

//#endregion	2.5.1
//#region	2.5.2: cos							()													

// @function Cosine of vector.
// @param this	`Vector3`	Source vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .from(1).cos()
// ```
export method cos (TMath.Vector3 this) =>
	TMath.Vector3.new(math.cos(this.x), math.cos(this.y), math.cos(this.z))

//#endregion	2.5.2
//#region	2.5.3: tan							()													

// @function Tangent of vector.
// @param this	`Vector3`	Source vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .from(1).tan()
// ```
export method tan (TMath.Vector3 this) =>
	TMath.Vector3.new(math.tan(this.x), math.tan(this.y), math.tan(this.z))

//#endregion	2.5.3
//#endregion	2.5
//#endregion	2
//#region	3: Static Methods.																		
//#region	3.01: vmax							()													
//#region	3.01.1: 2 vectors:																		

// @function Highest elements of the properties from two vectors.
// @param a	`Vector3`	Vector.
// @param b `Vector3`	Vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .vmax(.one(), .from(2))
// ```
export vmax (TMath.Vector3 a, TMath.Vector3 b) =>
	TMath.Vector3.new(
	 math.max(a.x, b.x),
	 math.max(a.y, b.y),
	 math.max(a.z, b.z))

//#endregion	3.01.1
//#region	3.01.2: 3 vectors:																		

// @function Highest elements of the properties from three vectors.
// @param a	`Vector3`	Vector.
// @param b `Vector3`	Vector.
// @param c `Vector3`	Vector. 
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .vmax(.new(0.1, 2.5, 3.4), .from(2), .from(3))
// ```
export vmax (TMath.Vector3 a, TMath.Vector3 b, TMath.Vector3 c) =>
	TMath.Vector3.new(
	 math.max(a.x, b.x, c.x),
	 math.max(a.y, b.y, c.y),
	 math.max(a.z, b.z, c.z))
//#endregion	3.01.2
//#endregion	3.01
//#region	3.02: vmin							()													
//#region	3.02.1: 2 vectors:																		

// @function Lowest elements of the properties from two vectors.
// @param a `Vector3`	Vector.
// @param b `Vector3`  	Vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .vmin(.one(), .from(2))
// ```
export vmin (TMath.Vector3 a, TMath.Vector3 b) =>
	TMath.Vector3.new(
	 math.min(a.x, b.x),
	 math.min(a.y, b.y),
	 math.min(a.z, b.z))

//#endregion	3.02.1
//#region	3.02.2: 3 vectors:																		

// @function Lowest elements of the properties from three vectors.
// @param a `Vector3`	Vector.
// @param b `Vector3`	Vector.
// @param c `Vector3`	Vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .vmin(.one(), .from(2), .new(3.3, 2.2, 0.5))
// ```
export vmin (TMath.Vector3 a, TMath.Vector3 b, TMath.Vector3 c) =>
	TMath.Vector3.new(
	 math.min(a.x, b.x, c.x),
	 math.min(a.y, b.y, c.y),
	 math.min(a.z, b.z, c.z))

//#endregion	3.02.2
//#endregion	3.02
//#region	3.03: distance						()													

// @function Distance between vector `a` and `b`.
// @param a	`Vector3`	Source vector.
// @param b	`Vector3`	Target vector.
// @returns `float`.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = distance(.from(3), .unit_z())
// ```
export distance (TMath.Vector3 a, TMath.Vector3 b) =>
	length(TMath.Vector3.new(a.x - b.x, a.y - b.y, a.z - b.z))

//#endregion	3.03
//#region	3.04: clamp							()													

// @function Restrict a vector between a min and max vector.
// @param a		`Vector3`	Source vector.
// @param min	`Vector3`	Minimum boundary vector.
// @param max	`Vector3`	Maximum boundary vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .clamp(a=.new(2.9, 1.5, 3.9), min=.from(2), max=.new(2.5, 3.0, 3.5))
// ```
export clamp (TMath.Vector3 a, TMath.Vector3 min, TMath.Vector3 max) =>
	TMath.Vector3.new(
	 a.x > min.x ? (a.x < max.x ? a.x : max.x) : min.x, 
	 a.y > min.y ? (a.y < max.y ? a.y : max.y) : min.y,
	 a.z > min.z ? (a.z < max.z ? a.z : max.z) : min.z)

//#endregion	3.04
//#region	3.05: clamp_magnitude				()													

// @function Vector with its magnitude clamped to a radius.
// @param a			`Vector3`	Source vector.object, vector with properties that should be restricted to a radius.
// @param radius	`float`		Maximum radius to restrict magnitude of vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .clamp_magnitude(.from(21), 7)
// ```
export clamp_magnitude (TMath.Vector3 a, float radius) =>
	float _sqrmag = magnitude_squared(a)
	if _sqrmag > radius * radius
		float _mag = math.sqrt(_sqrmag)
		//these intermediate variables force the intermediate result to be
		//of float precision. without this, the intermediate result can be of higher
		//precision, which changes behavior.
		float _normalized_x = a.x / _mag
		float _normalized_y = a.y / _mag
		float _normalized_z = a.z / _mag
		TMath.Vector3.new(
		 _normalized_x * radius,
		 _normalized_y * radius,
		 _normalized_z * radius)
	else
		TMath.Vector3.copy(a)
//#endregion	3.05
//#region	3.06: lerp_unclamped				()													

// @function `Unclamped` linearly interpolates between provided vectors by a rate.
// @param a		`Vector3`	Source vector.
// @param b 	`Vector3`	Target vector.
// @param rate 	`float`		Rate of interpolation, range(0 > 1) where 0 == source vector and 1 == target vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .lerp_unclamped(.from(1), .from(2), 1.2)
// ```
export lerp_unclamped (TMath.Vector3 a, TMath.Vector3 b, float rate) =>
	TMath.Vector3.new(
	 x = a.x + (b.x - a.x) * rate	,
	 y = a.y + (b.y - a.y) * rate	,
	 z = a.z + (b.z - a.z) * rate	)

//#endregion	3.06
//#region	3.07: lerp							()													

// @function Linearly interpolates between provided vectors by a rate.
// @param a		`Vector3`	Source vector.
// @param b		`Vector3`	Target vector.
// @param rate	`float`		Rate of interpolation, range(0 > 1) where 0 == source vector and 1 == target vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = lerp(.one(), .from(2), 0.2)
// ```
export lerp (TMath.Vector3 a, TMath.Vector3 b, float rate) =>
	float _t = rate > 0.0 ? (rate < 1.0 ? rate : 1.0) : 0.0
	TMath.Vector3.new(
	 x = a.x + (b.x - a.x) * _t		,
	 y = a.y + (b.y - a.y) * _t		, 
	 z = a.z + (b.z - a.z) * _t		)

//#endregion	3.07
//#region	3.08: herp							()													

// @function Hermite curve interpolation between provided vectors.
// @param start			`Vector3`	Start vector.
// @param start_tangent	`Vector3`	Start vector tangent.
// @param end			`Vector3`	End vector.
// @param end_tangent	`Vector3`	End vector tangent.
// @param rate			`float`		Rate of the movement from `start` to `end` to get position, should be range(0 > 1).
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// s = .new(0, 0, 0)		, st = .new(0, 1, 1)
// e = .new(1, 2, 2)		, et = .new(-1, -1, 3)
// h = .herp(s, st, e, et, 0.3)
// ```
// ___
// **Reference:**	https://en.m.wikibooks.org/wiki/Cg_Programming/Unity/Hermite_Curves
export herp (
 TMath.Vector3 start	, TMath.Vector3 start_tangent	, 
 TMath.Vector3 end		, TMath.Vector3 end_tangent		, int rate	) =>
	//
	float _m0x = start_tangent.x - start.x		, float _m1x = end_tangent.x - end.x
	float _m0y = start_tangent.y - start.y		, float _m1y = end_tangent.y - end.y
	float _m0z = start_tangent.z - start.z		, float _m1z = end_tangent.z - end.z
	float _t2  = rate * rate		, float _t3  = rate * _t2
	float _2t2 = 2.0 * _t2 			, float _2t3 = 2.0 * _t3			, float _3t2 = 3.0 * _t2
	float _a   = _2t3 - _3t2 + 1.0	, float _b   = _t3 - _2t2 + rate
	float _c   = -_2t3 + _3t2		, float _d   = (_t3 - _t2)
	TMath.Vector3.new(
	 x = (_a * start.x) + (_b * _m0x) + (_c * end.x) + (_d * _m1x)		,
	 y = (_a * start.y) + (_b * _m0y) + (_c * end.y) + (_d * _m1y)		,
	 z = (_a * start.z) + (_b * _m0z) + (_c * end.z) + (_d * _m1z)		)

//#endregion	3.08
//#region	3.09: herp_2						()													

// @function Hermite curve interpolation between provided vectors.
// @param a		`Vector3` Source vector.
// @param b		`Vector3` Target vector.
// @param rate	`Vector3` Rate of the movement per component from `start` to `end` to get position, should be range(0 > 1).
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// h = .herp_2(.one(), .new(0.1, 3, 2), 0.6)
// ```
export herp_2 (TMath.Vector3 a, TMath.Vector3 b, TMath.Vector3 rate) =>
	// used on noise() function
	float _tx = math.max(math.min((rate.x - a.x) / (b.x - a.x), 1.0), 0.0)
	float _ty = math.max(math.min((rate.y - a.y) / (b.y - a.y), 1.0), 0.0)
	float _tz = math.max(math.min((rate.z - a.z) / (b.z - a.z), 1.0), 0.0)
	TMath.Vector3.new(
	 x = _tx * _tx * (3.0 - 2.0 * _tx)	, 
	 y = _ty * _ty * (3.0 - 2.0 * _ty)	, 
	 z = _tz * _tz * (3.0 - 2.0 * _tz)	)

//#endregion	3.09
//#region	3.10: noise							()													

// @function 3D Noise based on Morgan McGuire @morgan3d
// @param a	`Vector3` Source vector.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = noise(.one())
// ```
// ___
// **Reference:**
// - https://thebookofshaders.com/11/
// - https://www.shadertoy.com/view/4dS3Wd
export noise (TMath.Vector3 a) =>
    TMath.Vector3 _step = TMath.Vector3.new(110.0, 241.0, 271.0)
    TMath.Vector3 _i = floor(a)
    TMath.Vector3 _f = fractional(a)
    // For performance, compute the base input to a 1D hash from the integer part of the argument and the 
    // incremental change to the 1D based on the 3D -> 1D wrapping
    float _n = dot_product(_i, _step)
    TMath.Vector3 _u     = herp_2(zero(), one(), _f)// multiply(multiply(_f, _f), subtract(from(3.0), multiply(from(2.0), _f))) // _f * _f * (3.0 - 2.0 * _f)
    TMath.Vector3 _mix00 = lerp( random(from(_n + dot_product(_step,       zero()))), random(from(_n + dot_product(_step,         right()))), _u.x)
    TMath.Vector3 _mix01 = lerp( random(from(_n + dot_product(_step,         up()))), random(from(_n + dot_product(_step, TMath.Vector3.new(1, 1, 0)))), _u.x)
    TMath.Vector3 _mix10 = lerp( random(from(_n + dot_product(_step,      front()))), random(from(_n + dot_product(_step, TMath.Vector3.new(1, 0, 1)))), _u.x)
    TMath.Vector3 _mix11 = lerp( random(from(_n + dot_product(_step, new(0, 1, 1)))), random(from(_n + dot_product(_step, TMath.Vector3.new(1, 1, 1)))), _u.x)
    TMath.Vector3 _mix0  = lerp(_mix00, _mix01, _u.y)
    TMath.Vector3 _mix1  = lerp(_mix10, _mix11, _u.y)
	lerp(_mix0, _mix1, _u.z)

//#endregion	3.10
//#region	3.11: Rotation.																			
//#region	3.11.1: rotate						()													

// @function Rotate a vector around a axis.
// @param a		`Vector3`	Source vector.
// @param axis	`string`	The plane to rotate around, `option="x", "y", "z"`.
// @param angle	`float`		Angle in radians.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .rotate(.from(3), 'y', math.toradians(45.0))
// ```
// ___
// **Reference:**
// - https://nikhilrao.blog/rotation-of-a-vector-in-python
export rotate (TMath.Vector3 a, string axis, float angle) =>
    float _sin = math.sin(angle)
    float _cos = math.cos(angle)
	switch axis
		'x' =>
			float _m00 = 1.0, float _m10 =  0.0, float _m20 = 0.0
			float _m01 = 0.0, float _m11 = _cos, float _m21 = -_sin
			float _m02 = 0.0, float _m12 = _sin, float _m22 = _cos
			// dot product of M.a
			TMath.Vector3.new(
			 x = ((_m00 * a.x) + (_m10 * a.y) + (_m20 * a.z))	,
			 y = ((_m01 * a.x) + (_m11 * a.y) + (_m21 * a.z))	,
			 z = ((_m02 * a.x) + (_m12 * a.y) + (_m22 * a.z))	)
		'y' =>
			float _m00 = _cos, float _m10 =  0.0, float _m20 = _sin
			float _m01 =  0.0, float _m11 =  1.0, float _m21 =  0.0
			float _m02 =  0.0, float _m12 =  0.0, float _m22 = _cos
			// dot product of M.a
			TMath.Vector3.new(
			 x = ((_m00 * a.x) + (_m10 * a.y) + (_m20 * a.z))	,
			 y = ((_m01 * a.x) + (_m11 * a.y) + (_m21 * a.z))	,
			 z = ((_m02 * a.x) + (_m12 * a.y) + (_m22 * a.z))	)
		'z' =>
			float _m00 = _cos, float _m10 = -_sin, float _m20 = 0.0
			float _m01 = _sin, float _m11 =  _cos, float _m21 = 0.0
			float _m02 =  0.0, float _m12 =   0.0, float _m22 = 1.0
			// dot product of M.a
			TMath.Vector3.new(
			 x = ((_m00 * a.x) + (_m10 * a.y) + (_m20 * a.z))	,
			 y = ((_m01 * a.x) + (_m11 * a.y) + (_m21 * a.z))	,
			 z = ((_m02 * a.x) + (_m12 * a.y) + (_m22 * a.z))	)
		=>
			TMath.Vector3.copy(a)

//#endregion	3.11.1
//#region	3.11.2: rotate_x					()													

// @function Rotate a vector on a fixed `x`.
// @param a		`Vector3` 	Source vector.
// @param angle `float`		Angle in radians.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .rotate_x(.from(3), math.toradians(90.0))
// ```
export rotate_x (TMath.Vector3 a, float angle) => 
	float _rcos = math.cos(angle), float _rsin = math.sin(angle)
	TMath.Vector3.new(a.x, a.y * _rcos - a.z * _rsin, a.y * _rsin + a.z * _rcos)

//#endregion	3.11.2
//#region	3.11.3: rotate_y					()													

// @function Rotate a vector on a fixed `y`.
// @param a		`Vector3`	Source vector.
// @param angle	`float`		Angle in radians.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .rotate_y(.from(3), math.toradians(90.0))
// ```
export rotate_y (TMath.Vector3 a, float angle) =>
	float _rcos = math.cos(angle), float _rsin = math.sin(angle)
	TMath.Vector3.new(a.z * _rsin + a.x * _rcos, a.y, a.z * _rcos - a.x * _rsin)

//#endregion	3.11.3
//#region	3.11.3: rotate_z					()													

// @function Rotate a vector on a fixed `z`.
// @param a		`Vector3`	Source vector.
// @param angle	`float`		Angle in radians.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .rotate_z(.from(3), math.toradians(90.0))
// ```
export rotate_z (TMath.Vector3 a, float angle) =>
	float _rcos = math.cos(angle), float _rsin = math.sin(angle)
	TMath.Vector3.new(a.x * _rcos - a.y * _rsin, a.x * _rsin + a.y * _rcos, a.z)

//#endregion	3.11.3
//#region	3.11.4: rotate_yaw_pitch			()													

// @function Rotate a vector by yaw and pitch values.
// @param a		`Vector3` 	Source vector.
// @param yaw	`float`		Angle in radians.
// @param pitch	`float`		Angle in radians.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .rotate_yaw_pitch(.from(3), math.toradians(90.0), math.toradians(45.0))
// ```
export rotate_yaw_pitch (TMath.Vector3 a, float yaw, float pitch) =>
	rotate_y(rotate_x(a, pitch), yaw)

//#endregion	3.11.4
//#endregion	3.11
//#region	3.12: Projection.																		
//#region	3.12.1: project						()													

// @function Project a vector off a plane defined by a normal.
// @param a			`Vector3`	Source vector.
// @param normal	`Vector3`	The normal of the surface being reflected off.
// @param eps		`float`		Minimum resolution to void division by zero (default=0.000001).
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .project(.one(), .down())
// ```
export project (TMath.Vector3 a, TMath.Vector3 normal, float eps = 0.000001) =>
	float _sqr_mag = normal.x * normal.x + normal.y * normal.y + normal.z * normal.z
	if _sqr_mag < eps
		zero()
	else
		float _dot = a.x * normal.x + a.y * normal.y + a.z * normal.z
		TMath.Vector3.new(normal.x * _dot / _sqr_mag, normal.y * _dot / _sqr_mag, normal.z * _dot / _sqr_mag)   

//#endregion	3.12.1
//#region	3.12.2: project_on_plane			()													

// @function Projects a vector onto a plane defined by a normal orthogonal to the plane.
// @param a			`Vector3`	Source vector.
// @param normal	`Vector3`	The normal of the surface being reflected off.
// @param eps		`float`		Minimum resolution to void division by zero (default=0.000001).
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .project_on_plane(.one(), .left())
// ```
export project_on_plane (TMath.Vector3 a, TMath.Vector3 normal, float eps = 0.000001) =>
	float _sqr_mag = normal.x * normal.x + normal.y * normal.y + normal.z * normal.z
	if _sqr_mag < eps
		TMath.Vector3.copy(a)
	else
		float _dot = a.x * normal.x + a.y * normal.y + a.z * normal.z
		TMath.Vector3.new(a.x - normal.x * _dot / _sqr_mag, a.y - normal.y * _dot / _sqr_mag, a.z - normal.z * _dot / _sqr_mag)   

//#endregion	3.12.2
//#region	3.12.3: project_to_2d				()													

// @function Project a vector onto a two dimensions plane.
// @param a					`Vector3`	Source vector.
// @param camera_position	`Vector3`	Camera position.
// @param camera_target		`Vector3`	Camera target plane position.
// @returns `Vector2` Generated new vector.
// ___
// **Usage:**
// ```
// a = .project_to_2d(.one(), .new(2, 2, 3), .zero())
// ```
export project_to_2d (TMath.Vector3 a, TMath.Vector3 camera_position, TMath.Vector3 camera_target) =>
	_d_to_source = subtract(a, camera_position)
	_d_to_target = subtract(camera_target, camera_position)
	_r = divide(_d_to_target, _d_to_source)
	V2.new(a.x - _d_to_source.x * _r.x, a.y - _d_to_source.y * _r.y)

//#endregion	3.12.3
//#endregion	3.12
//#region	3.13: reflect						()													

// @function Reflects a vector off a plane defined by a normal.
// @param a			`Vector3`	Source vector.
// @param normal	`Vector3`	The normal of the surface being reflected off.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .reflect(.one(), .right())
// ```
export reflect (TMath.Vector3 a, TMath.Vector3 normal) =>
	float _dot = a.x * normal.x + a.y * normal.y + a.z * normal.z
	float _factor = 2.0 * _dot
	float _tx = normal.x * _factor
	float _ty = normal.y * _factor
	float _tz = normal.z * _factor
	TMath.Vector3.new(a.x - _tx, a.y - _ty, a.z - _tz)

//#endregion	3.13
//#region	3.14: Angle.																			
//#region	3.14.1: angle						()													

// @function Angle in degrees between two vectors.
// @param a		`Vector3`	Source vector.
// @param b		`Vector3`	Target vector.
// @param eps	`float`		Minimum resolution to void division by zero (default=1.0e-15).
// @returns `float` Angle value in degrees.
// ___
// **Usage:**
// ```
// a = .angle(.one(), .up())
// ```
export angle (TMath.Vector3 a, TMath.Vector3 b, float eps = 1.0e-15) =>
	// allways the smallest	
	// sqrt(a) * sqrt(b) = sqrt(a * b) -- valid for real numbers
    float _denominator = math.sqrt(magnitude_squared(a) * magnitude_squared(b))
	if _denominator < eps
        0.0
	else
		float _dot = math.max(math.min(dot_product(a, b) / _denominator, 1.0), -1.0)
		math.todegrees(math.acos(_dot))

//#endregion	3.14.1
//#region	3.14.2: angle_signed				()													

// @function Signed angle in degrees between two vectors.
// @param a		`Vector3` Source vector.
// @param b		`Vector3` Target vector.
// @param axis	`Vector3` Axis vector.
// @returns `float` Angle value in degrees.
// ___
// **Usage:**
// ```
// a = .angle_signed(.one(), .left(), .down())
// ```
// ___
// **Notes:**
// - The smaller of the two possible angles between the two vectors is returned, therefore the result will never 
//	be greater than 180 degrees or smaller than -180 degrees.
// - If you imagine the from and to vectors as lines on a piece of paper, both originating from the same point, 
//	then the /axis/ vector would point up out of the paper.
// - The measured angle between the two vectors would be positive in a clockwise direction and negative in an 
//	anti-clockwise direction.
// ___
// **Reference:**
// - https://github.com/Unity-Technologies/UnityCsReference/blob/master/Runtime/Export/Math/Vector3.cs#L335
export angle_signed (TMath.Vector3 a, TMath.Vector3 b, TMath.Vector3 axis) =>
	float _unsigned_angle = angle(a, b)
	//
	float _cross_x = a.y * b.z - a.z * b.y
	float _cross_y = a.z * b.x - a.x * b.z
	float _cross_z = a.x * b.y - a.y * b.x
	float _sign = math.sign(axis.x * _cross_x + axis.y * _cross_y + axis.z * _cross_z)
	_unsigned_angle * _sign

//#endregion	3.14.2
//#region	3.14.3: angle_2d					()													

// @function 2D angle between two vectors.
// @param a	`Vector3`	Source vector.
// @param b	`Vector3`	Target vector.
// @returns `float` Angle value in degrees.
// ___
// **Usage:**
// ```
// a = .angle2d(.one(), .left())
// ```
export angle2d (TMath.Vector3 a, TMath.Vector3 b) =>
	V2.atan2(V2.new(b.x - a.x, b.z - a.z))

//#endregion	3.14.3
//#endregion	3.14
//#region	3.15: Transforms.																		
//#region	3.15.1: transform_Matrix			()													

// @function Transforms a vector by the given matrix.
// @param a	`Vector3`	Source vector.
// @param M	`matrix<float>` A 4x4 matrix. The transformation matrix.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// mat = matrix.new<float>(4, 0)
// mat.add_row(0, array.from(0.0, 0.0, 0.0, 1.0))
// mat.add_row(1, array.from(0.0, 0.0, 1.0, 0.0))
// mat.add_row(2, array.from(0.0, 1.0, 0.0, 0.0))
// mat.add_row(3, array.from(1.0, 0.0, 0.0, 0.0))
// b = .transform_Matrix(.one(), mat)
// ```
export transform_Matrix (TMath.Vector3 a, matrix<float> M) =>
	if matrix.rows(M) == 4 and matrix.columns(M) == 4
		TMath.Vector3.new(
		 a.x * M.get(0, 0) + a.y * M.get(0, 1) + a.z * M.get(0, 2) + M.get(0, 3)	,
		 a.x * M.get(1, 0) + a.y * M.get(1, 1) + a.z * M.get(1, 2) + M.get(1, 3)	,
		 a.x * M.get(2, 0) + a.y * M.get(2, 1) + a.z * M.get(2, 2) + M.get(2, 3)	)
	else
		TMath.Vector3.copy(a)

//#endregion	3.15.1
//#region	3.15.2: transform_M44				()													

// @function Transforms a vector by the given matrix.
// @param a	`Vector3`	Source vector.
// @param M	`M44` 		A 4x4 matrix. The transformation matrix.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .transform_M44(.one(), .M44.new(0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0))
// ```
// ___
// **Notes:**
// - Type `M44` from `CommonTypesMath` library.
export transform_M44 (TMath.Vector3 a, TMath.M44 M) =>
	TMath.Vector3.new(
	 x = a.x * M.m11 + a.y * M.m12 + a.z * M.m13 + M.m14	,
	 y = a.x * M.m21 + a.y * M.m22 + a.z * M.m23 + M.m24	,
	 z = a.x * M.m31 + a.y * M.m32 + a.z * M.m33 + M.m34	)

//#endregion	3.15.2
//#region	3.15.3: transform_normal_Matrix		()													

// @function Transforms a vector by the given matrix.
// @param a	`Vector3` 		Source vector.
// @param M	`matrix<float>`	A 4x4 matrix. The transformation matrix.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// mat = matrix.new<float>(4, 0)
// mat.add_row(0, array.from(0.0, 0.0, 0.0, 1.0))
// mat.add_row(1, array.from(0.0, 0.0, 1.0, 0.0))
// mat.add_row(2, array.from(0.0, 1.0, 0.0, 0.0))
// mat.add_row(3, array.from(1.0, 0.0, 0.0, 0.0))
// b = .transform_normal_Matrix(.one(), mat)
// ```
export transform_normal_Matrix (TMath.Vector3 a, matrix<float> M) =>
	if matrix.rows(M) == 4 and matrix.columns(M) == 4
		TMath.Vector3.new(
		 a.x * M.get(0, 0) + a.y * M.get(1, 0) + a.z * M.get(2, 0)	,
		 a.x * M.get(0, 1) + a.y * M.get(1, 1) + a.z * M.get(2, 1)	,
		 a.x * M.get(0, 2) + a.y * M.get(1, 2) + a.z * M.get(2, 2)	)
	else
		TMath.Vector3.copy(a)

//#endregion	3.15.3
//#region	3.15.4: transform_normal_M44		()													

// @function Transforms a vector by the given matrix.
// @param a	`Vector3` 		Source vector.
// @param M	`M44`	A 4x4 matrix. The transformation matrix.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .transform_normal_M44(.one(), .M44.new(0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0))
// ```
// ___
// **Notes:**
// - Type `M44` from `CommonTypesMath` library.
export transform_normal_M44 (TMath.Vector3 a, TMath.M44 M) =>
	TMath.Vector3.new(
	 x = a.x * M.m11 + a.y * M.m21 + a.z * M.m31	,
	 y = a.x * M.m12 + a.y * M.m22 + a.z * M.m32	,
	 z = a.x * M.m13 + a.y * M.m23 + a.z * M.m33	)

//#endregion	3.15.3
//#region	3.15.4: transform_Array				()													

// @function Transforms a vector by the given Quaternion rotation value.
// @param a			`Vector3`		Source vector. The source vector to be rotated.
// @param rotation	`array<float>`	A 4 element array. Quaternion. The rotation to apply.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .transform_Array(.one(), array.from(0.2, 0.2, 0.2, 1.0))
// ```
// ___
// **Reference:**
// - https://referencesource.microsoft.com/#System.Numerics/System/Numerics/Vector3.cs,340
export transform_Array (TMath.Vector3 a, array<float> rotation) =>
	if array.size(rotation) >= 4
		float _rx = array.get(rotation, 0), float _ry = array.get(rotation, 1), float _rz = array.get(rotation, 2), float _rw = array.get(rotation, 3)
		float _x2 = _rx + _rx, float _y2 = _ry + _ry, float _z2 = _rz + _rz

		float _wx2 = _rw * _x2
		float _wy2 = _rw * _y2
		float _wz2 = _rw * _z2
		float _xx2 = _rx * _x2
		float _xy2 = _rx * _y2
		float _xz2 = _rx * _z2
		float _yy2 = _ry * _y2
		float _yz2 = _ry * _z2
		float _zz2 = _rz * _z2

		TMath.Vector3.new(
		 a.x * (1.0 - _yy2 - _zz2) + a.y * (_xy2 - _wz2) + a.z * (_xz2 + _wy2),
		 a.x * (_xy2 + _wz2) + a.y * (1.0 - _xx2 - _zz2) + a.z * (_yz2 - _wx2),
		 a.x * (_xz2 - _wy2) + a.y * (_yz2 + _wx2) + a.z * (1.0 - _xx2 - _yy2))
	else
		TMath.Vector3.copy(a)

//#endregion	3.15.4
//#region	3.15.4: transform_Quaternion		()													

// @function Transforms a vector by the given Quaternion rotation value.
// @param a			`Vector3`		Source vector. The source vector to be rotated.
// @param rotation	`array<float>`	A 4 element array. Quaternion. The rotation to apply.
// @returns `Vector3` Generated new vector.
// ___
// **Usage:**
// ```
// a = .transform_Quaternion(.one(), .Quaternion.new(0.2, 0.2, 0.2, 1.0))
// ```
// ___
// **Notes:**
// - Type `Quaternion` from `CommonTypesMath` library.
// ___
// **Reference:**
// - https://github.com/microsoft/referencesource/blob/master/System.Numerics/System/Numerics/Vector3.cs
export transform_Quaternion (TMath.Vector3 a, TMath.Quaternion rotation) =>
	float _rx = rotation.x, float _ry = rotation.y, float _rz = rotation.z, float _rw = rotation.w
	float _x2 = _rx + _rx, float _y2 = _ry + _ry, float _z2 = _rz + _rz

	float _wx2 = _rw * _x2
	float _wy2 = _rw * _y2
	float _wz2 = _rw * _z2
	float _xx2 = _rx * _x2
	float _xy2 = _rx * _y2
	float _xz2 = _rx * _z2
	float _yy2 = _ry * _y2
	float _yz2 = _ry * _z2
	float _zz2 = _rz * _z2

	TMath.Vector3.new(
	 x = a.x * (1.0 - _yy2 - _zz2) + a.y * (_xy2 - _wz2)       + a.z * (_xz2 + _wy2)		,
	 y = a.x * (_xy2 + _wz2)       + a.y * (1.0 - _xx2 - _zz2) + a.z * (_yz2 - _wx2)		,
	 z = a.x * (_xz2 - _wy2)       + a.y * (_yz2 + _wx2)       + a.z * (1.0 - _xx2 - _yy2)	)

//#endregion	3.15.4
//#endregion	3.15
//#endregion	3



logger.update()