/* * Test 3: inverses of powers of two */ static void test3(void) { rational_t r, aux; uint32_t i; printf("\nTest 3\n\n"); q_init(&r); q_init(&aux); q_set_int32(&aux, 1, 2); // 1/2 q_set_one(&r); for (i=0; i<68; i++) { test_conversions(&r); q_mul(&r, &aux); } q_set_minus_one(&r); for (i=0; i<68; i++) { test_conversions(&r); q_mul(&r, &aux); } q_clear(&aux); q_clear(&r); }
/* * Test 4: construct 1/(2^n-1) */ static void test4(void) { rational_t r, aux, aux2; uint32_t i; printf("\nTest 4\n\n"); q_init(&r); q_init(&aux); q_init(&aux2); q_set32(&aux, 2); q_set_one(&aux2); q_set_one(&r); for (i=0; i<68; i++) { q_inv(&r); test_conversions(&r); q_inv(&r); q_mul(&r, &aux); q_add(&r, &aux2); } q_set_minus_one(&r); for (i=0; i<68; i++) { q_inv(&r); test_conversions(&r); q_inv(&r); q_mul(&r, &aux); q_sub(&r, &aux2); } q_clear(&aux); q_clear(&aux2); q_clear(&r); }
/* * Test1: construct powers of two */ static void test1(void) { rational_t r, aux; uint32_t i; printf("\nTest 1\n\n"); q_init(&r); q_init(&aux); q_set32(&aux, 2); q_set_one(&r); for (i=0; i<68; i++) { test_conversions(&r); q_mul(&r, &aux); } // negative powers q_set_minus_one(&r); for (i=0; i<68; i++) { test_conversions(&r); q_mul(&r, &aux); } q_clear(&aux); q_clear(&r); }
quaternion_t plSideralRotationAtTime(pl_astrobody_t *ab, double t) { quaternion_t q = ab->kepler->qOrbit; q = q_mul(q, q_rot(1.0, 0.0, 0.0, ab->obliquity)); double rotations = t/ab->siderealPeriod; double rotFrac = fmod(rotations, 1.0); quaternion_t z_rot = q_rot(0.0f, 0.0f, 1.0f, rotFrac * 2.0 * M_PI); return q_mul(q, z_rot); }
quaternion_t pl_orbital_quaternion(pl_keplerelems_t *kepler) { quaternion_t qasc = q_rot(0.0, 0.0, 1.0, kepler->longAsc); quaternion_t qinc = q_rot(1.0, 0.0, 0.0, kepler->inc); quaternion_t qaps = q_rot(0.0, 0.0, 1.0, kepler->argPeri); quaternion_t q = q_mul(qasc, qinc); q = q_mul(q, qaps); return q; }
pl_system_t* pl_new_orbital_object(pl_world_t *world, const char *name, double m, double gm, double orbitPeriod, double obliquity, double siderealPeriod, double semiMaj, double semiMin, double inc, double ascendingNode, double argOfPeriapsis, double meanAnomaly, double eqRadius, double flattening) { assert(world); pl_system_t *sys = smalloc(sizeof(pl_system_t)); obj_array_init(&sys->orbits); obj_array_init(&sys->astroObjs); obj_array_init(&sys->rigidObjs); sys->name = strdup(name); sys->world = world; sys->parent = NULL; sys->orbitalPeriod = orbitPeriod; // TODO: Stack allocation based on untrusted length should not be here char orbitName[strlen(name) + strlen(" Orbit") + 1]; strcpy(orbitName, name); // safe as size is checked in allocation strcat(orbitName, " Orbit"); lwcoord_t p; lwc_set(&p, 0.0, 0.0, 0.0); // TODO: Cleanup this quaternion // Z-X-Z for euler angles quaternion_t q = q_rot(0.0, 0.0, 1.0, DEG_TO_RAD(ascendingNode)); q = q_mul(q, q_rot(1.0, 0.0, 0.0, DEG_TO_RAD(inc))); q = q_mul(q, q_rot(0.0, 0.0, 1.0, DEG_TO_RAD(argOfPeriapsis))); // TODO: Correct axis? q = q_mul(q, q_rot(1.0, 0.0, 0.0, DEG_TO_RAD(obliquity))); sys->orbitalBody = pl_new_obj_in_sys(sys/*world->rootSys*/, name, m, gm, &p, q, siderealPeriod, obliquity, eqRadius, flattening); sys->orbitalBody->kepler = plNewKeplerElements(sqrt((semiMaj*semiMaj-semiMin*semiMin)/(semiMaj*semiMaj)), semiMaj, inc, ascendingNode, argOfPeriapsis, meanAnomaly); return sys; }
/* * Multiply b by constant a */ void arith_buffer_mul_const(arith_buffer_t *b, rational_t *a) { mlist_t *p; p = b->list; while (p->next != NULL) { q_mul(&p->coeff, a); p = p->next; } }
void q_div ( Q a, Q x, Q y ) { Q inv; /* Doesn't seem to work. Will need to better understand inversion */ if ( q_is_zero(y) ) { return; } q_inv(inv,y); q_mul(a,x,inv); }
/* * Multiply b by a * r */ void arith_buffer_mul_mono(arith_buffer_t *b, rational_t *a, pprod_t *r) { pprod_table_t *tbl; mlist_t *p; tbl = b->ptbl; p = b->list; while (p->next != NULL) { assert(p->prod != end_pp); p->prod = pprod_mul(tbl, p->prod, r); q_mul(&p->coeff, a); p = p->next; } }