Patrick Kelley 8fd444092b initial
2025-05-07 15:35:15 -04:00

174 lines
5.5 KiB
C

#include "fiber/fiber.h"
#include "test_pre.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
double A[20];
#define CAT0(a, b) a##b
#define CAT(a, b) CAT0(a, b)
#define TMP(a) CAT(CAT(tmp_, a), __LINE__)
#define STR0(a) #a
#define STR(a) STR0(a)
#define DEF_A(i, j, k, l) \
double CAT(a, i) = A[i] + args->id; \
double CAT(a, j) = A[j] + 3 * args->id; \
double CAT(a, k) = A[k] - 1 * args->id; \
double CAT(a, l) = A[l] - 3 * args->id
#define STORE(i, j, k, l) \
A[i] = CAT(a, i); \
A[j] = CAT(a, j); \
A[k] = CAT(a, k); \
A[l] = CAT(a, l)
#define CLAMP(x, y, l) \
while (x * x + y * y > l) { \
double TMP(x) = x; \
double TMP(y) = y; \
x = (TMP(x) + TMP(y)) * (1. / 17); \
y = (TMP(x) - TMP(y)) * (1. / 18); \
}
#define MIX_(a, b, c, d) \
do { \
a = b * c - 31 * d + 1; \
b = a * b - c * d * 2 + 1; \
c = d * d + a * 3 - 1; \
d = a + b - c - 11 * d - 1; \
CLAMP(a, b, 24); \
CLAMP(c, d, 27); \
CLAMP(a, d, 29); \
CLAMP(b, c, 31); \
} while (0)
#define MIX(i, j, k, l) MIX_(CAT(a, i), CAT(a, j), CAT(a, k), CAT(a, l))
#define PRINT1(i) fprintf(out, "a%02d=%+.13le ", i, A[i])
#define PRINT(i, j, k, l) \
PRINT1(i); \
PRINT1(j); \
PRINT1(k); \
PRINT1(l); \
println("")
#define MAP(F) \
do { \
F(0, 1, 2, 3); \
F(4, 5, 6, 7); \
F(8, 9, 10, 11); \
F(12, 13, 14, 15); \
F(16, 17, 18, 19); \
} while (0)
#define STORE_ALL MAP(STORE)
typedef struct
{
Fiber *self;
Fiber *caller;
int n;
int id;
bool done;
} Args;
static void
print(int id)
{
fprintf(out, "Fiber[%d]\n", id);
MAP(PRINT);
println("");
}
static void
entry(void *args0)
{
Args *args = (Args *) args0;
DEF_A(0, 1, 2, 3);
DEF_A(4, 5, 6, 7);
DEF_A(8, 9, 10, 11);
DEF_A(12, 13, 14, 15);
DEF_A(16, 17, 18, 19);
for (int i = 0; i < args->n; ++i) {
for (int j = 0; j < 16; ++j) {
if (j & 1) {
MIX(0, 2, 4, 6);
MIX(1, 3, 5, 7);
} else {
MIX(8, 10, 12, 14);
MIX(9, 11, 13, 15);
}
if (a2 > 0 || a11 < 0) {
MIX(0, 16, 3, 17);
MIX(12, 18, 15, 19);
}
}
fiber_switch(args->self, args->caller);
if (i % 50 == 0) {
STORE_ALL;
print(args->id);
}
}
STORE_ALL;
print(args->id);
args->done = true;
fiber_switch(args->self, args->caller);
}
static void
guard(Fiber *fiber, void *null)
{
(void) fiber;
(void) null;
abort();
}
static void
setup_fiber(Fiber *caller, Fiber *fiber, Args **args, int id)
{
(void) fiber_alloc(fiber, 16 * 1024, guard, NULL, FIBER_FLAG_GUARD_LO);
fiber_reserve_return(fiber, entry, (void **) args, sizeof *args);
(*args)->self = fiber;
(*args)->caller = caller;
(*args)->n = 256;
(*args)->id = id;
(*args)->done = false;
}
int
main(int argc, char *argv[])
{
test_main_begin(&argc, &argv);
#if HU_OS_WINDOWS_P && defined(_TWO_DIGIT_EXPONENT)
_set_output_format(_TWO_DIGIT_EXPONENT);
#endif
Fiber toplevel;
fiber_init_toplevel(&toplevel);
Fiber fiber1;
Args *args1;
setup_fiber(&toplevel, &fiber1, &args1, 1);
Fiber fiber2;
Args *args2;
setup_fiber(&toplevel, &fiber2, &args2, 2);
while (!args1->done || !args2->done) {
if (!args1->done)
fiber_switch(&toplevel, &fiber1);
if (!args2->done)
fiber_switch(&toplevel, &fiber2);
}
fiber_destroy(&fiber1);
fiber_destroy(&fiber2);
test_main_end();
return 0;
}