void idle(void) { static int frames; static float time; float ifps; vec3 v; vec4 q0,q1,q2; matrix m; ifps = 1.0 / getfps(); if(!my_pause) angle += ifps * 360.0 / 4.0; v_set(sin(angle * DEG2RAD / 3),cos(angle * DEG2RAD / 7),2,light); v_set(0,0,1,v); q_set(v,psi,q0); v_set(0,1,0,v); q_set(v,phi,q1); q_multiply(q0,q1,q2); q_to_matrix(q2,m); v_set(dist,0,0,camera); v_transform(camera,m,camera); v_add(camera,mesh,camera); frames++; time += ifps; if(time > 1.0) { printf("%d frames %.2f fps\n",frames,(float)frames / time); frames = 0; time = 0; } }
// Swaps q[a] with q[b] void swap( vertex_t *v , uint16_t *q , uint16_t a , uint16_t b ) { uint16_t s = 0; s = q[a]; q_set(v, q, a, q[b]); q_set(v, q, b, s); }
/* * Check whether b is of the form a * X - a * Y * for a non-zero rational a and two products X and Y. * If so return X in *r1 and Y in *r2 */ bool arith_buffer_is_equality(arith_buffer_t *b, pprod_t **r1, pprod_t **r2) { mlist_t *p, *q; pprod_t *x, *y; rational_t a; bool is_eq; is_eq = false; if (b->nterms == 2) { p = b->list; q = p->next; x = p->prod; y = p->prod; if (x != empty_pp) { *r1 = x; *r2 = y; q_init(&a); q_set(&a, &p->coeff); q_add(&a, &q->coeff); is_eq = q_is_zero(&a); q_clear(&a); } } return is_eq; }
/* * Add a * r to b */ void arith_buffer_add_mono(arith_buffer_t *b, rational_t *a, pprod_t *r) { mlist_t *p, *aux; mlist_t **q; if (q_is_zero(a)) return; q = &b->list; p = *q; assert(p == b->list); while (pprod_precedes(p->prod, r)) { q = &p->next; p = *q; } // p points to a monomial with p->prod >= r, *q == p // q is &b->list if p is first in the list // q is &p0->next otherwise, where p0 = predecessor of p if (p->prod == r) { q_add(&p->coeff, a); } else { assert(pprod_precedes(r, p->prod)); aux = alloc_list_elem(b->store); aux->next = p; q_set(&aux->coeff, a); aux->prod = r; *q = aux; b->nterms ++; } }
/* * Get the constant term of p and copy it in c * - p must be normalized */ void monarray_constant(monomial_t *p, rational_t *c) { if (p->var == const_idx) { q_set(c, &p->coeff); } else { q_clear(c); } }
/* * Test 4: a is large, b is large */ static void test_big_big(void) { rational_t a, b, c; uint32_t i, j; q_init(&a); q_init(&b); q_init(&c); for (i=0; i<NBIGS; i++) { q_set_from_string(&b, large_divisor[i]); for (j=0; j<NBIGS; j++) { q_set_from_string(&a, large_signed[j]); q_set(&c, &a); q_integer_div(&a, &b); q_integer_rem(&c, &b); printf("div[%s, %s]: quotient = ", large_signed[j], large_divisor[i]); q_print(stdout, &a); printf(", remainder = "); q_print(stdout, &c); printf("\n"); } printf("\n"); } q_clear(&a); q_clear(&b); q_clear(&c); }
/* * Test 2: a is large, b is small */ static void test_big_small(void) { rational_t a, b, c; uint32_t i; int32_t y; q_init(&a); q_init(&b); q_init(&c); for (y=1; y<8; y++) { q_set32(&b, y); for (i=0; i<NBIGS; i++) { q_set_from_string(&a, large_signed[i]); q_set(&c, &a); q_integer_div(&a, &b); q_integer_rem(&c, &b); printf("div[%s, %"PRId32"]: quotient = ", large_signed[i], y); q_print(stdout, &a); printf(", remainder = "); q_print(stdout, &c); printf("\n"); } printf("\n"); } q_clear(&a); q_clear(&b); q_clear(&c); }
/* The q_space parameter must have enough storage capacity for 7 quaternion structures */ void mol_rotate(cVector *axis, cVector *origin, float phi, quaternion *q_space, cTetrahedron *target) { int i; quaternion *to_rotate, *q_target; cVector *ptr_axis; to_rotate = q_space++; q_target = q_space++; ptr_axis = (cVector *) malloc(sizeof(cVector)); for(i = 0; i < 5; i++) { v_set(ptr_axis, axis->x, axis->y, axis->z); q_set(q_target, 0, 0, 0, 0); to_rotate->s = 0; to_rotate->v.x = target->cAtoms[i].v.x; to_rotate->v.y = target->cAtoms[i].v.y; to_rotate->v.z = target->cAtoms[i].v.z; q_rotate(to_rotate, ptr_axis, origin, phi, q_space, q_target); target->cAtoms[i].v.x = q_target->v.x; target->cAtoms[i].v.y = q_target->v.y; target->cAtoms[i].v.z = q_target->v.z; } free(ptr_axis); }
/* * Copy the content of buffer b into f */ static void set_normal_form(normal_form_t *f, poly_buffer_t *b) { monomial_t *mono; uint32_t i, n; n = poly_buffer_nterms(b); mono = poly_buffer_mono(b); assert(n <= f->size); for (i=0; i<n; i++) { f->mono[i].var = mono[i].var; q_set(&f->mono[i].coeff, &mono[i].coeff); } f->mono[i].var = max_idx; // end marker f->nterms = n; f->hash = hash_monarray(f->mono, n); }
/* * Add poly to buffer b */ void arith_buffer_add_monarray(arith_buffer_t *b, monomial_t *poly, pprod_t **pp) { mlist_t *p, *aux; mlist_t **q; pprod_t *r1; assert(good_pprod_array(poly, pp)); q = &b->list; p = *q; while (poly->var < max_idx) { // poly points to a pair (coeff, x_i) // r1 = power product for x_i r1 = *pp; while (pprod_precedes(p->prod, r1)) { q = &p->next; p = *q; } // p points to monomial whose prod is >= r1 in the deg-lex order // q is either &b->list or &p0->next where p0 is the predecessor // of p in the list if (p->prod == r1) { q_add(&p->coeff, &poly->coeff); q = &p->next; p = *q; } else { assert(pprod_precedes(r1, p->prod)); aux = alloc_list_elem(b->store); aux->next = p; q_set(&aux->coeff, &poly->coeff); aux->prod = r1; *q = aux; q = &aux->next; b->nterms ++; } // move to the next monomial of poly poly ++; pp ++; } }
/* * Copy p into q: * - p must be terminated by the end marked * - q must be large enough to store the result (including end marker) */ uint32_t copy_monarray(monomial_t *p, monomial_t *p1) { uint32_t n; int32_t v; v = p1->var; n = 0; while (v != max_idx) { p->var = v; q_set(&p->coeff, &p1->coeff); n ++; p ++; p1 ++; v = p1->var; } p->var = max_idx; return n; }
/* * Allocate a polynomial_t object and copy a into it. * - a must be normalized. * - no side effect. */ polynomial_t *monarray_copy_to_poly(monomial_t *a, uint32_t n) { polynomial_t *p; uint32_t i; if (n >= MAX_POLY_SIZE) { out_of_memory(); } p = (polynomial_t *) safe_malloc(sizeof(polynomial_t) + (n + 1) * sizeof(monomial_t)); p->nterms = n; for (i=0; i<n; i++) { p->mono[i].var = a[i].var; q_init(&p->mono[i].coeff); q_set(&p->mono[i].coeff, &a[i].coeff); } // end-marker p->mono[i].var = max_idx; q_init(&p->mono[i].coeff); return p; }
/* * Add r * b1 to b */ void arith_buffer_add_pp_times_buffer(arith_buffer_t *b, arith_buffer_t *b1, pprod_t *r) { mlist_t *p, *aux, *p1; mlist_t **q; pprod_t *r1; q = &b->list; p = *q; p1 = b1->list; while (p1->next != NULL) { r1 = pprod_mul(b->ptbl, p1->prod, r); while (pprod_precedes(p->prod, r1)) { q = &p->next; p = *q; } if (p->prod == r1) { q_add(&p->coeff, &p1->coeff); // q = p; // p = p->next; q = &p->next; p = *q; } else { assert(pprod_precedes(r1, p->prod)); aux = alloc_list_elem(b->store); aux->next = p; q_set(&aux->coeff, &p1->coeff); aux->prod = r1; // q->next = aux; // q = aux; *q = aux; q = &aux->next; b->nterms ++; } p1 = p1->next; } }
/* * Phase and period of p * - p is c + (a_1/b_1) x_1 + ... + (a_n/b_n) x_n where * a_i/b_i is an irreducible fraction * - let D = gcd(a_1,..., a_n) and L = lcm(b_1,...,b_n) * then period = D/L and phase = c - floor(c/period) * period */ void monarray_period_and_phase(monomial_t *p, rational_t *period, rational_t *phase) { rational_t aux; monomial_t *c; int32_t v; /* * c := the constant monomial of p or NULL if p's constant is zero */ c = NULL; v = p->var; if (v == const_idx) { c = p; p ++; v = p->var; } if (v < max_idx) { /* * p is not a constant: compute D and L * we use period for D and phase for L */ q_get_num(period, &p->coeff); // D := |a_1| if (q_is_neg(period)) { q_neg(period); } q_get_den(phase, &p->coeff); // L := b_1 q_init(&aux); for (;;) { p ++; v = p->var; if (v >= max_idx) break; q_get_num(&aux, &p->coeff); q_gcd(period, &aux); // D := gcd(D, a_i) q_get_den(&aux, &p->coeff); q_lcm(phase, &aux); // L := lcm(L, b_i) } assert(q_is_pos(period) && q_is_pos(phase)); q_div(period, phase); // period := D/L /* * Phase: constant modulo D/L */ if (c == NULL) { q_clear(phase); // no constant: phase = 0 } else { q_set(&aux, &c->coeff); q_div(&aux, period); q_floor(&aux); // aux = floor(c/period) q_set(phase, &c->coeff); q_submul(phase, &aux, period); // phase = c - aux * period assert(q_is_nonneg(phase) && q_lt(phase, period)); } q_clear(&aux); } else { /* * p is constant: period := 0, phase = constant coeff */ q_clear(period); if (c == NULL) { q_clear(phase); } else { q_set(phase, &c->coeff); } } }