mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-22 12:31:10 +00:00
136 lines
3 KiB
R
136 lines
3 KiB
R
|
#include <stdlib.h>
|
||
|
|
||
|
#include "algebra.h"
|
||
|
#include "metric.h"
|
||
|
#include "basisblade.h"
|
||
|
#include "basisgroup.h"
|
||
|
#include "basislayout.h"
|
||
|
#include "util.h"
|
||
|
|
||
|
@implementation Algebra
|
||
|
+(Algebra *) R:(int)p, int m, int z
|
||
|
{
|
||
|
Algebra *a = [[[Algebra alloc] init] autorelease];
|
||
|
a.metric = [[Metric R:p, m, z] retain];
|
||
|
|
||
|
int d = p + m + z;
|
||
|
a.dimension = d;
|
||
|
a.num_components = 1 << d;
|
||
|
BasisBlade **blades = obj_malloc (a.num_components * sizeof (BasisBlade *));
|
||
|
int *counts = binomial (d);
|
||
|
int *indices = obj_malloc ((d + 1) * sizeof (int));
|
||
|
|
||
|
indices[0] = 0;
|
||
|
for (int i = 0; i < d; i++) {
|
||
|
indices[i + 1] = counts[i];
|
||
|
}
|
||
|
prefixsum (indices, d + 1);
|
||
|
for (int i = 0; i < a.num_components; i++) {
|
||
|
int grade = count_bits (i);
|
||
|
int ind = indices[grade]++;
|
||
|
blades[ind] = [BasisBlade basis:i];
|
||
|
}
|
||
|
|
||
|
a.grades = obj_malloc ((d + 1) * sizeof (BasisGroup *));
|
||
|
for (int i = 0; i < d + 1; i++) {
|
||
|
int c = counts[i];
|
||
|
int ind = indices[i];
|
||
|
a.grades[i] = [BasisGroup new:c basis:blades + ind - c];
|
||
|
}
|
||
|
|
||
|
if (p == 3 && m == 0 && z == 1) {
|
||
|
// 3d PGA (w squares to 0, x y z square to +1):
|
||
|
// : x y z w
|
||
|
// : yz zx xy 1
|
||
|
// : xw yw zw xyzw
|
||
|
// : zyw xzw yxw xyz
|
||
|
BasisBlade *pga_blades[16] = {
|
||
|
blades[1], blades[2], blades[3], blades[4],
|
||
|
blades[7], blades[6], blades[5], blades[0],
|
||
|
blades[8], blades[9], blades[10], blades[15],
|
||
|
blades[14], blades[13], blades[12], blades[11],
|
||
|
};
|
||
|
BasisGroup *pga_groups[4] = {
|
||
|
[BasisGroup new:4 basis:pga_blades + 0],
|
||
|
[BasisGroup new:4 basis:pga_blades + 4],
|
||
|
[BasisGroup new:4 basis:pga_blades + 8],
|
||
|
[BasisGroup new:4 basis:pga_blades + 12],
|
||
|
};
|
||
|
a.layout = [[BasisLayout new:4 groups: pga_groups] retain];
|
||
|
} else if (p == 2 && m == 0 && z == 1) {
|
||
|
// 2d PGA (w squares to 0, x y square to +1):
|
||
|
// : x y w 1
|
||
|
// : yw wx xy xyw
|
||
|
BasisBlade *pga_blades[8] = {
|
||
|
blades[1], blades[2], blades[3], blades[0],
|
||
|
blades[6], blades[5], blades[4], blades[7],
|
||
|
};
|
||
|
BasisGroup *pga_groups[2] = {
|
||
|
[BasisGroup new:4 basis:pga_blades + 0],
|
||
|
[BasisGroup new:4 basis:pga_blades + 4],
|
||
|
};
|
||
|
a.layout = [[BasisLayout new:2 groups: pga_groups] retain];
|
||
|
} else {
|
||
|
// just use the grades as the default layout
|
||
|
a.layout = [[BasisLayout new:d + 1 groups: a.grades] retain];
|
||
|
}
|
||
|
|
||
|
obj_free (indices);
|
||
|
obj_free (counts);
|
||
|
obj_free (blades);
|
||
|
return a;
|
||
|
}
|
||
|
|
||
|
+(Algebra *) PGA:(int)n
|
||
|
{
|
||
|
return [Algebra R:n, 0, 1];
|
||
|
}
|
||
|
|
||
|
-(void)dealloc
|
||
|
{
|
||
|
obj_free (grades);
|
||
|
[metric release];
|
||
|
[layout release];
|
||
|
[super dealloc];
|
||
|
}
|
||
|
|
||
|
-(BasisGroup *)grade:(int)k
|
||
|
{
|
||
|
return grades[k];
|
||
|
}
|
||
|
|
||
|
-(BasisLayout *)layout
|
||
|
{
|
||
|
return layout;
|
||
|
}
|
||
|
|
||
|
-(Metric *) metric
|
||
|
{
|
||
|
return metric;
|
||
|
}
|
||
|
|
||
|
-(int)count
|
||
|
{
|
||
|
return num_components;
|
||
|
}
|
||
|
|
||
|
-(int)dimension
|
||
|
{
|
||
|
return dimension;
|
||
|
}
|
||
|
|
||
|
-(void) print
|
||
|
{
|
||
|
int count = [layout count];
|
||
|
for (int i = 0; i < count; i++) {
|
||
|
BasisGroup *g = [layout group:i];
|
||
|
int c = [g count];
|
||
|
printf ("%d %d %@\n", i, c, [g set]);
|
||
|
for (int j = 0; j < c; j++) {
|
||
|
printf (" %@\n", [g bladeAt:j]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@end
|