diff -urN rt_v20/Makefile rt_v21/Makefile --- rt_v20/Makefile 1970-01-01 09:00:00.000000000 +0900 +++ rt_v21/Makefile 2018-04-13 22:02:41.000000000 +0900 @@ -0,0 +1,11 @@ +CC = gcc +CFLAGS += -Wall +OBJS = sock.o cross.o ax.o vecs.o line.o v.o mt.o + +all: sock + +sock: $(OBJS) + gcc -o $@ $(OBJS) +clean: + rm -f *.o *~ +# EOF diff -urN rt_v20/ax.c rt_v21/ax.c --- rt_v20/ax.c 1970-01-01 09:00:00.000000000 +0900 +++ rt_v21/ax.c 2018-04-13 20:24:38.000000000 +0900 @@ -0,0 +1,205 @@ +#include "ax.h" + +void +ax_new(struct ax *ax, double *p, struct vecs *vs) +{ + v_set(ax->p, p); + ax->vs = *vs; +} + +void +ax_l2g(struct ax *ax, double *p, double *rp) +{ + double tmp[3]; + vecs_l2g(&ax->vs, p, tmp); + v_add(tmp, ax->p, rp); +} + +void +ax_g2l(struct ax *ax, double *p, double *rp) +{ + double tmp[3]; + v_sub(p, ax->p, tmp); + vecs_g2l(&ax->vs, tmp, rp); +} + +void +ax_tr_p(struct ax *ax, int d, double *p, double *rp) +{ + if(d == L2G){ + ax_l2g(ax, p, rp); + }else{ + ax_g2l(ax, p, rp); + } +} + +void +ax_tr_v(struct ax *ax, int d, double *v, double *rv) +{ + vecs_tr( &ax->vs, d, v, rv ); +} + +void +ax_tr_line(struct ax *ax, int d, struct line *l, struct line *rl) +{ + double p[3], v[3]; + + ax_tr_p(ax, d, l->p, p); + ax_tr_v(ax, d, l->v, v); + line_new(rl, p, v); +} + +void +ax_compo(struct ax *ax, struct ax *ax_outside, struct ax *rax) +{ + double p_[3]; + struct vecs tmp, vs_; + int i; + + for(i=0; i<3; i++){ + vecs_l2g( &ax_outside->vs, &VECS_ACC( &ax->vs, i, 0 ), &VECS_ACC( &tmp, i, 0 ) ); + } + vecs_new(&vs_, tmp.v3); + + ax_l2g( ax_outside, ax->p, p_ ); + ax_new(rax, p_, &vs_); +} + +int +ax_rev(struct ax *ax, struct ax *rax) +{ + struct vecs *vs_; + double np[3], p_[3]; + + vecs_mk_rev(&ax->vs); + vs_ = ax->vs.rev; + if(vs_ == NULL){ + return 0; + } + v_neg(ax->p, np); + vecs_l2g( vs_, np, p_ ); + ax_new(rax, p_, vs_); + return 1; +} + +struct ax ax_one = { {0,0,0}, { {1,0,0, 0,1,0, 0,0,1}, {1,0,0, 0,1,0, 0,0,1}, NULL } }; + +void +ax_slide(struct ax *ax, double *sld) +{ + ax_new( ax, sld, &vecs_one ); +} + +void +ax_slide_x(struct ax *ax, double x) +{ + double sld[3] = {x, 0, 0}; + ax_slide(ax, sld); +} + +void +ax_slide_y(struct ax *ax, double y) +{ + double sld[3] = {0, y, 0}; + ax_slide(ax, sld); +} + +void +ax_slide_z(struct ax *ax, double z) +{ + double sld[3] = {0, 0, z}; + ax_slide(ax, sld); +} + +void +ax_zoom(struct ax *ax, double *zm3) +{ + double zero[3] = {0,0,0}; + struct vecs vs; + vecs_zoom(&vs, zm3); + ax_new(ax, zero, &vs); +} + +void +ax_zoom_all(struct ax *ax, double zm) +{ + double zm3[3] = {zm, zm, zm}; + ax_zoom(ax, zm3); +} + +void +ax_zoom_x(struct ax *ax, double zm) +{ + double zm3[3] = {zm, 1, 1}; + ax_zoom(ax, zm3); +} + +void +ax_zoom_y(struct ax *ax, double zm) +{ + double zm3[3] = {1, zm, 1}; + ax_zoom(ax, zm3); +} + +void +ax_zoom_z(struct ax *ax, double zm) +{ + double zm3[3] = {1, 1, zm}; + ax_zoom(ax, zm3); +} + +void +ax_rot_y(struct ax *ax, double deg) +{ + double zero[3] = {0,0,0}; + struct vecs vs; + vecs_rot_y(&vs, deg); + ax_new(ax, zero, &vs); +} + +void +ax_rot(struct ax *ax, struct line *l, double deg) +{ + struct ax a, r, a_r_y, tmp; + + ax_new_line(&a, l); + ax_rev(&a, &r); + ax_rot_y(&a_r_y, deg); + ax_compo(&r, &a_r_y, &tmp); + ax_compo(&tmp, &a, ax); +} + +void +ax_rot_x(struct ax *ax, double deg) +{ + ax_rot(ax, &line_x1, deg); +} + +void +ax_rot_z(struct ax *ax, double deg) +{ + ax_rot(ax, &line_z1, deg); +} + +void +ax_wh_map(struct ax *ax, int w, int h) +{ + double sld[3] = { -w*0.5, -h*0.5, 0 }; + struct ax t1, t2, t3, t4; + + ax_slide(&t1, sld); + ax_zoom_all(&t2, 1.0/w); + ax_rot_x(&t3, 180); + ax_compo(&t1, &t2, &t4); + ax_compo(&t4, &t3, ax); +} + +void +ax_new_line(struct ax *ax, struct line *l) +{ + struct vecs vs; + vecs_by_fix_ref(&vs, 'y', l->v, 'z', v_z1); + ax_new(ax, l->p, &vs); +} + +/* EOF */ diff -urN rt_v20/ax.h rt_v21/ax.h --- rt_v20/ax.h 1970-01-01 09:00:00.000000000 +0900 +++ rt_v21/ax.h 2018-04-13 20:24:38.000000000 +0900 @@ -0,0 +1,41 @@ +#ifndef __AX_H__ +#define __AX_H__ 1 + +#include "vecs.h" +#include "line.h" + +struct ax{ + double p[3]; + struct vecs vs; +}; + +void ax_new(struct ax *ax, double *p, struct vecs *vs); +void ax_l2g(struct ax *ax, double *p, double *rp); +void ax_g2l(struct ax *ax, double *p, double *rp); +void ax_tr_p(struct ax *ax, int d, double *p, double *rp); +void ax_tr_v(struct ax *ax, int d, double *v, double *rv); +void ax_tr_line(struct ax *ax, int d, struct line *l, struct line *rl); +void ax_compo(struct ax *ax, struct ax *ax_outside, struct ax *rax); +int ax_rev(struct ax *ax, struct ax *rax); + +extern struct ax ax_one; + +void ax_slide(struct ax *ax, double *sld); +void ax_slide_x(struct ax *ax, double x); +void ax_slide_y(struct ax *ax, double y); +void ax_slide_z(struct ax *ax, double z); +void ax_zoom(struct ax *ax, double *zm3); +void ax_zoom_all(struct ax *ax, double zm); +void ax_zoom_x(struct ax *ax, double zm); +void ax_zoom_y(struct ax *ax, double zm); +void ax_zoom_z(struct ax *ax, double zm); +void ax_rot_y(struct ax *ax, double deg); +void ax_rot(struct ax *ax, struct line *l, double deg); +void ax_rot_x(struct ax *ax, double deg); +void ax_rot_z(struct ax *ax, double deg); + +void ax_wh_map(struct ax *ax, int w, int h); + +void ax_new_line(struct ax *ax, struct line *l); + +#endif diff -urN rt_v20/cross.c rt_v21/cross.c --- rt_v20/cross.c 1970-01-01 09:00:00.000000000 +0900 +++ rt_v21/cross.c 2018-04-14 09:02:21.000000000 +0900 @@ -0,0 +1,260 @@ +#include "cross.h" + +int +plane_z0(struct line *l, double *rt) +{ + double vz, pz, t; + + vz = l->v[2]; + if(vz == 0){ + return 0; + } + pz = l->p[2]; + t = -pz / vz; + if(t <= 0){ + return 0; + } + *rt = t; + return 1; +} + +int +plane_z0_xy_cond(struct line *l, + int (*xy_cond_f)(double x, double y), + double *rt) +{ + double t, p[3]; + + if( !plane_z0(l, rt) ){ + return 0; + } + t = *rt; + line_on_line_p(l, t, p); + return xy_cond_f( p[0], p[1] ); +} + +int +square_xy(double x, double y) +{ + return fabs(x) <= 1 && fabs(y) <= 1; +} + +int +square(struct line *l, double *rt) +{ + return plane_z0_xy_cond(l, square_xy, rt); +} + +int +circle_xy(double x, double y) +{ + return x*x + y*y <= 1; +} + +int +circle(struct line *l, double *rt) +{ + return plane_z0_xy_cond(l, circle_xy, rt); +} + +int +triangle_xy(double x, double y) +{ + return x+y<=1 && -x+y<=1 && y>=0; +} + +int +triangle(struct line *l, double *rt) +{ + return plane_z0_xy_cond(l, triangle_xy, rt); +} + +int +ball(struct line *l, double *rt, int eq_d) +{ + double a, b, c, ts[2], tmp[2]; + int n, i, tmp_n; + + a = dot( l->v, l->v ); + b = 2 * dot( l->v, l->p ); + c = dot( l->p, l->p ) - 1; + + n = quadratic_formula(a, b, c, ts); + if(n == 0){ + return 0; + } + if(n > 1 && eq_d){ + if( fabs(ts[0]) < fabs(ts[1]) ){ + ts[0] = ts[1]; + } + n = 1; + } + for(i=0; i 0){ + ts[n++] = tmp[i]; + } + } + if(n == 0){ + return 0; + } + *rt = (n == 2 && ts[0] > ts[1]) ? ts[1] : ts[0]; + return 1; +} + +int +pipe_side(struct line *l, double *rt, int eq_d) +{ + double px, py, vx, vy; + double a, b, c, ts[2], tmp[2]; + int n, i, tmp_n; + double p[3]; + + px = l->p[0]; + py = l->p[1]; + vx = l->v[0]; + vy = l->v[1]; + + a = vx*vx + vy*vy; + b = 2 * (px*vx + py*vy); + c = px*px + py*py - 1; + + n = quadratic_formula(a, b, c, ts); + if(n == 0){ + return 0; + } + if(n > 1 && eq_d){ + if( fabs(ts[0]) < fabs(ts[1]) ){ + ts[0] = ts[1]; + } + n = 1; + } + for(i=0; i 0){ + ts[n++] = tmp[i]; + } + } + if(n == 0){ + return 0; + } + if(n==2 && ts[0] > ts[1]){ + double tt = ts[0]; + ts[0] = ts[1]; + ts[1] = tt; + } + + for(i=0; ip[0]; + py = l->p[1]; + pz = l->p[2]; + vx = l->v[0]; + vy = l->v[1]; + vz = l->v[2]; + + a = vx*vx + vy*vy - vz*vz; + b = 2 * (px*vx + py*vy + (1 - pz)*vz); + c = px*px + py*py - pz*pz + 2*pz - 1; + + n = quadratic_formula(a, b, c, ts); + if(n == 0){ + return 0; + } + if(n > 1 && eq_d){ + if( fabs(ts[0]) < fabs(ts[1]) ){ + ts[0] = ts[1]; + } + n = 1; + } + for(i=0; i 0){ + ts[n++] = tmp[i]; + } + } + if(n == 0){ + return 0; + } + if(n==2 && ts[0] > ts[1]){ + double tt = ts[0]; + ts[0] = ts[1]; + ts[1] = tt; + } + + for(i=0; ip, p); + v_set(l->v, v); +} + +void +line_on_line_p(struct line *l, double t, double *rp) +{ + on_line_p(l->p, l->v, t, rp); +} + +void +line_tr_by_func(struct line *l, void (*f)(double *s, double *d), struct line *rl) +{ + double p[3], tmp[3], tmp2[3], v[3]; + + f(l->p, p); + v_add(l->p, l->v, tmp); + f(tmp, tmp2); + v_sub(tmp2, l->p, v); + line_new(rl, p, v); +} + +int +is_plane_side(struct line *plane, double *p) +{ + double tmp[3]; + + v_sub(p, plane->p, tmp); + return dot(plane->v, tmp) >= 0; +} + +int +cross_plane_line(struct line *plane, struct line *other_line, double *rp) +{ + struct line *l = other_line; + double base = dot( l->v, plane->v ); + double tmp[3], t; + + if(base == 0){ + return 0; + } + v_sub( plane->p, l->p, tmp ); + t = dot( tmp, plane->v ) / base; + line_on_line_p(l, t, rp); + return 1; +} + +void +line_new_p2(struct line *l, double *p, double *t) +{ + double v[3]; + + v_sub(t, p, v); + unit(v, v); + line_new(l, p, v); +} + +struct line line_x1 = { {0,0,0}, {1,0,0} }; +struct line line_y1 = { {0,0,0}, {0,1,0} }; +struct line line_z1 = { {0,0,0}, {0,0,1} }; + +/* EOF */ diff -urN rt_v20/line.h rt_v21/line.h --- rt_v20/line.h 1970-01-01 09:00:00.000000000 +0900 +++ rt_v21/line.h 2018-04-13 20:24:38.000000000 +0900 @@ -0,0 +1,24 @@ +#ifndef __LINE_H__ +#define __LINE_H__ 1 + +#include "v.h" + +struct line{ + double p[3], v[3]; +}; + +void on_line_p(double *p, double *v, double t, double *rp); + +void line_new(struct line *l, double *p, double *v); +void line_on_line_p(struct line *l, double t, double *rp); + +int is_plane_side(struct line *l, double *p); +int cross_plane_line(struct line *plane, struct line *other_line, double *rp); + +void line_new_p2(struct line *l, double *p, double *t); + +extern struct line line_x1; +extern struct line line_y1; +extern struct line line_z1; + +#endif diff -urN rt_v20/mt.c rt_v21/mt.c --- rt_v20/mt.c 1970-01-01 09:00:00.000000000 +0900 +++ rt_v21/mt.c 2018-04-13 20:24:38.000000000 +0900 @@ -0,0 +1,42 @@ +#include "mt.h" + +double +deg_to_rad(double deg) +{ + return deg * M_PI / 180; +} + +double +rad_to_deg(double rad) +{ + return rad * 180 / M_PI; +} + +int +quadratic_formula(double a, double b, double c, double *ts) +{ + double d, a2, d_; + + if(a == 0){ + if(b != 0){ + *ts = -c / b; + return 1; + } + return 0; + } + d = b * b - 4 * a * c; + if(d < 0){ + return 0; + } + a2 = 2.0 * a; + if(d == 0){ + *ts = -b / a2; + return 1; + } + d_ = sqrt(d); + ts[0] = (-b + d_) / a2; + ts[1] = (-b - d_) / a2; + return 2; +} + +/* EOF */ diff -urN rt_v20/mt.h rt_v21/mt.h --- rt_v20/mt.h 1970-01-01 09:00:00.000000000 +0900 +++ rt_v21/mt.h 2018-04-13 20:24:38.000000000 +0900 @@ -0,0 +1,11 @@ +#ifndef __MT_H__ +#define __MT_H__ 1 + +#include + +double deg_to_rad(double deg); +double rad_to_deg(double rad); + +int quadratic_formula(double a, double b, double c, double *ts); + +#endif Binary files rt_v20/sock and rt_v21/sock differ diff -urN rt_v20/sock.c rt_v21/sock.c --- rt_v20/sock.c 1970-01-01 09:00:00.000000000 +0900 +++ rt_v21/sock.c 2018-04-14 09:03:29.000000000 +0900 @@ -0,0 +1,158 @@ +#include +#include +#include +#include "cross.h" + +/* FILE *dbg; */ + +struct data{ + int ki; + struct ax l2g; +}; + +struct data *data = NULL; +int data_n = 0; + +void +alloc(int n) +{ + int sz = sizeof(*data) * n; + + if(data){ + free(data); + data = NULL; + } + data = malloc(sz); + data_n = n; +} + +void +clear(void) +{ + int i; + + for(i=0; i + +extern double v_x1[3]; +extern double v_y1[3]; +extern double v_z1[3]; + +double dot(double *a, double *b); +void v_set(double *d, double *s); +int v_eq(double *a, double *b); +void v_add(double *a, double *b, double *r); +void v_sub(double *a, double *b, double *r); +void v_neg(double *a, double *r); +double len1(double *v); +void unit(double *s, double *d); +void cross_product(double *a, double *b, double *r); +void cross_product_unit(double *a, double *b, double *r); + +#endif diff -urN rt_v20/vecs.c rt_v21/vecs.c --- rt_v20/vecs.c 1970-01-01 09:00:00.000000000 +0900 +++ rt_v21/vecs.c 2018-04-13 20:24:38.000000000 +0900 @@ -0,0 +1,238 @@ +#include "vecs.h" + +void +vecs_init(struct vecs *vs) +{ + vs->rev = NULL; +} + +void +vecs_new(struct vecs *vs, double *v3) +{ + memcpy(vs->v3, v3, sizeof(vs->v3)); + vecs_init(vs); +} + +void +vecs_new_3(struct vecs *vs, double *v0, double *v1, double *v2) +{ + double *v3 = vs->v3; + + *v3++ = *v0++; + *v3++ = *v0++; + *v3++ = *v0++; + *v3++ = *v1++; + *v3++ = *v1++; + *v3++ = *v1++; + *v3++ = *v2++; + *v3++ = *v2++; + *v3++ = *v2++; + vecs_init(vs); +} + +void +vecs_T(struct vecs *s, struct vecs *d) +{ + int i, j; + + for(i=0; i<3; i++){ + for(j=0; j<3; j++){ + VECS_ACC(d, i, j) = VECS_ACC(s, j, i); + } + } + vecs_init(d); +} + +void +vecs_dot(struct vecs *vs, double *p, double *rp) +{ + *rp++ = dot( &VECS_ACC(vs, 0, 0), p ); + *rp++ = dot( &VECS_ACC(vs, 1, 0), p ); + *rp++ = dot( &VECS_ACC(vs, 2, 0), p ); +} + +void +vecs_l2g(struct vecs *vs, double *p, double *rp) +{ + struct vecs t; + + vecs_T(vs, &t); + vecs_dot(&t, p, rp); +} + +void +vecs_g2l(struct vecs *vs, double *p, double *rp) +{ + vecs_mk_rev(vs); + vecs_l2g(vs->rev, p, rp); +} + +double +vecs_det(struct vecs *vs) +{ + double *v3 = vs->v3; + double xx = *v3++; + double xy = *v3++; + double xz = *v3++; + double yx = *v3++; + double yy = *v3++; + double yz = *v3++; + double zx = *v3++; + double zy = *v3++; + double zz = *v3++; + return xx*yy*zz + xy*yz*zx + xz*yx*zy - xx*yz*zy - xz*yy*zx - xy*yx*zz; +} + +void +vecs_mk_rev(struct vecs *vs) +{ + double d, d_, *v3, xx, xy, xz, yx, yy, yz, zx, zy, zz; + + if(vs->rev) + return; + + d = vecs_det(vs); + if(d == 0) + return; + d_ = 1.0 / d; + + v3 = vs->v3; + xx = *v3++; + xy = *v3++; + xz = *v3++; + yx = *v3++; + yy = *v3++; + yz = *v3++; + zx = *v3++; + zy = *v3++; + zz = *v3++; + + v3 = vs->rev_v3; + *v3++ = (yy*zz - zy*yz) * d_; + *v3++ = (zy*xz - xy*zz) * d_; + *v3++ = (xy*yz - yy*xz) * d_; + *v3++ = (zx*yz - yx*zz) * d_; + *v3++ = (xx*zz - zx*xz) * d_; + *v3++ = (yx*xz - xx*yz) * d_; + *v3++ = (yx*zy - zx*yy) * d_; + *v3++ = (zx*xy - xx*zy) * d_; + *v3++ = (xx*yy - yx*xy) * d_; + + vs->rev = (struct vecs *)vs->rev_v3; /* ! */ +} + +void +vecs_tr(struct vecs *vs, int d, double *p, double *rp) +{ + if(d == L2G){ + vecs_l2g(vs, p, rp); + }else{ + vecs_g2l(vs, p, rp); + } +} + +void +vecs_zoom(struct vecs *vs, double *zm3) +{ + int i, j; + + for(i=0; i<3; i++){ + for(j=0; j<3; j++){ + VECS_ACC(vs, i, j) *= zm3[i]; + } + } + vecs_init(vs); +} + +void +vecs_zoom_all(struct vecs *vs, double zm) +{ + double zm3[3] = { zm, zm, zm }; + vecs_zoom(vs, zm3); +} + +void +vecs_zoom_x(struct vecs *vs, double zm) +{ + double zm3[3] = { zm, 1, 1 }; + vecs_zoom(vs, zm3); +} + +void +vecs_zoom_y(struct vecs *vs, double zm) +{ + double zm3[3] = { 1, zm, 1 }; + vecs_zoom(vs, zm3); +} + +void +vecs_zoom_z(struct vecs *vs, double zm) +{ + double zm3[3] = { 1, 1, zm }; + vecs_zoom(vs, zm3); +} + +struct vecs vecs_one = { {1,0,0, 0,1,0, 0,0,1}, {1,0,0, 0,1,0, 0,0,1}, NULL }; + +void +vecs_by_fix_ref(struct vecs *vs, char fix_nm, double *fix, char ref_nm, double *ref) +{ + int fix_i = fix_nm - 'x'; + int ref_i = ref_nm - 'x'; + int i = 3 - fix_i - ref_i; + double *v3[3], *a, *b, *c; + double tmp[3], tmp2[3], tmp3[3]; + + v3[fix_i] = fix; + + if( v_eq(fix, ref) ){ + if( !v_eq(ref, v_z1) ){ + tmp[0] = -ref[1]; + tmp[1] = ref[0]; + tmp[2] = ref[2]; + ref = tmp; + }else{ + ref = v_x1; + } + } + + if( (fix_i + 1) % 3 == ref_i ){ + a = fix; + b = ref; + }else{ + a = ref; + b = fix; + } + + cross_product_unit(a, b, tmp2); + v3[i] = c = tmp2; + + if( (fix_i + 1) % 3 == i ){ + a = fix; + b = c; + }else{ + a = c; + b = fix; + } + cross_product_unit(a, b, tmp3); + v3[ref_i] = tmp3; + + vecs_new_3( vs, v3[0], v3[1], v3[2] ); +} + +void +vecs_rot_y(struct vecs *vs, double deg) +{ + double rad = deg_to_rad(deg); + double s = sin(rad); + double c = cos(rad); + + *vs = vecs_one; + VECS_ACC(vs, 2, 2) = VECS_ACC(vs, 0, 0) = c; + VECS_ACC(vs, 0, 2) = -s; + VECS_ACC(vs, 2, 0) = s; + + vecs_init(vs); +} + +/* EOF */ diff -urN rt_v20/vecs.h rt_v21/vecs.h --- rt_v20/vecs.h 1970-01-01 09:00:00.000000000 +0900 +++ rt_v21/vecs.h 2018-04-13 20:24:38.000000000 +0900 @@ -0,0 +1,44 @@ +#ifndef __VECS_H__ +#define __VECS_H__ + +#include +#include +#include "mt.h" +#include "v.h" + +struct vecs{ + double v3[3*3]; + double rev_v3[3*3]; + struct vecs *rev; +}; + +#define VECS_IDX(i, j) ( (i)*3+(j) ) +#define VECS_ACC(p, i, j) (p)->v3[ VECS_IDX(i, j) ] + +void vecs_init(struct vecs *vs); +void vecs_new(struct vecs *vs, double *v3); +void vecs_new_3(struct vecs *vs, double *v0, double *v1, double *v2); +void vecs_T(struct vecs *s, struct vecs *d); +void vecs_dot(struct vecs *vs, double *p, double *rp); +void vecs_l2g(struct vecs *vs, double *p, double *rp); +void vecs_g2l(struct vecs *vs, double *p, double *rp); +double vecs_det(struct vecs *vs); +void vecs_mk_rev(struct vecs *vs); + +#define L2G 0 +#define G2L 1 + +void vecs_tr(struct vecs *vs, int d, double *p, double *rp); + +void vecs_zoom(struct vecs *vs, double *zm3); +void vecs_zoom_all(struct vecs *vs, double zm); +void vecs_zoom_x(struct vecs *vs, double zm); +void vecs_zoom_y(struct vecs *vs, double zm); +void vecs_zoom_z(struct vecs *vs, double zm); + +extern struct vecs vecs_one; + +void vecs_by_fix_ref(struct vecs *vs, char fix_nm, double *fix, char ref_nm, double *ref); +void vecs_rot_y(struct vecs *vs, double deg); + +#endif