1 #pragma once
2 
3 /** @file fixed2.h  Fixed-point 48.16 2D vector.
4 
5 @authors Copyright (c) 2020 Jaakko Keränen <jaakko.keranen@iki.fi>
6 
7 @par License
8 
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
11 
12 1. Redistributions of source code must retain the above copyright notice, this
13    list of conditions and the following disclaimer.
14 2. Redistributions in binary form must reproduce the above copyright notice,
15    this list of conditions and the following disclaimer in the documentation
16    and/or other materials provided with the distribution.
17 
18 <small>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
22 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</small>
28 */
29 
30 #include "fixed.h"
31 
32 iDeclareType(Fixed2)
33 
34 struct Impl_Fixed2 {
35     iFixed x, y;
36 };
37 
init1_X2(const iFixed x)38 iLocalDef iFixed2 init1_X2(const iFixed x) {
39     return (iFixed2){ x, x };
40 }
41 
initi1_X2(int x)42 iLocalDef iFixed2 initi1_X2(int x) {
43     return init1_X2(initi_Fixed(x));
44 }
45 
initf1_X2(float x)46 iLocalDef iFixed2 initf1_X2(float x) {
47     return init1_X2(initf_Fixed(x));
48 }
49 
init_X2(const iFixed x,const iFixed y)50 iLocalDef iFixed2 init_X2(const iFixed x, const iFixed y) {
51     return (iFixed2){ x, y };
52 }
53 
initi_X2(int x,int y)54 iLocalDef iFixed2 initi_X2(int x, int y) {
55     return init_X2(initi_Fixed(x), initi_Fixed(y));
56 }
57 
initf_X2(float x,float y)58 iLocalDef iFixed2 initf_X2(float x, float y) {
59     return init_X2(initf_Fixed(x), initf_Fixed(y));
60 }
61 
initv_X2(const iFixed * v)62 iLocalDef iFixed2 initv_X2(const iFixed *v) {
63     return (iFixed2){ v[0], v[1] };
64 }
65 
zero_X2(void)66 iLocalDef iFixed2 zero_X2(void) {
67     return (iFixed2){ .x = zero_Fixed(), .y = zero_Fixed() };
68 }
69 
one_X2(void)70 iLocalDef iFixed2 one_X2(void) {
71     return init1_X2(one_Fixed());
72 }
73 
store_X2(const iFixed2 d,iFixed * p_out)74 iLocalDef void store_X2(const iFixed2 d, iFixed *p_out) {
75     p_out[0] = d.x;
76     p_out[1] = d.y;
77 }
78 
yx_X2(const iFixed2 d)79 iLocalDef iFixed2 yx_X2(const iFixed2 d) {
80     return (iFixed2){ d.y, d.x };
81 }
82 
addX_X2(const iFixed2 a,const iFixed dx)83 iLocalDef iFixed2 addX_X2   (const iFixed2 a, const iFixed dx)  { return (iFixed2){ add_Fixed(a.x, dx), a.y }; }
addY_X2(const iFixed2 a,const iFixed dy)84 iLocalDef iFixed2 addY_X2   (const iFixed2 a, const iFixed dy)  { return (iFixed2){ a.x, add_Fixed(a.y, dy) }; }
85 
add_X2(const iFixed2 a,const iFixed2 b)86 iLocalDef iFixed2 add_X2    (const iFixed2 a, const iFixed2 b)  { return (iFixed2){ add_Fixed(a.x, b.x), add_Fixed(a.y, b.y) }; }
addi_X2(const iFixed2 a,int b)87 iLocalDef iFixed2 addi_X2   (const iFixed2 a, int b)            { return add_X2(a, initi1_X2(b)); }
addf_X2(const iFixed2 a,float b)88 iLocalDef iFixed2 addf_X2   (const iFixed2 a, float b)          { return add_X2(a, initf1_X2(b)); }
sub_X2(const iFixed2 a,const iFixed2 b)89 iLocalDef iFixed2 sub_X2    (const iFixed2 a, const iFixed2 b)  { return (iFixed2){ sub_Fixed(a.x, b.x), sub_Fixed(a.y, b.y) }; }
subi_X2(const iFixed2 a,int b)90 iLocalDef iFixed2 subi_X2   (const iFixed2 a, int b)            { return sub_X2(a, initi1_X2(b)); }
subf_X2(const iFixed2 a,float b)91 iLocalDef iFixed2 subf_X2   (const iFixed2 a, float b)          { return sub_X2(a, initf1_X2(b)); }
mul_X2(const iFixed2 a,const iFixed2 b)92 iLocalDef iFixed2 mul_X2    (const iFixed2 a, const iFixed2 b)  { return (iFixed2){ mul_Fixed(a.x, b.x), mul_Fixed(a.y, b.y) }; }
muli_X2(const iFixed2 a,int b)93 iLocalDef iFixed2 muli_X2   (const iFixed2 a, int b)            { return mul_X2(a, initi1_X2(b)); }
mulf_X2(const iFixed2 a,float b)94 iLocalDef iFixed2 mulf_X2   (const iFixed2 a, float b)          { return mul_X2(a, initf1_X2(b)); }
div_X2(const iFixed2 a,const iFixed2 b)95 iLocalDef iFixed2 div_X2    (const iFixed2 a, const iFixed2 b)  { return (iFixed2){ div_Fixed(a.x, b.x), div_Fixed(a.y, b.y) }; }
divi_X2(const iFixed2 a,int b)96 iLocalDef iFixed2 divi_X2   (const iFixed2 a, int b)            { return div_X2(a, initi1_X2(b)); }
divf_X2(const iFixed2 a,float b)97 iLocalDef iFixed2 divf_X2   (const iFixed2 a, float b)          { return div_X2(a, initf1_X2(b)); }
98 
addv_X2(iFixed2 * a,const iFixed2 b)99 iLocalDef iFixed2 addv_X2   (iFixed2 *a, const iFixed2 b)       { addv_Fixed(&a->x, b.x); addv_Fixed(&a->y, b.y); return *a; }
addiv_X2(iFixed2 * a,int b)100 iLocalDef iFixed2 addiv_X2  (iFixed2 *a, int b)                 { return addv_X2(a, initi1_X2(b)); }
addfv_X2(iFixed2 * a,float b)101 iLocalDef iFixed2 addfv_X2  (iFixed2 *a, float b)               { return addv_X2(a, initf1_X2(b)); }
subv_X2(iFixed2 * a,const iFixed2 b)102 iLocalDef iFixed2 subv_X2   (iFixed2 *a, const iFixed2 b)       { subv_Fixed(&a->x, b.x); subv_Fixed(&a->y, b.y); return *a; }
subiv_X2(iFixed2 * a,int b)103 iLocalDef iFixed2 subiv_X2  (iFixed2 *a, int b)                 { return subv_X2(a, initi1_X2(b)); }
subfv_X2(iFixed2 * a,float b)104 iLocalDef iFixed2 subfv_X2  (iFixed2 *a, float b)               { return subv_X2(a, initf1_X2(b)); }
mulv_X2(iFixed2 * a,const iFixed2 b)105 iLocalDef iFixed2 mulv_X2   (iFixed2 *a, const iFixed2 b)       { mulv_Fixed(&a->x, b.x); mulv_Fixed(&a->y, b.y); return *a; }
muliv_X2(iFixed2 * a,int b)106 iLocalDef iFixed2 muliv_X2  (iFixed2 *a, int b)                 { return mulv_X2(a, initi1_X2(b)); }
mulfv_X2(iFixed2 * a,float b)107 iLocalDef iFixed2 mulfv_X2  (iFixed2 *a, float b)               { return mulv_X2(a, initf1_X2(b)); }
divv_X2(iFixed2 * a,const iFixed2 b)108 iLocalDef iFixed2 divv_X2   (iFixed2 *a, const iFixed2 b)       { divv_Fixed(&a->x, b.x); divv_Fixed(&a->y, b.y); return *a; }
diviv_X2(iFixed2 * a,int b)109 iLocalDef iFixed2 diviv_X2  (iFixed2 *a, int b)                 { return divv_X2(a, initi1_X2(b)); }
divfv_X2(iFixed2 * a,float b)110 iLocalDef iFixed2 divfv_X2  (iFixed2 *a, float b)               { return divv_X2(a, initf1_X2(b)); }
111 
min_X2(const iFixed2 a,const iFixed2 b)112 iLocalDef iFixed2 min_X2    (const iFixed2 a, const iFixed2 b)  { return (iFixed2){ min_Fixed(a.x, b.x), min_Fixed(a.y, b.y) }; }
max_X2(const iFixed2 a,const iFixed2 b)113 iLocalDef iFixed2 max_X2    (const iFixed2 a, const iFixed2 b)  { return (iFixed2){ max_Fixed(a.x, b.x), max_Fixed(a.y, b.y) }; }
neg_X2(const iFixed2 a)114 iLocalDef iFixed2 neg_X2    (const iFixed2 a)                   { return (iFixed2){ neg_Fixed(a.x), neg_Fixed(a.y) }; }
abs_X2(const iFixed2 a)115 iLocalDef iFixed2 abs_X2    (const iFixed2 a)                   { return (iFixed2){ abs_Fixed(a.x), abs_Fixed(a.y) }; }
116 
isEqual_X2(const iFixed2 a,const iFixed2 b)117 iLocalDef iBool   isEqual_X2(const iFixed2 a, const iFixed2 b)  { return value_Fixed(a.x) == value_Fixed(b.x) && value_Fixed(a.y) == value_Fixed(b.y); }
118 
equal_X2(const iFixed2 a,const iFixed2 b)119 iLocalDef iBoolv equal_X2   (const iFixed2 a, const iFixed2 b) {
120     return init2_Boolv(value_Fixed(a.x) == value_Fixed(b.x), value_Fixed(a.y) == value_Fixed(b.y));
121 }
122 
notEqual_X2(const iFixed2 a,const iFixed2 b)123 iLocalDef iBoolv notEqual_X2(const iFixed2 a, const iFixed2 b) {
124     return init2_Boolv(value_Fixed(a.x) != value_Fixed(b.x), value_Fixed(a.y) != value_Fixed(b.y));
125 }
126 
greater_X2(const iFixed2 a,const iFixed2 b)127 iLocalDef iBoolv greater_X2 (const iFixed2 a, const iFixed2 b) {
128     return init2_Boolv(value_Fixed(a.x) > value_Fixed(b.x), value_Fixed(a.y) > value_Fixed(b.y));
129 }
130 
greaterEqual_X2(const iFixed2 a,const iFixed2 b)131 iLocalDef iBoolv greaterEqual_X2 (const iFixed2 a, const iFixed2 b) {
132     return init2_Boolv(value_Fixed(a.x) >= value_Fixed(b.x), value_Fixed(a.y) >= value_Fixed(b.y));
133 }
134 
less_X2(const iFixed2 a,const iFixed2 b)135 iLocalDef iBoolv less_X2 (const iFixed2 a, const iFixed2 b) {
136     return init2_Boolv(value_Fixed(a.x) < value_Fixed(b.x), value_Fixed(a.y) < value_Fixed(b.y));
137 }
138 
lessEqual_X2(const iFixed2 a,const iFixed2 b)139 iLocalDef iBoolv lessEqual_X2 (const iFixed2 a, const iFixed2 b) {
140     return init2_Boolv(value_Fixed(a.x) <= value_Fixed(b.x), value_Fixed(a.y) <= value_Fixed(b.y));
141 }
142 
clamp_X2(const iFixed2 t,const iFixed2 a,const iFixed2 b)143 iLocalDef iFixed2   clamp_X2        (const iFixed2 t, const iFixed2 a, const iFixed2 b) { return min_X2(max_X2(t, a), b); }
sum_X2(const iFixed2 a)144 iLocalDef iFixed    sum_X2          (const iFixed2 a) { return init_Fixed(value_Fixed(a.x) + value_Fixed(a.y)); }
dot_X2(const iFixed2 a,const iFixed2 b)145 iLocalDef iFixed    dot_X2          (const iFixed2 a, const iFixed2 b) { return sum_X2(mul_X2(a, b)); }
lengthSq_X2(const iFixed2 a)146 iLocalDef iFixed    lengthSq_X2     (const iFixed2 a) { return dot_X2(a, a); }
lengthf_X2(const iFixed2 a)147 iLocalDef float     lengthf_X2      (const iFixed2 a) { return sqrtf(f32_Fixed(lengthSq_X2(a))); }
length_X2(const iFixed2 a)148 iLocalDef iFixed    length_X2       (const iFixed2 a) { return initf_Fixed(lengthf_X2(a)); }
normalize_X2(const iFixed2 a)149 iLocalDef iFixed2   normalize_X2    (const iFixed2 a) { return div_X2(a, init1_X2(length_X2(a))); }
150 
sqrt_X2(const iFixed2 a)151 iLocalDef iFixed2 sqrt_X2(const iFixed2 a) {
152     return (iFixed2){ initf_Fixed(sqrtf(f32_Fixed(a.x))),
153                      initf_Fixed(sqrtf(f32_Fixed(a.y))) };
154 }
155 
mix_X2(const iFixed2 a,const iFixed2 b,const iFixed t)156 iLocalDef iFixed2 mix_X2(const iFixed2 a, const iFixed2 b, const iFixed t) {
157     return add_X2(a, mul_X2(sub_X2(b, a), init1_X2(t)));
158 }
159