#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); }