ass_transform/cimpl/unstable.c
2022-04-24 03:09:27 +02:00

126 lines
2.8 KiB
C

#include "common.h"
inline bool zero(double d)
{
return fabs(d) < 700 * DBL_EPSILON;
// For reference musl (64bit double) uses:
// DBL_EPSILON 2.22044604925031308085e-16
}
/*
* a == 0 \implies b == 0
* and
* d == 0 \implies c == 0
*/
void case_trivial(const double* m, Tags* t)
{
t->scale_x = m[0];
t->scale_y = m[3];
t->fax = zero(m[0]) ? 0 : (m[1] / m[0]); // case condition
t->fay = zero(m[3]) ? 0 : (m[2] / m[3]); // case condition
if(t->scale_x < 0) {
t->rot_y = true;
t->scale_x = fabs(t->scale_x);
}
if(t->scale_y < 0) {
t->rot_x = true;
t->scale_y = fabs(t->scale_y);
}
}
/**
* |0 b| |0 0| |0 b| |0 b| |a b|
* |0 0|, |c 0|, |c 0|, |c d| or |c 0| with letters non-zero
* (i.e. c==0 \implies d==0 and a==0 \implies d==0)
*
* apply rot_z of 90° to get
* |a b| |-scale_y*fay -scale_y |
* |c d| = | scale_x scale_x*fax|
*/
void case_rowswap(const double* m, Tags* t)
{
t->rot_z = 90;
t->scale_x = m[2];
t->scale_y = -m[1];
t->fax = zero(m[2]) ? 0 : (m[3] / m[2]); // case condition
t->fay = zero(m[1]) ? 0 : (m[0] / m[1]); // case condition
if(t->scale_x < 0) {
t->rot_x = true;
t->scale_x = fabs(t->scale_x);
}
if(t->scale_y < 0) {
t->rot_y = true;
t->scale_y = fabs(t->scale_y);
}
}
/**
* |a 0|
* |c 0| with letters non-zero
*/
void case_zerocol_r(const double* m, Tags* t)
{
t->scale_y = 0;
t->fax = 0;
t->fay = 0; // Arbitrary
t->scale_x = sqrt(m[0] * m[0] + m[2] * m[2]);
t->rot_z = atan(m[2] / m[0]) * 180 / C_PI;
if (m[0] < 0) // atan always yields positive cos
t->rot_z += 180;
}
/**
* |0 b|
* |0 d| with letters non-zero
*/
void case_zerocol_l(const double* m, Tags* t)
{
t->scale_x = 0;
t->fay = 0;
t->fax = 0; // Arbitrary
t->scale_y = sqrt(m[1] * m[1] + m[3] * m[3]);
t->rot_z = atan(-m[1] / m[3]) * 180 / C_PI;
if (m[3] < 0) // atan always yields positive cos
t->rot_z += 180;
}
int main(int argc, char** argv)
{
double tar[4] = {0};
if(!parse_args(argc, argv, tar))
exit(5);
print_matrix("target", tar);
Tags tags = {0};
if(
!( (zero(tar[0]) && !zero(tar[1]))
|| (zero(tar[3]) && !zero(tar[2])) )
) {
printf(" --trivial\n");
case_trivial(tar, &tags);
} else if(
!( (zero(tar[1]) && !zero(tar[0]))
|| (zero(tar[2]) && !zero(tar[3])) )
) {
printf(" --rowswap\n");
case_rowswap(tar, &tags);
} else if(
zero(tar[0]) && zero(tar[2]) && !zero(tar[1]) && !zero(tar[3])
) {
printf(" --zerocol_l\n");
case_zerocol_l(tar, &tags);
} else if(
!zero(tar[0]) && !zero(tar[2]) && zero(tar[1]) && zero(tar[3])
) {
printf(" --zerocol_r\n");
case_zerocol_r(tar, &tags);
} else {
fprintf(stderr, "Oupsie, unknown matrix-case encountered. This shouldn't happen :P\n");
exit(6);
}
return evaluate_result(tar, &tags);
}