quakeforge/ruamoko/gatest/basislayout.r
Bill Currie c1c77bd64a [gatest] Add basic geometric algebra test
This is for developing methods of implementing geometric algebra and
eventually playing with it visually.
2023-05-19 00:34:05 +09:00

111 lines
2.4 KiB
R

#include <stdlib.h>
#include <Set.h>
#include "basisblade.h"
#include "basisgroup.h"
#include "basislayout.h"
#include "util.h"
@implementation BasisLayout
+(BasisLayout *) new:(int) count groups:(BasisGroup **)groups
{
BasisLayout *layout = [[[BasisLayout alloc] init] autorelease];
layout.count = count;
layout.groups = obj_malloc (count * sizeof (BasisGroup *));
layout.set = [[Set set] retain];
layout.range = { ~0u, 0 };
int *group_base = obj_malloc ((count + 1) * sizeof (int));
group_base[0] = 0;
int num_blades = 0;
for (int i = 0; i < count; i++) {
layout.groups[i] = [groups[i] retain];
[layout.set union:[groups[i] set]];
group_base[i + 1] = [groups[i] count];
num_blades += group_base[i + 1];
uivec2 r = [groups[i] blade_range];
if (r[0] < layout.range[0]) {
layout.range[0] = r[0];
}
if (r[1] > layout.range[1]) {
layout.range[1] = r[1];
}
}
prefixsum (group_base, count);
layout.blade_count = num_blades;
layout.group_map = obj_malloc (num_blades * sizeof (ivec3));
int num = layout.range[1] - layout.range[0] + 1;
layout.mask_map = obj_malloc (num * sizeof (int));
int *group_inds = obj_malloc ((count + 1) * sizeof (int));
for (int i = 0; i < count; i++) {
BasisGroup *g = groups[i];
group_inds[i] = 0;
for (int j = 0; j < [g count]; j++) {
BasisBlade *b = [g bladeAt:j];
layout.mask_map[[b mask] - layout.range[0]] = group_inds[count];
layout.group_map[group_inds[count]][0] = i;
layout.group_map[group_inds[count]][1] = group_inds[i]++;
layout.group_map[group_inds[count]][2] = group_base[i];
group_inds[count]++;
}
}
obj_free (group_inds);
return layout;
}
-(void)dealloc
{
[set release];
for (int i = 0; i < count; i++) {
[groups[i] release];
}
obj_free (groups);
obj_free (group_map);
[super dealloc];
}
-(int)count
{
return count;
}
-(int)num_components
{
int num_components = 0;
// assumes there is no overlap
for (int i = 0; i < count; i++) {
num_components += [groups[i] count];
}
return num_components;
}
-(int)blade_count
{
return blade_count;
}
-(BasisGroup *) group:(int) ind
{
return groups[ind];
}
-(BasisBlade *) bladeAt:(int) ind
{
ivec3 gm = group_map[ind];
BasisGroup *g = groups[gm[0]];
return [g bladeAt:ind - gm[2]];
}
-(int) bladeIndex:(unsigned) mask
{
if (![set is_member:mask]) {
return 0;
}
return mask_map[mask - range[0]];
}
-(Set *) set
{
return set;
}
@end