Initial import
This commit is contained in:
commit
4304edc0f0
113
COPYING
Normal file
113
COPYING
Normal file
@ -0,0 +1,113 @@
|
||||
CC0 1.0 Universal
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator and
|
||||
subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for the
|
||||
purpose of contributing to a commons of creative, cultural and scientific
|
||||
works ("Commons") that the public can reliably and without fear of later
|
||||
claims of infringement build upon, modify, incorporate in other works, reuse
|
||||
and redistribute as freely as possible in any form whatsoever and for any
|
||||
purposes, including without limitation commercial purposes. These owners may
|
||||
contribute to the Commons to promote the ideal of a free culture and the
|
||||
further production of creative, cultural and scientific works, or to gain
|
||||
reputation or greater distribution for their Work in part through the use and
|
||||
efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any expectation
|
||||
of additional consideration or compensation, the person associating CC0 with a
|
||||
Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
|
||||
and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
|
||||
and publicly distribute the Work under its terms, with knowledge of his or her
|
||||
Copyright and Related Rights in the Work and the meaning and intended legal
|
||||
effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not limited
|
||||
to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display, communicate,
|
||||
and translate a Work;
|
||||
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
|
||||
iii. publicity and privacy rights pertaining to a person's image or likeness
|
||||
depicted in a Work;
|
||||
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data in
|
||||
a Work;
|
||||
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation thereof,
|
||||
including any amended or successor version of such directive); and
|
||||
|
||||
vii. other similar, equivalent or corresponding rights throughout the world
|
||||
based on applicable law or treaty, and any national implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention of,
|
||||
applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
|
||||
unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
|
||||
and Related Rights and associated claims and causes of action, whether now
|
||||
known or unknown (including existing as well as future claims and causes of
|
||||
action), in the Work (i) in all territories worldwide, (ii) for the maximum
|
||||
duration provided by applicable law or treaty (including future time
|
||||
extensions), (iii) in any current or future medium and for any number of
|
||||
copies, and (iv) for any purpose whatsoever, including without limitation
|
||||
commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
|
||||
the Waiver for the benefit of each member of the public at large and to the
|
||||
detriment of Affirmer's heirs and successors, fully intending that such Waiver
|
||||
shall not be subject to revocation, rescission, cancellation, termination, or
|
||||
any other legal or equitable action to disrupt the quiet enjoyment of the Work
|
||||
by the public as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason be
|
||||
judged legally invalid or ineffective under applicable law, then the Waiver
|
||||
shall be preserved to the maximum extent permitted taking into account
|
||||
Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
|
||||
is so judged Affirmer hereby grants to each affected person a royalty-free,
|
||||
non transferable, non sublicensable, non exclusive, irrevocable and
|
||||
unconditional license to exercise Affirmer's Copyright and Related Rights in
|
||||
the Work (i) in all territories worldwide, (ii) for the maximum duration
|
||||
provided by applicable law or treaty (including future time extensions), (iii)
|
||||
in any current or future medium and for any number of copies, and (iv) for any
|
||||
purpose whatsoever, including without limitation commercial, advertising or
|
||||
promotional purposes (the "License"). The License shall be deemed effective as
|
||||
of the date CC0 was applied by Affirmer to the Work. Should any part of the
|
||||
License for any reason be judged legally invalid or ineffective under
|
||||
applicable law, such partial invalidity or ineffectiveness shall not
|
||||
invalidate the remainder of the License, and in such case Affirmer hereby
|
||||
affirms that he or she will not (i) exercise any of his or her remaining
|
||||
Copyright and Related Rights in the Work or (ii) assert any associated claims
|
||||
and causes of action with respect to the Work, in either case contrary to
|
||||
Affirmer's express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
|
||||
b. Affirmer offers the Work as-is and makes no representations or warranties
|
||||
of any kind concerning the Work, express, implied, statutory or otherwise,
|
||||
including without limitation warranties of title, merchantability, fitness
|
||||
for a particular purpose, non infringement, or the absence of latent or
|
||||
other defects, accuracy, or the present or absence of errors, whether or not
|
||||
discoverable, all to the greatest extent permissible under applicable law.
|
||||
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without limitation
|
||||
any person's Copyright and Related Rights in the Work. Further, Affirmer
|
||||
disclaims responsibility for obtaining any necessary consents, permissions
|
||||
or other rights required for any use of the Work.
|
||||
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to this
|
||||
CC0 or use of the Work.
|
37
Makefile
Normal file
37
Makefile
Normal file
@ -0,0 +1,37 @@
|
||||
# fractal
|
||||
# Written in 2020 by Lucas
|
||||
# CC0 1.0 Universal/Public domain - No rights reserved
|
||||
#
|
||||
# To the extent possible under law, the author(s) have dedicated all
|
||||
# copyright and related and neighboring rights to this software to the
|
||||
# public domain worldwide. This software is distributed without any
|
||||
# warranty. You should have received a copy of the CC0 Public Domain
|
||||
# Dedication along with this software. If not, see
|
||||
# <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
.POSIX:
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .o
|
||||
|
||||
.c.o:
|
||||
${CC} ${FRACTAL_CFLAGS} -c $<
|
||||
|
||||
FRACTAL_CFLAGS = -O3 -ffast-math -march=native -mtune=native \
|
||||
${CFLAGS}
|
||||
|
||||
BIN = fractal fun-gen
|
||||
FRACTAL_OBJ = criticals.o fractal.o julia.o palette.o pnmout.o util.o
|
||||
FUN_GEN_OBJ = fun-gen.o
|
||||
OBJ = ${FRACTAL_OBJ} ${FUN_GEN_OBJ}
|
||||
|
||||
all: fractal
|
||||
|
||||
julia.o: fun.h
|
||||
|
||||
fractal: ${FRACTAL_OBJ}
|
||||
${CC} ${LDFLAGS} -o $@ ${FRACTAL_OBJ} -lm
|
||||
|
||||
fun-gen: ${FUN_GEN_OBJ}
|
||||
${CC} ${LDFLAGS} -o $@ ${FUN_GEN_OBJ} -lm
|
||||
|
||||
clean:
|
||||
rm -f ${OBJ} ${BIN} fun.h
|
70
criticals.c
Normal file
70
criticals.c
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* fractal
|
||||
* Written in 2020 by Lucas
|
||||
* CC0 1.0 Universal/Public domain - No rights reserved
|
||||
*
|
||||
* To the extent possible under law, the author(s) have dedicated all
|
||||
* copyright and related and neighboring rights to this software to the
|
||||
* public domain worldwide. This software is distributed without any
|
||||
* warranty. You should have received a copy of the CC0 Public Domain
|
||||
* Dedication along with this software. If not, see
|
||||
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "criticals.h"
|
||||
#include "util.h"
|
||||
|
||||
size_t newton_iters = 100;
|
||||
|
||||
static size_t idx = 0;
|
||||
static long double complex criticals[100];
|
||||
|
||||
int
|
||||
behaves_critical(long double complex (*df)(long double complex),
|
||||
long double complex (*ddf)(long double complex), long double complex z,
|
||||
long double complex *crit, long double bailout, long double epsilon)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < newton_iters && cabsl(z) < bailout; i++)
|
||||
z = z - df(z) / ddf(z);
|
||||
|
||||
if (cabsl(df(z)) < epsilon) {
|
||||
*crit = z;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
add_critical_point(long double complex z)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (idx >= nelems(criticals))
|
||||
return;
|
||||
for (i = 0; i < idx; i++)
|
||||
if (cabsl(z - criticals[i]) < 1.0e-9)
|
||||
return;
|
||||
|
||||
criticals[idx++] = z;
|
||||
}
|
||||
|
||||
size_t
|
||||
ncriticals(void)
|
||||
{
|
||||
return idx;
|
||||
}
|
||||
|
||||
long double complex
|
||||
get_critical(size_t i)
|
||||
{
|
||||
if (i >= idx) {
|
||||
fprintf(stderr, "get_critical: index %zu out of range", i);
|
||||
exit(1);
|
||||
}
|
||||
return criticals[i];
|
||||
}
|
21
criticals.h
Normal file
21
criticals.h
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* fractal
|
||||
* Written in 2020 by Lucas
|
||||
* CC0 1.0 Universal/Public domain - No rights reserved
|
||||
*
|
||||
* To the extent possible under law, the author(s) have dedicated all
|
||||
* copyright and related and neighboring rights to this software to the
|
||||
* public domain worldwide. This software is distributed without any
|
||||
* warranty. You should have received a copy of the CC0 Public Domain
|
||||
* Dedication along with this software. If not, see
|
||||
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
#include <complex.h>
|
||||
#include <stddef.h>
|
||||
|
||||
int behaves_critical(long double complex (*)(long double complex),
|
||||
long double complex (*)(long double complex), long double complex,
|
||||
long double complex *, long double, long double);
|
||||
void add_critical_point(long double complex);
|
||||
size_t ncriticals(void);
|
||||
long double complex get_critical(size_t);
|
78
fractal.c
Normal file
78
fractal.c
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* fractal
|
||||
* Written in 2020 by Lucas
|
||||
* CC0 1.0 Universal/Public domain - No rights reserved
|
||||
*
|
||||
* To the extent possible under law, the author(s) have dedicated all
|
||||
* copyright and related and neighboring rights to this software to the
|
||||
* public domain worldwide. This software is distributed without any
|
||||
* warranty. You should have received a copy of the CC0 Public Domain
|
||||
* Dedication along with this software. If not, see
|
||||
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
int palette_main(int, char *[]);
|
||||
int julia_main(int, char *[]);
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [-s seed] <prog> [prog_args]\n",
|
||||
xgetprogname());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
char *end;
|
||||
intmax_t v;
|
||||
long seed;
|
||||
int ch;
|
||||
|
||||
seed = time(NULL);
|
||||
while ((ch = getopt(argc, argv, "s:")) != -1)
|
||||
switch (ch) {
|
||||
case 's':
|
||||
errno = 0;
|
||||
v = strtoimax(optarg, &end, 0);
|
||||
if (*end != '\0' || errno != 0 || v > LONG_MAX ||
|
||||
v < LONG_MIN) {
|
||||
fprintf(stderr, "-s: Invalid value \"%s\".",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
seed = (long)v;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
optind = 1;
|
||||
|
||||
if (argc == 0)
|
||||
usage();
|
||||
|
||||
fprintf(stderr, "seed=%ld\n", seed);
|
||||
xsrand48(seed);
|
||||
|
||||
if (strcmp(argv[0], "palette") == 0)
|
||||
return palette_main(argc, argv);
|
||||
else if (strcmp(argv[0], "julia") == 0)
|
||||
return julia_main(argc, argv);
|
||||
else
|
||||
usage();
|
||||
|
||||
return 1; /* UNREACHABLE */
|
||||
}
|
296
fun-gen.c
Normal file
296
fun-gen.c
Normal file
@ -0,0 +1,296 @@
|
||||
/*
|
||||
* fractal
|
||||
* Written in 2020 by Lucas
|
||||
* CC0 1.0 Universal/Public domain - No rights reserved
|
||||
*
|
||||
* To the extent possible under law, the author(s) have dedicated all
|
||||
* copyright and related and neighboring rights to this software to the
|
||||
* public domain worldwide. This software is distributed without any
|
||||
* warranty. You should have received a copy of the CC0 Public Domain
|
||||
* Dedication along with this software. If not, see
|
||||
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
static char *argv0;
|
||||
|
||||
struct poly {
|
||||
unsigned int degree;
|
||||
double *coefs;
|
||||
const char *expr;
|
||||
};
|
||||
|
||||
static void
|
||||
poly_init(struct poly *p, unsigned int degree, const char *expr)
|
||||
{
|
||||
if ((p->coefs = malloc((degree + 1) * sizeof(double))) == NULL) {
|
||||
fprintf(stderr, "out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
p->degree = degree;
|
||||
p->expr = expr;
|
||||
}
|
||||
|
||||
static void
|
||||
poly_derivate(struct poly p, struct poly *dp, const char *expr)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
poly_init(dp, p.degree == 0 ? 0 : p.degree - 1, expr);
|
||||
for (i = p.degree; i > 0; i--)
|
||||
dp->coefs[i - 1] = p.coefs[i] * i;
|
||||
}
|
||||
|
||||
static int
|
||||
poly_cmp(const void *vp, const void *vq)
|
||||
{
|
||||
const struct poly *p = vp, *q = vq;
|
||||
return p->degree - q->degree;
|
||||
}
|
||||
|
||||
static void
|
||||
poly_free(struct poly *p)
|
||||
{
|
||||
free(p->coefs);
|
||||
}
|
||||
|
||||
static void
|
||||
print_fun_header(const char *fun_name)
|
||||
{
|
||||
printf("static long double complex\n");
|
||||
printf("%s(long double complex z)\n", fun_name);
|
||||
printf("{\n");
|
||||
}
|
||||
|
||||
static void
|
||||
print_fun_body(size_t n, struct poly *polys)
|
||||
{
|
||||
size_t i, j;
|
||||
unsigned int d;
|
||||
|
||||
printf("\tlong double complex a");
|
||||
for (i = 0; i < n; i++)
|
||||
printf(", %s = 0.0L", polys[i].expr);
|
||||
printf(";\n\n");
|
||||
|
||||
d = 0;
|
||||
for (i = 0; i < n; i++) {
|
||||
for (; d <= polys[i].degree; d++) {
|
||||
if (d == 0)
|
||||
printf("\ta = 1.0L;\n");
|
||||
else
|
||||
printf("\ta *= z;\n");
|
||||
for (j = n; j > i; j--)
|
||||
if (polys[j - 1].coefs[d] != 0.0L)
|
||||
printf("\t%s += %.20f * a;\n",
|
||||
polys[j - 1].expr,
|
||||
polys[j - 1].coefs[d]);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_fun_footer(void)
|
||||
{
|
||||
printf("}\n");
|
||||
}
|
||||
|
||||
static void
|
||||
print_funs(struct poly p, struct poly q)
|
||||
{
|
||||
struct poly polys[6];
|
||||
struct poly dp, ddp, dq, ddq;
|
||||
|
||||
polys[0] = p;
|
||||
polys[1] = q;
|
||||
qsort(polys, 2, sizeof(struct poly), &poly_cmp);
|
||||
|
||||
print_fun_header("f");
|
||||
print_fun_body(2, polys);
|
||||
printf("\treturn p / q;\n");
|
||||
print_fun_footer();
|
||||
|
||||
poly_derivate(p, &dp, "dp");
|
||||
poly_derivate(q, &dq, "dq");
|
||||
polys[0] = p;
|
||||
polys[1] = q;
|
||||
polys[2] = dp;
|
||||
polys[3] = dq;
|
||||
qsort(polys, 4, sizeof(struct poly), &poly_cmp);
|
||||
|
||||
printf("\n");
|
||||
print_fun_header("df");
|
||||
print_fun_body(4, polys);
|
||||
printf("\treturn (dp * q - p * dq) / (q * q);\n");
|
||||
print_fun_footer();
|
||||
|
||||
poly_derivate(dp, &ddp, "ddp");
|
||||
poly_derivate(dq, &ddq, "ddq");
|
||||
polys[0] = p;
|
||||
polys[1] = q;
|
||||
polys[2] = dp;
|
||||
polys[3] = dq;
|
||||
polys[4] = ddp;
|
||||
polys[5] = ddq;
|
||||
qsort(polys, 6, sizeof(struct poly), &poly_cmp);
|
||||
|
||||
printf("\n");
|
||||
print_fun_header("ddf");
|
||||
print_fun_body(6, polys);
|
||||
printf("\treturn ("
|
||||
"q * q * ddp "
|
||||
"- q * (2.0L * dp * dq + p * ddq) "
|
||||
"+ 2.0L * p * dq * dq"
|
||||
") / (q * q * q);\n");
|
||||
/*printf("\treturn (ddp "
|
||||
"- 2.0 * ((dp * q - p * dq) / (q * q)) * dq "
|
||||
"- (p / q) * ddq) / q;\n");*/
|
||||
print_fun_footer();
|
||||
|
||||
poly_free(&dp);
|
||||
poly_free(&dq);
|
||||
poly_free(&ddp);
|
||||
poly_free(&ddq);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
parse_uint(const char *s)
|
||||
{
|
||||
char *end;
|
||||
uintmax_t v;
|
||||
|
||||
errno = 0;
|
||||
v = strtoumax(s, &end, 10);
|
||||
if (s == end || *end != '\0' || errno != 0 || v > UINT_MAX) {
|
||||
fprintf(stderr, "%s: invalid value: %s\n", argv0, s);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return (unsigned int)v;
|
||||
}
|
||||
|
||||
static double
|
||||
parse_double(const char *s)
|
||||
{
|
||||
char *end;
|
||||
double d;
|
||||
|
||||
errno = 0;
|
||||
d = strtod(s, &end);
|
||||
if (s == end || *end != '\0' || errno != 0 || !isfinite(d)) {
|
||||
fprintf(stderr, "%s: invalid value: %s\n", argv0, s);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s p-degree q-degree p-coefs q-coefs\n"
|
||||
" %s -n p-degree p-coefs\n", argv0, argv0);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void
|
||||
do_poly_div(int argc, char *argv[])
|
||||
{
|
||||
struct poly p, q;
|
||||
unsigned int i, j, p_degree, q_degree;
|
||||
|
||||
if (argc < 2)
|
||||
usage();
|
||||
|
||||
p_degree = parse_uint(argv[0]);
|
||||
q_degree = parse_uint(argv[1]);
|
||||
if (argc != p_degree + q_degree + 2 + 2)
|
||||
usage();
|
||||
|
||||
poly_init(&p, p_degree, "p");
|
||||
poly_init(&q, q_degree, "q");
|
||||
|
||||
for (j = 0, i = 1 + 1 + p.degree + 1 + q.degree;
|
||||
i > 1 + 1 + p.degree;
|
||||
i--, j++)
|
||||
q.coefs[j] = parse_double(argv[i]);
|
||||
for (j = 0;
|
||||
i > 1;
|
||||
i--, j++)
|
||||
p.coefs[j] = parse_double(argv[i]);
|
||||
|
||||
print_funs(p, q);
|
||||
poly_free(&p);
|
||||
poly_free(&q);
|
||||
}
|
||||
|
||||
static void
|
||||
do_newton(int argc, char *argv[])
|
||||
{
|
||||
struct poly f, df, p;
|
||||
unsigned int i, j, f_degree;
|
||||
|
||||
if (argc < 1)
|
||||
usage();
|
||||
|
||||
f_degree = parse_uint(argv[0]);
|
||||
if (argc != f_degree + 1 + 1)
|
||||
usage();
|
||||
|
||||
poly_init(&f, f_degree, "f");
|
||||
for (j = 0, i = 1 + f.degree;
|
||||
i > 0;
|
||||
i--, j++)
|
||||
f.coefs[j] = parse_double(argv[i]);
|
||||
|
||||
poly_derivate(f, &df, "q");
|
||||
poly_init(&p, f_degree, "p");
|
||||
for (i = 0; i <= f.degree; i++)
|
||||
p.coefs[i] = (i == 0 ? 0.0 : df.coefs[i - 1]) - f.coefs[i];
|
||||
|
||||
print_funs(p, df);
|
||||
poly_free(&f);
|
||||
poly_free(&df);
|
||||
poly_free(&p);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct poly p, q;
|
||||
char *end;
|
||||
uintmax_t v;
|
||||
unsigned int i, j, p_degree, q_degree;
|
||||
int ch, nflag;
|
||||
|
||||
argv0 = argv[0];
|
||||
nflag = 0;
|
||||
while ((ch = getopt(argc, argv, "n")) != -1)
|
||||
switch (ch) {
|
||||
case 'n':
|
||||
nflag = 1;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (nflag)
|
||||
do_newton(argc, argv);
|
||||
else
|
||||
do_poly_div(argc, argv);
|
||||
|
||||
return 0;
|
||||
}
|
34
hi-res.sh
Normal file
34
hi-res.sh
Normal file
@ -0,0 +1,34 @@
|
||||
#!/bin/sh
|
||||
# fractal
|
||||
# Written in 2020 by Lucas
|
||||
# CC0 1.0 Universal/Public domain - No rights reserved
|
||||
#
|
||||
# To the extent possible under law, the author(s) have dedicated all
|
||||
# copyright and related and neighboring rights to this software to the
|
||||
# public domain worldwide. This software is distributed without any
|
||||
# warranty. You should have received a copy of the CC0 Public Domain
|
||||
# Dedication along with this software. If not, see
|
||||
# <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
usage()
|
||||
{
|
||||
printf "Usage: %s width height [fractal args...]\n" "${0##*/}" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
tonumber()
|
||||
{
|
||||
printf "%u\n" "$*"
|
||||
}
|
||||
|
||||
width=
|
||||
height=
|
||||
if [ $# -lt 2 ] || ! width=$(tonumber "$1") || ! height=$(tonumber "$2"); then
|
||||
usage
|
||||
fi
|
||||
shift 2
|
||||
|
||||
upwidth=$((width * 4))
|
||||
upheight=$((height * 4))
|
||||
./fractal "$@" -w $upwidth -h $upheight |
|
||||
pamscale -width $width -height $height |
|
||||
pamtopng >julia.png
|
361
julia.c
Normal file
361
julia.c
Normal file
@ -0,0 +1,361 @@
|
||||
/*
|
||||
* fractal
|
||||
* Written in 2020 by Lucas
|
||||
* CC0 1.0 Universal/Public domain - No rights reserved
|
||||
*
|
||||
* To the extent possible under law, the author(s) have dedicated all
|
||||
* copyright and related and neighboring rights to this software to the
|
||||
* public domain worldwide. This software is distributed without any
|
||||
* warranty. You should have received a copy of the CC0 Public Domain
|
||||
* Dedication along with this software. If not, see
|
||||
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
#include <complex.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "criticals.h"
|
||||
#include "palette.h"
|
||||
#include "pnmout.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "fun.h"
|
||||
|
||||
struct color contour_color = { 0 };
|
||||
static long double bailout = 1e100,
|
||||
epsilon = 1e-8,
|
||||
sec_w = 4.0,
|
||||
contour = 0.0005L;
|
||||
static unsigned long niters = 250;
|
||||
|
||||
static void
|
||||
print_critical_points(void)
|
||||
{
|
||||
long double complex z;
|
||||
size_t i, n;
|
||||
|
||||
n = ncriticals();
|
||||
fprintf(stderr, "Critical points:\n");
|
||||
for (i = 0; i < n; i++) {
|
||||
z = get_critical(i);
|
||||
fprintf(stderr, "%4zu. (%.20Lf, %.20Lf)\n", i, creall(z),
|
||||
cimagl(z));
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
tends_to_critical(long double complex z, long double *t)
|
||||
{
|
||||
long double d;
|
||||
size_t i, n;
|
||||
|
||||
n = ncriticals();
|
||||
for (i = 0; i < n; i++) {
|
||||
d = cabsl(z - get_critical(i));
|
||||
if (d < epsilon) {
|
||||
*t = d;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long
|
||||
iterate(long double complex z, long double complex c, long double *rit)
|
||||
{
|
||||
long double complex dz = 1.0L;
|
||||
long double t;
|
||||
unsigned long ci, i;
|
||||
|
||||
for (i = 0; i < niters && cabsl(z) < bailout; i++) {
|
||||
dz = df(z) * dz;
|
||||
z = f(z) + c;
|
||||
|
||||
if (tends_to_critical(z, &t)) {
|
||||
*rit = logl(logl(t) / logl(epsilon)) / logl(2.0L);
|
||||
return fabsl(logl(t)) * t < sec_w * contour * cabsl(dz)
|
||||
? -1 : i;
|
||||
}
|
||||
}
|
||||
|
||||
t = cabsl(z);
|
||||
if (t >= bailout) {
|
||||
*rit = logl(logl(t) / logl(bailout)) / logl(2.0L);
|
||||
return fabsl(logl(t)) * t < sec_w * contour * cabsl(dz)
|
||||
? -1 : i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static long
|
||||
fast_iterate(long double complex z, long double complex c, long double *rit)
|
||||
{
|
||||
long double t;
|
||||
unsigned long ci, i;
|
||||
|
||||
for (i = 0; i < niters && cabsl(z) < bailout; i++) {
|
||||
z = f(z) + c;
|
||||
|
||||
if (tends_to_critical(z, &t)) {
|
||||
*rit = logl(logl(t) / logl(epsilon)) / logl(2.0L);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
t = cabsl(z);
|
||||
if (t >= bailout) {
|
||||
*rit = logl(logl(t) / logl(bailout)) / logl(2.0L);
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s julia [-L] [-x julia_x] [-y julia_y]\n"
|
||||
" [-n niters] [-h height] [-w width] [-z zoom]\n"
|
||||
" [-a center_x] [-b center_y] [-l light_intensity]\n"
|
||||
" [-d density] [-c contour]\n",
|
||||
xgetprogname());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
julia_main(int argc, char *argv[])
|
||||
{
|
||||
struct color *palette;
|
||||
struct {
|
||||
long long it;
|
||||
long double rit;
|
||||
} *rescache;
|
||||
char *end;
|
||||
struct color color;
|
||||
long double complex crit, julia, z;
|
||||
long double julia_x = 0.0,
|
||||
julia_y = 0.0,
|
||||
cen_x = 0.0,
|
||||
cen_y = 0.0,
|
||||
density = 28.3L,
|
||||
light_intensity = 84.3L,
|
||||
displacement = 0,
|
||||
zoom = 1.0,
|
||||
light, light_x, light_y, light_z, rit, sec_h, zx, zy;
|
||||
intmax_t v;
|
||||
long long it, idx, ritnum;
|
||||
unsigned int palette_size = 720,
|
||||
width = 640,
|
||||
height = 400,
|
||||
i, j;
|
||||
int ch, do_light = 0;
|
||||
|
||||
while ((ch = getopt(argc, argv, "a:b:c:d:h:Ll:n:w:x:y:z:")) != -1)
|
||||
switch (ch) {
|
||||
case 'a':
|
||||
errno = 0;
|
||||
cen_x = strtold(optarg, &end);
|
||||
if (end == optarg || *end != '\0' || errno != 0) {
|
||||
fprintf(stderr, "-a: invalid value \"%s\"",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
errno = 0;
|
||||
cen_y = strtold(optarg, &end);
|
||||
if (end == optarg || *end != '\0' || errno != 0) {
|
||||
fprintf(stderr, "-b: invalid value \"%s\"",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
errno = 0;
|
||||
contour = strtold(optarg, &end);
|
||||
if (end == optarg || *end != '\0' || errno != 0
|
||||
|| contour <= 0) {
|
||||
fprintf(stderr, "-c: invalid value \"%s\"",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
errno = 0;
|
||||
density = strtold(optarg, &end);
|
||||
if (end == optarg || *end != '\0' || errno != 0) {
|
||||
fprintf(stderr, "-d: invalid value \"%s\"",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
errno = 0;
|
||||
v = strtoimax(optarg, &end, 0);
|
||||
if (end == optarg || *end != '\0' || errno != 0 ||
|
||||
v <= 0 || v >= 65536) {
|
||||
fprintf(stderr, "-h: invalid value \"%s\"",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
height = (unsigned int)v + 1;
|
||||
break;
|
||||
case 'L':
|
||||
do_light = 1;
|
||||
break;
|
||||
case 'l':
|
||||
errno = 0;
|
||||
light_intensity = strtold(optarg, &end);
|
||||
if (end == optarg || *end != '\0' || errno != 0) {
|
||||
fprintf(stderr, "-l: invalid value \"%s\"",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
errno = 0;
|
||||
v = strtoimax(optarg, &end, 0);
|
||||
if (end == optarg || *end != '\0' || errno != 0 ||
|
||||
v <= 0 || v >= ULONG_MAX) {
|
||||
fprintf(stderr, "-n: invalid value \"%s\"",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
niters = (unsigned long)v;
|
||||
break;
|
||||
case 'w':
|
||||
errno = 0;
|
||||
v = strtoimax(optarg, &end, 0);
|
||||
if (end == optarg || *end != '\0' || errno != 0 ||
|
||||
v <= 0 || v >= 65536) {
|
||||
fprintf(stderr, "-w: invalid value \"%s\"",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
width = (unsigned int)v + 1;
|
||||
break;
|
||||
case 'x':
|
||||
errno = 0;
|
||||
julia_x = strtold(optarg, &end);
|
||||
if (end == optarg || *end != '\0' || errno != 0) {
|
||||
fprintf(stderr, "-x: invalid value \"%s\"",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'y':
|
||||
errno = 0;
|
||||
julia_y = strtold(optarg, &end);
|
||||
if (end == optarg || *end != '\0' || errno != 0) {
|
||||
fprintf(stderr, "-y: invalid value \"%s\"",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'z':
|
||||
errno = 0;
|
||||
zoom = strtold(optarg, &end);
|
||||
if (end == optarg || *end != '\0' || errno != 0
|
||||
|| zoom <= 0) {
|
||||
fprintf(stderr, "-z: invalid value \"%s\"",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
if (argc > 1)
|
||||
usage();
|
||||
|
||||
palette = palette_gen(palette_size);
|
||||
|
||||
if ((rescache = malloc(sizeof(*rescache) * width * height)) == NULL) {
|
||||
fprintf(stderr, "out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (do_light) {
|
||||
long double angle_xy, angle_z;
|
||||
angle_xy = drand48() * 2.0L * 3.14159265358979323846L;
|
||||
angle_z = (0.2L + 0.6L * drand48()) * 3.14159265358979323846L;
|
||||
light_x = cosl(angle_xy) * sinl(angle_z);
|
||||
light_y = sinl(angle_xy) * sinl(angle_z);
|
||||
light_z = cosl(angle_z);
|
||||
}
|
||||
|
||||
sec_h = sec_w * height / (long double)width;
|
||||
julia = julia_x + I * julia_y;
|
||||
|
||||
for (i = 0; i < height; i++) {
|
||||
zy = cen_y + (0.5 - i / (long double)height) * sec_h;
|
||||
for (j = 0; j < width; j++) {
|
||||
zx = cen_x + (j / (long double)width - 0.5L) * sec_w;
|
||||
z = zx + I * zy;
|
||||
if (behaves_critical(df, ddf, z, &crit, bailout,
|
||||
epsilon))
|
||||
add_critical_point(crit);
|
||||
}
|
||||
}
|
||||
|
||||
print_critical_points();
|
||||
|
||||
sec_w /= zoom; sec_h /= zoom;
|
||||
for (i = 0; i < height; i++) {
|
||||
zy = cen_y + (0.5L - i / (long double)height) * sec_h;
|
||||
for (j = 0; j < width; j++) {
|
||||
zx = cen_x + (j / (long double)width - 0.5L) * sec_w;
|
||||
z = zx + I * zy;
|
||||
it = iterate(z, julia, &rit);
|
||||
rescache[i * width + j].it = it;
|
||||
rescache[i * width + j].rit = rit;
|
||||
}
|
||||
}
|
||||
|
||||
pnmout_header(stdout, width - 1, height - 1);
|
||||
for (i = 0; i < height - 1; i++) {
|
||||
for (j = 0; j < width - 1; j++) {
|
||||
it = rescache[i * width + j].it;
|
||||
rit = rescache[i * width + j].rit;
|
||||
|
||||
if (it < 0)
|
||||
color = contour_color;
|
||||
else {
|
||||
ritnum = (it - rit) * density;
|
||||
if (do_light) {
|
||||
long double lxrn, lyrn, l, lx, ly, lz;
|
||||
lxrn = rescache[i * width + j + 1].it
|
||||
- rescache[i * width + j + 1].rit;
|
||||
lyrn = rescache[(i + 1) * width + j].it
|
||||
- rescache[(i + 1) * width + j].rit;
|
||||
lx = -sec_h * (lxrn - it + rit);
|
||||
ly = sec_w * (lyrn - it + rit);
|
||||
lz = sec_w * sec_h;
|
||||
l = sqrtl(lx * lx + ly * ly + lz * lz);
|
||||
light = (light_x * lx + light_y * ly
|
||||
+ light_z * lz) / l;
|
||||
ritnum += light * light_intensity;
|
||||
}
|
||||
idx = (long long)ritnum
|
||||
+ 1000000 * palette_size + displacement;
|
||||
color = palette[idx % palette_size
|
||||
+ (idx < 0 ? palette_size : 0)];
|
||||
}
|
||||
|
||||
pnmout_pixel(stdout, color);
|
||||
}
|
||||
}
|
||||
|
||||
free(rescache);
|
||||
free(palette);
|
||||
|
||||
return !(fflush(stdout) == 0);
|
||||
}
|
131
palette.c
Normal file
131
palette.c
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* fractal
|
||||
* Written in 2020 by Lucas
|
||||
* CC0 1.0 Universal/Public domain - No rights reserved
|
||||
*
|
||||
* To the extent possible under law, the author(s) have dedicated all
|
||||
* copyright and related and neighboring rights to this software to the
|
||||
* public domain worldwide. This software is distributed without any
|
||||
* warranty. You should have received a copy of the CC0 Public Domain
|
||||
* Dedication along with this software. If not, see
|
||||
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "palette.h"
|
||||
#include "pnmout.h"
|
||||
#include "util.h"
|
||||
|
||||
#define CLAMP(x, a, b) ((x) < (a) ? (a) : (x) > (b) ? (b) : (x))
|
||||
|
||||
static double
|
||||
bezier3(double t, double p0, double p1, double p2, double p3)
|
||||
{
|
||||
double u = 1.0 - t;
|
||||
return u * u * u * p0
|
||||
+ 3.0 * u * u * t * p1
|
||||
+ 3.0 * u * t * t * p2
|
||||
+ t * t * t * p3;
|
||||
}
|
||||
|
||||
static double
|
||||
bezier4(double t, double p0, double p1, double p2, double p3)
|
||||
{
|
||||
return (1.0 - t) * bezier3(t, p0, p1, p2, p3)
|
||||
+ t * bezier3(t, p1, p2, p3, p0);
|
||||
}
|
||||
|
||||
struct color *
|
||||
palette_gen(size_t n)
|
||||
{
|
||||
struct color *palette;
|
||||
double p[12] = {
|
||||
drand48(), drand48(), drand48(),
|
||||
drand48(), drand48(), drand48(),
|
||||
drand48(), drand48(), drand48(),
|
||||
drand48(), drand48(), drand48(),
|
||||
};
|
||||
double r, g, b, t;
|
||||
size_t i;
|
||||
|
||||
if (!(palette = malloc(n * sizeof(*palette)))) {
|
||||
fprintf(stderr, "out of memory");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
t = i / (double)n;
|
||||
r = bezier4(t, p[0], p[3], p[6], p[9]);
|
||||
g = bezier4(t, p[1], p[4], p[7], p[10]);
|
||||
b = bezier4(t, p[2], p[5], p[8], p[11]);
|
||||
palette[i].r = 65535.0 * CLAMP(r, 0.0, 1.0);
|
||||
palette[i].g = 65535.0 * CLAMP(g, 0.0, 1.0);
|
||||
palette[i].b = 65535.0 * CLAMP(b, 0.0, 1.0);
|
||||
}
|
||||
|
||||
return palette;
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s palette [-h height] [-w width]\n",
|
||||
xgetprogname());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
palette_main(int argc, char *argv[])
|
||||
{
|
||||
struct color *palette;
|
||||
char *end;
|
||||
uintmax_t v;
|
||||
unsigned int width, height;
|
||||
int ch, i, j;
|
||||
|
||||
height = 100;
|
||||
width = 720;
|
||||
while ((ch = getopt(argc, argv, "h:w:")) != -1)
|
||||
switch (ch) {
|
||||
case 'h':
|
||||
errno = 0;
|
||||
v = strtoumax(optarg, &end, 0);
|
||||
if (*end != '\0' || errno != 0 || v == 0
|
||||
|| v > UINT_MAX) {
|
||||
fprintf(stderr, "-h: Invalid value \"%s\"",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
height = v;
|
||||
case 'w':
|
||||
errno = 0;
|
||||
v = strtoumax(optarg, &end, 0);
|
||||
if (*end != '\0' || errno != 0 || v == 0
|
||||
|| v > UINT_MAX) {
|
||||
fprintf(stderr, "-w: Invalid value \"%s\"",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
width = v;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc > 1)
|
||||
usage();
|
||||
|
||||
palette = palette_gen(width);
|
||||
pnmout_header(stdout, width, height);
|
||||
for (i = 0; i < height; i++)
|
||||
for (j = 0; j < width; j++)
|
||||
pnmout_pixel(stdout, palette[j]);
|
||||
free(palette);
|
||||
|
||||
return !(fflush(stdout) == 0);
|
||||
}
|
21
palette.h
Normal file
21
palette.h
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* fractal
|
||||
* Written in 2020 by Lucas
|
||||
* CC0 1.0 Universal/Public domain - No rights reserved
|
||||
*
|
||||
* To the extent possible under law, the author(s) have dedicated all
|
||||
* copyright and related and neighboring rights to this software to the
|
||||
* public domain worldwide. This software is distributed without any
|
||||
* warranty. You should have received a copy of the CC0 Public Domain
|
||||
* Dedication along with this software. If not, see
|
||||
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct color {
|
||||
uint16_t r, g, b;
|
||||
};
|
||||
|
||||
struct color * palette_gen(size_t);
|
||||
int palette_main(int, char *[]);
|
40
pnmout.c
Normal file
40
pnmout.c
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* fractal
|
||||
* Written in 2020 by Lucas
|
||||
* CC0 1.0 Universal/Public domain - No rights reserved
|
||||
*
|
||||
* To the extent possible under law, the author(s) have dedicated all
|
||||
* copyright and related and neighboring rights to this software to the
|
||||
* public domain worldwide. This software is distributed without any
|
||||
* warranty. You should have received a copy of the CC0 Public Domain
|
||||
* Dedication along with this software. If not, see
|
||||
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "palette.h"
|
||||
#include "pnmout.h"
|
||||
|
||||
void
|
||||
pnmout_header(FILE *fp, unsigned int width, unsigned int height)
|
||||
{
|
||||
if (fprintf(fp, "P6\n%u %u 255\n", width, height) < 0) {
|
||||
perror("fprintf");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pnmout_pixel(FILE *fp, struct color c)
|
||||
{
|
||||
uint8_t v[3];
|
||||
v[0] = c.r / 256;
|
||||
v[1] = c.g / 256;
|
||||
v[2] = c.b / 256;
|
||||
if (fwrite(v, sizeof(v[0]), sizeof(v) / sizeof(v[0]), fp) != 3) {
|
||||
perror("fwrite");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
16
pnmout.h
Normal file
16
pnmout.h
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* fractal
|
||||
* Written in 2020 by Lucas
|
||||
* CC0 1.0 Universal/Public domain - No rights reserved
|
||||
*
|
||||
* To the extent possible under law, the author(s) have dedicated all
|
||||
* copyright and related and neighboring rights to this software to the
|
||||
* public domain worldwide. This software is distributed without any
|
||||
* warranty. You should have received a copy of the CC0 Public Domain
|
||||
* Dedication along with this software. If not, see
|
||||
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
void pnmout_header(FILE *, unsigned int, unsigned int);
|
||||
void pnmout_pixel(FILE *, struct color);
|
34
util.c
Normal file
34
util.c
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* fractal
|
||||
* Written in 2020 by Lucas
|
||||
* CC0 1.0 Universal/Public domain - No rights reserved
|
||||
*
|
||||
* To the extent possible under law, the author(s) have dedicated all
|
||||
* copyright and related and neighboring rights to this software to the
|
||||
* public domain worldwide. This software is distributed without any
|
||||
* warranty. You should have received a copy of the CC0 Public Domain
|
||||
* Dedication along with this software. If not, see
|
||||
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
|
||||
const char *
|
||||
xgetprogname(void)
|
||||
{
|
||||
#if defined(__OpenBSD__)
|
||||
return getprogname();
|
||||
#else
|
||||
extern char *__progname;
|
||||
return __progname;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
xsrand48(long seed)
|
||||
{
|
||||
#if defined(__OpenBSD__)
|
||||
srand48_deterministic(seed);
|
||||
#else
|
||||
srand48(seed);
|
||||
#endif
|
||||
}
|
16
util.h
Normal file
16
util.h
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* fractal
|
||||
* Written in 2020 by Lucas
|
||||
* CC0 1.0 Universal/Public domain - No rights reserved
|
||||
*
|
||||
* To the extent possible under law, the author(s) have dedicated all
|
||||
* copyright and related and neighboring rights to this software to the
|
||||
* public domain worldwide. This software is distributed without any
|
||||
* warranty. You should have received a copy of the CC0 Public Domain
|
||||
* Dedication along with this software. If not, see
|
||||
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
#define nelems(_a) (sizeof((_a)) / sizeof((_a)[0]))
|
||||
|
||||
const char * xgetprogname(void);
|
||||
void xsrand48(long);
|
Loading…
Reference in New Issue
Block a user