From 705f8dee50e2073a3aba60b03e5c9b86672abd4c Mon Sep 17 00:00:00 2001 From: "B. Bogart" Date: Tue, 30 Sep 2003 16:04:40 +0000 Subject: Opps - forgot to add the files that did not exist in chaosI! svn path=/trunk/externals/bbogart/chaos/; revision=1052 --- attract1.c | 369 ++++++++++++++++++++++++++++ base.c | 269 +++++++++++++++++++++ base3.c | 269 +++++++++++++++++++++ dejong.c | 325 +++++++++++++++++++++++++ gingerbreadman.c | 101 ++++++++ hopalong.c | 303 +++++++++++++++++++++++ latoocarfian.c | 325 +++++++++++++++++++++++++ latoomutalpha.c | 325 +++++++++++++++++++++++++ latoomutbeta.c | 325 +++++++++++++++++++++++++ latoomutgamma.c | 325 +++++++++++++++++++++++++ mlogistic.c | 247 +++++++++++++++++++ pickover.c | 335 ++++++++++++++++++++++++++ popcorn.c | 259 ++++++++++++++++++++ quadruptwo.c | 303 +++++++++++++++++++++++ standardmap.c | 259 ++++++++++++++++++++ strange1.c | 501 +++++++++++++++++++++++++++++++++++++++ tent.c | 247 +++++++++++++++++++ three_d.c | 357 ++++++++++++++++++++++++++++ threeply.c | 303 +++++++++++++++++++++++ tinkerbell.c | 325 +++++++++++++++++++++++++ tools/fractal-tools.pd | 27 +++ tools/help-attract1.pd | 35 +++ tools/help-base.pd | 28 +++ tools/help-gingerbreadman.pd | 31 +++ tools/help-henon.pd | 30 +++ tools/help-hopalong.pd | 32 +++ tools/help-ikeda.pd | 33 +++ tools/help-latoocarfian.pd | 35 +++ tools/help-latoomutalpha.pd | 35 +++ tools/help-latoomutbeta.pd | 35 +++ tools/help-latoomutgamma.pd | 35 +++ tools/help-lorenz.pd | 32 +++ tools/help-martin-test.pd | 92 +++++++ tools/help-martin.pd | 38 +++ tools/help-popcorn-test.pd | 62 +++++ tools/help-popcorn.pd | 35 +++ tools/help-quaruptwo-test.pd | 69 ++++++ tools/help-quaruptwo.pd | 32 +++ tools/help-standardmap.pd | 32 +++ tools/loop.pd | 43 ++++ tools/readme-frac-format.pd | 22 ++ tools/readme-fractals.pd | 54 +++++ tools/readme-gen-fractal.pd | 6 + tools/readme-lyapunov.pd | 16 ++ tools/readme-operation.pd | 34 +++ tools/readme-parameter-ranges.pd | 23 ++ tools/readme-searching.pd | 101 ++++++++ tools/search-tools.pd | 186 +++++++++++++++ unity.c | 102 ++++++++ 49 files changed, 7407 insertions(+) create mode 100644 attract1.c create mode 100644 base.c create mode 100644 base3.c create mode 100644 dejong.c create mode 100644 gingerbreadman.c create mode 100644 hopalong.c create mode 100644 latoocarfian.c create mode 100644 latoomutalpha.c create mode 100644 latoomutbeta.c create mode 100644 latoomutgamma.c create mode 100644 mlogistic.c create mode 100644 pickover.c create mode 100644 popcorn.c create mode 100644 quadruptwo.c create mode 100644 standardmap.c create mode 100644 strange1.c create mode 100644 tent.c create mode 100644 three_d.c create mode 100644 threeply.c create mode 100644 tinkerbell.c create mode 100644 tools/fractal-tools.pd create mode 100644 tools/help-attract1.pd create mode 100644 tools/help-base.pd create mode 100644 tools/help-gingerbreadman.pd create mode 100644 tools/help-henon.pd create mode 100644 tools/help-hopalong.pd create mode 100644 tools/help-ikeda.pd create mode 100644 tools/help-latoocarfian.pd create mode 100644 tools/help-latoomutalpha.pd create mode 100644 tools/help-latoomutbeta.pd create mode 100644 tools/help-latoomutgamma.pd create mode 100644 tools/help-lorenz.pd create mode 100644 tools/help-martin-test.pd create mode 100644 tools/help-martin.pd create mode 100644 tools/help-popcorn-test.pd create mode 100644 tools/help-popcorn.pd create mode 100644 tools/help-quaruptwo-test.pd create mode 100644 tools/help-quaruptwo.pd create mode 100644 tools/help-standardmap.pd create mode 100644 tools/loop.pd create mode 100644 tools/readme-frac-format.pd create mode 100644 tools/readme-fractals.pd create mode 100644 tools/readme-gen-fractal.pd create mode 100644 tools/readme-lyapunov.pd create mode 100644 tools/readme-operation.pd create mode 100644 tools/readme-parameter-ranges.pd create mode 100644 tools/readme-searching.pd create mode 100644 tools/search-tools.pd create mode 100644 unity.c diff --git a/attract1.c b/attract1.c new file mode 100644 index 0000000..dc1f4c1 --- /dev/null +++ b/attract1.c @@ -0,0 +1,369 @@ +/* attract1 Attractor PD External */ +/* Copyright Michael McGonagle, from 'attract.java' by Julian Sprott, 2003 */ +/* This program is distributed under the params of the GNU Public License */ + +/////////////////////////////////////////////////////////////////////////////////// +/* This file is part of Chaos PD Externals. */ +/* */ +/* Chaos PD Externals are free software; you can redistribute them and/or modify */ +/* them under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Chaos PD Externals are distributed in the hope that they will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with the Chaos PD Externals; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "lyapunov.h" + +#define M_a0_lo -3 +#define M_a0_hi 3 +#define M_a1_lo -3 +#define M_a1_hi 3 +#define M_a2_lo -3 +#define M_a2_hi 3 +#define M_a3_lo -3 +#define M_a3_hi 3 +#define M_a4_lo -3 +#define M_a4_hi 3 +#define M_a5_lo -3 +#define M_a5_hi 3 + +#define M_a0 0 +#define M_a1 1 +#define M_a2 2 +#define M_a3 3 +#define M_a4 4 +#define M_a5 5 + +#define M_x 0 +#define M_y 1 + +#define M_param_count 6 +#define M_var_count 2 +#define M_search_count 3 +#define M_failure_limit 1000 + +static char *version = "attract1 v0.0, by Michael McGonagle, from 'attract.java' by Julian Sprott, 2003"; + +t_class *attract1_class; + +typedef struct attract1_struct { + t_object x_obj; + + double vars[M_var_count]; + double vars_init[M_var_count]; + t_atom vars_out[M_var_count]; + t_outlet *vars_outlet; + + t_atom search_out[M_search_count]; + t_outlet *search_outlet; + + double a0, a0_lo, a0_hi, a1, a1_lo, a1_hi, a2, a2_lo, a2_hi, a3, a3_lo, a3_hi, a4, a4_lo, a4_hi, a5, a5_lo, a5_hi; + t_atom params_out[M_param_count]; + t_outlet *params_outlet; + double lyap_exp, lyap_lo, lyap_hi, lyap_limit, failure_ratio; + + t_outlet *outlets[M_var_count - 1]; +} attract1_struct; + +static void calc(attract1_struct *attract1, double *vars) { + double x_0, y_0; + x_0 =attract1 -> a0+vars[M_x]*(attract1 -> a1+attract1 -> a2*vars[M_x]+attract1 -> a3*vars[M_y])+vars[M_y]*(attract1 -> a4+attract1 -> a5*vars[M_y]); + y_0 =vars[M_x]; + vars[M_x] = x_0; + vars[M_y] = y_0; +} // end calc + +static void calculate(attract1_struct *attract1) { + calc(attract1, attract1 -> vars); + outlet_float(attract1 -> x_obj.ob_outlet, attract1 -> vars[M_x]); + outlet_float(attract1 -> outlets[M_y - 1], attract1 -> vars[M_y]); +} // end calculate + +static void reset(attract1_struct *attract1, t_symbol *s, int argc, t_atom *argv) { + if (argc == M_var_count) { + attract1 -> vars[M_x] = (double) atom_getfloatarg(M_x, argc, argv); + attract1 -> vars[M_y] = (double) atom_getfloatarg(M_y, argc, argv); + } else { + attract1 -> vars[M_x] = attract1 -> vars_init[M_x]; + attract1 -> vars[M_y] = attract1 -> vars_init[M_y]; + } // end if +} // end reset + +static char *classify(attract1_struct *attract1) { + static char buff[7]; + char *c = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + buff[0] = c[(int) (((attract1 -> a0 - M_a0_lo) * (1.0 / (M_a0_hi - M_a0_lo))) * 26)]; + buff[1] = c[(int) (((attract1 -> a1 - M_a1_lo) * (1.0 / (M_a1_hi - M_a1_lo))) * 26)]; + buff[2] = c[(int) (((attract1 -> a2 - M_a2_lo) * (1.0 / (M_a2_hi - M_a2_lo))) * 26)]; + buff[3] = c[(int) (((attract1 -> a3 - M_a3_lo) * (1.0 / (M_a3_hi - M_a3_lo))) * 26)]; + buff[4] = c[(int) (((attract1 -> a4 - M_a4_lo) * (1.0 / (M_a4_hi - M_a4_lo))) * 26)]; + buff[5] = c[(int) (((attract1 -> a5 - M_a5_lo) * (1.0 / (M_a5_hi - M_a5_lo))) * 26)]; + buff[6] = '\0'; + return buff; +} + +static void make_results(attract1_struct *attract1) { + SETFLOAT(&attract1 -> search_out[0], attract1 -> lyap_exp); + SETSYMBOL(&attract1 -> search_out[1], gensym(classify(attract1))); + SETFLOAT(&attract1 -> search_out[2], attract1 -> failure_ratio); + SETFLOAT(&attract1 -> vars_out[M_x], attract1 -> vars[M_x]); + SETFLOAT(&attract1 -> vars_out[M_y], attract1 -> vars[M_y]); + SETFLOAT(&attract1 -> params_out[M_a0], attract1 -> a0); + SETFLOAT(&attract1 -> params_out[M_a1], attract1 -> a1); + SETFLOAT(&attract1 -> params_out[M_a2], attract1 -> a2); + SETFLOAT(&attract1 -> params_out[M_a3], attract1 -> a3); + SETFLOAT(&attract1 -> params_out[M_a4], attract1 -> a4); + SETFLOAT(&attract1 -> params_out[M_a5], attract1 -> a5); + outlet_list(attract1 -> params_outlet, gensym("list"), M_param_count, attract1 -> params_out); + outlet_list(attract1 -> vars_outlet, gensym("list"), M_var_count, attract1 -> vars_out); +} + +static void show(attract1_struct *attract1) { + make_results(attract1); + outlet_anything(attract1 -> search_outlet, gensym("show"), M_search_count, attract1 -> search_out); +} + +static void param(attract1_struct *attract1, t_symbol *s, int argc, t_atom *argv) { + if (argc != 6) { + post("Incorrect number of arguments for attract1 fractal. Expecting 6 arguments."); + return; + } + attract1 -> a0 = (double) atom_getfloatarg(0, argc, argv); + attract1 -> a1 = (double) atom_getfloatarg(1, argc, argv); + attract1 -> a2 = (double) atom_getfloatarg(2, argc, argv); + attract1 -> a3 = (double) atom_getfloatarg(3, argc, argv); + attract1 -> a4 = (double) atom_getfloatarg(4, argc, argv); + attract1 -> a5 = (double) atom_getfloatarg(5, argc, argv); +} + +static void seed(attract1_struct *attract1, t_symbol *s, int argc, t_atom *argv) { + if (argc > 0) { + srand48(((unsigned int)time(0))|1); + } else { + srand48((unsigned int) atom_getfloatarg(0, argc, argv)); + } +} + +static void lyap(attract1_struct *attract1, t_floatarg l, t_floatarg h, t_floatarg lim) { + attract1 -> lyap_lo = l; + attract1 -> lyap_hi = h; + attract1 -> lyap_limit = (double) ((int) lim); +} + +static void elyap(attract1_struct *attract1) { + double results[M_var_count]; + int i; + if (lyapunov_full((void *) attract1, (t_gotfn) calc, M_var_count, attract1 -> vars, results) != NULL) { + post("elyapunov:"); + for(i = 0; i < M_var_count; i++) { post("%d: %3.80f", i, results[i]); } + } +} + +static void limiter(attract1_struct *attract1) { + if (attract1 -> a0_lo < M_a0_lo) { attract1 -> a0_lo = M_a0_lo; } + if (attract1 -> a0_lo > M_a0_hi) { attract1 -> a0_lo = M_a0_hi; } + if (attract1 -> a0_hi < M_a0_lo) { attract1 -> a0_hi = M_a0_lo; } + if (attract1 -> a0_hi > M_a0_hi) { attract1 -> a0_hi = M_a0_hi; } + if (attract1 -> a1_lo < M_a1_lo) { attract1 -> a1_lo = M_a1_lo; } + if (attract1 -> a1_lo > M_a1_hi) { attract1 -> a1_lo = M_a1_hi; } + if (attract1 -> a1_hi < M_a1_lo) { attract1 -> a1_hi = M_a1_lo; } + if (attract1 -> a1_hi > M_a1_hi) { attract1 -> a1_hi = M_a1_hi; } + if (attract1 -> a2_lo < M_a2_lo) { attract1 -> a2_lo = M_a2_lo; } + if (attract1 -> a2_lo > M_a2_hi) { attract1 -> a2_lo = M_a2_hi; } + if (attract1 -> a2_hi < M_a2_lo) { attract1 -> a2_hi = M_a2_lo; } + if (attract1 -> a2_hi > M_a2_hi) { attract1 -> a2_hi = M_a2_hi; } + if (attract1 -> a3_lo < M_a3_lo) { attract1 -> a3_lo = M_a3_lo; } + if (attract1 -> a3_lo > M_a3_hi) { attract1 -> a3_lo = M_a3_hi; } + if (attract1 -> a3_hi < M_a3_lo) { attract1 -> a3_hi = M_a3_lo; } + if (attract1 -> a3_hi > M_a3_hi) { attract1 -> a3_hi = M_a3_hi; } + if (attract1 -> a4_lo < M_a4_lo) { attract1 -> a4_lo = M_a4_lo; } + if (attract1 -> a4_lo > M_a4_hi) { attract1 -> a4_lo = M_a4_hi; } + if (attract1 -> a4_hi < M_a4_lo) { attract1 -> a4_hi = M_a4_lo; } + if (attract1 -> a4_hi > M_a4_hi) { attract1 -> a4_hi = M_a4_hi; } + if (attract1 -> a5_lo < M_a5_lo) { attract1 -> a5_lo = M_a5_lo; } + if (attract1 -> a5_lo > M_a5_hi) { attract1 -> a5_lo = M_a5_hi; } + if (attract1 -> a5_hi < M_a5_lo) { attract1 -> a5_hi = M_a5_lo; } + if (attract1 -> a5_hi > M_a5_hi) { attract1 -> a5_hi = M_a5_hi; } +} + +static void constrain(attract1_struct *attract1, t_symbol *s, int argc, t_atom *argv) { + int i; + t_atom *arg = argv; + if (argc == 0) { + // reset to full limits of search ranges + attract1 -> a0_lo = M_a0_lo; + attract1 -> a0_hi = M_a0_hi; + attract1 -> a1_lo = M_a1_lo; + attract1 -> a1_hi = M_a1_hi; + attract1 -> a2_lo = M_a2_lo; + attract1 -> a2_hi = M_a2_hi; + attract1 -> a3_lo = M_a3_lo; + attract1 -> a3_hi = M_a3_hi; + attract1 -> a4_lo = M_a4_lo; + attract1 -> a4_hi = M_a4_hi; + attract1 -> a5_lo = M_a5_lo; + attract1 -> a5_hi = M_a5_hi; + return; + } + if (argc == 1) { + // set the ranges based on percentage of full range + double percent = atom_getfloat(arg); + double a0_spread = ((M_a0_hi - M_a0_lo) * percent) / 2; + double a1_spread = ((M_a1_hi - M_a1_lo) * percent) / 2; + double a2_spread = ((M_a2_hi - M_a2_lo) * percent) / 2; + double a3_spread = ((M_a3_hi - M_a3_lo) * percent) / 2; + double a4_spread = ((M_a4_hi - M_a4_lo) * percent) / 2; + double a5_spread = ((M_a5_hi - M_a5_lo) * percent) / 2; + attract1 -> a0_lo = attract1 -> a0 - a0_spread; + attract1 -> a0_hi = attract1 -> a0 + a0_spread; + attract1 -> a1_lo = attract1 -> a1 - a1_spread; + attract1 -> a1_hi = attract1 -> a1 + a1_spread; + attract1 -> a2_lo = attract1 -> a2 - a2_spread; + attract1 -> a2_hi = attract1 -> a2 + a2_spread; + attract1 -> a3_lo = attract1 -> a3 - a3_spread; + attract1 -> a3_hi = attract1 -> a3 + a3_spread; + attract1 -> a4_lo = attract1 -> a4 - a4_spread; + attract1 -> a4_hi = attract1 -> a4 + a4_spread; + attract1 -> a5_lo = attract1 -> a5 - a5_spread; + attract1 -> a5_hi = attract1 -> a5 + a5_spread; + limiter(attract1); + return; + } + if (argc != M_param_count * 2) { + post("Invalid number of arguments for attract1 constraints, requires 12 values, got %d", argc); + return; + } + attract1 -> a0_lo = atom_getfloat(arg++); + attract1 -> a0_hi = atom_getfloat(arg++); + attract1 -> a1_lo = atom_getfloat(arg++); + attract1 -> a1_hi = atom_getfloat(arg++); + attract1 -> a2_lo = atom_getfloat(arg++); + attract1 -> a2_hi = atom_getfloat(arg++); + attract1 -> a3_lo = atom_getfloat(arg++); + attract1 -> a3_hi = atom_getfloat(arg++); + attract1 -> a4_lo = atom_getfloat(arg++); + attract1 -> a4_hi = atom_getfloat(arg++); + attract1 -> a5_lo = atom_getfloat(arg++); + attract1 -> a5_hi = atom_getfloat(arg++); + limiter(attract1); +} + +static void search(attract1_struct *attract1, t_symbol *s, int argc, t_atom *argv) { + int not_found, not_expired = attract1 -> lyap_limit; + int jump, i, iterations; + t_atom vars[M_var_count]; + double temp_a0 = attract1 -> a0; + double temp_a1 = attract1 -> a1; + double temp_a2 = attract1 -> a2; + double temp_a3 = attract1 -> a3; + double temp_a4 = attract1 -> a4; + double temp_a5 = attract1 -> a5; + if (argc > 0) { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], atom_getfloatarg(i, argc, argv)); + } + } else { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], attract1 -> vars_init[i]); + } + } + do { + jump = 500; + not_found = 0; + iterations = 10000; + bad_params: + attract1 -> a0 = (drand48() * (attract1 -> a0_hi - attract1 -> a0_lo)) + attract1 -> a0_lo; + attract1 -> a1 = (drand48() * (attract1 -> a1_hi - attract1 -> a1_lo)) + attract1 -> a1_lo; + attract1 -> a2 = (drand48() * (attract1 -> a2_hi - attract1 -> a2_lo)) + attract1 -> a2_lo; + attract1 -> a3 = (drand48() * (attract1 -> a3_hi - attract1 -> a3_lo)) + attract1 -> a3_lo; + attract1 -> a4 = (drand48() * (attract1 -> a4_hi - attract1 -> a4_lo)) + attract1 -> a4_lo; + attract1 -> a5 = (drand48() * (attract1 -> a5_hi - attract1 -> a5_lo)) + attract1 -> a5_lo; + // put any preliminary checks specific to this fractal to eliminate bad_params + + reset(attract1, NULL, argc, vars); + do { calc(attract1, attract1 -> vars); } while(jump--); + attract1 -> lyap_exp = lyapunov((void *) attract1, (t_gotfn) calc, M_var_count, (double *) attract1 -> vars); + if (isnan(attract1 -> lyap_exp)) { not_found = 1; } + if (attract1 -> lyap_exp < attract1 -> lyap_lo || attract1 -> lyap_exp > attract1 -> lyap_hi) { not_found = 1; } + not_expired--; + } while(not_found && not_expired); + reset(attract1, NULL, argc, vars); + if (!not_expired) { + post("Could not find a fractal after %d attempts.", (int) attract1 -> lyap_limit); + post("Try using wider constraints."); + attract1 -> a0 = temp_a0; + attract1 -> a1 = temp_a1; + attract1 -> a2 = temp_a2; + attract1 -> a3 = temp_a3; + attract1 -> a4 = temp_a4; + attract1 -> a5 = temp_a5; + outlet_anything(attract1 -> search_outlet, gensym("invalid"), 0, NULL); + } else { + attract1 -> failure_ratio = (attract1 -> lyap_limit - not_expired) / attract1 -> lyap_limit; + make_results(attract1); + outlet_anything(attract1 -> search_outlet, gensym("search"), M_search_count, attract1 -> search_out); + } +} + +void *attract1_new(t_symbol *s, int argc, t_atom *argv) { + attract1_struct *attract1 = (attract1_struct *) pd_new(attract1_class); + if (attract1 != NULL) { + outlet_new(&attract1 -> x_obj, &s_float); + attract1 -> outlets[0] = outlet_new(&attract1 -> x_obj, &s_float); + attract1 -> search_outlet = outlet_new(&attract1 -> x_obj, &s_list); + attract1 -> vars_outlet = outlet_new(&attract1 -> x_obj, &s_list); + attract1 -> params_outlet = outlet_new(&attract1 -> x_obj, &s_list); + if (argc == M_param_count + M_var_count) { + attract1 -> vars_init[M_x] = attract1 -> vars[M_x] = (double) atom_getfloatarg(0, argc, argv); + attract1 -> vars_init[M_y] = attract1 -> vars[M_y] = (double) atom_getfloatarg(1, argc, argv); + attract1 -> a0 = (double) atom_getfloatarg(2, argc, argv); + attract1 -> a1 = (double) atom_getfloatarg(3, argc, argv); + attract1 -> a2 = (double) atom_getfloatarg(4, argc, argv); + attract1 -> a3 = (double) atom_getfloatarg(5, argc, argv); + attract1 -> a4 = (double) atom_getfloatarg(6, argc, argv); + attract1 -> a5 = (double) atom_getfloatarg(7, argc, argv); + } else { + if (argc != 0 && argc != M_param_count + M_var_count) { + post("Incorrect number of arguments for attract1 fractal. Expecting 8 arguments."); + } + attract1 -> vars_init[M_x] = 0; + attract1 -> vars_init[M_y] = 0; + attract1 -> a0 = 1; + attract1 -> a1 = 1; + attract1 -> a2 = 1; + attract1 -> a3 = 1; + attract1 -> a4 = 1; + attract1 -> a5 = 1; + } + constrain(attract1, NULL, 0, NULL); + lyap(attract1, -1000000.0, 1000000.0, M_failure_limit); + } + return (void *)attract1; +} + +void attract1_setup(void) { + attract1_class = class_new(gensym("attract1"), (t_newmethod) attract1_new, 0, sizeof(attract1_struct), 0, A_GIMME, 0); + class_addbang(attract1_class, (t_method) calculate); + class_addmethod(attract1_class, (t_method) reset, gensym("reset"), A_GIMME, 0); + class_addmethod(attract1_class, (t_method) show, gensym("show"), 0); + class_addmethod(attract1_class, (t_method) param, gensym("param"), A_GIMME, 0); + class_addmethod(attract1_class, (t_method) seed, gensym("seed"), A_GIMME, 0); + class_addmethod(attract1_class, (t_method) lyap, gensym("lyapunov"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(attract1_class, (t_method) elyap, gensym("elyapunov"), 0); + class_addmethod(attract1_class, (t_method) search, gensym("search"), A_GIMME, 0); + class_addmethod(attract1_class, (t_method) constrain, gensym("constrain"), A_GIMME, 0); + class_sethelpsymbol(attract1_class, gensym("help-attract1.pd")); +} + diff --git a/base.c b/base.c new file mode 100644 index 0000000..ffdcb9f --- /dev/null +++ b/base.c @@ -0,0 +1,269 @@ +/* base Attractor PD External */ +/* Copyright Michael McGonagle, 2003 */ +/* This program is distributed under the params of the GNU Public License */ + +/////////////////////////////////////////////////////////////////////////////////// +/* This file is part of Chaos PD Externals. */ +/* */ +/* Chaos PD Externals are free software; you can redistribute them and/or modify */ +/* them under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Chaos PD Externals are distributed in the hope that they will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with the Chaos PD Externals; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "lyapunov.h" + +#define M_a_lo 0 +#define M_a_hi 3 +#define M_b_lo 0.001 +#define M_b_hi 2.6667 + +#define M_a 0 +#define M_b 1 + +#define M_x 0 + +#define M_param_count 2 +#define M_var_count 1 +#define M_search_count 3 +#define M_failure_limit 1000 + +static char *version = "base v0.0, by Michael McGonagle, 2003"; + +t_class *base_class; + +typedef struct base_struct { + t_object x_obj; + + double vars[M_var_count]; + double vars_init[M_var_count]; + t_atom vars_out[M_var_count]; + t_outlet *vars_outlet; + + t_atom search_out[M_search_count]; + t_outlet *search_outlet; + + double a, a_lo, a_hi, b, b_lo, b_hi; + t_atom params_out[M_param_count]; + t_outlet *params_outlet; + double lyap_exp, lyap_lo, lyap_hi, lyap_limit, failure_ratio; +} base_struct; + +static void calc(base_struct *base, double *vars) { + double x_0; + x_0 =vars[M_x]+(base -> a*sin(pow(vars[M_x],base -> b))); + vars[M_x] = x_0; +} // end calc + +static void calculate(base_struct *base) { + calc(base, base -> vars); + outlet_float(base -> x_obj.ob_outlet, base -> vars[M_x]); +} // end calculate + +static void reset(base_struct *base, t_symbol *s, int argc, t_atom *argv) { + if (argc == M_var_count) { + base -> vars[M_x] = (double) atom_getfloatarg(M_x, argc, argv); + } else { + base -> vars[M_x] = base -> vars_init[M_x]; + } // end if +} // end reset + +static char *classify(base_struct *base) { + static char buff[3]; + char *c = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + buff[0] = c[(int) (((base -> a - M_a_lo) * (1.0 / (M_a_hi - M_a_lo))) * 26)]; + buff[1] = c[(int) (((base -> b - M_b_lo) * (1.0 / (M_b_hi - M_b_lo))) * 26)]; + buff[2] = '\0'; + return buff; +} + +static void make_results(base_struct *base) { + SETFLOAT(&base -> search_out[0], base -> lyap_exp); + SETSYMBOL(&base -> search_out[1], gensym(classify(base))); + SETFLOAT(&base -> search_out[2], base -> failure_ratio); + SETFLOAT(&base -> vars_out[M_x], base -> vars[M_x]); + SETFLOAT(&base -> params_out[M_a], base -> a); + SETFLOAT(&base -> params_out[M_b], base -> b); + outlet_list(base -> params_outlet, gensym("list"), M_param_count, base -> params_out); + outlet_list(base -> vars_outlet, gensym("list"), M_var_count, base -> vars_out); +} + +static void show(base_struct *base) { + make_results(base); + outlet_anything(base -> search_outlet, gensym("show"), M_search_count, base -> search_out); +} + +static void param(base_struct *base, t_symbol *s, int argc, t_atom *argv) { + if (argc != 2) { + post("Incorrect number of arguments for base fractal. Expecting 2 arguments."); + return; + } + base -> a = (double) atom_getfloatarg(0, argc, argv); + base -> b = (double) atom_getfloatarg(1, argc, argv); +} + +static void seed(base_struct *base, t_symbol *s, int argc, t_atom *argv) { + if (argc > 0) { + srand48(((unsigned int)time(0))|1); + } else { + srand48((unsigned int) atom_getfloatarg(0, argc, argv)); + } +} + +static void lyap(base_struct *base, t_floatarg l, t_floatarg h, t_floatarg lim) { + base -> lyap_lo = l; + base -> lyap_hi = h; + base -> lyap_limit = (double) ((int) lim); +} + +static void elyap(base_struct *base) { + double results[M_var_count]; + int i; + if (lyapunov_full((void *) base, (t_gotfn) calc, M_var_count, base -> vars, results) != NULL) { + post("elyapunov:"); + for(i = 0; i < M_var_count; i++) { post("%d: %3.80f", i, results[i]); } + } +} + +static void limiter(base_struct *base) { + if (base -> a_lo < M_a_lo) { base -> a_lo = M_a_lo; } + if (base -> a_lo > M_a_hi) { base -> a_lo = M_a_hi; } + if (base -> a_hi < M_a_lo) { base -> a_hi = M_a_lo; } + if (base -> a_hi > M_a_hi) { base -> a_hi = M_a_hi; } + if (base -> b_lo < M_b_lo) { base -> b_lo = M_b_lo; } + if (base -> b_lo > M_b_hi) { base -> b_lo = M_b_hi; } + if (base -> b_hi < M_b_lo) { base -> b_hi = M_b_lo; } + if (base -> b_hi > M_b_hi) { base -> b_hi = M_b_hi; } +} + +static void constrain(base_struct *base, t_symbol *s, int argc, t_atom *argv) { + int i; + t_atom *arg = argv; + if (argc == 0) { + // reset to full limits of search ranges + base -> a_lo = M_a_lo; + base -> a_hi = M_a_hi; + base -> b_lo = M_b_lo; + base -> b_hi = M_b_hi; + return; + } + if (argc == 1) { + // set the ranges based on percentage of full range + double percent = atom_getfloat(arg); + double a_spread = ((M_a_hi - M_a_lo) * percent) / 2; + double b_spread = ((M_b_hi - M_b_lo) * percent) / 2; + base -> a_lo = base -> a - a_spread; + base -> a_hi = base -> a + a_spread; + base -> b_lo = base -> b - b_spread; + base -> b_hi = base -> b + b_spread; + limiter(base); + return; + } + if (argc != M_param_count * 2) { + post("Invalid number of arguments for base constraints, requires 4 values, got %d", argc); + return; + } + base -> a_lo = atom_getfloat(arg++); + base -> a_hi = atom_getfloat(arg++); + base -> b_lo = atom_getfloat(arg++); + base -> b_hi = atom_getfloat(arg++); + limiter(base); +} + +static void search(base_struct *base, t_symbol *s, int argc, t_atom *argv) { + int not_found, not_expired = base -> lyap_limit; + int jump, i, iterations; + t_atom vars[M_var_count]; + double temp_a = base -> a; + double temp_b = base -> b; + if (argc > 0) { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], atom_getfloatarg(i, argc, argv)); + } + } else { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], base -> vars_init[i]); + } + } + do { + jump = 500; + not_found = 0; + iterations = 10000; + bad_params: + base -> a = (drand48() * (base -> a_hi - base -> a_lo)) + base -> a_lo; + base -> b = (drand48() * (base -> b_hi - base -> b_lo)) + base -> b_lo; + // put any preliminary checks specific to this fractal to eliminate bad_params + + reset(base, NULL, argc, vars); + do { calc(base, base -> vars); } while(jump--); + base -> lyap_exp = lyapunov((void *) base, (t_gotfn) calc, M_var_count, (double *) base -> vars); + if (isnan(base -> lyap_exp)) { not_found = 1; } + if (base -> lyap_exp < base -> lyap_lo || base -> lyap_exp > base -> lyap_hi) { not_found = 1; } + not_expired--; + } while(not_found && not_expired); + reset(base, NULL, argc, vars); + if (!not_expired) { + post("Could not find a fractal after %d attempts.", (int) base -> lyap_limit); + post("Try using wider constraints."); + base -> a = temp_a; + base -> b = temp_b; + outlet_anything(base -> search_outlet, gensym("invalid"), 0, NULL); + } else { + base -> failure_ratio = (base -> lyap_limit - not_expired) / base -> lyap_limit; + make_results(base); + outlet_anything(base -> search_outlet, gensym("search"), M_search_count, base -> search_out); + } +} + +void *base_new(t_symbol *s, int argc, t_atom *argv) { + base_struct *base = (base_struct *) pd_new(base_class); + if (base != NULL) { + outlet_new(&base -> x_obj, &s_float); + base -> search_outlet = outlet_new(&base -> x_obj, &s_list); + base -> vars_outlet = outlet_new(&base -> x_obj, &s_list); + base -> params_outlet = outlet_new(&base -> x_obj, &s_list); + if (argc == M_param_count + M_var_count) { + base -> vars_init[M_x] = base -> vars[M_x] = (double) atom_getfloatarg(0, argc, argv); + base -> a = (double) atom_getfloatarg(1, argc, argv); + base -> b = (double) atom_getfloatarg(2, argc, argv); + } else { + if (argc != 0 && argc != M_param_count + M_var_count) { + post("Incorrect number of arguments for base fractal. Expecting 3 arguments."); + } + base -> vars_init[M_x] = 0.1; + base -> a = 1; + base -> b = 1; + } + constrain(base, NULL, 0, NULL); + lyap(base, -1000000.0, 1000000.0, M_failure_limit); + } + return (void *)base; +} + +void base_setup(void) { + base_class = class_new(gensym("base"), (t_newmethod) base_new, 0, sizeof(base_struct), 0, A_GIMME, 0); + class_addbang(base_class, (t_method) calculate); + class_addmethod(base_class, (t_method) reset, gensym("reset"), A_GIMME, 0); + class_addmethod(base_class, (t_method) show, gensym("show"), 0); + class_addmethod(base_class, (t_method) param, gensym("param"), A_GIMME, 0); + class_addmethod(base_class, (t_method) seed, gensym("seed"), A_GIMME, 0); + class_addmethod(base_class, (t_method) lyap, gensym("lyapunov"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(base_class, (t_method) elyap, gensym("elyapunov"), 0); + class_addmethod(base_class, (t_method) search, gensym("search"), A_GIMME, 0); + class_addmethod(base_class, (t_method) constrain, gensym("constrain"), A_GIMME, 0); + class_sethelpsymbol(base_class, gensym("help-base.pd")); +} + diff --git a/base3.c b/base3.c new file mode 100644 index 0000000..24f5a5e --- /dev/null +++ b/base3.c @@ -0,0 +1,269 @@ +/* base3 Attractor PD External */ +/* Copyright Michael McGonagle, 2003 */ +/* This program is distributed under the params of the GNU Public License */ + +/////////////////////////////////////////////////////////////////////////////////// +/* This file is part of Chaos PD Externals. */ +/* */ +/* Chaos PD Externals are free software; you can redistribute them and/or modify */ +/* them under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Chaos PD Externals are distributed in the hope that they will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with the Chaos PD Externals; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "lyapunov.h" + +#define M_a_lo 0 +#define M_a_hi 3 +#define M_b_lo 0.001 +#define M_b_hi 2.6667 + +#define M_a 0 +#define M_b 1 + +#define M_x 0 + +#define M_param_count 2 +#define M_var_count 1 +#define M_search_count 3 +#define M_failure_limit 1000 + +static char *version = "base3 v0.0, by Michael McGonagle, 2003"; + +t_class *base3_class; + +typedef struct base3_struct { + t_object x_obj; + + double vars[M_var_count]; + double vars_init[M_var_count]; + t_atom vars_out[M_var_count]; + t_outlet *vars_outlet; + + t_atom search_out[M_search_count]; + t_outlet *search_outlet; + + double a, a_lo, a_hi, b, b_lo, b_hi; + t_atom params_out[M_param_count]; + t_outlet *params_outlet; + double lyap_exp, lyap_lo, lyap_hi, lyap_limit, failure_ratio; +} base3_struct; + +static void calc(base3_struct *base3, double *vars) { + double x_0; + x_0 =base3 -> a*sin(pow(vars[M_x],base3 -> b)); + vars[M_x] = x_0; +} // end calc + +static void calculate(base3_struct *base3) { + calc(base3, base3 -> vars); + outlet_float(base3 -> x_obj.ob_outlet, base3 -> vars[M_x]); +} // end calculate + +static void reset(base3_struct *base3, t_symbol *s, int argc, t_atom *argv) { + if (argc == M_var_count) { + base3 -> vars[M_x] = (double) atom_getfloatarg(M_x, argc, argv); + } else { + base3 -> vars[M_x] = base3 -> vars_init[M_x]; + } // end if +} // end reset + +static char *classify(base3_struct *base3) { + static char buff[3]; + char *c = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + buff[0] = c[(int) (((base3 -> a - M_a_lo) * (1.0 / (M_a_hi - M_a_lo))) * 26)]; + buff[1] = c[(int) (((base3 -> b - M_b_lo) * (1.0 / (M_b_hi - M_b_lo))) * 26)]; + buff[2] = '\0'; + return buff; +} + +static void make_results(base3_struct *base3) { + SETFLOAT(&base3 -> search_out[0], base3 -> lyap_exp); + SETSYMBOL(&base3 -> search_out[1], gensym(classify(base3))); + SETFLOAT(&base3 -> search_out[2], base3 -> failure_ratio); + SETFLOAT(&base3 -> vars_out[M_x], base3 -> vars[M_x]); + SETFLOAT(&base3 -> params_out[M_a], base3 -> a); + SETFLOAT(&base3 -> params_out[M_b], base3 -> b); + outlet_list(base3 -> params_outlet, gensym("list"), M_param_count, base3 -> params_out); + outlet_list(base3 -> vars_outlet, gensym("list"), M_var_count, base3 -> vars_out); +} + +static void show(base3_struct *base3) { + make_results(base3); + outlet_anything(base3 -> search_outlet, gensym("show"), M_search_count, base3 -> search_out); +} + +static void param(base3_struct *base3, t_symbol *s, int argc, t_atom *argv) { + if (argc != 2) { + post("Incorrect number of arguments for base3 fractal. Expecting 2 arguments."); + return; + } + base3 -> a = (double) atom_getfloatarg(0, argc, argv); + base3 -> b = (double) atom_getfloatarg(1, argc, argv); +} + +static void seed(base3_struct *base3, t_symbol *s, int argc, t_atom *argv) { + if (argc > 0) { + srand48(((unsigned int)time(0))|1); + } else { + srand48((unsigned int) atom_getfloatarg(0, argc, argv)); + } +} + +static void lyap(base3_struct *base3, t_floatarg l, t_floatarg h, t_floatarg lim) { + base3 -> lyap_lo = l; + base3 -> lyap_hi = h; + base3 -> lyap_limit = (double) ((int) lim); +} + +static void elyap(base3_struct *base3) { + double results[M_var_count]; + int i; + if (lyapunov_full((void *) base3, (t_gotfn) calc, M_var_count, base3 -> vars, results) != NULL) { + post("elyapunov:"); + for(i = 0; i < M_var_count; i++) { post("%d: %3.80f", i, results[i]); } + } +} + +static void limiter(base3_struct *base3) { + if (base3 -> a_lo < M_a_lo) { base3 -> a_lo = M_a_lo; } + if (base3 -> a_lo > M_a_hi) { base3 -> a_lo = M_a_hi; } + if (base3 -> a_hi < M_a_lo) { base3 -> a_hi = M_a_lo; } + if (base3 -> a_hi > M_a_hi) { base3 -> a_hi = M_a_hi; } + if (base3 -> b_lo < M_b_lo) { base3 -> b_lo = M_b_lo; } + if (base3 -> b_lo > M_b_hi) { base3 -> b_lo = M_b_hi; } + if (base3 -> b_hi < M_b_lo) { base3 -> b_hi = M_b_lo; } + if (base3 -> b_hi > M_b_hi) { base3 -> b_hi = M_b_hi; } +} + +static void constrain(base3_struct *base3, t_symbol *s, int argc, t_atom *argv) { + int i; + t_atom *arg = argv; + if (argc == 0) { + // reset to full limits of search ranges + base3 -> a_lo = M_a_lo; + base3 -> a_hi = M_a_hi; + base3 -> b_lo = M_b_lo; + base3 -> b_hi = M_b_hi; + return; + } + if (argc == 1) { + // set the ranges based on percentage of full range + double percent = atom_getfloat(arg); + double a_spread = ((M_a_hi - M_a_lo) * percent) / 2; + double b_spread = ((M_b_hi - M_b_lo) * percent) / 2; + base3 -> a_lo = base3 -> a - a_spread; + base3 -> a_hi = base3 -> a + a_spread; + base3 -> b_lo = base3 -> b - b_spread; + base3 -> b_hi = base3 -> b + b_spread; + limiter(base3); + return; + } + if (argc != M_param_count * 2) { + post("Invalid number of arguments for base3 constraints, requires 4 values, got %d", argc); + return; + } + base3 -> a_lo = atom_getfloat(arg++); + base3 -> a_hi = atom_getfloat(arg++); + base3 -> b_lo = atom_getfloat(arg++); + base3 -> b_hi = atom_getfloat(arg++); + limiter(base3); +} + +static void search(base3_struct *base3, t_symbol *s, int argc, t_atom *argv) { + int not_found, not_expired = base3 -> lyap_limit; + int jump, i, iterations; + t_atom vars[M_var_count]; + double temp_a = base3 -> a; + double temp_b = base3 -> b; + if (argc > 0) { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], atom_getfloatarg(i, argc, argv)); + } + } else { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], base3 -> vars_init[i]); + } + } + do { + jump = 500; + not_found = 0; + iterations = 10000; + bad_params: + base3 -> a = (drand48() * (base3 -> a_hi - base3 -> a_lo)) + base3 -> a_lo; + base3 -> b = (drand48() * (base3 -> b_hi - base3 -> b_lo)) + base3 -> b_lo; + // put any preliminary checks specific to this fractal to eliminate bad_params + + reset(base3, NULL, argc, vars); + do { calc(base3, base3 -> vars); } while(jump--); + base3 -> lyap_exp = lyapunov((void *) base3, (t_gotfn) calc, M_var_count, (double *) base3 -> vars); + if (isnan(base3 -> lyap_exp)) { not_found = 1; } + if (base3 -> lyap_exp < base3 -> lyap_lo || base3 -> lyap_exp > base3 -> lyap_hi) { not_found = 1; } + not_expired--; + } while(not_found && not_expired); + reset(base3, NULL, argc, vars); + if (!not_expired) { + post("Could not find a fractal after %d attempts.", (int) base3 -> lyap_limit); + post("Try using wider constraints."); + base3 -> a = temp_a; + base3 -> b = temp_b; + outlet_anything(base3 -> search_outlet, gensym("invalid"), 0, NULL); + } else { + base3 -> failure_ratio = (base3 -> lyap_limit - not_expired) / base3 -> lyap_limit; + make_results(base3); + outlet_anything(base3 -> search_outlet, gensym("search"), M_search_count, base3 -> search_out); + } +} + +void *base3_new(t_symbol *s, int argc, t_atom *argv) { + base3_struct *base3 = (base3_struct *) pd_new(base3_class); + if (base3 != NULL) { + outlet_new(&base3 -> x_obj, &s_float); + base3 -> search_outlet = outlet_new(&base3 -> x_obj, &s_list); + base3 -> vars_outlet = outlet_new(&base3 -> x_obj, &s_list); + base3 -> params_outlet = outlet_new(&base3 -> x_obj, &s_list); + if (argc == M_param_count + M_var_count) { + base3 -> vars_init[M_x] = base3 -> vars[M_x] = (double) atom_getfloatarg(0, argc, argv); + base3 -> a = (double) atom_getfloatarg(1, argc, argv); + base3 -> b = (double) atom_getfloatarg(2, argc, argv); + } else { + if (argc != 0 && argc != M_param_count + M_var_count) { + post("Incorrect number of arguments for base3 fractal. Expecting 3 arguments."); + } + base3 -> vars_init[M_x] = 0.1; + base3 -> a = 1; + base3 -> b = 1; + } + constrain(base3, NULL, 0, NULL); + lyap(base3, -1000000.0, 1000000.0, M_failure_limit); + } + return (void *)base3; +} + +void base3_setup(void) { + base3_class = class_new(gensym("base3"), (t_newmethod) base3_new, 0, sizeof(base3_struct), 0, A_GIMME, 0); + class_addbang(base3_class, (t_method) calculate); + class_addmethod(base3_class, (t_method) reset, gensym("reset"), A_GIMME, 0); + class_addmethod(base3_class, (t_method) show, gensym("show"), 0); + class_addmethod(base3_class, (t_method) param, gensym("param"), A_GIMME, 0); + class_addmethod(base3_class, (t_method) seed, gensym("seed"), A_GIMME, 0); + class_addmethod(base3_class, (t_method) lyap, gensym("lyapunov"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(base3_class, (t_method) elyap, gensym("elyapunov"), 0); + class_addmethod(base3_class, (t_method) search, gensym("search"), A_GIMME, 0); + class_addmethod(base3_class, (t_method) constrain, gensym("constrain"), A_GIMME, 0); + class_sethelpsymbol(base3_class, gensym("help-base3.pd")); +} + diff --git a/dejong.c b/dejong.c new file mode 100644 index 0000000..8cd806f --- /dev/null +++ b/dejong.c @@ -0,0 +1,325 @@ +/* dejong Attractor PD External */ +/* Copyright Michael McGonagle, from ???pbourke???, 2003 */ +/* This program is distributed under the params of the GNU Public License */ + +/////////////////////////////////////////////////////////////////////////////////// +/* This file is part of Chaos PD Externals. */ +/* */ +/* Chaos PD Externals are free software; you can redistribute them and/or modify */ +/* them under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Chaos PD Externals are distributed in the hope that they will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with the Chaos PD Externals; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "lyapunov.h" + +#define M_a_lo -1000 +#define M_a_hi 1000 +#define M_b_lo -1000 +#define M_b_hi 1000 +#define M_c_lo -1000 +#define M_c_hi 1000 +#define M_d_lo -1000 +#define M_d_hi 1000 + +#define M_a 0 +#define M_b 1 +#define M_c 2 +#define M_d 3 + +#define M_x 0 +#define M_y 1 + +#define M_param_count 4 +#define M_var_count 2 +#define M_search_count 3 +#define M_failure_limit 1000 + +static char *version = "dejong v0.0, by Michael McGonagle, from ???pbourke???, 2003"; + +t_class *dejong_class; + +typedef struct dejong_struct { + t_object x_obj; + + double vars[M_var_count]; + double vars_init[M_var_count]; + t_atom vars_out[M_var_count]; + t_outlet *vars_outlet; + + t_atom search_out[M_search_count]; + t_outlet *search_outlet; + + double a, a_lo, a_hi, b, b_lo, b_hi, c, c_lo, c_hi, d, d_lo, d_hi; + t_atom params_out[M_param_count]; + t_outlet *params_outlet; + double lyap_exp, lyap_lo, lyap_hi, lyap_limit, failure_ratio; + + t_outlet *outlets[M_var_count - 1]; +} dejong_struct; + +static void calc(dejong_struct *dejong, double *vars) { + double x_0, y_0; + x_0 =sin(dejong -> a*vars[M_y])-cos(dejong -> b*vars[M_x]); + y_0 =sin(dejong -> c*vars[M_x])-cos(dejong -> d*vars[M_y]); + vars[M_x] = x_0; + vars[M_y] = y_0; +} // end calc + +static void calculate(dejong_struct *dejong) { + calc(dejong, dejong -> vars); + outlet_float(dejong -> x_obj.ob_outlet, dejong -> vars[M_x]); + outlet_float(dejong -> outlets[M_y - 1], dejong -> vars[M_y]); +} // end calculate + +static void reset(dejong_struct *dejong, t_symbol *s, int argc, t_atom *argv) { + if (argc == M_var_count) { + dejong -> vars[M_x] = (double) atom_getfloatarg(M_x, argc, argv); + dejong -> vars[M_y] = (double) atom_getfloatarg(M_y, argc, argv); + } else { + dejong -> vars[M_x] = dejong -> vars_init[M_x]; + dejong -> vars[M_y] = dejong -> vars_init[M_y]; + } // end if +} // end reset + +static char *classify(dejong_struct *dejong) { + static char buff[5]; + char *c = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + buff[0] = c[(int) (((dejong -> a - M_a_lo) * (1.0 / (M_a_hi - M_a_lo))) * 26)]; + buff[1] = c[(int) (((dejong -> b - M_b_lo) * (1.0 / (M_b_hi - M_b_lo))) * 26)]; + buff[2] = c[(int) (((dejong -> c - M_c_lo) * (1.0 / (M_c_hi - M_c_lo))) * 26)]; + buff[3] = c[(int) (((dejong -> d - M_d_lo) * (1.0 / (M_d_hi - M_d_lo))) * 26)]; + buff[4] = '\0'; + return buff; +} + +static void make_results(dejong_struct *dejong) { + SETFLOAT(&dejong -> search_out[0], dejong -> lyap_exp); + SETSYMBOL(&dejong -> search_out[1], gensym(classify(dejong))); + SETFLOAT(&dejong -> search_out[2], dejong -> failure_ratio); + SETFLOAT(&dejong -> vars_out[M_x], dejong -> vars[M_x]); + SETFLOAT(&dejong -> vars_out[M_y], dejong -> vars[M_y]); + SETFLOAT(&dejong -> params_out[M_a], dejong -> a); + SETFLOAT(&dejong -> params_out[M_b], dejong -> b); + SETFLOAT(&dejong -> params_out[M_c], dejong -> c); + SETFLOAT(&dejong -> params_out[M_d], dejong -> d); + outlet_list(dejong -> params_outlet, gensym("list"), M_param_count, dejong -> params_out); + outlet_list(dejong -> vars_outlet, gensym("list"), M_var_count, dejong -> vars_out); +} + +static void show(dejong_struct *dejong) { + make_results(dejong); + outlet_anything(dejong -> search_outlet, gensym("show"), M_search_count, dejong -> search_out); +} + +static void param(dejong_struct *dejong, t_symbol *s, int argc, t_atom *argv) { + if (argc != 4) { + post("Incorrect number of arguments for dejong fractal. Expecting 4 arguments."); + return; + } + dejong -> a = (double) atom_getfloatarg(0, argc, argv); + dejong -> b = (double) atom_getfloatarg(1, argc, argv); + dejong -> c = (double) atom_getfloatarg(2, argc, argv); + dejong -> d = (double) atom_getfloatarg(3, argc, argv); +} + +static void seed(dejong_struct *dejong, t_symbol *s, int argc, t_atom *argv) { + if (argc > 0) { + srand48(((unsigned int)time(0))|1); + } else { + srand48((unsigned int) atom_getfloatarg(0, argc, argv)); + } +} + +static void lyap(dejong_struct *dejong, t_floatarg l, t_floatarg h, t_floatarg lim) { + dejong -> lyap_lo = l; + dejong -> lyap_hi = h; + dejong -> lyap_limit = (double) ((int) lim); +} + +static void elyap(dejong_struct *dejong) { + double results[M_var_count]; + int i; + if (lyapunov_full((void *) dejong, (t_gotfn) calc, M_var_count, dejong -> vars, results) != NULL) { + post("elyapunov:"); + for(i = 0; i < M_var_count; i++) { post("%d: %3.80f", i, results[i]); } + } +} + +static void limiter(dejong_struct *dejong) { + if (dejong -> a_lo < M_a_lo) { dejong -> a_lo = M_a_lo; } + if (dejong -> a_lo > M_a_hi) { dejong -> a_lo = M_a_hi; } + if (dejong -> a_hi < M_a_lo) { dejong -> a_hi = M_a_lo; } + if (dejong -> a_hi > M_a_hi) { dejong -> a_hi = M_a_hi; } + if (dejong -> b_lo < M_b_lo) { dejong -> b_lo = M_b_lo; } + if (dejong -> b_lo > M_b_hi) { dejong -> b_lo = M_b_hi; } + if (dejong -> b_hi < M_b_lo) { dejong -> b_hi = M_b_lo; } + if (dejong -> b_hi > M_b_hi) { dejong -> b_hi = M_b_hi; } + if (dejong -> c_lo < M_c_lo) { dejong -> c_lo = M_c_lo; } + if (dejong -> c_lo > M_c_hi) { dejong -> c_lo = M_c_hi; } + if (dejong -> c_hi < M_c_lo) { dejong -> c_hi = M_c_lo; } + if (dejong -> c_hi > M_c_hi) { dejong -> c_hi = M_c_hi; } + if (dejong -> d_lo < M_d_lo) { dejong -> d_lo = M_d_lo; } + if (dejong -> d_lo > M_d_hi) { dejong -> d_lo = M_d_hi; } + if (dejong -> d_hi < M_d_lo) { dejong -> d_hi = M_d_lo; } + if (dejong -> d_hi > M_d_hi) { dejong -> d_hi = M_d_hi; } +} + +static void constrain(dejong_struct *dejong, t_symbol *s, int argc, t_atom *argv) { + int i; + t_atom *arg = argv; + if (argc == 0) { + // reset to full limits of search ranges + dejong -> a_lo = M_a_lo; + dejong -> a_hi = M_a_hi; + dejong -> b_lo = M_b_lo; + dejong -> b_hi = M_b_hi; + dejong -> c_lo = M_c_lo; + dejong -> c_hi = M_c_hi; + dejong -> d_lo = M_d_lo; + dejong -> d_hi = M_d_hi; + return; + } + if (argc == 1) { + // set the ranges based on percentage of full range + double percent = atom_getfloat(arg); + double a_spread = ((M_a_hi - M_a_lo) * percent) / 2; + double b_spread = ((M_b_hi - M_b_lo) * percent) / 2; + double c_spread = ((M_c_hi - M_c_lo) * percent) / 2; + double d_spread = ((M_d_hi - M_d_lo) * percent) / 2; + dejong -> a_lo = dejong -> a - a_spread; + dejong -> a_hi = dejong -> a + a_spread; + dejong -> b_lo = dejong -> b - b_spread; + dejong -> b_hi = dejong -> b + b_spread; + dejong -> c_lo = dejong -> c - c_spread; + dejong -> c_hi = dejong -> c + c_spread; + dejong -> d_lo = dejong -> d - d_spread; + dejong -> d_hi = dejong -> d + d_spread; + limiter(dejong); + return; + } + if (argc != M_param_count * 2) { + post("Invalid number of arguments for dejong constraints, requires 8 values, got %d", argc); + return; + } + dejong -> a_lo = atom_getfloat(arg++); + dejong -> a_hi = atom_getfloat(arg++); + dejong -> b_lo = atom_getfloat(arg++); + dejong -> b_hi = atom_getfloat(arg++); + dejong -> c_lo = atom_getfloat(arg++); + dejong -> c_hi = atom_getfloat(arg++); + dejong -> d_lo = atom_getfloat(arg++); + dejong -> d_hi = atom_getfloat(arg++); + limiter(dejong); +} + +static void search(dejong_struct *dejong, t_symbol *s, int argc, t_atom *argv) { + int not_found, not_expired = dejong -> lyap_limit; + int jump, i, iterations; + t_atom vars[M_var_count]; + double temp_a = dejong -> a; + double temp_b = dejong -> b; + double temp_c = dejong -> c; + double temp_d = dejong -> d; + if (argc > 0) { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], atom_getfloatarg(i, argc, argv)); + } + } else { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], dejong -> vars_init[i]); + } + } + do { + jump = 500; + not_found = 0; + iterations = 10000; + bad_params: + dejong -> a = (drand48() * (dejong -> a_hi - dejong -> a_lo)) + dejong -> a_lo; + dejong -> b = (drand48() * (dejong -> b_hi - dejong -> b_lo)) + dejong -> b_lo; + dejong -> c = (drand48() * (dejong -> c_hi - dejong -> c_lo)) + dejong -> c_lo; + dejong -> d = (drand48() * (dejong -> d_hi - dejong -> d_lo)) + dejong -> d_lo; + // put any preliminary checks specific to this fractal to eliminate bad_params + + reset(dejong, NULL, argc, vars); + do { calc(dejong, dejong -> vars); } while(jump--); + dejong -> lyap_exp = lyapunov((void *) dejong, (t_gotfn) calc, M_var_count, (double *) dejong -> vars); + if (isnan(dejong -> lyap_exp)) { not_found = 1; } + if (dejong -> lyap_exp < dejong -> lyap_lo || dejong -> lyap_exp > dejong -> lyap_hi) { not_found = 1; } + not_expired--; + } while(not_found && not_expired); + reset(dejong, NULL, argc, vars); + if (!not_expired) { + post("Could not find a fractal after %d attempts.", (int) dejong -> lyap_limit); + post("Try using wider constraints."); + dejong -> a = temp_a; + dejong -> b = temp_b; + dejong -> c = temp_c; + dejong -> d = temp_d; + outlet_anything(dejong -> search_outlet, gensym("invalid"), 0, NULL); + } else { + dejong -> failure_ratio = (dejong -> lyap_limit - not_expired) / dejong -> lyap_limit; + make_results(dejong); + outlet_anything(dejong -> search_outlet, gensym("search"), M_search_count, dejong -> search_out); + } +} + +void *dejong_new(t_symbol *s, int argc, t_atom *argv) { + dejong_struct *dejong = (dejong_struct *) pd_new(dejong_class); + if (dejong != NULL) { + outlet_new(&dejong -> x_obj, &s_float); + dejong -> outlets[0] = outlet_new(&dejong -> x_obj, &s_float); + dejong -> search_outlet = outlet_new(&dejong -> x_obj, &s_list); + dejong -> vars_outlet = outlet_new(&dejong -> x_obj, &s_list); + dejong -> params_outlet = outlet_new(&dejong -> x_obj, &s_list); + if (argc == M_param_count + M_var_count) { + dejong -> vars_init[M_x] = dejong -> vars[M_x] = (double) atom_getfloatarg(0, argc, argv); + dejong -> vars_init[M_y] = dejong -> vars[M_y] = (double) atom_getfloatarg(1, argc, argv); + dejong -> a = (double) atom_getfloatarg(2, argc, argv); + dejong -> b = (double) atom_getfloatarg(3, argc, argv); + dejong -> c = (double) atom_getfloatarg(4, argc, argv); + dejong -> d = (double) atom_getfloatarg(5, argc, argv); + } else { + if (argc != 0 && argc != M_param_count + M_var_count) { + post("Incorrect number of arguments for dejong fractal. Expecting 6 arguments."); + } + dejong -> vars_init[M_x] = 0.01; + dejong -> vars_init[M_y] = 0; + dejong -> a = -2.24; + dejong -> b = -0.65; + dejong -> c = 0.43; + dejong -> d = -2.43; + } + constrain(dejong, NULL, 0, NULL); + lyap(dejong, -1000000.0, 1000000.0, M_failure_limit); + } + return (void *)dejong; +} + +void dejong_setup(void) { + dejong_class = class_new(gensym("dejong"), (t_newmethod) dejong_new, 0, sizeof(dejong_struct), 0, A_GIMME, 0); + class_addbang(dejong_class, (t_method) calculate); + class_addmethod(dejong_class, (t_method) reset, gensym("reset"), A_GIMME, 0); + class_addmethod(dejong_class, (t_method) show, gensym("show"), 0); + class_addmethod(dejong_class, (t_method) param, gensym("param"), A_GIMME, 0); + class_addmethod(dejong_class, (t_method) seed, gensym("seed"), A_GIMME, 0); + class_addmethod(dejong_class, (t_method) lyap, gensym("lyapunov"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(dejong_class, (t_method) elyap, gensym("elyapunov"), 0); + class_addmethod(dejong_class, (t_method) search, gensym("search"), A_GIMME, 0); + class_addmethod(dejong_class, (t_method) constrain, gensym("constrain"), A_GIMME, 0); + class_sethelpsymbol(dejong_class, gensym("help-dejong.pd")); +} + diff --git a/gingerbreadman.c b/gingerbreadman.c new file mode 100644 index 0000000..51218a1 --- /dev/null +++ b/gingerbreadman.c @@ -0,0 +1,101 @@ +/* gingerbreadman Attractor PD External */ +/* Copyright Michael McGonagle, from ??????, 2003 */ +/* This program is distributed under the params of the GNU Public License */ + +/////////////////////////////////////////////////////////////////////////////////// +/* This file is part of Chaos PD Externals. */ +/* */ +/* Chaos PD Externals are free software; you can redistribute them and/or modify */ +/* them under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Chaos PD Externals are distributed in the hope that they will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with the Chaos PD Externals; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "m_pd.h" + + + +#define M_x 0 +#define M_y 1 + +#define M_param_count 0 +#define M_var_count 2 +#define M_search_count 0 +#define M_failure_limit 1000 + +static char *version = "gingerbreadman v0.0, by Michael McGonagle, from ??????, 2003"; + +t_class *gingerbreadman_class; + +typedef struct gingerbreadman_struct { + t_object x_obj; + + double vars[M_var_count]; + double vars_init[M_var_count]; + + t_outlet *outlets[M_var_count - 1]; +} gingerbreadman_struct; + +static void calc(gingerbreadman_struct *gingerbreadman, double *vars) { + double x_0, y_0; + x_0 =1-vars[M_y]+abs(vars[M_x]); + y_0 =vars[M_x]; + vars[M_x] = x_0; + vars[M_y] = y_0; +} // end calc + +static void calculate(gingerbreadman_struct *gingerbreadman) { + calc(gingerbreadman, gingerbreadman -> vars); + outlet_float(gingerbreadman -> x_obj.ob_outlet, gingerbreadman -> vars[M_x]); + outlet_float(gingerbreadman -> outlets[M_y - 1], gingerbreadman -> vars[M_y]); +} // end calculate + +static void reset(gingerbreadman_struct *gingerbreadman, t_symbol *s, int argc, t_atom *argv) { + if (argc == M_var_count) { + gingerbreadman -> vars[M_x] = (double) atom_getfloatarg(M_x, argc, argv); + gingerbreadman -> vars[M_y] = (double) atom_getfloatarg(M_y, argc, argv); + } else { + gingerbreadman -> vars[M_x] = gingerbreadman -> vars_init[M_x]; + gingerbreadman -> vars[M_y] = gingerbreadman -> vars_init[M_y]; + } // end if +} // end reset + +void *gingerbreadman_new(t_symbol *s, int argc, t_atom *argv) { + gingerbreadman_struct *gingerbreadman = (gingerbreadman_struct *) pd_new(gingerbreadman_class); + if (gingerbreadman != NULL) { + outlet_new(&gingerbreadman -> x_obj, &s_float); + gingerbreadman -> outlets[0] = outlet_new(&gingerbreadman -> x_obj, &s_float); + if (argc == M_param_count + M_var_count) { + gingerbreadman -> vars_init[M_x] = gingerbreadman -> vars[M_x] = (double) atom_getfloatarg(0, argc, argv); + gingerbreadman -> vars_init[M_y] = gingerbreadman -> vars[M_y] = (double) atom_getfloatarg(1, argc, argv); + } else { + if (argc != 0 && argc != M_param_count + M_var_count) { + post("Incorrect number of arguments for gingerbreadman fractal. Expecting 2 arguments."); + } + gingerbreadman -> vars_init[M_x] = -0.1; + gingerbreadman -> vars_init[M_y] = 0; + } + } + return (void *)gingerbreadman; +} + +void gingerbreadman_setup(void) { + gingerbreadman_class = class_new(gensym("gingerbreadman"), (t_newmethod) gingerbreadman_new, 0, sizeof(gingerbreadman_struct), 0, A_GIMME, 0); + class_addbang(gingerbreadman_class, (t_method) calculate); + class_addmethod(gingerbreadman_class, (t_method) reset, gensym("reset"), A_GIMME, 0); + class_sethelpsymbol(gingerbreadman_class, gensym("help-gingerbreadman.pd")); +} + diff --git a/hopalong.c b/hopalong.c new file mode 100644 index 0000000..01f6d13 --- /dev/null +++ b/hopalong.c @@ -0,0 +1,303 @@ +/* hopalong Attractor PD External */ +/* Copyright Michael McGonagle, from ??????, 2003 */ +/* This program is distributed under the params of the GNU Public License */ + +/////////////////////////////////////////////////////////////////////////////////// +/* This file is part of Chaos PD Externals. */ +/* */ +/* Chaos PD Externals are free software; you can redistribute them and/or modify */ +/* them under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Chaos PD Externals are distributed in the hope that they will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with the Chaos PD Externals; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "lyapunov.h" + +#define M_a_lo -1000 +#define M_a_hi 1000 +#define M_b_lo -1000 +#define M_b_hi 1000 +#define M_c_lo -1000 +#define M_c_hi 1000 + +#define M_a 0 +#define M_b 1 +#define M_c 2 + +#define M_x 0 +#define M_y 1 + +#define M_param_count 3 +#define M_var_count 2 +#define M_search_count 3 +#define M_failure_limit 1000 + +static char *version = "hopalong v0.0, by Michael McGonagle, from ??????, 2003"; + +t_class *hopalong_class; + +typedef struct hopalong_struct { + t_object x_obj; + + double vars[M_var_count]; + double vars_init[M_var_count]; + t_atom vars_out[M_var_count]; + t_outlet *vars_outlet; + + t_atom search_out[M_search_count]; + t_outlet *search_outlet; + + double a, a_lo, a_hi, b, b_lo, b_hi, c, c_lo, c_hi; + t_atom params_out[M_param_count]; + t_outlet *params_outlet; + double lyap_exp, lyap_lo, lyap_hi, lyap_limit, failure_ratio; + + t_outlet *outlets[M_var_count - 1]; +} hopalong_struct; + +static void calc(hopalong_struct *hopalong, double *vars) { + double x_0, y_0; + x_0 =vars[M_y]-((vars[M_x]<0)?-1:1)*sqrt(abs(hopalong -> b*vars[M_x]-hopalong -> c)); + y_0 =hopalong -> a-vars[M_x]; + vars[M_x] = x_0; + vars[M_y] = y_0; +} // end calc + +static void calculate(hopalong_struct *hopalong) { + calc(hopalong, hopalong -> vars); + outlet_float(hopalong -> x_obj.ob_outlet, hopalong -> vars[M_x]); + outlet_float(hopalong -> outlets[M_y - 1], hopalong -> vars[M_y]); +} // end calculate + +static void reset(hopalong_struct *hopalong, t_symbol *s, int argc, t_atom *argv) { + if (argc == M_var_count) { + hopalong -> vars[M_x] = (double) atom_getfloatarg(M_x, argc, argv); + hopalong -> vars[M_y] = (double) atom_getfloatarg(M_y, argc, argv); + } else { + hopalong -> vars[M_x] = hopalong -> vars_init[M_x]; + hopalong -> vars[M_y] = hopalong -> vars_init[M_y]; + } // end if +} // end reset + +static char *classify(hopalong_struct *hopalong) { + static char buff[4]; + char *c = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + buff[0] = c[(int) (((hopalong -> a - M_a_lo) * (1.0 / (M_a_hi - M_a_lo))) * 26)]; + buff[1] = c[(int) (((hopalong -> b - M_b_lo) * (1.0 / (M_b_hi - M_b_lo))) * 26)]; + buff[2] = c[(int) (((hopalong -> c - M_c_lo) * (1.0 / (M_c_hi - M_c_lo))) * 26)]; + buff[3] = '\0'; + return buff; +} + +static void make_results(hopalong_struct *hopalong) { + SETFLOAT(&hopalong -> search_out[0], hopalong -> lyap_exp); + SETSYMBOL(&hopalong -> search_out[1], gensym(classify(hopalong))); + SETFLOAT(&hopalong -> search_out[2], hopalong -> failure_ratio); + SETFLOAT(&hopalong -> vars_out[M_x], hopalong -> vars[M_x]); + SETFLOAT(&hopalong -> vars_out[M_y], hopalong -> vars[M_y]); + SETFLOAT(&hopalong -> params_out[M_a], hopalong -> a); + SETFLOAT(&hopalong -> params_out[M_b], hopalong -> b); + SETFLOAT(&hopalong -> params_out[M_c], hopalong -> c); + outlet_list(hopalong -> params_outlet, gensym("list"), M_param_count, hopalong -> params_out); + outlet_list(hopalong -> vars_outlet, gensym("list"), M_var_count, hopalong -> vars_out); +} + +static void show(hopalong_struct *hopalong) { + make_results(hopalong); + outlet_anything(hopalong -> search_outlet, gensym("show"), M_search_count, hopalong -> search_out); +} + +static void param(hopalong_struct *hopalong, t_symbol *s, int argc, t_atom *argv) { + if (argc != 3) { + post("Incorrect number of arguments for hopalong fractal. Expecting 3 arguments."); + return; + } + hopalong -> a = (double) atom_getfloatarg(0, argc, argv); + hopalong -> b = (double) atom_getfloatarg(1, argc, argv); + hopalong -> c = (double) atom_getfloatarg(2, argc, argv); +} + +static void seed(hopalong_struct *hopalong, t_symbol *s, int argc, t_atom *argv) { + if (argc > 0) { + srand48(((unsigned int)time(0))|1); + } else { + srand48((unsigned int) atom_getfloatarg(0, argc, argv)); + } +} + +static void lyap(hopalong_struct *hopalong, t_floatarg l, t_floatarg h, t_floatarg lim) { + hopalong -> lyap_lo = l; + hopalong -> lyap_hi = h; + hopalong -> lyap_limit = (double) ((int) lim); +} + +static void elyap(hopalong_struct *hopalong) { + double results[M_var_count]; + int i; + if (lyapunov_full((void *) hopalong, (t_gotfn) calc, M_var_count, hopalong -> vars, results) != NULL) { + post("elyapunov:"); + for(i = 0; i < M_var_count; i++) { post("%d: %3.80f", i, results[i]); } + } +} + +static void limiter(hopalong_struct *hopalong) { + if (hopalong -> a_lo < M_a_lo) { hopalong -> a_lo = M_a_lo; } + if (hopalong -> a_lo > M_a_hi) { hopalong -> a_lo = M_a_hi; } + if (hopalong -> a_hi < M_a_lo) { hopalong -> a_hi = M_a_lo; } + if (hopalong -> a_hi > M_a_hi) { hopalong -> a_hi = M_a_hi; } + if (hopalong -> b_lo < M_b_lo) { hopalong -> b_lo = M_b_lo; } + if (hopalong -> b_lo > M_b_hi) { hopalong -> b_lo = M_b_hi; } + if (hopalong -> b_hi < M_b_lo) { hopalong -> b_hi = M_b_lo; } + if (hopalong -> b_hi > M_b_hi) { hopalong -> b_hi = M_b_hi; } + if (hopalong -> c_lo < M_c_lo) { hopalong -> c_lo = M_c_lo; } + if (hopalong -> c_lo > M_c_hi) { hopalong -> c_lo = M_c_hi; } + if (hopalong -> c_hi < M_c_lo) { hopalong -> c_hi = M_c_lo; } + if (hopalong -> c_hi > M_c_hi) { hopalong -> c_hi = M_c_hi; } +} + +static void constrain(hopalong_struct *hopalong, t_symbol *s, int argc, t_atom *argv) { + int i; + t_atom *arg = argv; + if (argc == 0) { + // reset to full limits of search ranges + hopalong -> a_lo = M_a_lo; + hopalong -> a_hi = M_a_hi; + hopalong -> b_lo = M_b_lo; + hopalong -> b_hi = M_b_hi; + hopalong -> c_lo = M_c_lo; + hopalong -> c_hi = M_c_hi; + return; + } + if (argc == 1) { + // set the ranges based on percentage of full range + double percent = atom_getfloat(arg); + double a_spread = ((M_a_hi - M_a_lo) * percent) / 2; + double b_spread = ((M_b_hi - M_b_lo) * percent) / 2; + double c_spread = ((M_c_hi - M_c_lo) * percent) / 2; + hopalong -> a_lo = hopalong -> a - a_spread; + hopalong -> a_hi = hopalong -> a + a_spread; + hopalong -> b_lo = hopalong -> b - b_spread; + hopalong -> b_hi = hopalong -> b + b_spread; + hopalong -> c_lo = hopalong -> c - c_spread; + hopalong -> c_hi = hopalong -> c + c_spread; + limiter(hopalong); + return; + } + if (argc != M_param_count * 2) { + post("Invalid number of arguments for hopalong constraints, requires 6 values, got %d", argc); + return; + } + hopalong -> a_lo = atom_getfloat(arg++); + hopalong -> a_hi = atom_getfloat(arg++); + hopalong -> b_lo = atom_getfloat(arg++); + hopalong -> b_hi = atom_getfloat(arg++); + hopalong -> c_lo = atom_getfloat(arg++); + hopalong -> c_hi = atom_getfloat(arg++); + limiter(hopalong); +} + +static void search(hopalong_struct *hopalong, t_symbol *s, int argc, t_atom *argv) { + int not_found, not_expired = hopalong -> lyap_limit; + int jump, i, iterations; + t_atom vars[M_var_count]; + double temp_a = hopalong -> a; + double temp_b = hopalong -> b; + double temp_c = hopalong -> c; + if (argc > 0) { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], atom_getfloatarg(i, argc, argv)); + } + } else { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], hopalong -> vars_init[i]); + } + } + do { + jump = 500; + not_found = 0; + iterations = 10000; + bad_params: + hopalong -> a = (drand48() * (hopalong -> a_hi - hopalong -> a_lo)) + hopalong -> a_lo; + hopalong -> b = (drand48() * (hopalong -> b_hi - hopalong -> b_lo)) + hopalong -> b_lo; + hopalong -> c = (drand48() * (hopalong -> c_hi - hopalong -> c_lo)) + hopalong -> c_lo; + // put any preliminary checks specific to this fractal to eliminate bad_params + + reset(hopalong, NULL, argc, vars); + do { calc(hopalong, hopalong -> vars); } while(jump--); + hopalong -> lyap_exp = lyapunov((void *) hopalong, (t_gotfn) calc, M_var_count, (double *) hopalong -> vars); + if (isnan(hopalong -> lyap_exp)) { not_found = 1; } + if (hopalong -> lyap_exp < hopalong -> lyap_lo || hopalong -> lyap_exp > hopalong -> lyap_hi) { not_found = 1; } + not_expired--; + } while(not_found && not_expired); + reset(hopalong, NULL, argc, vars); + if (!not_expired) { + post("Could not find a fractal after %d attempts.", (int) hopalong -> lyap_limit); + post("Try using wider constraints."); + hopalong -> a = temp_a; + hopalong -> b = temp_b; + hopalong -> c = temp_c; + outlet_anything(hopalong -> search_outlet, gensym("invalid"), 0, NULL); + } else { + hopalong -> failure_ratio = (hopalong -> lyap_limit - not_expired) / hopalong -> lyap_limit; + make_results(hopalong); + outlet_anything(hopalong -> search_outlet, gensym("search"), M_search_count, hopalong -> search_out); + } +} + +void *hopalong_new(t_symbol *s, int argc, t_atom *argv) { + hopalong_struct *hopalong = (hopalong_struct *) pd_new(hopalong_class); + if (hopalong != NULL) { + outlet_new(&hopalong -> x_obj, &s_float); + hopalong -> outlets[0] = outlet_new(&hopalong -> x_obj, &s_float); + hopalong -> search_outlet = outlet_new(&hopalong -> x_obj, &s_list); + hopalong -> vars_outlet = outlet_new(&hopalong -> x_obj, &s_list); + hopalong -> params_outlet = outlet_new(&hopalong -> x_obj, &s_list); + if (argc == M_param_count + M_var_count) { + hopalong -> vars_init[M_x] = hopalong -> vars[M_x] = (double) atom_getfloatarg(0, argc, argv); + hopalong -> vars_init[M_y] = hopalong -> vars[M_y] = (double) atom_getfloatarg(1, argc, argv); + hopalong -> a = (double) atom_getfloatarg(2, argc, argv); + hopalong -> b = (double) atom_getfloatarg(3, argc, argv); + hopalong -> c = (double) atom_getfloatarg(4, argc, argv); + } else { + if (argc != 0 && argc != M_param_count + M_var_count) { + post("Incorrect number of arguments for hopalong fractal. Expecting 5 arguments."); + } + hopalong -> vars_init[M_x] = 0.1; + hopalong -> vars_init[M_y] = 0.1; + hopalong -> a = 1; + hopalong -> b = 1; + hopalong -> c = 0; + } + constrain(hopalong, NULL, 0, NULL); + lyap(hopalong, -1000000.0, 1000000.0, M_failure_limit); + } + return (void *)hopalong; +} + +void hopalong_setup(void) { + hopalong_class = class_new(gensym("hopalong"), (t_newmethod) hopalong_new, 0, sizeof(hopalong_struct), 0, A_GIMME, 0); + class_addbang(hopalong_class, (t_method) calculate); + class_addmethod(hopalong_class, (t_method) reset, gensym("reset"), A_GIMME, 0); + class_addmethod(hopalong_class, (t_method) show, gensym("show"), 0); + class_addmethod(hopalong_class, (t_method) param, gensym("param"), A_GIMME, 0); + class_addmethod(hopalong_class, (t_method) seed, gensym("seed"), A_GIMME, 0); + class_addmethod(hopalong_class, (t_method) lyap, gensym("lyapunov"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(hopalong_class, (t_method) elyap, gensym("elyapunov"), 0); + class_addmethod(hopalong_class, (t_method) search, gensym("search"), A_GIMME, 0); + class_addmethod(hopalong_class, (t_method) constrain, gensym("constrain"), A_GIMME, 0); + class_sethelpsymbol(hopalong_class, gensym("help-hopalong.pd")); +} + diff --git a/latoocarfian.c b/latoocarfian.c new file mode 100644 index 0000000..996d987 --- /dev/null +++ b/latoocarfian.c @@ -0,0 +1,325 @@ +/* latoocarfian Attractor PD External */ +/* Copyright Michael McGonagle, from Cliff Pickover, 2003 */ +/* This program is distributed under the params of the GNU Public License */ + +/////////////////////////////////////////////////////////////////////////////////// +/* This file is part of Chaos PD Externals. */ +/* */ +/* Chaos PD Externals are free software; you can redistribute them and/or modify */ +/* them under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Chaos PD Externals are distributed in the hope that they will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with the Chaos PD Externals; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "lyapunov.h" + +#define M_a_lo -3 +#define M_a_hi 3 +#define M_b_lo -3 +#define M_b_hi 3 +#define M_c_lo 0.5 +#define M_c_hi 1.5 +#define M_d_lo 0.5 +#define M_d_hi 1.5 + +#define M_a 0 +#define M_b 1 +#define M_c 2 +#define M_d 3 + +#define M_x 0 +#define M_y 1 + +#define M_param_count 4 +#define M_var_count 2 +#define M_search_count 3 +#define M_failure_limit 1000 + +static char *version = "latoocarfian v0.0, by Michael McGonagle, from Cliff Pickover, 2003"; + +t_class *latoocarfian_class; + +typedef struct latoocarfian_struct { + t_object x_obj; + + double vars[M_var_count]; + double vars_init[M_var_count]; + t_atom vars_out[M_var_count]; + t_outlet *vars_outlet; + + t_atom search_out[M_search_count]; + t_outlet *search_outlet; + + double a, a_lo, a_hi, b, b_lo, b_hi, c, c_lo, c_hi, d, d_lo, d_hi; + t_atom params_out[M_param_count]; + t_outlet *params_outlet; + double lyap_exp, lyap_lo, lyap_hi, lyap_limit, failure_ratio; + + t_outlet *outlets[M_var_count - 1]; +} latoocarfian_struct; + +static void calc(latoocarfian_struct *latoocarfian, double *vars) { + double x_0, y_0; + x_0 =sin(vars[M_y]*latoocarfian -> b)+(latoocarfian -> c*sin(vars[M_x]*latoocarfian -> b)); + y_0 =sin(vars[M_x]*latoocarfian -> a)+(latoocarfian -> d*sin(vars[M_y]*latoocarfian -> a)); + vars[M_x] = x_0; + vars[M_y] = y_0; +} // end calc + +static void calculate(latoocarfian_struct *latoocarfian) { + calc(latoocarfian, latoocarfian -> vars); + outlet_float(latoocarfian -> x_obj.ob_outlet, latoocarfian -> vars[M_x]); + outlet_float(latoocarfian -> outlets[M_y - 1], latoocarfian -> vars[M_y]); +} // end calculate + +static void reset(latoocarfian_struct *latoocarfian, t_symbol *s, int argc, t_atom *argv) { + if (argc == M_var_count) { + latoocarfian -> vars[M_x] = (double) atom_getfloatarg(M_x, argc, argv); + latoocarfian -> vars[M_y] = (double) atom_getfloatarg(M_y, argc, argv); + } else { + latoocarfian -> vars[M_x] = latoocarfian -> vars_init[M_x]; + latoocarfian -> vars[M_y] = latoocarfian -> vars_init[M_y]; + } // end if +} // end reset + +static char *classify(latoocarfian_struct *latoocarfian) { + static char buff[5]; + char *c = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + buff[0] = c[(int) (((latoocarfian -> a - M_a_lo) * (1.0 / (M_a_hi - M_a_lo))) * 26)]; + buff[1] = c[(int) (((latoocarfian -> b - M_b_lo) * (1.0 / (M_b_hi - M_b_lo))) * 26)]; + buff[2] = c[(int) (((latoocarfian -> c - M_c_lo) * (1.0 / (M_c_hi - M_c_lo))) * 26)]; + buff[3] = c[(int) (((latoocarfian -> d - M_d_lo) * (1.0 / (M_d_hi - M_d_lo))) * 26)]; + buff[4] = '\0'; + return buff; +} + +static void make_results(latoocarfian_struct *latoocarfian) { + SETFLOAT(&latoocarfian -> search_out[0], latoocarfian -> lyap_exp); + SETSYMBOL(&latoocarfian -> search_out[1], gensym(classify(latoocarfian))); + SETFLOAT(&latoocarfian -> search_out[2], latoocarfian -> failure_ratio); + SETFLOAT(&latoocarfian -> vars_out[M_x], latoocarfian -> vars[M_x]); + SETFLOAT(&latoocarfian -> vars_out[M_y], latoocarfian -> vars[M_y]); + SETFLOAT(&latoocarfian -> params_out[M_a], latoocarfian -> a); + SETFLOAT(&latoocarfian -> params_out[M_b], latoocarfian -> b); + SETFLOAT(&latoocarfian -> params_out[M_c], latoocarfian -> c); + SETFLOAT(&latoocarfian -> params_out[M_d], latoocarfian -> d); + outlet_list(latoocarfian -> params_outlet, gensym("list"), M_param_count, latoocarfian -> params_out); + outlet_list(latoocarfian -> vars_outlet, gensym("list"), M_var_count, latoocarfian -> vars_out); +} + +static void show(latoocarfian_struct *latoocarfian) { + make_results(latoocarfian); + outlet_anything(latoocarfian -> search_outlet, gensym("show"), M_search_count, latoocarfian -> search_out); +} + +static void param(latoocarfian_struct *latoocarfian, t_symbol *s, int argc, t_atom *argv) { + if (argc != 4) { + post("Incorrect number of arguments for latoocarfian fractal. Expecting 4 arguments."); + return; + } + latoocarfian -> a = (double) atom_getfloatarg(0, argc, argv); + latoocarfian -> b = (double) atom_getfloatarg(1, argc, argv); + latoocarfian -> c = (double) atom_getfloatarg(2, argc, argv); + latoocarfian -> d = (double) atom_getfloatarg(3, argc, argv); +} + +static void seed(latoocarfian_struct *latoocarfian, t_symbol *s, int argc, t_atom *argv) { + if (argc > 0) { + srand48(((unsigned int)time(0))|1); + } else { + srand48((unsigned int) atom_getfloatarg(0, argc, argv)); + } +} + +static void lyap(latoocarfian_struct *latoocarfian, t_floatarg l, t_floatarg h, t_floatarg lim) { + latoocarfian -> lyap_lo = l; + latoocarfian -> lyap_hi = h; + latoocarfian -> lyap_limit = (double) ((int) lim); +} + +static void elyap(latoocarfian_struct *latoocarfian) { + double results[M_var_count]; + int i; + if (lyapunov_full((void *) latoocarfian, (t_gotfn) calc, M_var_count, latoocarfian -> vars, results) != NULL) { + post("elyapunov:"); + for(i = 0; i < M_var_count; i++) { post("%d: %3.80f", i, results[i]); } + } +} + +static void limiter(latoocarfian_struct *latoocarfian) { + if (latoocarfian -> a_lo < M_a_lo) { latoocarfian -> a_lo = M_a_lo; } + if (latoocarfian -> a_lo > M_a_hi) { latoocarfian -> a_lo = M_a_hi; } + if (latoocarfian -> a_hi < M_a_lo) { latoocarfian -> a_hi = M_a_lo; } + if (latoocarfian -> a_hi > M_a_hi) { latoocarfian -> a_hi = M_a_hi; } + if (latoocarfian -> b_lo < M_b_lo) { latoocarfian -> b_lo = M_b_lo; } + if (latoocarfian -> b_lo > M_b_hi) { latoocarfian -> b_lo = M_b_hi; } + if (latoocarfian -> b_hi < M_b_lo) { latoocarfian -> b_hi = M_b_lo; } + if (latoocarfian -> b_hi > M_b_hi) { latoocarfian -> b_hi = M_b_hi; } + if (latoocarfian -> c_lo < M_c_lo) { latoocarfian -> c_lo = M_c_lo; } + if (latoocarfian -> c_lo > M_c_hi) { latoocarfian -> c_lo = M_c_hi; } + if (latoocarfian -> c_hi < M_c_lo) { latoocarfian -> c_hi = M_c_lo; } + if (latoocarfian -> c_hi > M_c_hi) { latoocarfian -> c_hi = M_c_hi; } + if (latoocarfian -> d_lo < M_d_lo) { latoocarfian -> d_lo = M_d_lo; } + if (latoocarfian -> d_lo > M_d_hi) { latoocarfian -> d_lo = M_d_hi; } + if (latoocarfian -> d_hi < M_d_lo) { latoocarfian -> d_hi = M_d_lo; } + if (latoocarfian -> d_hi > M_d_hi) { latoocarfian -> d_hi = M_d_hi; } +} + +static void constrain(latoocarfian_struct *latoocarfian, t_symbol *s, int argc, t_atom *argv) { + int i; + t_atom *arg = argv; + if (argc == 0) { + // reset to full limits of search ranges + latoocarfian -> a_lo = M_a_lo; + latoocarfian -> a_hi = M_a_hi; + latoocarfian -> b_lo = M_b_lo; + latoocarfian -> b_hi = M_b_hi; + latoocarfian -> c_lo = M_c_lo; + latoocarfian -> c_hi = M_c_hi; + latoocarfian -> d_lo = M_d_lo; + latoocarfian -> d_hi = M_d_hi; + return; + } + if (argc == 1) { + // set the ranges based on percentage of full range + double percent = atom_getfloat(arg); + double a_spread = ((M_a_hi - M_a_lo) * percent) / 2; + double b_spread = ((M_b_hi - M_b_lo) * percent) / 2; + double c_spread = ((M_c_hi - M_c_lo) * percent) / 2; + double d_spread = ((M_d_hi - M_d_lo) * percent) / 2; + latoocarfian -> a_lo = latoocarfian -> a - a_spread; + latoocarfian -> a_hi = latoocarfian -> a + a_spread; + latoocarfian -> b_lo = latoocarfian -> b - b_spread; + latoocarfian -> b_hi = latoocarfian -> b + b_spread; + latoocarfian -> c_lo = latoocarfian -> c - c_spread; + latoocarfian -> c_hi = latoocarfian -> c + c_spread; + latoocarfian -> d_lo = latoocarfian -> d - d_spread; + latoocarfian -> d_hi = latoocarfian -> d + d_spread; + limiter(latoocarfian); + return; + } + if (argc != M_param_count * 2) { + post("Invalid number of arguments for latoocarfian constraints, requires 8 values, got %d", argc); + return; + } + latoocarfian -> a_lo = atom_getfloat(arg++); + latoocarfian -> a_hi = atom_getfloat(arg++); + latoocarfian -> b_lo = atom_getfloat(arg++); + latoocarfian -> b_hi = atom_getfloat(arg++); + latoocarfian -> c_lo = atom_getfloat(arg++); + latoocarfian -> c_hi = atom_getfloat(arg++); + latoocarfian -> d_lo = atom_getfloat(arg++); + latoocarfian -> d_hi = atom_getfloat(arg++); + limiter(latoocarfian); +} + +static void search(latoocarfian_struct *latoocarfian, t_symbol *s, int argc, t_atom *argv) { + int not_found, not_expired = latoocarfian -> lyap_limit; + int jump, i, iterations; + t_atom vars[M_var_count]; + double temp_a = latoocarfian -> a; + double temp_b = latoocarfian -> b; + double temp_c = latoocarfian -> c; + double temp_d = latoocarfian -> d; + if (argc > 0) { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], atom_getfloatarg(i, argc, argv)); + } + } else { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], latoocarfian -> vars_init[i]); + } + } + do { + jump = 500; + not_found = 0; + iterations = 10000; + bad_params: + latoocarfian -> a = (drand48() * (latoocarfian -> a_hi - latoocarfian -> a_lo)) + latoocarfian -> a_lo; + latoocarfian -> b = (drand48() * (latoocarfian -> b_hi - latoocarfian -> b_lo)) + latoocarfian -> b_lo; + latoocarfian -> c = (drand48() * (latoocarfian -> c_hi - latoocarfian -> c_lo)) + latoocarfian -> c_lo; + latoocarfian -> d = (drand48() * (latoocarfian -> d_hi - latoocarfian -> d_lo)) + latoocarfian -> d_lo; + // put any preliminary checks specific to this fractal to eliminate bad_params + + reset(latoocarfian, NULL, argc, vars); + do { calc(latoocarfian, latoocarfian -> vars); } while(jump--); + latoocarfian -> lyap_exp = lyapunov((void *) latoocarfian, (t_gotfn) calc, M_var_count, (double *) latoocarfian -> vars); + if (isnan(latoocarfian -> lyap_exp)) { not_found = 1; } + if (latoocarfian -> lyap_exp < latoocarfian -> lyap_lo || latoocarfian -> lyap_exp > latoocarfian -> lyap_hi) { not_found = 1; } + not_expired--; + } while(not_found && not_expired); + reset(latoocarfian, NULL, argc, vars); + if (!not_expired) { + post("Could not find a fractal after %d attempts.", (int) latoocarfian -> lyap_limit); + post("Try using wider constraints."); + latoocarfian -> a = temp_a; + latoocarfian -> b = temp_b; + latoocarfian -> c = temp_c; + latoocarfian -> d = temp_d; + outlet_anything(latoocarfian -> search_outlet, gensym("invalid"), 0, NULL); + } else { + latoocarfian -> failure_ratio = (latoocarfian -> lyap_limit - not_expired) / latoocarfian -> lyap_limit; + make_results(latoocarfian); + outlet_anything(latoocarfian -> search_outlet, gensym("search"), M_search_count, latoocarfian -> search_out); + } +} + +void *latoocarfian_new(t_symbol *s, int argc, t_atom *argv) { + latoocarfian_struct *latoocarfian = (latoocarfian_struct *) pd_new(latoocarfian_class); + if (latoocarfian != NULL) { + outlet_new(&latoocarfian -> x_obj, &s_float); + latoocarfian -> outlets[0] = outlet_new(&latoocarfian -> x_obj, &s_float); + latoocarfian -> search_outlet = outlet_new(&latoocarfian -> x_obj, &s_list); + latoocarfian -> vars_outlet = outlet_new(&latoocarfian -> x_obj, &s_list); + latoocarfian -> params_outlet = outlet_new(&latoocarfian -> x_obj, &s_list); + if (argc == M_param_count + M_var_count) { + latoocarfian -> vars_init[M_x] = latoocarfian -> vars[M_x] = (double) atom_getfloatarg(0, argc, argv); + latoocarfian -> vars_init[M_y] = latoocarfian -> vars[M_y] = (double) atom_getfloatarg(1, argc, argv); + latoocarfian -> a = (double) atom_getfloatarg(2, argc, argv); + latoocarfian -> b = (double) atom_getfloatarg(3, argc, argv); + latoocarfian -> c = (double) atom_getfloatarg(4, argc, argv); + latoocarfian -> d = (double) atom_getfloatarg(5, argc, argv); + } else { + if (argc != 0 && argc != M_param_count + M_var_count) { + post("Incorrect number of arguments for latoocarfian fractal. Expecting 6 arguments."); + } + latoocarfian -> vars_init[M_x] = 0.1; + latoocarfian -> vars_init[M_y] = 0.1; + latoocarfian -> a = -0.966918; + latoocarfian -> b = 2.87988; + latoocarfian -> c = 0.756145; + latoocarfian -> d = 0.744728; + } + constrain(latoocarfian, NULL, 0, NULL); + lyap(latoocarfian, -1000000.0, 1000000.0, M_failure_limit); + } + return (void *)latoocarfian; +} + +void latoocarfian_setup(void) { + latoocarfian_class = class_new(gensym("latoocarfian"), (t_newmethod) latoocarfian_new, 0, sizeof(latoocarfian_struct), 0, A_GIMME, 0); + class_addbang(latoocarfian_class, (t_method) calculate); + class_addmethod(latoocarfian_class, (t_method) reset, gensym("reset"), A_GIMME, 0); + class_addmethod(latoocarfian_class, (t_method) show, gensym("show"), 0); + class_addmethod(latoocarfian_class, (t_method) param, gensym("param"), A_GIMME, 0); + class_addmethod(latoocarfian_class, (t_method) seed, gensym("seed"), A_GIMME, 0); + class_addmethod(latoocarfian_class, (t_method) lyap, gensym("lyapunov"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(latoocarfian_class, (t_method) elyap, gensym("elyapunov"), 0); + class_addmethod(latoocarfian_class, (t_method) search, gensym("search"), A_GIMME, 0); + class_addmethod(latoocarfian_class, (t_method) constrain, gensym("constrain"), A_GIMME, 0); + class_sethelpsymbol(latoocarfian_class, gensym("help-latoocarfian.pd")); +} + diff --git a/latoomutalpha.c b/latoomutalpha.c new file mode 100644 index 0000000..3648d8c --- /dev/null +++ b/latoomutalpha.c @@ -0,0 +1,325 @@ +/* latoomutalpha Attractor PD External */ +/* Copyright Michael McGonagle, from Cliff Pickover, 2003 */ +/* This program is distributed under the params of the GNU Public License */ + +/////////////////////////////////////////////////////////////////////////////////// +/* This file is part of Chaos PD Externals. */ +/* */ +/* Chaos PD Externals are free software; you can redistribute them and/or modify */ +/* them under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Chaos PD Externals are distributed in the hope that they will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with the Chaos PD Externals; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "lyapunov.h" + +#define M_a_lo -3 +#define M_a_hi 3 +#define M_b_lo -3 +#define M_b_hi 3 +#define M_c_lo 0.5 +#define M_c_hi 1.5 +#define M_d_lo 0.5 +#define M_d_hi 1.5 + +#define M_a 0 +#define M_b 1 +#define M_c 2 +#define M_d 3 + +#define M_x 0 +#define M_y 1 + +#define M_param_count 4 +#define M_var_count 2 +#define M_search_count 3 +#define M_failure_limit 1000 + +static char *version = "latoomutalpha v0.0, by Michael McGonagle, from Cliff Pickover, 2003"; + +t_class *latoomutalpha_class; + +typedef struct latoomutalpha_struct { + t_object x_obj; + + double vars[M_var_count]; + double vars_init[M_var_count]; + t_atom vars_out[M_var_count]; + t_outlet *vars_outlet; + + t_atom search_out[M_search_count]; + t_outlet *search_outlet; + + double a, a_lo, a_hi, b, b_lo, b_hi, c, c_lo, c_hi, d, d_lo, d_hi; + t_atom params_out[M_param_count]; + t_outlet *params_outlet; + double lyap_exp, lyap_lo, lyap_hi, lyap_limit, failure_ratio; + + t_outlet *outlets[M_var_count - 1]; +} latoomutalpha_struct; + +static void calc(latoomutalpha_struct *latoomutalpha, double *vars) { + double x_0, y_0; + x_0 =sin(vars[M_y]*latoomutalpha -> b)+pow(sin(vars[M_x]*latoomutalpha -> b),2)+pow(sin(vars[M_x]*latoomutalpha -> b),3); + y_0 =sin(vars[M_x]*latoomutalpha -> a)+pow(sin(vars[M_y]*latoomutalpha -> a),2)+pow(sin(vars[M_y]*latoomutalpha -> c),3); + vars[M_x] = x_0; + vars[M_y] = y_0; +} // end calc + +static void calculate(latoomutalpha_struct *latoomutalpha) { + calc(latoomutalpha, latoomutalpha -> vars); + outlet_float(latoomutalpha -> x_obj.ob_outlet, latoomutalpha -> vars[M_x]); + outlet_float(latoomutalpha -> outlets[M_y - 1], latoomutalpha -> vars[M_y]); +} // end calculate + +static void reset(latoomutalpha_struct *latoomutalpha, t_symbol *s, int argc, t_atom *argv) { + if (argc == M_var_count) { + latoomutalpha -> vars[M_x] = (double) atom_getfloatarg(M_x, argc, argv); + latoomutalpha -> vars[M_y] = (double) atom_getfloatarg(M_y, argc, argv); + } else { + latoomutalpha -> vars[M_x] = latoomutalpha -> vars_init[M_x]; + latoomutalpha -> vars[M_y] = latoomutalpha -> vars_init[M_y]; + } // end if +} // end reset + +static char *classify(latoomutalpha_struct *latoomutalpha) { + static char buff[5]; + char *c = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + buff[0] = c[(int) (((latoomutalpha -> a - M_a_lo) * (1.0 / (M_a_hi - M_a_lo))) * 26)]; + buff[1] = c[(int) (((latoomutalpha -> b - M_b_lo) * (1.0 / (M_b_hi - M_b_lo))) * 26)]; + buff[2] = c[(int) (((latoomutalpha -> c - M_c_lo) * (1.0 / (M_c_hi - M_c_lo))) * 26)]; + buff[3] = c[(int) (((latoomutalpha -> d - M_d_lo) * (1.0 / (M_d_hi - M_d_lo))) * 26)]; + buff[4] = '\0'; + return buff; +} + +static void make_results(latoomutalpha_struct *latoomutalpha) { + SETFLOAT(&latoomutalpha -> search_out[0], latoomutalpha -> lyap_exp); + SETSYMBOL(&latoomutalpha -> search_out[1], gensym(classify(latoomutalpha))); + SETFLOAT(&latoomutalpha -> search_out[2], latoomutalpha -> failure_ratio); + SETFLOAT(&latoomutalpha -> vars_out[M_x], latoomutalpha -> vars[M_x]); + SETFLOAT(&latoomutalpha -> vars_out[M_y], latoomutalpha -> vars[M_y]); + SETFLOAT(&latoomutalpha -> params_out[M_a], latoomutalpha -> a); + SETFLOAT(&latoomutalpha -> params_out[M_b], latoomutalpha -> b); + SETFLOAT(&latoomutalpha -> params_out[M_c], latoomutalpha -> c); + SETFLOAT(&latoomutalpha -> params_out[M_d], latoomutalpha -> d); + outlet_list(latoomutalpha -> params_outlet, gensym("list"), M_param_count, latoomutalpha -> params_out); + outlet_list(latoomutalpha -> vars_outlet, gensym("list"), M_var_count, latoomutalpha -> vars_out); +} + +static void show(latoomutalpha_struct *latoomutalpha) { + make_results(latoomutalpha); + outlet_anything(latoomutalpha -> search_outlet, gensym("show"), M_search_count, latoomutalpha -> search_out); +} + +static void param(latoomutalpha_struct *latoomutalpha, t_symbol *s, int argc, t_atom *argv) { + if (argc != 4) { + post("Incorrect number of arguments for latoomutalpha fractal. Expecting 4 arguments."); + return; + } + latoomutalpha -> a = (double) atom_getfloatarg(0, argc, argv); + latoomutalpha -> b = (double) atom_getfloatarg(1, argc, argv); + latoomutalpha -> c = (double) atom_getfloatarg(2, argc, argv); + latoomutalpha -> d = (double) atom_getfloatarg(3, argc, argv); +} + +static void seed(latoomutalpha_struct *latoomutalpha, t_symbol *s, int argc, t_atom *argv) { + if (argc > 0) { + srand48(((unsigned int)time(0))|1); + } else { + srand48((unsigned int) atom_getfloatarg(0, argc, argv)); + } +} + +static void lyap(latoomutalpha_struct *latoomutalpha, t_floatarg l, t_floatarg h, t_floatarg lim) { + latoomutalpha -> lyap_lo = l; + latoomutalpha -> lyap_hi = h; + latoomutalpha -> lyap_limit = (double) ((int) lim); +} + +static void elyap(latoomutalpha_struct *latoomutalpha) { + double results[M_var_count]; + int i; + if (lyapunov_full((void *) latoomutalpha, (t_gotfn) calc, M_var_count, latoomutalpha -> vars, results) != NULL) { + post("elyapunov:"); + for(i = 0; i < M_var_count; i++) { post("%d: %3.80f", i, results[i]); } + } +} + +static void limiter(latoomutalpha_struct *latoomutalpha) { + if (latoomutalpha -> a_lo < M_a_lo) { latoomutalpha -> a_lo = M_a_lo; } + if (latoomutalpha -> a_lo > M_a_hi) { latoomutalpha -> a_lo = M_a_hi; } + if (latoomutalpha -> a_hi < M_a_lo) { latoomutalpha -> a_hi = M_a_lo; } + if (latoomutalpha -> a_hi > M_a_hi) { latoomutalpha -> a_hi = M_a_hi; } + if (latoomutalpha -> b_lo < M_b_lo) { latoomutalpha -> b_lo = M_b_lo; } + if (latoomutalpha -> b_lo > M_b_hi) { latoomutalpha -> b_lo = M_b_hi; } + if (latoomutalpha -> b_hi < M_b_lo) { latoomutalpha -> b_hi = M_b_lo; } + if (latoomutalpha -> b_hi > M_b_hi) { latoomutalpha -> b_hi = M_b_hi; } + if (latoomutalpha -> c_lo < M_c_lo) { latoomutalpha -> c_lo = M_c_lo; } + if (latoomutalpha -> c_lo > M_c_hi) { latoomutalpha -> c_lo = M_c_hi; } + if (latoomutalpha -> c_hi < M_c_lo) { latoomutalpha -> c_hi = M_c_lo; } + if (latoomutalpha -> c_hi > M_c_hi) { latoomutalpha -> c_hi = M_c_hi; } + if (latoomutalpha -> d_lo < M_d_lo) { latoomutalpha -> d_lo = M_d_lo; } + if (latoomutalpha -> d_lo > M_d_hi) { latoomutalpha -> d_lo = M_d_hi; } + if (latoomutalpha -> d_hi < M_d_lo) { latoomutalpha -> d_hi = M_d_lo; } + if (latoomutalpha -> d_hi > M_d_hi) { latoomutalpha -> d_hi = M_d_hi; } +} + +static void constrain(latoomutalpha_struct *latoomutalpha, t_symbol *s, int argc, t_atom *argv) { + int i; + t_atom *arg = argv; + if (argc == 0) { + // reset to full limits of search ranges + latoomutalpha -> a_lo = M_a_lo; + latoomutalpha -> a_hi = M_a_hi; + latoomutalpha -> b_lo = M_b_lo; + latoomutalpha -> b_hi = M_b_hi; + latoomutalpha -> c_lo = M_c_lo; + latoomutalpha -> c_hi = M_c_hi; + latoomutalpha -> d_lo = M_d_lo; + latoomutalpha -> d_hi = M_d_hi; + return; + } + if (argc == 1) { + // set the ranges based on percentage of full range + double percent = atom_getfloat(arg); + double a_spread = ((M_a_hi - M_a_lo) * percent) / 2; + double b_spread = ((M_b_hi - M_b_lo) * percent) / 2; + double c_spread = ((M_c_hi - M_c_lo) * percent) / 2; + double d_spread = ((M_d_hi - M_d_lo) * percent) / 2; + latoomutalpha -> a_lo = latoomutalpha -> a - a_spread; + latoomutalpha -> a_hi = latoomutalpha -> a + a_spread; + latoomutalpha -> b_lo = latoomutalpha -> b - b_spread; + latoomutalpha -> b_hi = latoomutalpha -> b + b_spread; + latoomutalpha -> c_lo = latoomutalpha -> c - c_spread; + latoomutalpha -> c_hi = latoomutalpha -> c + c_spread; + latoomutalpha -> d_lo = latoomutalpha -> d - d_spread; + latoomutalpha -> d_hi = latoomutalpha -> d + d_spread; + limiter(latoomutalpha); + return; + } + if (argc != M_param_count * 2) { + post("Invalid number of arguments for latoomutalpha constraints, requires 8 values, got %d", argc); + return; + } + latoomutalpha -> a_lo = atom_getfloat(arg++); + latoomutalpha -> a_hi = atom_getfloat(arg++); + latoomutalpha -> b_lo = atom_getfloat(arg++); + latoomutalpha -> b_hi = atom_getfloat(arg++); + latoomutalpha -> c_lo = atom_getfloat(arg++); + latoomutalpha -> c_hi = atom_getfloat(arg++); + latoomutalpha -> d_lo = atom_getfloat(arg++); + latoomutalpha -> d_hi = atom_getfloat(arg++); + limiter(latoomutalpha); +} + +static void search(latoomutalpha_struct *latoomutalpha, t_symbol *s, int argc, t_atom *argv) { + int not_found, not_expired = latoomutalpha -> lyap_limit; + int jump, i, iterations; + t_atom vars[M_var_count]; + double temp_a = latoomutalpha -> a; + double temp_b = latoomutalpha -> b; + double temp_c = latoomutalpha -> c; + double temp_d = latoomutalpha -> d; + if (argc > 0) { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], atom_getfloatarg(i, argc, argv)); + } + } else { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], latoomutalpha -> vars_init[i]); + } + } + do { + jump = 500; + not_found = 0; + iterations = 10000; + bad_params: + latoomutalpha -> a = (drand48() * (latoomutalpha -> a_hi - latoomutalpha -> a_lo)) + latoomutalpha -> a_lo; + latoomutalpha -> b = (drand48() * (latoomutalpha -> b_hi - latoomutalpha -> b_lo)) + latoomutalpha -> b_lo; + latoomutalpha -> c = (drand48() * (latoomutalpha -> c_hi - latoomutalpha -> c_lo)) + latoomutalpha -> c_lo; + latoomutalpha -> d = (drand48() * (latoomutalpha -> d_hi - latoomutalpha -> d_lo)) + latoomutalpha -> d_lo; + // put any preliminary checks specific to this fractal to eliminate bad_params + + reset(latoomutalpha, NULL, argc, vars); + do { calc(latoomutalpha, latoomutalpha -> vars); } while(jump--); + latoomutalpha -> lyap_exp = lyapunov((void *) latoomutalpha, (t_gotfn) calc, M_var_count, (double *) latoomutalpha -> vars); + if (isnan(latoomutalpha -> lyap_exp)) { not_found = 1; } + if (latoomutalpha -> lyap_exp < latoomutalpha -> lyap_lo || latoomutalpha -> lyap_exp > latoomutalpha -> lyap_hi) { not_found = 1; } + not_expired--; + } while(not_found && not_expired); + reset(latoomutalpha, NULL, argc, vars); + if (!not_expired) { + post("Could not find a fractal after %d attempts.", (int) latoomutalpha -> lyap_limit); + post("Try using wider constraints."); + latoomutalpha -> a = temp_a; + latoomutalpha -> b = temp_b; + latoomutalpha -> c = temp_c; + latoomutalpha -> d = temp_d; + outlet_anything(latoomutalpha -> search_outlet, gensym("invalid"), 0, NULL); + } else { + latoomutalpha -> failure_ratio = (latoomutalpha -> lyap_limit - not_expired) / latoomutalpha -> lyap_limit; + make_results(latoomutalpha); + outlet_anything(latoomutalpha -> search_outlet, gensym("search"), M_search_count, latoomutalpha -> search_out); + } +} + +void *latoomutalpha_new(t_symbol *s, int argc, t_atom *argv) { + latoomutalpha_struct *latoomutalpha = (latoomutalpha_struct *) pd_new(latoomutalpha_class); + if (latoomutalpha != NULL) { + outlet_new(&latoomutalpha -> x_obj, &s_float); + latoomutalpha -> outlets[0] = outlet_new(&latoomutalpha -> x_obj, &s_float); + latoomutalpha -> search_outlet = outlet_new(&latoomutalpha -> x_obj, &s_list); + latoomutalpha -> vars_outlet = outlet_new(&latoomutalpha -> x_obj, &s_list); + latoomutalpha -> params_outlet = outlet_new(&latoomutalpha -> x_obj, &s_list); + if (argc == M_param_count + M_var_count) { + latoomutalpha -> vars_init[M_x] = latoomutalpha -> vars[M_x] = (double) atom_getfloatarg(0, argc, argv); + latoomutalpha -> vars_init[M_y] = latoomutalpha -> vars[M_y] = (double) atom_getfloatarg(1, argc, argv); + latoomutalpha -> a = (double) atom_getfloatarg(2, argc, argv); + latoomutalpha -> b = (double) atom_getfloatarg(3, argc, argv); + latoomutalpha -> c = (double) atom_getfloatarg(4, argc, argv); + latoomutalpha -> d = (double) atom_getfloatarg(5, argc, argv); + } else { + if (argc != 0 && argc != M_param_count + M_var_count) { + post("Incorrect number of arguments for latoomutalpha fractal. Expecting 6 arguments."); + } + latoomutalpha -> vars_init[M_x] = 0.1; + latoomutalpha -> vars_init[M_y] = 0.1; + latoomutalpha -> a = 1; + latoomutalpha -> b = 1; + latoomutalpha -> c = 1; + latoomutalpha -> d = 1; + } + constrain(latoomutalpha, NULL, 0, NULL); + lyap(latoomutalpha, -1000000.0, 1000000.0, M_failure_limit); + } + return (void *)latoomutalpha; +} + +void latoomutalpha_setup(void) { + latoomutalpha_class = class_new(gensym("latoomutalpha"), (t_newmethod) latoomutalpha_new, 0, sizeof(latoomutalpha_struct), 0, A_GIMME, 0); + class_addbang(latoomutalpha_class, (t_method) calculate); + class_addmethod(latoomutalpha_class, (t_method) reset, gensym("reset"), A_GIMME, 0); + class_addmethod(latoomutalpha_class, (t_method) show, gensym("show"), 0); + class_addmethod(latoomutalpha_class, (t_method) param, gensym("param"), A_GIMME, 0); + class_addmethod(latoomutalpha_class, (t_method) seed, gensym("seed"), A_GIMME, 0); + class_addmethod(latoomutalpha_class, (t_method) lyap, gensym("lyapunov"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(latoomutalpha_class, (t_method) elyap, gensym("elyapunov"), 0); + class_addmethod(latoomutalpha_class, (t_method) search, gensym("search"), A_GIMME, 0); + class_addmethod(latoomutalpha_class, (t_method) constrain, gensym("constrain"), A_GIMME, 0); + class_sethelpsymbol(latoomutalpha_class, gensym("help-latoomutalpha.pd")); +} + diff --git a/latoomutbeta.c b/latoomutbeta.c new file mode 100644 index 0000000..759cddd --- /dev/null +++ b/latoomutbeta.c @@ -0,0 +1,325 @@ +/* latoomutbeta Attractor PD External */ +/* Copyright Michael McGonagle, from Cliff Pickover, 2003 */ +/* This program is distributed under the params of the GNU Public License */ + +/////////////////////////////////////////////////////////////////////////////////// +/* This file is part of Chaos PD Externals. */ +/* */ +/* Chaos PD Externals are free software; you can redistribute them and/or modify */ +/* them under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Chaos PD Externals are distributed in the hope that they will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with the Chaos PD Externals; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "lyapunov.h" + +#define M_a_lo -3 +#define M_a_hi 3 +#define M_b_lo -3 +#define M_b_hi 3 +#define M_c_lo 0.5 +#define M_c_hi 1.5 +#define M_d_lo 0.5 +#define M_d_hi 1.5 + +#define M_a 0 +#define M_b 1 +#define M_c 2 +#define M_d 3 + +#define M_x 0 +#define M_y 1 + +#define M_param_count 4 +#define M_var_count 2 +#define M_search_count 3 +#define M_failure_limit 1000 + +static char *version = "latoomutbeta v0.0, by Michael McGonagle, from Cliff Pickover, 2003"; + +t_class *latoomutbeta_class; + +typedef struct latoomutbeta_struct { + t_object x_obj; + + double vars[M_var_count]; + double vars_init[M_var_count]; + t_atom vars_out[M_var_count]; + t_outlet *vars_outlet; + + t_atom search_out[M_search_count]; + t_outlet *search_outlet; + + double a, a_lo, a_hi, b, b_lo, b_hi, c, c_lo, c_hi, d, d_lo, d_hi; + t_atom params_out[M_param_count]; + t_outlet *params_outlet; + double lyap_exp, lyap_lo, lyap_hi, lyap_limit, failure_ratio; + + t_outlet *outlets[M_var_count - 1]; +} latoomutbeta_struct; + +static void calc(latoomutbeta_struct *latoomutbeta, double *vars) { + double x_0, y_0; + x_0 =sin(vars[M_y]*latoomutbeta -> b)+pow(sin(vars[M_x]*latoomutbeta -> b),2); + y_0 =sin(vars[M_x]*latoomutbeta -> a)+pow(sin(vars[M_y]*latoomutbeta -> a),2); + vars[M_x] = x_0; + vars[M_y] = y_0; +} // end calc + +static void calculate(latoomutbeta_struct *latoomutbeta) { + calc(latoomutbeta, latoomutbeta -> vars); + outlet_float(latoomutbeta -> x_obj.ob_outlet, latoomutbeta -> vars[M_x]); + outlet_float(latoomutbeta -> outlets[M_y - 1], latoomutbeta -> vars[M_y]); +} // end calculate + +static void reset(latoomutbeta_struct *latoomutbeta, t_symbol *s, int argc, t_atom *argv) { + if (argc == M_var_count) { + latoomutbeta -> vars[M_x] = (double) atom_getfloatarg(M_x, argc, argv); + latoomutbeta -> vars[M_y] = (double) atom_getfloatarg(M_y, argc, argv); + } else { + latoomutbeta -> vars[M_x] = latoomutbeta -> vars_init[M_x]; + latoomutbeta -> vars[M_y] = latoomutbeta -> vars_init[M_y]; + } // end if +} // end reset + +static char *classify(latoomutbeta_struct *latoomutbeta) { + static char buff[5]; + char *c = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + buff[0] = c[(int) (((latoomutbeta -> a - M_a_lo) * (1.0 / (M_a_hi - M_a_lo))) * 26)]; + buff[1] = c[(int) (((latoomutbeta -> b - M_b_lo) * (1.0 / (M_b_hi - M_b_lo))) * 26)]; + buff[2] = c[(int) (((latoomutbeta -> c - M_c_lo) * (1.0 / (M_c_hi - M_c_lo))) * 26)]; + buff[3] = c[(int) (((latoomutbeta -> d - M_d_lo) * (1.0 / (M_d_hi - M_d_lo))) * 26)]; + buff[4] = '\0'; + return buff; +} + +static void make_results(latoomutbeta_struct *latoomutbeta) { + SETFLOAT(&latoomutbeta -> search_out[0], latoomutbeta -> lyap_exp); + SETSYMBOL(&latoomutbeta -> search_out[1], gensym(classify(latoomutbeta))); + SETFLOAT(&latoomutbeta -> search_out[2], latoomutbeta -> failure_ratio); + SETFLOAT(&latoomutbeta -> vars_out[M_x], latoomutbeta -> vars[M_x]); + SETFLOAT(&latoomutbeta -> vars_out[M_y], latoomutbeta -> vars[M_y]); + SETFLOAT(&latoomutbeta -> params_out[M_a], latoomutbeta -> a); + SETFLOAT(&latoomutbeta -> params_out[M_b], latoomutbeta -> b); + SETFLOAT(&latoomutbeta -> params_out[M_c], latoomutbeta -> c); + SETFLOAT(&latoomutbeta -> params_out[M_d], latoomutbeta -> d); + outlet_list(latoomutbeta -> params_outlet, gensym("list"), M_param_count, latoomutbeta -> params_out); + outlet_list(latoomutbeta -> vars_outlet, gensym("list"), M_var_count, latoomutbeta -> vars_out); +} + +static void show(latoomutbeta_struct *latoomutbeta) { + make_results(latoomutbeta); + outlet_anything(latoomutbeta -> search_outlet, gensym("show"), M_search_count, latoomutbeta -> search_out); +} + +static void param(latoomutbeta_struct *latoomutbeta, t_symbol *s, int argc, t_atom *argv) { + if (argc != 4) { + post("Incorrect number of arguments for latoomutbeta fractal. Expecting 4 arguments."); + return; + } + latoomutbeta -> a = (double) atom_getfloatarg(0, argc, argv); + latoomutbeta -> b = (double) atom_getfloatarg(1, argc, argv); + latoomutbeta -> c = (double) atom_getfloatarg(2, argc, argv); + latoomutbeta -> d = (double) atom_getfloatarg(3, argc, argv); +} + +static void seed(latoomutbeta_struct *latoomutbeta, t_symbol *s, int argc, t_atom *argv) { + if (argc > 0) { + srand48(((unsigned int)time(0))|1); + } else { + srand48((unsigned int) atom_getfloatarg(0, argc, argv)); + } +} + +static void lyap(latoomutbeta_struct *latoomutbeta, t_floatarg l, t_floatarg h, t_floatarg lim) { + latoomutbeta -> lyap_lo = l; + latoomutbeta -> lyap_hi = h; + latoomutbeta -> lyap_limit = (double) ((int) lim); +} + +static void elyap(latoomutbeta_struct *latoomutbeta) { + double results[M_var_count]; + int i; + if (lyapunov_full((void *) latoomutbeta, (t_gotfn) calc, M_var_count, latoomutbeta -> vars, results) != NULL) { + post("elyapunov:"); + for(i = 0; i < M_var_count; i++) { post("%d: %3.80f", i, results[i]); } + } +} + +static void limiter(latoomutbeta_struct *latoomutbeta) { + if (latoomutbeta -> a_lo < M_a_lo) { latoomutbeta -> a_lo = M_a_lo; } + if (latoomutbeta -> a_lo > M_a_hi) { latoomutbeta -> a_lo = M_a_hi; } + if (latoomutbeta -> a_hi < M_a_lo) { latoomutbeta -> a_hi = M_a_lo; } + if (latoomutbeta -> a_hi > M_a_hi) { latoomutbeta -> a_hi = M_a_hi; } + if (latoomutbeta -> b_lo < M_b_lo) { latoomutbeta -> b_lo = M_b_lo; } + if (latoomutbeta -> b_lo > M_b_hi) { latoomutbeta -> b_lo = M_b_hi; } + if (latoomutbeta -> b_hi < M_b_lo) { latoomutbeta -> b_hi = M_b_lo; } + if (latoomutbeta -> b_hi > M_b_hi) { latoomutbeta -> b_hi = M_b_hi; } + if (latoomutbeta -> c_lo < M_c_lo) { latoomutbeta -> c_lo = M_c_lo; } + if (latoomutbeta -> c_lo > M_c_hi) { latoomutbeta -> c_lo = M_c_hi; } + if (latoomutbeta -> c_hi < M_c_lo) { latoomutbeta -> c_hi = M_c_lo; } + if (latoomutbeta -> c_hi > M_c_hi) { latoomutbeta -> c_hi = M_c_hi; } + if (latoomutbeta -> d_lo < M_d_lo) { latoomutbeta -> d_lo = M_d_lo; } + if (latoomutbeta -> d_lo > M_d_hi) { latoomutbeta -> d_lo = M_d_hi; } + if (latoomutbeta -> d_hi < M_d_lo) { latoomutbeta -> d_hi = M_d_lo; } + if (latoomutbeta -> d_hi > M_d_hi) { latoomutbeta -> d_hi = M_d_hi; } +} + +static void constrain(latoomutbeta_struct *latoomutbeta, t_symbol *s, int argc, t_atom *argv) { + int i; + t_atom *arg = argv; + if (argc == 0) { + // reset to full limits of search ranges + latoomutbeta -> a_lo = M_a_lo; + latoomutbeta -> a_hi = M_a_hi; + latoomutbeta -> b_lo = M_b_lo; + latoomutbeta -> b_hi = M_b_hi; + latoomutbeta -> c_lo = M_c_lo; + latoomutbeta -> c_hi = M_c_hi; + latoomutbeta -> d_lo = M_d_lo; + latoomutbeta -> d_hi = M_d_hi; + return; + } + if (argc == 1) { + // set the ranges based on percentage of full range + double percent = atom_getfloat(arg); + double a_spread = ((M_a_hi - M_a_lo) * percent) / 2; + double b_spread = ((M_b_hi - M_b_lo) * percent) / 2; + double c_spread = ((M_c_hi - M_c_lo) * percent) / 2; + double d_spread = ((M_d_hi - M_d_lo) * percent) / 2; + latoomutbeta -> a_lo = latoomutbeta -> a - a_spread; + latoomutbeta -> a_hi = latoomutbeta -> a + a_spread; + latoomutbeta -> b_lo = latoomutbeta -> b - b_spread; + latoomutbeta -> b_hi = latoomutbeta -> b + b_spread; + latoomutbeta -> c_lo = latoomutbeta -> c - c_spread; + latoomutbeta -> c_hi = latoomutbeta -> c + c_spread; + latoomutbeta -> d_lo = latoomutbeta -> d - d_spread; + latoomutbeta -> d_hi = latoomutbeta -> d + d_spread; + limiter(latoomutbeta); + return; + } + if (argc != M_param_count * 2) { + post("Invalid number of arguments for latoomutbeta constraints, requires 8 values, got %d", argc); + return; + } + latoomutbeta -> a_lo = atom_getfloat(arg++); + latoomutbeta -> a_hi = atom_getfloat(arg++); + latoomutbeta -> b_lo = atom_getfloat(arg++); + latoomutbeta -> b_hi = atom_getfloat(arg++); + latoomutbeta -> c_lo = atom_getfloat(arg++); + latoomutbeta -> c_hi = atom_getfloat(arg++); + latoomutbeta -> d_lo = atom_getfloat(arg++); + latoomutbeta -> d_hi = atom_getfloat(arg++); + limiter(latoomutbeta); +} + +static void search(latoomutbeta_struct *latoomutbeta, t_symbol *s, int argc, t_atom *argv) { + int not_found, not_expired = latoomutbeta -> lyap_limit; + int jump, i, iterations; + t_atom vars[M_var_count]; + double temp_a = latoomutbeta -> a; + double temp_b = latoomutbeta -> b; + double temp_c = latoomutbeta -> c; + double temp_d = latoomutbeta -> d; + if (argc > 0) { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], atom_getfloatarg(i, argc, argv)); + } + } else { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], latoomutbeta -> vars_init[i]); + } + } + do { + jump = 500; + not_found = 0; + iterations = 10000; + bad_params: + latoomutbeta -> a = (drand48() * (latoomutbeta -> a_hi - latoomutbeta -> a_lo)) + latoomutbeta -> a_lo; + latoomutbeta -> b = (drand48() * (latoomutbeta -> b_hi - latoomutbeta -> b_lo)) + latoomutbeta -> b_lo; + latoomutbeta -> c = (drand48() * (latoomutbeta -> c_hi - latoomutbeta -> c_lo)) + latoomutbeta -> c_lo; + latoomutbeta -> d = (drand48() * (latoomutbeta -> d_hi - latoomutbeta -> d_lo)) + latoomutbeta -> d_lo; + // put any preliminary checks specific to this fractal to eliminate bad_params + + reset(latoomutbeta, NULL, argc, vars); + do { calc(latoomutbeta, latoomutbeta -> vars); } while(jump--); + latoomutbeta -> lyap_exp = lyapunov((void *) latoomutbeta, (t_gotfn) calc, M_var_count, (double *) latoomutbeta -> vars); + if (isnan(latoomutbeta -> lyap_exp)) { not_found = 1; } + if (latoomutbeta -> lyap_exp < latoomutbeta -> lyap_lo || latoomutbeta -> lyap_exp > latoomutbeta -> lyap_hi) { not_found = 1; } + not_expired--; + } while(not_found && not_expired); + reset(latoomutbeta, NULL, argc, vars); + if (!not_expired) { + post("Could not find a fractal after %d attempts.", (int) latoomutbeta -> lyap_limit); + post("Try using wider constraints."); + latoomutbeta -> a = temp_a; + latoomutbeta -> b = temp_b; + latoomutbeta -> c = temp_c; + latoomutbeta -> d = temp_d; + outlet_anything(latoomutbeta -> search_outlet, gensym("invalid"), 0, NULL); + } else { + latoomutbeta -> failure_ratio = (latoomutbeta -> lyap_limit - not_expired) / latoomutbeta -> lyap_limit; + make_results(latoomutbeta); + outlet_anything(latoomutbeta -> search_outlet, gensym("search"), M_search_count, latoomutbeta -> search_out); + } +} + +void *latoomutbeta_new(t_symbol *s, int argc, t_atom *argv) { + latoomutbeta_struct *latoomutbeta = (latoomutbeta_struct *) pd_new(latoomutbeta_class); + if (latoomutbeta != NULL) { + outlet_new(&latoomutbeta -> x_obj, &s_float); + latoomutbeta -> outlets[0] = outlet_new(&latoomutbeta -> x_obj, &s_float); + latoomutbeta -> search_outlet = outlet_new(&latoomutbeta -> x_obj, &s_list); + latoomutbeta -> vars_outlet = outlet_new(&latoomutbeta -> x_obj, &s_list); + latoomutbeta -> params_outlet = outlet_new(&latoomutbeta -> x_obj, &s_list); + if (argc == M_param_count + M_var_count) { + latoomutbeta -> vars_init[M_x] = latoomutbeta -> vars[M_x] = (double) atom_getfloatarg(0, argc, argv); + latoomutbeta -> vars_init[M_y] = latoomutbeta -> vars[M_y] = (double) atom_getfloatarg(1, argc, argv); + latoomutbeta -> a = (double) atom_getfloatarg(2, argc, argv); + latoomutbeta -> b = (double) atom_getfloatarg(3, argc, argv); + latoomutbeta -> c = (double) atom_getfloatarg(4, argc, argv); + latoomutbeta -> d = (double) atom_getfloatarg(5, argc, argv); + } else { + if (argc != 0 && argc != M_param_count + M_var_count) { + post("Incorrect number of arguments for latoomutbeta fractal. Expecting 6 arguments."); + } + latoomutbeta -> vars_init[M_x] = 0.1; + latoomutbeta -> vars_init[M_y] = 0.1; + latoomutbeta -> a = 1; + latoomutbeta -> b = 1; + latoomutbeta -> c = 1; + latoomutbeta -> d = 1; + } + constrain(latoomutbeta, NULL, 0, NULL); + lyap(latoomutbeta, -1000000.0, 1000000.0, M_failure_limit); + } + return (void *)latoomutbeta; +} + +void latoomutbeta_setup(void) { + latoomutbeta_class = class_new(gensym("latoomutbeta"), (t_newmethod) latoomutbeta_new, 0, sizeof(latoomutbeta_struct), 0, A_GIMME, 0); + class_addbang(latoomutbeta_class, (t_method) calculate); + class_addmethod(latoomutbeta_class, (t_method) reset, gensym("reset"), A_GIMME, 0); + class_addmethod(latoomutbeta_class, (t_method) show, gensym("show"), 0); + class_addmethod(latoomutbeta_class, (t_method) param, gensym("param"), A_GIMME, 0); + class_addmethod(latoomutbeta_class, (t_method) seed, gensym("seed"), A_GIMME, 0); + class_addmethod(latoomutbeta_class, (t_method) lyap, gensym("lyapunov"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(latoomutbeta_class, (t_method) elyap, gensym("elyapunov"), 0); + class_addmethod(latoomutbeta_class, (t_method) search, gensym("search"), A_GIMME, 0); + class_addmethod(latoomutbeta_class, (t_method) constrain, gensym("constrain"), A_GIMME, 0); + class_sethelpsymbol(latoomutbeta_class, gensym("help-latoomutbeta.pd")); +} + diff --git a/latoomutgamma.c b/latoomutgamma.c new file mode 100644 index 0000000..ea9f717 --- /dev/null +++ b/latoomutgamma.c @@ -0,0 +1,325 @@ +/* latoomutgamma Attractor PD External */ +/* Copyright Michael McGonagle, from Cliff Pickover, 2003 */ +/* This program is distributed under the params of the GNU Public License */ + +/////////////////////////////////////////////////////////////////////////////////// +/* This file is part of Chaos PD Externals. */ +/* */ +/* Chaos PD Externals are free software; you can redistribute them and/or modify */ +/* them under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Chaos PD Externals are distributed in the hope that they will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with the Chaos PD Externals; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "lyapunov.h" + +#define M_a_lo -3 +#define M_a_hi 3 +#define M_b_lo -3 +#define M_b_hi 3 +#define M_c_lo 0.5 +#define M_c_hi 1.5 +#define M_d_lo 0.5 +#define M_d_hi 1.5 + +#define M_a 0 +#define M_b 1 +#define M_c 2 +#define M_d 3 + +#define M_x 0 +#define M_y 1 + +#define M_param_count 4 +#define M_var_count 2 +#define M_search_count 3 +#define M_failure_limit 1000 + +static char *version = "latoomutgamma v0.0, by Michael McGonagle, from Cliff Pickover, 2003"; + +t_class *latoomutgamma_class; + +typedef struct latoomutgamma_struct { + t_object x_obj; + + double vars[M_var_count]; + double vars_init[M_var_count]; + t_atom vars_out[M_var_count]; + t_outlet *vars_outlet; + + t_atom search_out[M_search_count]; + t_outlet *search_outlet; + + double a, a_lo, a_hi, b, b_lo, b_hi, c, c_lo, c_hi, d, d_lo, d_hi; + t_atom params_out[M_param_count]; + t_outlet *params_outlet; + double lyap_exp, lyap_lo, lyap_hi, lyap_limit, failure_ratio; + + t_outlet *outlets[M_var_count - 1]; +} latoomutgamma_struct; + +static void calc(latoomutgamma_struct *latoomutgamma, double *vars) { + double x_0, y_0; + x_0 =abs(sin(vars[M_y]*latoomutgamma -> b))+pow(sin(vars[M_x]*latoomutgamma -> b),2); + y_0 =abs(sin(vars[M_x]*latoomutgamma -> a))+pow(sin(vars[M_y]*latoomutgamma -> b),2); + vars[M_x] = x_0; + vars[M_y] = y_0; +} // end calc + +static void calculate(latoomutgamma_struct *latoomutgamma) { + calc(latoomutgamma, latoomutgamma -> vars); + outlet_float(latoomutgamma -> x_obj.ob_outlet, latoomutgamma -> vars[M_x]); + outlet_float(latoomutgamma -> outlets[M_y - 1], latoomutgamma -> vars[M_y]); +} // end calculate + +static void reset(latoomutgamma_struct *latoomutgamma, t_symbol *s, int argc, t_atom *argv) { + if (argc == M_var_count) { + latoomutgamma -> vars[M_x] = (double) atom_getfloatarg(M_x, argc, argv); + latoomutgamma -> vars[M_y] = (double) atom_getfloatarg(M_y, argc, argv); + } else { + latoomutgamma -> vars[M_x] = latoomutgamma -> vars_init[M_x]; + latoomutgamma -> vars[M_y] = latoomutgamma -> vars_init[M_y]; + } // end if +} // end reset + +static char *classify(latoomutgamma_struct *latoomutgamma) { + static char buff[5]; + char *c = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + buff[0] = c[(int) (((latoomutgamma -> a - M_a_lo) * (1.0 / (M_a_hi - M_a_lo))) * 26)]; + buff[1] = c[(int) (((latoomutgamma -> b - M_b_lo) * (1.0 / (M_b_hi - M_b_lo))) * 26)]; + buff[2] = c[(int) (((latoomutgamma -> c - M_c_lo) * (1.0 / (M_c_hi - M_c_lo))) * 26)]; + buff[3] = c[(int) (((latoomutgamma -> d - M_d_lo) * (1.0 / (M_d_hi - M_d_lo))) * 26)]; + buff[4] = '\0'; + return buff; +} + +static void make_results(latoomutgamma_struct *latoomutgamma) { + SETFLOAT(&latoomutgamma -> search_out[0], latoomutgamma -> lyap_exp); + SETSYMBOL(&latoomutgamma -> search_out[1], gensym(classify(latoomutgamma))); + SETFLOAT(&latoomutgamma -> search_out[2], latoomutgamma -> failure_ratio); + SETFLOAT(&latoomutgamma -> vars_out[M_x], latoomutgamma -> vars[M_x]); + SETFLOAT(&latoomutgamma -> vars_out[M_y], latoomutgamma -> vars[M_y]); + SETFLOAT(&latoomutgamma -> params_out[M_a], latoomutgamma -> a); + SETFLOAT(&latoomutgamma -> params_out[M_b], latoomutgamma -> b); + SETFLOAT(&latoomutgamma -> params_out[M_c], latoomutgamma -> c); + SETFLOAT(&latoomutgamma -> params_out[M_d], latoomutgamma -> d); + outlet_list(latoomutgamma -> params_outlet, gensym("list"), M_param_count, latoomutgamma -> params_out); + outlet_list(latoomutgamma -> vars_outlet, gensym("list"), M_var_count, latoomutgamma -> vars_out); +} + +static void show(latoomutgamma_struct *latoomutgamma) { + make_results(latoomutgamma); + outlet_anything(latoomutgamma -> search_outlet, gensym("show"), M_search_count, latoomutgamma -> search_out); +} + +static void param(latoomutgamma_struct *latoomutgamma, t_symbol *s, int argc, t_atom *argv) { + if (argc != 4) { + post("Incorrect number of arguments for latoomutgamma fractal. Expecting 4 arguments."); + return; + } + latoomutgamma -> a = (double) atom_getfloatarg(0, argc, argv); + latoomutgamma -> b = (double) atom_getfloatarg(1, argc, argv); + latoomutgamma -> c = (double) atom_getfloatarg(2, argc, argv); + latoomutgamma -> d = (double) atom_getfloatarg(3, argc, argv); +} + +static void seed(latoomutgamma_struct *latoomutgamma, t_symbol *s, int argc, t_atom *argv) { + if (argc > 0) { + srand48(((unsigned int)time(0))|1); + } else { + srand48((unsigned int) atom_getfloatarg(0, argc, argv)); + } +} + +static void lyap(latoomutgamma_struct *latoomutgamma, t_floatarg l, t_floatarg h, t_floatarg lim) { + latoomutgamma -> lyap_lo = l; + latoomutgamma -> lyap_hi = h; + latoomutgamma -> lyap_limit = (double) ((int) lim); +} + +static void elyap(latoomutgamma_struct *latoomutgamma) { + double results[M_var_count]; + int i; + if (lyapunov_full((void *) latoomutgamma, (t_gotfn) calc, M_var_count, latoomutgamma -> vars, results) != NULL) { + post("elyapunov:"); + for(i = 0; i < M_var_count; i++) { post("%d: %3.80f", i, results[i]); } + } +} + +static void limiter(latoomutgamma_struct *latoomutgamma) { + if (latoomutgamma -> a_lo < M_a_lo) { latoomutgamma -> a_lo = M_a_lo; } + if (latoomutgamma -> a_lo > M_a_hi) { latoomutgamma -> a_lo = M_a_hi; } + if (latoomutgamma -> a_hi < M_a_lo) { latoomutgamma -> a_hi = M_a_lo; } + if (latoomutgamma -> a_hi > M_a_hi) { latoomutgamma -> a_hi = M_a_hi; } + if (latoomutgamma -> b_lo < M_b_lo) { latoomutgamma -> b_lo = M_b_lo; } + if (latoomutgamma -> b_lo > M_b_hi) { latoomutgamma -> b_lo = M_b_hi; } + if (latoomutgamma -> b_hi < M_b_lo) { latoomutgamma -> b_hi = M_b_lo; } + if (latoomutgamma -> b_hi > M_b_hi) { latoomutgamma -> b_hi = M_b_hi; } + if (latoomutgamma -> c_lo < M_c_lo) { latoomutgamma -> c_lo = M_c_lo; } + if (latoomutgamma -> c_lo > M_c_hi) { latoomutgamma -> c_lo = M_c_hi; } + if (latoomutgamma -> c_hi < M_c_lo) { latoomutgamma -> c_hi = M_c_lo; } + if (latoomutgamma -> c_hi > M_c_hi) { latoomutgamma -> c_hi = M_c_hi; } + if (latoomutgamma -> d_lo < M_d_lo) { latoomutgamma -> d_lo = M_d_lo; } + if (latoomutgamma -> d_lo > M_d_hi) { latoomutgamma -> d_lo = M_d_hi; } + if (latoomutgamma -> d_hi < M_d_lo) { latoomutgamma -> d_hi = M_d_lo; } + if (latoomutgamma -> d_hi > M_d_hi) { latoomutgamma -> d_hi = M_d_hi; } +} + +static void constrain(latoomutgamma_struct *latoomutgamma, t_symbol *s, int argc, t_atom *argv) { + int i; + t_atom *arg = argv; + if (argc == 0) { + // reset to full limits of search ranges + latoomutgamma -> a_lo = M_a_lo; + latoomutgamma -> a_hi = M_a_hi; + latoomutgamma -> b_lo = M_b_lo; + latoomutgamma -> b_hi = M_b_hi; + latoomutgamma -> c_lo = M_c_lo; + latoomutgamma -> c_hi = M_c_hi; + latoomutgamma -> d_lo = M_d_lo; + latoomutgamma -> d_hi = M_d_hi; + return; + } + if (argc == 1) { + // set the ranges based on percentage of full range + double percent = atom_getfloat(arg); + double a_spread = ((M_a_hi - M_a_lo) * percent) / 2; + double b_spread = ((M_b_hi - M_b_lo) * percent) / 2; + double c_spread = ((M_c_hi - M_c_lo) * percent) / 2; + double d_spread = ((M_d_hi - M_d_lo) * percent) / 2; + latoomutgamma -> a_lo = latoomutgamma -> a - a_spread; + latoomutgamma -> a_hi = latoomutgamma -> a + a_spread; + latoomutgamma -> b_lo = latoomutgamma -> b - b_spread; + latoomutgamma -> b_hi = latoomutgamma -> b + b_spread; + latoomutgamma -> c_lo = latoomutgamma -> c - c_spread; + latoomutgamma -> c_hi = latoomutgamma -> c + c_spread; + latoomutgamma -> d_lo = latoomutgamma -> d - d_spread; + latoomutgamma -> d_hi = latoomutgamma -> d + d_spread; + limiter(latoomutgamma); + return; + } + if (argc != M_param_count * 2) { + post("Invalid number of arguments for latoomutgamma constraints, requires 8 values, got %d", argc); + return; + } + latoomutgamma -> a_lo = atom_getfloat(arg++); + latoomutgamma -> a_hi = atom_getfloat(arg++); + latoomutgamma -> b_lo = atom_getfloat(arg++); + latoomutgamma -> b_hi = atom_getfloat(arg++); + latoomutgamma -> c_lo = atom_getfloat(arg++); + latoomutgamma -> c_hi = atom_getfloat(arg++); + latoomutgamma -> d_lo = atom_getfloat(arg++); + latoomutgamma -> d_hi = atom_getfloat(arg++); + limiter(latoomutgamma); +} + +static void search(latoomutgamma_struct *latoomutgamma, t_symbol *s, int argc, t_atom *argv) { + int not_found, not_expired = latoomutgamma -> lyap_limit; + int jump, i, iterations; + t_atom vars[M_var_count]; + double temp_a = latoomutgamma -> a; + double temp_b = latoomutgamma -> b; + double temp_c = latoomutgamma -> c; + double temp_d = latoomutgamma -> d; + if (argc > 0) { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], atom_getfloatarg(i, argc, argv)); + } + } else { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], latoomutgamma -> vars_init[i]); + } + } + do { + jump = 500; + not_found = 0; + iterations = 10000; + bad_params: + latoomutgamma -> a = (drand48() * (latoomutgamma -> a_hi - latoomutgamma -> a_lo)) + latoomutgamma -> a_lo; + latoomutgamma -> b = (drand48() * (latoomutgamma -> b_hi - latoomutgamma -> b_lo)) + latoomutgamma -> b_lo; + latoomutgamma -> c = (drand48() * (latoomutgamma -> c_hi - latoomutgamma -> c_lo)) + latoomutgamma -> c_lo; + latoomutgamma -> d = (drand48() * (latoomutgamma -> d_hi - latoomutgamma -> d_lo)) + latoomutgamma -> d_lo; + // put any preliminary checks specific to this fractal to eliminate bad_params + + reset(latoomutgamma, NULL, argc, vars); + do { calc(latoomutgamma, latoomutgamma -> vars); } while(jump--); + latoomutgamma -> lyap_exp = lyapunov((void *) latoomutgamma, (t_gotfn) calc, M_var_count, (double *) latoomutgamma -> vars); + if (isnan(latoomutgamma -> lyap_exp)) { not_found = 1; } + if (latoomutgamma -> lyap_exp < latoomutgamma -> lyap_lo || latoomutgamma -> lyap_exp > latoomutgamma -> lyap_hi) { not_found = 1; } + not_expired--; + } while(not_found && not_expired); + reset(latoomutgamma, NULL, argc, vars); + if (!not_expired) { + post("Could not find a fractal after %d attempts.", (int) latoomutgamma -> lyap_limit); + post("Try using wider constraints."); + latoomutgamma -> a = temp_a; + latoomutgamma -> b = temp_b; + latoomutgamma -> c = temp_c; + latoomutgamma -> d = temp_d; + outlet_anything(latoomutgamma -> search_outlet, gensym("invalid"), 0, NULL); + } else { + latoomutgamma -> failure_ratio = (latoomutgamma -> lyap_limit - not_expired) / latoomutgamma -> lyap_limit; + make_results(latoomutgamma); + outlet_anything(latoomutgamma -> search_outlet, gensym("search"), M_search_count, latoomutgamma -> search_out); + } +} + +void *latoomutgamma_new(t_symbol *s, int argc, t_atom *argv) { + latoomutgamma_struct *latoomutgamma = (latoomutgamma_struct *) pd_new(latoomutgamma_class); + if (latoomutgamma != NULL) { + outlet_new(&latoomutgamma -> x_obj, &s_float); + latoomutgamma -> outlets[0] = outlet_new(&latoomutgamma -> x_obj, &s_float); + latoomutgamma -> search_outlet = outlet_new(&latoomutgamma -> x_obj, &s_list); + latoomutgamma -> vars_outlet = outlet_new(&latoomutgamma -> x_obj, &s_list); + latoomutgamma -> params_outlet = outlet_new(&latoomutgamma -> x_obj, &s_list); + if (argc == M_param_count + M_var_count) { + latoomutgamma -> vars_init[M_x] = latoomutgamma -> vars[M_x] = (double) atom_getfloatarg(0, argc, argv); + latoomutgamma -> vars_init[M_y] = latoomutgamma -> vars[M_y] = (double) atom_getfloatarg(1, argc, argv); + latoomutgamma -> a = (double) atom_getfloatarg(2, argc, argv); + latoomutgamma -> b = (double) atom_getfloatarg(3, argc, argv); + latoomutgamma -> c = (double) atom_getfloatarg(4, argc, argv); + latoomutgamma -> d = (double) atom_getfloatarg(5, argc, argv); + } else { + if (argc != 0 && argc != M_param_count + M_var_count) { + post("Incorrect number of arguments for latoomutgamma fractal. Expecting 6 arguments."); + } + latoomutgamma -> vars_init[M_x] = 0.1; + latoomutgamma -> vars_init[M_y] = 0.1; + latoomutgamma -> a = 1; + latoomutgamma -> b = 1; + latoomutgamma -> c = 1; + latoomutgamma -> d = 1; + } + constrain(latoomutgamma, NULL, 0, NULL); + lyap(latoomutgamma, -1000000.0, 1000000.0, M_failure_limit); + } + return (void *)latoomutgamma; +} + +void latoomutgamma_setup(void) { + latoomutgamma_class = class_new(gensym("latoomutgamma"), (t_newmethod) latoomutgamma_new, 0, sizeof(latoomutgamma_struct), 0, A_GIMME, 0); + class_addbang(latoomutgamma_class, (t_method) calculate); + class_addmethod(latoomutgamma_class, (t_method) reset, gensym("reset"), A_GIMME, 0); + class_addmethod(latoomutgamma_class, (t_method) show, gensym("show"), 0); + class_addmethod(latoomutgamma_class, (t_method) param, gensym("param"), A_GIMME, 0); + class_addmethod(latoomutgamma_class, (t_method) seed, gensym("seed"), A_GIMME, 0); + class_addmethod(latoomutgamma_class, (t_method) lyap, gensym("lyapunov"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(latoomutgamma_class, (t_method) elyap, gensym("elyapunov"), 0); + class_addmethod(latoomutgamma_class, (t_method) search, gensym("search"), A_GIMME, 0); + class_addmethod(latoomutgamma_class, (t_method) constrain, gensym("constrain"), A_GIMME, 0); + class_sethelpsymbol(latoomutgamma_class, gensym("help-latoomutgamma.pd")); +} + diff --git a/mlogistic.c b/mlogistic.c new file mode 100644 index 0000000..def932b --- /dev/null +++ b/mlogistic.c @@ -0,0 +1,247 @@ +/* mlogistic Attractor PD External */ +/* Copyright Michael McGonagle, from ??????, 2003 */ +/* This program is distributed under the params of the GNU Public License */ + +/////////////////////////////////////////////////////////////////////////////////// +/* This file is part of Chaos PD Externals. */ +/* */ +/* Chaos PD Externals are free software; you can redistribute them and/or modify */ +/* them under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Chaos PD Externals are distributed in the hope that they will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with the Chaos PD Externals; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "lyapunov.h" + +#define M_c_lo 0 +#define M_c_hi 4 + +#define M_c 0 + +#define M_x 0 + +#define M_param_count 1 +#define M_var_count 1 +#define M_search_count 3 +#define M_failure_limit 1000 + +static char *version = "mlogistic v0.0, by Michael McGonagle, from ??????, 2003"; + +t_class *mlogistic_class; + +typedef struct mlogistic_struct { + t_object x_obj; + + double vars[M_var_count]; + double vars_init[M_var_count]; + t_atom vars_out[M_var_count]; + t_outlet *vars_outlet; + + t_atom search_out[M_search_count]; + t_outlet *search_outlet; + + double c, c_lo, c_hi; + t_atom params_out[M_param_count]; + t_outlet *params_outlet; + double lyap_exp, lyap_lo, lyap_hi, lyap_limit, failure_ratio; +} mlogistic_struct; + +static void calc(mlogistic_struct *mlogistic, double *vars) { + double x_0; + x_0 =(vars[M_x]*vars[M_x])+mlogistic -> c; + vars[M_x] = x_0; +} // end calc + +static void calculate(mlogistic_struct *mlogistic) { + calc(mlogistic, mlogistic -> vars); + outlet_float(mlogistic -> x_obj.ob_outlet, mlogistic -> vars[M_x]); +} // end calculate + +static void reset(mlogistic_struct *mlogistic, t_symbol *s, int argc, t_atom *argv) { + if (argc == M_var_count) { + mlogistic -> vars[M_x] = (double) atom_getfloatarg(M_x, argc, argv); + } else { + mlogistic -> vars[M_x] = mlogistic -> vars_init[M_x]; + } // end if +} // end reset + +static char *classify(mlogistic_struct *mlogistic) { + static char buff[2]; + char *c = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + buff[0] = c[(int) (((mlogistic -> c - M_c_lo) * (1.0 / (M_c_hi - M_c_lo))) * 26)]; + buff[1] = '\0'; + return buff; +} + +static void make_results(mlogistic_struct *mlogistic) { + SETFLOAT(&mlogistic -> search_out[0], mlogistic -> lyap_exp); + SETSYMBOL(&mlogistic -> search_out[1], gensym(classify(mlogistic))); + SETFLOAT(&mlogistic -> search_out[2], mlogistic -> failure_ratio); + SETFLOAT(&mlogistic -> vars_out[M_x], mlogistic -> vars[M_x]); + SETFLOAT(&mlogistic -> params_out[M_c], mlogistic -> c); + outlet_list(mlogistic -> params_outlet, gensym("list"), M_param_count, mlogistic -> params_out); + outlet_list(mlogistic -> vars_outlet, gensym("list"), M_var_count, mlogistic -> vars_out); +} + +static void show(mlogistic_struct *mlogistic) { + make_results(mlogistic); + outlet_anything(mlogistic -> search_outlet, gensym("show"), M_search_count, mlogistic -> search_out); +} + +static void param(mlogistic_struct *mlogistic, t_symbol *s, int argc, t_atom *argv) { + if (argc != 1) { + post("Incorrect number of arguments for mlogistic fractal. Expecting 1 arguments."); + return; + } + mlogistic -> c = (double) atom_getfloatarg(0, argc, argv); +} + +static void seed(mlogistic_struct *mlogistic, t_symbol *s, int argc, t_atom *argv) { + if (argc > 0) { + srand48(((unsigned int)time(0))|1); + } else { + srand48((unsigned int) atom_getfloatarg(0, argc, argv)); + } +} + +static void lyap(mlogistic_struct *mlogistic, t_floatarg l, t_floatarg h, t_floatarg lim) { + mlogistic -> lyap_lo = l; + mlogistic -> lyap_hi = h; + mlogistic -> lyap_limit = (double) ((int) lim); +} + +static void elyap(mlogistic_struct *mlogistic) { + double results[M_var_count]; + int i; + if (lyapunov_full((void *) mlogistic, (t_gotfn) calc, M_var_count, mlogistic -> vars, results) != NULL) { + post("elyapunov:"); + for(i = 0; i < M_var_count; i++) { post("%d: %3.80f", i, results[i]); } + } +} + +static void limiter(mlogistic_struct *mlogistic) { + if (mlogistic -> c_lo < M_c_lo) { mlogistic -> c_lo = M_c_lo; } + if (mlogistic -> c_lo > M_c_hi) { mlogistic -> c_lo = M_c_hi; } + if (mlogistic -> c_hi < M_c_lo) { mlogistic -> c_hi = M_c_lo; } + if (mlogistic -> c_hi > M_c_hi) { mlogistic -> c_hi = M_c_hi; } +} + +static void constrain(mlogistic_struct *mlogistic, t_symbol *s, int argc, t_atom *argv) { + int i; + t_atom *arg = argv; + if (argc == 0) { + // reset to full limits of search ranges + mlogistic -> c_lo = M_c_lo; + mlogistic -> c_hi = M_c_hi; + return; + } + if (argc == 1) { + // set the ranges based on percentage of full range + double percent = atom_getfloat(arg); + double c_spread = ((M_c_hi - M_c_lo) * percent) / 2; + mlogistic -> c_lo = mlogistic -> c - c_spread; + mlogistic -> c_hi = mlogistic -> c + c_spread; + limiter(mlogistic); + return; + } + if (argc != M_param_count * 2) { + post("Invalid number of arguments for mlogistic constraints, requires 2 values, got %d", argc); + return; + } + mlogistic -> c_lo = atom_getfloat(arg++); + mlogistic -> c_hi = atom_getfloat(arg++); + limiter(mlogistic); +} + +static void search(mlogistic_struct *mlogistic, t_symbol *s, int argc, t_atom *argv) { + int not_found, not_expired = mlogistic -> lyap_limit; + int jump, i, iterations; + t_atom vars[M_var_count]; + double temp_c = mlogistic -> c; + if (argc > 0) { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], atom_getfloatarg(i, argc, argv)); + } + } else { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], mlogistic -> vars_init[i]); + } + } + do { + jump = 500; + not_found = 0; + iterations = 10000; + bad_params: + mlogistic -> c = (drand48() * (mlogistic -> c_hi - mlogistic -> c_lo)) + mlogistic -> c_lo; + // put any preliminary checks specific to this fractal to eliminate bad_params + + reset(mlogistic, NULL, argc, vars); + do { calc(mlogistic, mlogistic -> vars); } while(jump--); + mlogistic -> lyap_exp = lyapunov((void *) mlogistic, (t_gotfn) calc, M_var_count, (double *) mlogistic -> vars); + if (isnan(mlogistic -> lyap_exp)) { not_found = 1; } + if (mlogistic -> lyap_exp < mlogistic -> lyap_lo || mlogistic -> lyap_exp > mlogistic -> lyap_hi) { not_found = 1; } + not_expired--; + } while(not_found && not_expired); + reset(mlogistic, NULL, argc, vars); + if (!not_expired) { + post("Could not find a fractal after %d attempts.", (int) mlogistic -> lyap_limit); + post("Try using wider constraints."); + mlogistic -> c = temp_c; + outlet_anything(mlogistic -> search_outlet, gensym("invalid"), 0, NULL); + } else { + mlogistic -> failure_ratio = (mlogistic -> lyap_limit - not_expired) / mlogistic -> lyap_limit; + make_results(mlogistic); + outlet_anything(mlogistic -> search_outlet, gensym("search"), M_search_count, mlogistic -> search_out); + } +} + +void *mlogistic_new(t_symbol *s, int argc, t_atom *argv) { + mlogistic_struct *mlogistic = (mlogistic_struct *) pd_new(mlogistic_class); + if (mlogistic != NULL) { + outlet_new(&mlogistic -> x_obj, &s_float); + mlogistic -> search_outlet = outlet_new(&mlogistic -> x_obj, &s_list); + mlogistic -> vars_outlet = outlet_new(&mlogistic -> x_obj, &s_list); + mlogistic -> params_outlet = outlet_new(&mlogistic -> x_obj, &s_list); + if (argc == M_param_count + M_var_count) { + mlogistic -> vars_init[M_x] = mlogistic -> vars[M_x] = (double) atom_getfloatarg(0, argc, argv); + mlogistic -> c = (double) atom_getfloatarg(1, argc, argv); + } else { + if (argc != 0 && argc != M_param_count + M_var_count) { + post("Incorrect number of arguments for mlogistic fractal. Expecting 2 arguments."); + } + mlogistic -> vars_init[M_x] = 0.1; + mlogistic -> c = 4; + } + constrain(mlogistic, NULL, 0, NULL); + lyap(mlogistic, -1000000.0, 1000000.0, M_failure_limit); + } + return (void *)mlogistic; +} + +void mlogistic_setup(void) { + mlogistic_class = class_new(gensym("mlogistic"), (t_newmethod) mlogistic_new, 0, sizeof(mlogistic_struct), 0, A_GIMME, 0); + class_addbang(mlogistic_class, (t_method) calculate); + class_addmethod(mlogistic_class, (t_method) reset, gensym("reset"), A_GIMME, 0); + class_addmethod(mlogistic_class, (t_method) show, gensym("show"), 0); + class_addmethod(mlogistic_class, (t_method) param, gensym("param"), A_GIMME, 0); + class_addmethod(mlogistic_class, (t_method) seed, gensym("seed"), A_GIMME, 0); + class_addmethod(mlogistic_class, (t_method) lyap, gensym("lyapunov"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(mlogistic_class, (t_method) elyap, gensym("elyapunov"), 0); + class_addmethod(mlogistic_class, (t_method) search, gensym("search"), A_GIMME, 0); + class_addmethod(mlogistic_class, (t_method) constrain, gensym("constrain"), A_GIMME, 0); + class_sethelpsymbol(mlogistic_class, gensym("help-mlogistic.pd")); +} + diff --git a/pickover.c b/pickover.c new file mode 100644 index 0000000..73a46e5 --- /dev/null +++ b/pickover.c @@ -0,0 +1,335 @@ +/* pickover Attractor PD External */ +/* Copyright Michael McGonagle, from Cliff Pickover, 2003 */ +/* This program is distributed under the params of the GNU Public License */ + +/////////////////////////////////////////////////////////////////////////////////// +/* This file is part of Chaos PD Externals. */ +/* */ +/* Chaos PD Externals are free software; you can redistribute them and/or modify */ +/* them under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Chaos PD Externals are distributed in the hope that they will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with the Chaos PD Externals; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "lyapunov.h" + +#define M_a_lo -1000 +#define M_a_hi 1000 +#define M_b_lo -1000 +#define M_b_hi 1000 +#define M_c_lo -1000 +#define M_c_hi 1000 +#define M_d_lo -1000 +#define M_d_hi 1000 + +#define M_a 0 +#define M_b 1 +#define M_c 2 +#define M_d 3 + +#define M_x 0 +#define M_y 1 +#define M_z 2 + +#define M_param_count 4 +#define M_var_count 3 +#define M_search_count 3 +#define M_failure_limit 1000 + +static char *version = "pickover v0.0, by Michael McGonagle, from Cliff Pickover, 2003"; + +t_class *pickover_class; + +typedef struct pickover_struct { + t_object x_obj; + + double vars[M_var_count]; + double vars_init[M_var_count]; + t_atom vars_out[M_var_count]; + t_outlet *vars_outlet; + + t_atom search_out[M_search_count]; + t_outlet *search_outlet; + + double a, a_lo, a_hi, b, b_lo, b_hi, c, c_lo, c_hi, d, d_lo, d_hi; + t_atom params_out[M_param_count]; + t_outlet *params_outlet; + double lyap_exp, lyap_lo, lyap_hi, lyap_limit, failure_ratio; + + t_outlet *outlets[M_var_count - 1]; +} pickover_struct; + +static void calc(pickover_struct *pickover, double *vars) { + double x_0, y_0, z_0; + x_0 =sin(pickover -> a*vars[M_y])-vars[M_z]*cos(pickover -> b*vars[M_x]); + y_0 =vars[M_z]*sin(pickover -> c*vars[M_x])-cos(pickover -> d*vars[M_y]); + z_0 =sin(vars[M_x]); + vars[M_x] = x_0; + vars[M_y] = y_0; + vars[M_z] = z_0; +} // end calc + +static void calculate(pickover_struct *pickover) { + calc(pickover, pickover -> vars); + outlet_float(pickover -> x_obj.ob_outlet, pickover -> vars[M_x]); + outlet_float(pickover -> outlets[M_y - 1], pickover -> vars[M_y]); + outlet_float(pickover -> outlets[M_z - 1], pickover -> vars[M_z]); +} // end calculate + +static void reset(pickover_struct *pickover, t_symbol *s, int argc, t_atom *argv) { + if (argc == M_var_count) { + pickover -> vars[M_x] = (double) atom_getfloatarg(M_x, argc, argv); + pickover -> vars[M_y] = (double) atom_getfloatarg(M_y, argc, argv); + pickover -> vars[M_z] = (double) atom_getfloatarg(M_z, argc, argv); + } else { + pickover -> vars[M_x] = pickover -> vars_init[M_x]; + pickover -> vars[M_y] = pickover -> vars_init[M_y]; + pickover -> vars[M_z] = pickover -> vars_init[M_z]; + } // end if +} // end reset + +static char *classify(pickover_struct *pickover) { + static char buff[5]; + char *c = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + buff[0] = c[(int) (((pickover -> a - M_a_lo) * (1.0 / (M_a_hi - M_a_lo))) * 26)]; + buff[1] = c[(int) (((pickover -> b - M_b_lo) * (1.0 / (M_b_hi - M_b_lo))) * 26)]; + buff[2] = c[(int) (((pickover -> c - M_c_lo) * (1.0 / (M_c_hi - M_c_lo))) * 26)]; + buff[3] = c[(int) (((pickover -> d - M_d_lo) * (1.0 / (M_d_hi - M_d_lo))) * 26)]; + buff[4] = '\0'; + return buff; +} + +static void make_results(pickover_struct *pickover) { + SETFLOAT(&pickover -> search_out[0], pickover -> lyap_exp); + SETSYMBOL(&pickover -> search_out[1], gensym(classify(pickover))); + SETFLOAT(&pickover -> search_out[2], pickover -> failure_ratio); + SETFLOAT(&pickover -> vars_out[M_x], pickover -> vars[M_x]); + SETFLOAT(&pickover -> vars_out[M_y], pickover -> vars[M_y]); + SETFLOAT(&pickover -> vars_out[M_z], pickover -> vars[M_z]); + SETFLOAT(&pickover -> params_out[M_a], pickover -> a); + SETFLOAT(&pickover -> params_out[M_b], pickover -> b); + SETFLOAT(&pickover -> params_out[M_c], pickover -> c); + SETFLOAT(&pickover -> params_out[M_d], pickover -> d); + outlet_list(pickover -> params_outlet, gensym("list"), M_param_count, pickover -> params_out); + outlet_list(pickover -> vars_outlet, gensym("list"), M_var_count, pickover -> vars_out); +} + +static void show(pickover_struct *pickover) { + make_results(pickover); + outlet_anything(pickover -> search_outlet, gensym("show"), M_search_count, pickover -> search_out); +} + +static void param(pickover_struct *pickover, t_symbol *s, int argc, t_atom *argv) { + if (argc != 4) { + post("Incorrect number of arguments for pickover fractal. Expecting 4 arguments."); + return; + } + pickover -> a = (double) atom_getfloatarg(0, argc, argv); + pickover -> b = (double) atom_getfloatarg(1, argc, argv); + pickover -> c = (double) atom_getfloatarg(2, argc, argv); + pickover -> d = (double) atom_getfloatarg(3, argc, argv); +} + +static void seed(pickover_struct *pickover, t_symbol *s, int argc, t_atom *argv) { + if (argc > 0) { + srand48(((unsigned int)time(0))|1); + } else { + srand48((unsigned int) atom_getfloatarg(0, argc, argv)); + } +} + +static void lyap(pickover_struct *pickover, t_floatarg l, t_floatarg h, t_floatarg lim) { + pickover -> lyap_lo = l; + pickover -> lyap_hi = h; + pickover -> lyap_limit = (double) ((int) lim); +} + +static void elyap(pickover_struct *pickover) { + double results[M_var_count]; + int i; + if (lyapunov_full((void *) pickover, (t_gotfn) calc, M_var_count, pickover -> vars, results) != NULL) { + post("elyapunov:"); + for(i = 0; i < M_var_count; i++) { post("%d: %3.80f", i, results[i]); } + } +} + +static void limiter(pickover_struct *pickover) { + if (pickover -> a_lo < M_a_lo) { pickover -> a_lo = M_a_lo; } + if (pickover -> a_lo > M_a_hi) { pickover -> a_lo = M_a_hi; } + if (pickover -> a_hi < M_a_lo) { pickover -> a_hi = M_a_lo; } + if (pickover -> a_hi > M_a_hi) { pickover -> a_hi = M_a_hi; } + if (pickover -> b_lo < M_b_lo) { pickover -> b_lo = M_b_lo; } + if (pickover -> b_lo > M_b_hi) { pickover -> b_lo = M_b_hi; } + if (pickover -> b_hi < M_b_lo) { pickover -> b_hi = M_b_lo; } + if (pickover -> b_hi > M_b_hi) { pickover -> b_hi = M_b_hi; } + if (pickover -> c_lo < M_c_lo) { pickover -> c_lo = M_c_lo; } + if (pickover -> c_lo > M_c_hi) { pickover -> c_lo = M_c_hi; } + if (pickover -> c_hi < M_c_lo) { pickover -> c_hi = M_c_lo; } + if (pickover -> c_hi > M_c_hi) { pickover -> c_hi = M_c_hi; } + if (pickover -> d_lo < M_d_lo) { pickover -> d_lo = M_d_lo; } + if (pickover -> d_lo > M_d_hi) { pickover -> d_lo = M_d_hi; } + if (pickover -> d_hi < M_d_lo) { pickover -> d_hi = M_d_lo; } + if (pickover -> d_hi > M_d_hi) { pickover -> d_hi = M_d_hi; } +} + +static void constrain(pickover_struct *pickover, t_symbol *s, int argc, t_atom *argv) { + int i; + t_atom *arg = argv; + if (argc == 0) { + // reset to full limits of search ranges + pickover -> a_lo = M_a_lo; + pickover -> a_hi = M_a_hi; + pickover -> b_lo = M_b_lo; + pickover -> b_hi = M_b_hi; + pickover -> c_lo = M_c_lo; + pickover -> c_hi = M_c_hi; + pickover -> d_lo = M_d_lo; + pickover -> d_hi = M_d_hi; + return; + } + if (argc == 1) { + // set the ranges based on percentage of full range + double percent = atom_getfloat(arg); + double a_spread = ((M_a_hi - M_a_lo) * percent) / 2; + double b_spread = ((M_b_hi - M_b_lo) * percent) / 2; + double c_spread = ((M_c_hi - M_c_lo) * percent) / 2; + double d_spread = ((M_d_hi - M_d_lo) * percent) / 2; + pickover -> a_lo = pickover -> a - a_spread; + pickover -> a_hi = pickover -> a + a_spread; + pickover -> b_lo = pickover -> b - b_spread; + pickover -> b_hi = pickover -> b + b_spread; + pickover -> c_lo = pickover -> c - c_spread; + pickover -> c_hi = pickover -> c + c_spread; + pickover -> d_lo = pickover -> d - d_spread; + pickover -> d_hi = pickover -> d + d_spread; + limiter(pickover); + return; + } + if (argc != M_param_count * 2) { + post("Invalid number of arguments for pickover constraints, requires 8 values, got %d", argc); + return; + } + pickover -> a_lo = atom_getfloat(arg++); + pickover -> a_hi = atom_getfloat(arg++); + pickover -> b_lo = atom_getfloat(arg++); + pickover -> b_hi = atom_getfloat(arg++); + pickover -> c_lo = atom_getfloat(arg++); + pickover -> c_hi = atom_getfloat(arg++); + pickover -> d_lo = atom_getfloat(arg++); + pickover -> d_hi = atom_getfloat(arg++); + limiter(pickover); +} + +static void search(pickover_struct *pickover, t_symbol *s, int argc, t_atom *argv) { + int not_found, not_expired = pickover -> lyap_limit; + int jump, i, iterations; + t_atom vars[M_var_count]; + double temp_a = pickover -> a; + double temp_b = pickover -> b; + double temp_c = pickover -> c; + double temp_d = pickover -> d; + if (argc > 0) { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], atom_getfloatarg(i, argc, argv)); + } + } else { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], pickover -> vars_init[i]); + } + } + do { + jump = 500; + not_found = 0; + iterations = 10000; + bad_params: + pickover -> a = (drand48() * (pickover -> a_hi - pickover -> a_lo)) + pickover -> a_lo; + pickover -> b = (drand48() * (pickover -> b_hi - pickover -> b_lo)) + pickover -> b_lo; + pickover -> c = (drand48() * (pickover -> c_hi - pickover -> c_lo)) + pickover -> c_lo; + pickover -> d = (drand48() * (pickover -> d_hi - pickover -> d_lo)) + pickover -> d_lo; + // put any preliminary checks specific to this fractal to eliminate bad_params + + reset(pickover, NULL, argc, vars); + do { calc(pickover, pickover -> vars); } while(jump--); + pickover -> lyap_exp = lyapunov((void *) pickover, (t_gotfn) calc, M_var_count, (double *) pickover -> vars); + if (isnan(pickover -> lyap_exp)) { not_found = 1; } + if (pickover -> lyap_exp < pickover -> lyap_lo || pickover -> lyap_exp > pickover -> lyap_hi) { not_found = 1; } + not_expired--; + } while(not_found && not_expired); + reset(pickover, NULL, argc, vars); + if (!not_expired) { + post("Could not find a fractal after %d attempts.", (int) pickover -> lyap_limit); + post("Try using wider constraints."); + pickover -> a = temp_a; + pickover -> b = temp_b; + pickover -> c = temp_c; + pickover -> d = temp_d; + outlet_anything(pickover -> search_outlet, gensym("invalid"), 0, NULL); + } else { + pickover -> failure_ratio = (pickover -> lyap_limit - not_expired) / pickover -> lyap_limit; + make_results(pickover); + outlet_anything(pickover -> search_outlet, gensym("search"), M_search_count, pickover -> search_out); + } +} + +void *pickover_new(t_symbol *s, int argc, t_atom *argv) { + pickover_struct *pickover = (pickover_struct *) pd_new(pickover_class); + if (pickover != NULL) { + outlet_new(&pickover -> x_obj, &s_float); + pickover -> outlets[0] = outlet_new(&pickover -> x_obj, &s_float); + pickover -> outlets[1] = outlet_new(&pickover -> x_obj, &s_float); + pickover -> search_outlet = outlet_new(&pickover -> x_obj, &s_list); + pickover -> vars_outlet = outlet_new(&pickover -> x_obj, &s_list); + pickover -> params_outlet = outlet_new(&pickover -> x_obj, &s_list); + if (argc == M_param_count + M_var_count) { + pickover -> vars_init[M_x] = pickover -> vars[M_x] = (double) atom_getfloatarg(0, argc, argv); + pickover -> vars_init[M_y] = pickover -> vars[M_y] = (double) atom_getfloatarg(1, argc, argv); + pickover -> vars_init[M_z] = pickover -> vars[M_z] = (double) atom_getfloatarg(2, argc, argv); + pickover -> a = (double) atom_getfloatarg(3, argc, argv); + pickover -> b = (double) atom_getfloatarg(4, argc, argv); + pickover -> c = (double) atom_getfloatarg(5, argc, argv); + pickover -> d = (double) atom_getfloatarg(6, argc, argv); + } else { + if (argc != 0 && argc != M_param_count + M_var_count) { + post("Incorrect number of arguments for pickover fractal. Expecting 7 arguments."); + } + pickover -> vars_init[M_x] = 0.01; + pickover -> vars_init[M_y] = 0; + pickover -> vars_init[M_z] = 0; + pickover -> a = 2.24; + pickover -> b = 0.43; + pickover -> c = -0.65; + pickover -> d = -2.43; + } + constrain(pickover, NULL, 0, NULL); + lyap(pickover, -1000000.0, 1000000.0, M_failure_limit); + } + return (void *)pickover; +} + +void pickover_setup(void) { + pickover_class = class_new(gensym("pickover"), (t_newmethod) pickover_new, 0, sizeof(pickover_struct), 0, A_GIMME, 0); + class_addbang(pickover_class, (t_method) calculate); + class_addmethod(pickover_class, (t_method) reset, gensym("reset"), A_GIMME, 0); + class_addmethod(pickover_class, (t_method) show, gensym("show"), 0); + class_addmethod(pickover_class, (t_method) param, gensym("param"), A_GIMME, 0); + class_addmethod(pickover_class, (t_method) seed, gensym("seed"), A_GIMME, 0); + class_addmethod(pickover_class, (t_method) lyap, gensym("lyapunov"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(pickover_class, (t_method) elyap, gensym("elyapunov"), 0); + class_addmethod(pickover_class, (t_method) search, gensym("search"), A_GIMME, 0); + class_addmethod(pickover_class, (t_method) constrain, gensym("constrain"), A_GIMME, 0); + class_sethelpsymbol(pickover_class, gensym("help-pickover.pd")); +} + diff --git a/popcorn.c b/popcorn.c new file mode 100644 index 0000000..8b46857 --- /dev/null +++ b/popcorn.c @@ -0,0 +1,259 @@ +/* popcorn Attractor PD External */ +/* Copyright Michael McGonagle, from Cliff Pickover, 2003 */ +/* This program is distributed under the params of the GNU Public License */ + +/////////////////////////////////////////////////////////////////////////////////// +/* This file is part of Chaos PD Externals. */ +/* */ +/* Chaos PD Externals are free software; you can redistribute them and/or modify */ +/* them under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Chaos PD Externals are distributed in the hope that they will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with the Chaos PD Externals; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "lyapunov.h" + +#define M_h_lo -1000 +#define M_h_hi 1000 + +#define M_h 0 + +#define M_x 0 +#define M_y 1 + +#define M_param_count 1 +#define M_var_count 2 +#define M_search_count 3 +#define M_failure_limit 1000 + +static char *version = "popcorn v0.0, by Michael McGonagle, from Cliff Pickover, 2003"; + +t_class *popcorn_class; + +typedef struct popcorn_struct { + t_object x_obj; + + double vars[M_var_count]; + double vars_init[M_var_count]; + t_atom vars_out[M_var_count]; + t_outlet *vars_outlet; + + t_atom search_out[M_search_count]; + t_outlet *search_outlet; + + double h, h_lo, h_hi; + t_atom params_out[M_param_count]; + t_outlet *params_outlet; + double lyap_exp, lyap_lo, lyap_hi, lyap_limit, failure_ratio; + + t_outlet *outlets[M_var_count - 1]; +} popcorn_struct; + +static void calc(popcorn_struct *popcorn, double *vars) { + double x_0, y_0; + x_0 =vars[M_x]-popcorn -> h*sin(vars[M_y]+tan(3*vars[M_y])); + y_0 =vars[M_y]-popcorn -> h*sin(vars[M_x]+tan(3*vars[M_x])); + vars[M_x] = x_0; + vars[M_y] = y_0; +} // end calc + +static void calculate(popcorn_struct *popcorn) { + calc(popcorn, popcorn -> vars); + outlet_float(popcorn -> x_obj.ob_outlet, popcorn -> vars[M_x]); + outlet_float(popcorn -> outlets[M_y - 1], popcorn -> vars[M_y]); +} // end calculate + +static void reset(popcorn_struct *popcorn, t_symbol *s, int argc, t_atom *argv) { + if (argc == M_var_count) { + popcorn -> vars[M_x] = (double) atom_getfloatarg(M_x, argc, argv); + popcorn -> vars[M_y] = (double) atom_getfloatarg(M_y, argc, argv); + } else { + popcorn -> vars[M_x] = popcorn -> vars_init[M_x]; + popcorn -> vars[M_y] = popcorn -> vars_init[M_y]; + } // end if +} // end reset + +static char *classify(popcorn_struct *popcorn) { + static char buff[2]; + char *c = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + buff[0] = c[(int) (((popcorn -> h - M_h_lo) * (1.0 / (M_h_hi - M_h_lo))) * 26)]; + buff[1] = '\0'; + return buff; +} + +static void make_results(popcorn_struct *popcorn) { + SETFLOAT(&popcorn -> search_out[0], popcorn -> lyap_exp); + SETSYMBOL(&popcorn -> search_out[1], gensym(classify(popcorn))); + SETFLOAT(&popcorn -> search_out[2], popcorn -> failure_ratio); + SETFLOAT(&popcorn -> vars_out[M_x], popcorn -> vars[M_x]); + SETFLOAT(&popcorn -> vars_out[M_y], popcorn -> vars[M_y]); + SETFLOAT(&popcorn -> params_out[M_h], popcorn -> h); + outlet_list(popcorn -> params_outlet, gensym("list"), M_param_count, popcorn -> params_out); + outlet_list(popcorn -> vars_outlet, gensym("list"), M_var_count, popcorn -> vars_out); +} + +static void show(popcorn_struct *popcorn) { + make_results(popcorn); + outlet_anything(popcorn -> search_outlet, gensym("show"), M_search_count, popcorn -> search_out); +} + +static void param(popcorn_struct *popcorn, t_symbol *s, int argc, t_atom *argv) { + if (argc != 1) { + post("Incorrect number of arguments for popcorn fractal. Expecting 1 arguments."); + return; + } + popcorn -> h = (double) atom_getfloatarg(0, argc, argv); +} + +static void seed(popcorn_struct *popcorn, t_symbol *s, int argc, t_atom *argv) { + if (argc > 0) { + srand48(((unsigned int)time(0))|1); + } else { + srand48((unsigned int) atom_getfloatarg(0, argc, argv)); + } +} + +static void lyap(popcorn_struct *popcorn, t_floatarg l, t_floatarg h, t_floatarg lim) { + popcorn -> lyap_lo = l; + popcorn -> lyap_hi = h; + popcorn -> lyap_limit = (double) ((int) lim); +} + +static void elyap(popcorn_struct *popcorn) { + double results[M_var_count]; + int i; + if (lyapunov_full((void *) popcorn, (t_gotfn) calc, M_var_count, popcorn -> vars, results) != NULL) { + post("elyapunov:"); + for(i = 0; i < M_var_count; i++) { post("%d: %3.80f", i, results[i]); } + } +} + +static void limiter(popcorn_struct *popcorn) { + if (popcorn -> h_lo < M_h_lo) { popcorn -> h_lo = M_h_lo; } + if (popcorn -> h_lo > M_h_hi) { popcorn -> h_lo = M_h_hi; } + if (popcorn -> h_hi < M_h_lo) { popcorn -> h_hi = M_h_lo; } + if (popcorn -> h_hi > M_h_hi) { popcorn -> h_hi = M_h_hi; } +} + +static void constrain(popcorn_struct *popcorn, t_symbol *s, int argc, t_atom *argv) { + int i; + t_atom *arg = argv; + if (argc == 0) { + // reset to full limits of search ranges + popcorn -> h_lo = M_h_lo; + popcorn -> h_hi = M_h_hi; + return; + } + if (argc == 1) { + // set the ranges based on percentage of full range + double percent = atom_getfloat(arg); + double h_spread = ((M_h_hi - M_h_lo) * percent) / 2; + popcorn -> h_lo = popcorn -> h - h_spread; + popcorn -> h_hi = popcorn -> h + h_spread; + limiter(popcorn); + return; + } + if (argc != M_param_count * 2) { + post("Invalid number of arguments for popcorn constraints, requires 2 values, got %d", argc); + return; + } + popcorn -> h_lo = atom_getfloat(arg++); + popcorn -> h_hi = atom_getfloat(arg++); + limiter(popcorn); +} + +static void search(popcorn_struct *popcorn, t_symbol *s, int argc, t_atom *argv) { + int not_found, not_expired = popcorn -> lyap_limit; + int jump, i, iterations; + t_atom vars[M_var_count]; + double temp_h = popcorn -> h; + if (argc > 0) { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], atom_getfloatarg(i, argc, argv)); + } + } else { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], popcorn -> vars_init[i]); + } + } + do { + jump = 500; + not_found = 0; + iterations = 10000; + bad_params: + popcorn -> h = (drand48() * (popcorn -> h_hi - popcorn -> h_lo)) + popcorn -> h_lo; + // put any preliminary checks specific to this fractal to eliminate bad_params + + reset(popcorn, NULL, argc, vars); + do { calc(popcorn, popcorn -> vars); } while(jump--); + popcorn -> lyap_exp = lyapunov((void *) popcorn, (t_gotfn) calc, M_var_count, (double *) popcorn -> vars); + if (isnan(popcorn -> lyap_exp)) { not_found = 1; } + if (popcorn -> lyap_exp < popcorn -> lyap_lo || popcorn -> lyap_exp > popcorn -> lyap_hi) { not_found = 1; } + not_expired--; + } while(not_found && not_expired); + reset(popcorn, NULL, argc, vars); + if (!not_expired) { + post("Could not find a fractal after %d attempts.", (int) popcorn -> lyap_limit); + post("Try using wider constraints."); + popcorn -> h = temp_h; + outlet_anything(popcorn -> search_outlet, gensym("invalid"), 0, NULL); + } else { + popcorn -> failure_ratio = (popcorn -> lyap_limit - not_expired) / popcorn -> lyap_limit; + make_results(popcorn); + outlet_anything(popcorn -> search_outlet, gensym("search"), M_search_count, popcorn -> search_out); + } +} + +void *popcorn_new(t_symbol *s, int argc, t_atom *argv) { + popcorn_struct *popcorn = (popcorn_struct *) pd_new(popcorn_class); + if (popcorn != NULL) { + outlet_new(&popcorn -> x_obj, &s_float); + popcorn -> outlets[0] = outlet_new(&popcorn -> x_obj, &s_float); + popcorn -> search_outlet = outlet_new(&popcorn -> x_obj, &s_list); + popcorn -> vars_outlet = outlet_new(&popcorn -> x_obj, &s_list); + popcorn -> params_outlet = outlet_new(&popcorn -> x_obj, &s_list); + if (argc == M_param_count + M_var_count) { + popcorn -> vars_init[M_x] = popcorn -> vars[M_x] = (double) atom_getfloatarg(0, argc, argv); + popcorn -> vars_init[M_y] = popcorn -> vars[M_y] = (double) atom_getfloatarg(1, argc, argv); + popcorn -> h = (double) atom_getfloatarg(2, argc, argv); + } else { + if (argc != 0 && argc != M_param_count + M_var_count) { + post("Incorrect number of arguments for popcorn fractal. Expecting 3 arguments."); + } + popcorn -> vars_init[M_x] = 0; + popcorn -> vars_init[M_y] = 0; + popcorn -> h = 0.05; + } + constrain(popcorn, NULL, 0, NULL); + lyap(popcorn, -1000000.0, 1000000.0, M_failure_limit); + } + return (void *)popcorn; +} + +void popcorn_setup(void) { + popcorn_class = class_new(gensym("popcorn"), (t_newmethod) popcorn_new, 0, sizeof(popcorn_struct), 0, A_GIMME, 0); + class_addbang(popcorn_class, (t_method) calculate); + class_addmethod(popcorn_class, (t_method) reset, gensym("reset"), A_GIMME, 0); + class_addmethod(popcorn_class, (t_method) show, gensym("show"), 0); + class_addmethod(popcorn_class, (t_method) param, gensym("param"), A_GIMME, 0); + class_addmethod(popcorn_class, (t_method) seed, gensym("seed"), A_GIMME, 0); + class_addmethod(popcorn_class, (t_method) lyap, gensym("lyapunov"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(popcorn_class, (t_method) elyap, gensym("elyapunov"), 0); + class_addmethod(popcorn_class, (t_method) search, gensym("search"), A_GIMME, 0); + class_addmethod(popcorn_class, (t_method) constrain, gensym("constrain"), A_GIMME, 0); + class_sethelpsymbol(popcorn_class, gensym("help-popcorn.pd")); +} + diff --git a/quadruptwo.c b/quadruptwo.c new file mode 100644 index 0000000..4869731 --- /dev/null +++ b/quadruptwo.c @@ -0,0 +1,303 @@ +/* quadruptwo Attractor PD External */ +/* Copyright Michael McGonagle, from ??????, 2003 */ +/* This program is distributed under the params of the GNU Public License */ + +/////////////////////////////////////////////////////////////////////////////////// +/* This file is part of Chaos PD Externals. */ +/* */ +/* Chaos PD Externals are free software; you can redistribute them and/or modify */ +/* them under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Chaos PD Externals are distributed in the hope that they will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with the Chaos PD Externals; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "lyapunov.h" + +#define M_a_lo -1000 +#define M_a_hi 1000 +#define M_b_lo -1000 +#define M_b_hi 1000 +#define M_c_lo -1000 +#define M_c_hi 1000 + +#define M_a 0 +#define M_b 1 +#define M_c 2 + +#define M_x 0 +#define M_y 1 + +#define M_param_count 3 +#define M_var_count 2 +#define M_search_count 3 +#define M_failure_limit 1000 + +static char *version = "quadruptwo v0.0, by Michael McGonagle, from ??????, 2003"; + +t_class *quadruptwo_class; + +typedef struct quadruptwo_struct { + t_object x_obj; + + double vars[M_var_count]; + double vars_init[M_var_count]; + t_atom vars_out[M_var_count]; + t_outlet *vars_outlet; + + t_atom search_out[M_search_count]; + t_outlet *search_outlet; + + double a, a_lo, a_hi, b, b_lo, b_hi, c, c_lo, c_hi; + t_atom params_out[M_param_count]; + t_outlet *params_outlet; + double lyap_exp, lyap_lo, lyap_hi, lyap_limit, failure_ratio; + + t_outlet *outlets[M_var_count - 1]; +} quadruptwo_struct; + +static void calc(quadruptwo_struct *quadruptwo, double *vars) { + double x_0, y_0; + x_0 =vars[M_y]-((vars[M_x]<0)?-1:1)*sin(log(abs(quadruptwo -> b*vars[M_x]-quadruptwo -> c)))*atan(pow(abs(quadruptwo -> c*vars[M_x]-quadruptwo -> b),2)); + y_0 =quadruptwo -> a-vars[M_x]; + vars[M_x] = x_0; + vars[M_y] = y_0; +} // end calc + +static void calculate(quadruptwo_struct *quadruptwo) { + calc(quadruptwo, quadruptwo -> vars); + outlet_float(quadruptwo -> x_obj.ob_outlet, quadruptwo -> vars[M_x]); + outlet_float(quadruptwo -> outlets[M_y - 1], quadruptwo -> vars[M_y]); +} // end calculate + +static void reset(quadruptwo_struct *quadruptwo, t_symbol *s, int argc, t_atom *argv) { + if (argc == M_var_count) { + quadruptwo -> vars[M_x] = (double) atom_getfloatarg(M_x, argc, argv); + quadruptwo -> vars[M_y] = (double) atom_getfloatarg(M_y, argc, argv); + } else { + quadruptwo -> vars[M_x] = quadruptwo -> vars_init[M_x]; + quadruptwo -> vars[M_y] = quadruptwo -> vars_init[M_y]; + } // end if +} // end reset + +static char *classify(quadruptwo_struct *quadruptwo) { + static char buff[4]; + char *c = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + buff[0] = c[(int) (((quadruptwo -> a - M_a_lo) * (1.0 / (M_a_hi - M_a_lo))) * 26)]; + buff[1] = c[(int) (((quadruptwo -> b - M_b_lo) * (1.0 / (M_b_hi - M_b_lo))) * 26)]; + buff[2] = c[(int) (((quadruptwo -> c - M_c_lo) * (1.0 / (M_c_hi - M_c_lo))) * 26)]; + buff[3] = '\0'; + return buff; +} + +static void make_results(quadruptwo_struct *quadruptwo) { + SETFLOAT(&quadruptwo -> search_out[0], quadruptwo -> lyap_exp); + SETSYMBOL(&quadruptwo -> search_out[1], gensym(classify(quadruptwo))); + SETFLOAT(&quadruptwo -> search_out[2], quadruptwo -> failure_ratio); + SETFLOAT(&quadruptwo -> vars_out[M_x], quadruptwo -> vars[M_x]); + SETFLOAT(&quadruptwo -> vars_out[M_y], quadruptwo -> vars[M_y]); + SETFLOAT(&quadruptwo -> params_out[M_a], quadruptwo -> a); + SETFLOAT(&quadruptwo -> params_out[M_b], quadruptwo -> b); + SETFLOAT(&quadruptwo -> params_out[M_c], quadruptwo -> c); + outlet_list(quadruptwo -> params_outlet, gensym("list"), M_param_count, quadruptwo -> params_out); + outlet_list(quadruptwo -> vars_outlet, gensym("list"), M_var_count, quadruptwo -> vars_out); +} + +static void show(quadruptwo_struct *quadruptwo) { + make_results(quadruptwo); + outlet_anything(quadruptwo -> search_outlet, gensym("show"), M_search_count, quadruptwo -> search_out); +} + +static void param(quadruptwo_struct *quadruptwo, t_symbol *s, int argc, t_atom *argv) { + if (argc != 3) { + post("Incorrect number of arguments for quadruptwo fractal. Expecting 3 arguments."); + return; + } + quadruptwo -> a = (double) atom_getfloatarg(0, argc, argv); + quadruptwo -> b = (double) atom_getfloatarg(1, argc, argv); + quadruptwo -> c = (double) atom_getfloatarg(2, argc, argv); +} + +static void seed(quadruptwo_struct *quadruptwo, t_symbol *s, int argc, t_atom *argv) { + if (argc > 0) { + srand48(((unsigned int)time(0))|1); + } else { + srand48((unsigned int) atom_getfloatarg(0, argc, argv)); + } +} + +static void lyap(quadruptwo_struct *quadruptwo, t_floatarg l, t_floatarg h, t_floatarg lim) { + quadruptwo -> lyap_lo = l; + quadruptwo -> lyap_hi = h; + quadruptwo -> lyap_limit = (double) ((int) lim); +} + +static void elyap(quadruptwo_struct *quadruptwo) { + double results[M_var_count]; + int i; + if (lyapunov_full((void *) quadruptwo, (t_gotfn) calc, M_var_count, quadruptwo -> vars, results) != NULL) { + post("elyapunov:"); + for(i = 0; i < M_var_count; i++) { post("%d: %3.80f", i, results[i]); } + } +} + +static void limiter(quadruptwo_struct *quadruptwo) { + if (quadruptwo -> a_lo < M_a_lo) { quadruptwo -> a_lo = M_a_lo; } + if (quadruptwo -> a_lo > M_a_hi) { quadruptwo -> a_lo = M_a_hi; } + if (quadruptwo -> a_hi < M_a_lo) { quadruptwo -> a_hi = M_a_lo; } + if (quadruptwo -> a_hi > M_a_hi) { quadruptwo -> a_hi = M_a_hi; } + if (quadruptwo -> b_lo < M_b_lo) { quadruptwo -> b_lo = M_b_lo; } + if (quadruptwo -> b_lo > M_b_hi) { quadruptwo -> b_lo = M_b_hi; } + if (quadruptwo -> b_hi < M_b_lo) { quadruptwo -> b_hi = M_b_lo; } + if (quadruptwo -> b_hi > M_b_hi) { quadruptwo -> b_hi = M_b_hi; } + if (quadruptwo -> c_lo < M_c_lo) { quadruptwo -> c_lo = M_c_lo; } + if (quadruptwo -> c_lo > M_c_hi) { quadruptwo -> c_lo = M_c_hi; } + if (quadruptwo -> c_hi < M_c_lo) { quadruptwo -> c_hi = M_c_lo; } + if (quadruptwo -> c_hi > M_c_hi) { quadruptwo -> c_hi = M_c_hi; } +} + +static void constrain(quadruptwo_struct *quadruptwo, t_symbol *s, int argc, t_atom *argv) { + int i; + t_atom *arg = argv; + if (argc == 0) { + // reset to full limits of search ranges + quadruptwo -> a_lo = M_a_lo; + quadruptwo -> a_hi = M_a_hi; + quadruptwo -> b_lo = M_b_lo; + quadruptwo -> b_hi = M_b_hi; + quadruptwo -> c_lo = M_c_lo; + quadruptwo -> c_hi = M_c_hi; + return; + } + if (argc == 1) { + // set the ranges based on percentage of full range + double percent = atom_getfloat(arg); + double a_spread = ((M_a_hi - M_a_lo) * percent) / 2; + double b_spread = ((M_b_hi - M_b_lo) * percent) / 2; + double c_spread = ((M_c_hi - M_c_lo) * percent) / 2; + quadruptwo -> a_lo = quadruptwo -> a - a_spread; + quadruptwo -> a_hi = quadruptwo -> a + a_spread; + quadruptwo -> b_lo = quadruptwo -> b - b_spread; + quadruptwo -> b_hi = quadruptwo -> b + b_spread; + quadruptwo -> c_lo = quadruptwo -> c - c_spread; + quadruptwo -> c_hi = quadruptwo -> c + c_spread; + limiter(quadruptwo); + return; + } + if (argc != M_param_count * 2) { + post("Invalid number of arguments for quadruptwo constraints, requires 6 values, got %d", argc); + return; + } + quadruptwo -> a_lo = atom_getfloat(arg++); + quadruptwo -> a_hi = atom_getfloat(arg++); + quadruptwo -> b_lo = atom_getfloat(arg++); + quadruptwo -> b_hi = atom_getfloat(arg++); + quadruptwo -> c_lo = atom_getfloat(arg++); + quadruptwo -> c_hi = atom_getfloat(arg++); + limiter(quadruptwo); +} + +static void search(quadruptwo_struct *quadruptwo, t_symbol *s, int argc, t_atom *argv) { + int not_found, not_expired = quadruptwo -> lyap_limit; + int jump, i, iterations; + t_atom vars[M_var_count]; + double temp_a = quadruptwo -> a; + double temp_b = quadruptwo -> b; + double temp_c = quadruptwo -> c; + if (argc > 0) { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], atom_getfloatarg(i, argc, argv)); + } + } else { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], quadruptwo -> vars_init[i]); + } + } + do { + jump = 500; + not_found = 0; + iterations = 10000; + bad_params: + quadruptwo -> a = (drand48() * (quadruptwo -> a_hi - quadruptwo -> a_lo)) + quadruptwo -> a_lo; + quadruptwo -> b = (drand48() * (quadruptwo -> b_hi - quadruptwo -> b_lo)) + quadruptwo -> b_lo; + quadruptwo -> c = (drand48() * (quadruptwo -> c_hi - quadruptwo -> c_lo)) + quadruptwo -> c_lo; + // put any preliminary checks specific to this fractal to eliminate bad_params + + reset(quadruptwo, NULL, argc, vars); + do { calc(quadruptwo, quadruptwo -> vars); } while(jump--); + quadruptwo -> lyap_exp = lyapunov((void *) quadruptwo, (t_gotfn) calc, M_var_count, (double *) quadruptwo -> vars); + if (isnan(quadruptwo -> lyap_exp)) { not_found = 1; } + if (quadruptwo -> lyap_exp < quadruptwo -> lyap_lo || quadruptwo -> lyap_exp > quadruptwo -> lyap_hi) { not_found = 1; } + not_expired--; + } while(not_found && not_expired); + reset(quadruptwo, NULL, argc, vars); + if (!not_expired) { + post("Could not find a fractal after %d attempts.", (int) quadruptwo -> lyap_limit); + post("Try using wider constraints."); + quadruptwo -> a = temp_a; + quadruptwo -> b = temp_b; + quadruptwo -> c = temp_c; + outlet_anything(quadruptwo -> search_outlet, gensym("invalid"), 0, NULL); + } else { + quadruptwo -> failure_ratio = (quadruptwo -> lyap_limit - not_expired) / quadruptwo -> lyap_limit; + make_results(quadruptwo); + outlet_anything(quadruptwo -> search_outlet, gensym("search"), M_search_count, quadruptwo -> search_out); + } +} + +void *quadruptwo_new(t_symbol *s, int argc, t_atom *argv) { + quadruptwo_struct *quadruptwo = (quadruptwo_struct *) pd_new(quadruptwo_class); + if (quadruptwo != NULL) { + outlet_new(&quadruptwo -> x_obj, &s_float); + quadruptwo -> outlets[0] = outlet_new(&quadruptwo -> x_obj, &s_float); + quadruptwo -> search_outlet = outlet_new(&quadruptwo -> x_obj, &s_list); + quadruptwo -> vars_outlet = outlet_new(&quadruptwo -> x_obj, &s_list); + quadruptwo -> params_outlet = outlet_new(&quadruptwo -> x_obj, &s_list); + if (argc == M_param_count + M_var_count) { + quadruptwo -> vars_init[M_x] = quadruptwo -> vars[M_x] = (double) atom_getfloatarg(0, argc, argv); + quadruptwo -> vars_init[M_y] = quadruptwo -> vars[M_y] = (double) atom_getfloatarg(1, argc, argv); + quadruptwo -> a = (double) atom_getfloatarg(2, argc, argv); + quadruptwo -> b = (double) atom_getfloatarg(3, argc, argv); + quadruptwo -> c = (double) atom_getfloatarg(4, argc, argv); + } else { + if (argc != 0 && argc != M_param_count + M_var_count) { + post("Incorrect number of arguments for quadruptwo fractal. Expecting 5 arguments."); + } + quadruptwo -> vars_init[M_x] = 0; + quadruptwo -> vars_init[M_y] = 0; + quadruptwo -> a = 34; + quadruptwo -> b = 1; + quadruptwo -> c = 5; + } + constrain(quadruptwo, NULL, 0, NULL); + lyap(quadruptwo, -1000000.0, 1000000.0, M_failure_limit); + } + return (void *)quadruptwo; +} + +void quadruptwo_setup(void) { + quadruptwo_class = class_new(gensym("quadruptwo"), (t_newmethod) quadruptwo_new, 0, sizeof(quadruptwo_struct), 0, A_GIMME, 0); + class_addbang(quadruptwo_class, (t_method) calculate); + class_addmethod(quadruptwo_class, (t_method) reset, gensym("reset"), A_GIMME, 0); + class_addmethod(quadruptwo_class, (t_method) show, gensym("show"), 0); + class_addmethod(quadruptwo_class, (t_method) param, gensym("param"), A_GIMME, 0); + class_addmethod(quadruptwo_class, (t_method) seed, gensym("seed"), A_GIMME, 0); + class_addmethod(quadruptwo_class, (t_method) lyap, gensym("lyapunov"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(quadruptwo_class, (t_method) elyap, gensym("elyapunov"), 0); + class_addmethod(quadruptwo_class, (t_method) search, gensym("search"), A_GIMME, 0); + class_addmethod(quadruptwo_class, (t_method) constrain, gensym("constrain"), A_GIMME, 0); + class_sethelpsymbol(quadruptwo_class, gensym("help-quadruptwo.pd")); +} + diff --git a/standardmap.c b/standardmap.c new file mode 100644 index 0000000..efb099c --- /dev/null +++ b/standardmap.c @@ -0,0 +1,259 @@ +/* standardmap Attractor PD External */ +/* Copyright Michael McGonagle, from ??????, 2003 */ +/* This program is distributed under the params of the GNU Public License */ + +/////////////////////////////////////////////////////////////////////////////////// +/* This file is part of Chaos PD Externals. */ +/* */ +/* Chaos PD Externals are free software; you can redistribute them and/or modify */ +/* them under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Chaos PD Externals are distributed in the hope that they will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with the Chaos PD Externals; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "lyapunov.h" + +#define M_k_lo -1000 +#define M_k_hi 1000 + +#define M_k 0 + +#define M_p 0 +#define M_q 1 + +#define M_param_count 1 +#define M_var_count 2 +#define M_search_count 3 +#define M_failure_limit 1000 + +static char *version = "standardmap v0.0, by Michael McGonagle, from ??????, 2003"; + +t_class *standardmap_class; + +typedef struct standardmap_struct { + t_object x_obj; + + double vars[M_var_count]; + double vars_init[M_var_count]; + t_atom vars_out[M_var_count]; + t_outlet *vars_outlet; + + t_atom search_out[M_search_count]; + t_outlet *search_outlet; + + double k, k_lo, k_hi; + t_atom params_out[M_param_count]; + t_outlet *params_outlet; + double lyap_exp, lyap_lo, lyap_hi, lyap_limit, failure_ratio; + + t_outlet *outlets[M_var_count - 1]; +} standardmap_struct; + +static void calc(standardmap_struct *standardmap, double *vars) { + double p_0, q_0; + p_0 =vars[M_p]+standardmap -> k*sin(vars[M_q]+vars[M_p]); + q_0 =vars[M_q]+vars[M_p]; + vars[M_p] = p_0; + vars[M_q] = q_0; +} // end calc + +static void calculate(standardmap_struct *standardmap) { + calc(standardmap, standardmap -> vars); + outlet_float(standardmap -> x_obj.ob_outlet, standardmap -> vars[M_p]); + outlet_float(standardmap -> outlets[M_q - 1], standardmap -> vars[M_q]); +} // end calculate + +static void reset(standardmap_struct *standardmap, t_symbol *s, int argc, t_atom *argv) { + if (argc == M_var_count) { + standardmap -> vars[M_p] = (double) atom_getfloatarg(M_p, argc, argv); + standardmap -> vars[M_q] = (double) atom_getfloatarg(M_q, argc, argv); + } else { + standardmap -> vars[M_p] = standardmap -> vars_init[M_p]; + standardmap -> vars[M_q] = standardmap -> vars_init[M_q]; + } // end if +} // end reset + +static char *classify(standardmap_struct *standardmap) { + static char buff[2]; + char *c = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + buff[0] = c[(int) (((standardmap -> k - M_k_lo) * (1.0 / (M_k_hi - M_k_lo))) * 26)]; + buff[1] = '\0'; + return buff; +} + +static void make_results(standardmap_struct *standardmap) { + SETFLOAT(&standardmap -> search_out[0], standardmap -> lyap_exp); + SETSYMBOL(&standardmap -> search_out[1], gensym(classify(standardmap))); + SETFLOAT(&standardmap -> search_out[2], standardmap -> failure_ratio); + SETFLOAT(&standardmap -> vars_out[M_p], standardmap -> vars[M_p]); + SETFLOAT(&standardmap -> vars_out[M_q], standardmap -> vars[M_q]); + SETFLOAT(&standardmap -> params_out[M_k], standardmap -> k); + outlet_list(standardmap -> params_outlet, gensym("list"), M_param_count, standardmap -> params_out); + outlet_list(standardmap -> vars_outlet, gensym("list"), M_var_count, standardmap -> vars_out); +} + +static void show(standardmap_struct *standardmap) { + make_results(standardmap); + outlet_anything(standardmap -> search_outlet, gensym("show"), M_search_count, standardmap -> search_out); +} + +static void param(standardmap_struct *standardmap, t_symbol *s, int argc, t_atom *argv) { + if (argc != 1) { + post("Incorrect number of arguments for standardmap fractal. Expecting 1 arguments."); + return; + } + standardmap -> k = (double) atom_getfloatarg(0, argc, argv); +} + +static void seed(standardmap_struct *standardmap, t_symbol *s, int argc, t_atom *argv) { + if (argc > 0) { + srand48(((unsigned int)time(0))|1); + } else { + srand48((unsigned int) atom_getfloatarg(0, argc, argv)); + } +} + +static void lyap(standardmap_struct *standardmap, t_floatarg l, t_floatarg h, t_floatarg lim) { + standardmap -> lyap_lo = l; + standardmap -> lyap_hi = h; + standardmap -> lyap_limit = (double) ((int) lim); +} + +static void elyap(standardmap_struct *standardmap) { + double results[M_var_count]; + int i; + if (lyapunov_full((void *) standardmap, (t_gotfn) calc, M_var_count, standardmap -> vars, results) != NULL) { + post("elyapunov:"); + for(i = 0; i < M_var_count; i++) { post("%d: %3.80f", i, results[i]); } + } +} + +static void limiter(standardmap_struct *standardmap) { + if (standardmap -> k_lo < M_k_lo) { standardmap -> k_lo = M_k_lo; } + if (standardmap -> k_lo > M_k_hi) { standardmap -> k_lo = M_k_hi; } + if (standardmap -> k_hi < M_k_lo) { standardmap -> k_hi = M_k_lo; } + if (standardmap -> k_hi > M_k_hi) { standardmap -> k_hi = M_k_hi; } +} + +static void constrain(standardmap_struct *standardmap, t_symbol *s, int argc, t_atom *argv) { + int i; + t_atom *arg = argv; + if (argc == 0) { + // reset to full limits of search ranges + standardmap -> k_lo = M_k_lo; + standardmap -> k_hi = M_k_hi; + return; + } + if (argc == 1) { + // set the ranges based on percentage of full range + double percent = atom_getfloat(arg); + double k_spread = ((M_k_hi - M_k_lo) * percent) / 2; + standardmap -> k_lo = standardmap -> k - k_spread; + standardmap -> k_hi = standardmap -> k + k_spread; + limiter(standardmap); + return; + } + if (argc != M_param_count * 2) { + post("Invalid number of arguments for standardmap constraints, requires 2 values, got %d", argc); + return; + } + standardmap -> k_lo = atom_getfloat(arg++); + standardmap -> k_hi = atom_getfloat(arg++); + limiter(standardmap); +} + +static void search(standardmap_struct *standardmap, t_symbol *s, int argc, t_atom *argv) { + int not_found, not_expired = standardmap -> lyap_limit; + int jump, i, iterations; + t_atom vars[M_var_count]; + double temp_k = standardmap -> k; + if (argc > 0) { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], atom_getfloatarg(i, argc, argv)); + } + } else { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], standardmap -> vars_init[i]); + } + } + do { + jump = 500; + not_found = 0; + iterations = 10000; + bad_params: + standardmap -> k = (drand48() * (standardmap -> k_hi - standardmap -> k_lo)) + standardmap -> k_lo; + // put any preliminary checks specific to this fractal to eliminate bad_params + + reset(standardmap, NULL, argc, vars); + do { calc(standardmap, standardmap -> vars); } while(jump--); + standardmap -> lyap_exp = lyapunov((void *) standardmap, (t_gotfn) calc, M_var_count, (double *) standardmap -> vars); + if (isnan(standardmap -> lyap_exp)) { not_found = 1; } + if (standardmap -> lyap_exp < standardmap -> lyap_lo || standardmap -> lyap_exp > standardmap -> lyap_hi) { not_found = 1; } + not_expired--; + } while(not_found && not_expired); + reset(standardmap, NULL, argc, vars); + if (!not_expired) { + post("Could not find a fractal after %d attempts.", (int) standardmap -> lyap_limit); + post("Try using wider constraints."); + standardmap -> k = temp_k; + outlet_anything(standardmap -> search_outlet, gensym("invalid"), 0, NULL); + } else { + standardmap -> failure_ratio = (standardmap -> lyap_limit - not_expired) / standardmap -> lyap_limit; + make_results(standardmap); + outlet_anything(standardmap -> search_outlet, gensym("search"), M_search_count, standardmap -> search_out); + } +} + +void *standardmap_new(t_symbol *s, int argc, t_atom *argv) { + standardmap_struct *standardmap = (standardmap_struct *) pd_new(standardmap_class); + if (standardmap != NULL) { + outlet_new(&standardmap -> x_obj, &s_float); + standardmap -> outlets[0] = outlet_new(&standardmap -> x_obj, &s_float); + standardmap -> search_outlet = outlet_new(&standardmap -> x_obj, &s_list); + standardmap -> vars_outlet = outlet_new(&standardmap -> x_obj, &s_list); + standardmap -> params_outlet = outlet_new(&standardmap -> x_obj, &s_list); + if (argc == M_param_count + M_var_count) { + standardmap -> vars_init[M_p] = standardmap -> vars[M_p] = (double) atom_getfloatarg(0, argc, argv); + standardmap -> vars_init[M_q] = standardmap -> vars[M_q] = (double) atom_getfloatarg(1, argc, argv); + standardmap -> k = (double) atom_getfloatarg(2, argc, argv); + } else { + if (argc != 0 && argc != M_param_count + M_var_count) { + post("Incorrect number of arguments for standardmap fractal. Expecting 3 arguments."); + } + standardmap -> vars_init[M_p] = 0.1; + standardmap -> vars_init[M_q] = 0.1; + standardmap -> k = 1; + } + constrain(standardmap, NULL, 0, NULL); + lyap(standardmap, -1000000.0, 1000000.0, M_failure_limit); + } + return (void *)standardmap; +} + +void standardmap_setup(void) { + standardmap_class = class_new(gensym("standardmap"), (t_newmethod) standardmap_new, 0, sizeof(standardmap_struct), 0, A_GIMME, 0); + class_addbang(standardmap_class, (t_method) calculate); + class_addmethod(standardmap_class, (t_method) reset, gensym("reset"), A_GIMME, 0); + class_addmethod(standardmap_class, (t_method) show, gensym("show"), 0); + class_addmethod(standardmap_class, (t_method) param, gensym("param"), A_GIMME, 0); + class_addmethod(standardmap_class, (t_method) seed, gensym("seed"), A_GIMME, 0); + class_addmethod(standardmap_class, (t_method) lyap, gensym("lyapunov"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(standardmap_class, (t_method) elyap, gensym("elyapunov"), 0); + class_addmethod(standardmap_class, (t_method) search, gensym("search"), A_GIMME, 0); + class_addmethod(standardmap_class, (t_method) constrain, gensym("constrain"), A_GIMME, 0); + class_sethelpsymbol(standardmap_class, gensym("help-standardmap.pd")); +} + diff --git a/strange1.c b/strange1.c new file mode 100644 index 0000000..2a4f500 --- /dev/null +++ b/strange1.c @@ -0,0 +1,501 @@ +/* strange1 Attractor PD External */ +/* Copyright Michael McGonagle, from ???pbourke???, 2003 */ +/* This program is distributed under the params of the GNU Public License */ + +/////////////////////////////////////////////////////////////////////////////////// +/* This file is part of Chaos PD Externals. */ +/* */ +/* Chaos PD Externals are free software; you can redistribute them and/or modify */ +/* them under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Chaos PD Externals are distributed in the hope that they will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with the Chaos PD Externals; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "lyapunov.h" + +#define M_a0_lo -2 +#define M_a0_hi 2 +#define M_a1_lo -2 +#define M_a1_hi 2 +#define M_a2_lo -2 +#define M_a2_hi 2 +#define M_a3_lo -2 +#define M_a3_hi 2 +#define M_a4_lo -2 +#define M_a4_hi 2 +#define M_a5_lo -2 +#define M_a5_hi 2 +#define M_b0_lo -2 +#define M_b0_hi 2 +#define M_b1_lo -2 +#define M_b1_hi 2 +#define M_b2_lo -2 +#define M_b2_hi 2 +#define M_b3_lo -2 +#define M_b3_hi 2 +#define M_b4_lo -2 +#define M_b4_hi 2 +#define M_b5_lo -2 +#define M_b5_hi 2 + +#define M_a0 0 +#define M_a1 1 +#define M_a2 2 +#define M_a3 3 +#define M_a4 4 +#define M_a5 5 +#define M_b0 6 +#define M_b1 7 +#define M_b2 8 +#define M_b3 9 +#define M_b4 10 +#define M_b5 11 + +#define M_x 0 +#define M_y 1 + +#define M_param_count 12 +#define M_var_count 2 +#define M_search_count 3 +#define M_failure_limit 1000 + +static char *version = "strange1 v0.0, by Michael McGonagle, from ???pbourke???, 2003"; + +t_class *strange1_class; + +typedef struct strange1_struct { + t_object x_obj; + + double vars[M_var_count]; + double vars_init[M_var_count]; + t_atom vars_out[M_var_count]; + t_outlet *vars_outlet; + + t_atom search_out[M_search_count]; + t_outlet *search_outlet; + + double a0, a0_lo, a0_hi, a1, a1_lo, a1_hi, a2, a2_lo, a2_hi, a3, a3_lo, a3_hi, a4, a4_lo, a4_hi, a5, a5_lo, a5_hi, b0, b0_lo, b0_hi, b1, b1_lo, b1_hi, b2, b2_lo, b2_hi, b3, b3_lo, b3_hi, b4, b4_lo, b4_hi, b5, b5_lo, b5_hi; + t_atom params_out[M_param_count]; + t_outlet *params_outlet; + double lyap_exp, lyap_lo, lyap_hi, lyap_limit, failure_ratio; + + t_outlet *outlets[M_var_count - 1]; +} strange1_struct; + +static void calc(strange1_struct *strange1, double *vars) { + double x_0, y_0; + x_0 =strange1 -> a0+strange1 -> a1*vars[M_x]+strange1 -> a2*vars[M_x]*vars[M_x]+strange1 -> a3*vars[M_x]*vars[M_y]+strange1 -> a4*vars[M_y]+strange1 -> a5*vars[M_y]*vars[M_y]; + y_0 =strange1 -> b0+strange1 -> b1*vars[M_x]+strange1 -> b2*vars[M_x]*vars[M_x]+strange1 -> b3*vars[M_x]*vars[M_y]+strange1 -> b4*vars[M_y]+strange1 -> b5*vars[M_y]*vars[M_y]; + vars[M_x] = x_0; + vars[M_y] = y_0; +} // end calc + +static void calculate(strange1_struct *strange1) { + calc(strange1, strange1 -> vars); + outlet_float(strange1 -> x_obj.ob_outlet, strange1 -> vars[M_x]); + outlet_float(strange1 -> outlets[M_y - 1], strange1 -> vars[M_y]); +} // end calculate + +static void reset(strange1_struct *strange1, t_symbol *s, int argc, t_atom *argv) { + if (argc == M_var_count) { + strange1 -> vars[M_x] = (double) atom_getfloatarg(M_x, argc, argv); + strange1 -> vars[M_y] = (double) atom_getfloatarg(M_y, argc, argv); + } else { + strange1 -> vars[M_x] = strange1 -> vars_init[M_x]; + strange1 -> vars[M_y] = strange1 -> vars_init[M_y]; + } // end if +} // end reset + +static char *classify(strange1_struct *strange1) { + static char buff[13]; + char *c = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + buff[0] = c[(int) (((strange1 -> a0 - M_a0_lo) * (1.0 / (M_a0_hi - M_a0_lo))) * 26)]; + buff[1] = c[(int) (((strange1 -> a1 - M_a1_lo) * (1.0 / (M_a1_hi - M_a1_lo))) * 26)]; + buff[2] = c[(int) (((strange1 -> a2 - M_a2_lo) * (1.0 / (M_a2_hi - M_a2_lo))) * 26)]; + buff[3] = c[(int) (((strange1 -> a3 - M_a3_lo) * (1.0 / (M_a3_hi - M_a3_lo))) * 26)]; + buff[4] = c[(int) (((strange1 -> a4 - M_a4_lo) * (1.0 / (M_a4_hi - M_a4_lo))) * 26)]; + buff[5] = c[(int) (((strange1 -> a5 - M_a5_lo) * (1.0 / (M_a5_hi - M_a5_lo))) * 26)]; + buff[6] = c[(int) (((strange1 -> b0 - M_b0_lo) * (1.0 / (M_b0_hi - M_b0_lo))) * 26)]; + buff[7] = c[(int) (((strange1 -> b1 - M_b1_lo) * (1.0 / (M_b1_hi - M_b1_lo))) * 26)]; + buff[8] = c[(int) (((strange1 -> b2 - M_b2_lo) * (1.0 / (M_b2_hi - M_b2_lo))) * 26)]; + buff[9] = c[(int) (((strange1 -> b3 - M_b3_lo) * (1.0 / (M_b3_hi - M_b3_lo))) * 26)]; + buff[10] = c[(int) (((strange1 -> b4 - M_b4_lo) * (1.0 / (M_b4_hi - M_b4_lo))) * 26)]; + buff[11] = c[(int) (((strange1 -> b5 - M_b5_lo) * (1.0 / (M_b5_hi - M_b5_lo))) * 26)]; + buff[12] = '\0'; + return buff; +} + +static void make_results(strange1_struct *strange1) { + SETFLOAT(&strange1 -> search_out[0], strange1 -> lyap_exp); + SETSYMBOL(&strange1 -> search_out[1], gensym(classify(strange1))); + SETFLOAT(&strange1 -> search_out[2], strange1 -> failure_ratio); + SETFLOAT(&strange1 -> vars_out[M_x], strange1 -> vars[M_x]); + SETFLOAT(&strange1 -> vars_out[M_y], strange1 -> vars[M_y]); + SETFLOAT(&strange1 -> params_out[M_a0], strange1 -> a0); + SETFLOAT(&strange1 -> params_out[M_a1], strange1 -> a1); + SETFLOAT(&strange1 -> params_out[M_a2], strange1 -> a2); + SETFLOAT(&strange1 -> params_out[M_a3], strange1 -> a3); + SETFLOAT(&strange1 -> params_out[M_a4], strange1 -> a4); + SETFLOAT(&strange1 -> params_out[M_a5], strange1 -> a5); + SETFLOAT(&strange1 -> params_out[M_b0], strange1 -> b0); + SETFLOAT(&strange1 -> params_out[M_b1], strange1 -> b1); + SETFLOAT(&strange1 -> params_out[M_b2], strange1 -> b2); + SETFLOAT(&strange1 -> params_out[M_b3], strange1 -> b3); + SETFLOAT(&strange1 -> params_out[M_b4], strange1 -> b4); + SETFLOAT(&strange1 -> params_out[M_b5], strange1 -> b5); + outlet_list(strange1 -> params_outlet, gensym("list"), M_param_count, strange1 -> params_out); + outlet_list(strange1 -> vars_outlet, gensym("list"), M_var_count, strange1 -> vars_out); +} + +static void show(strange1_struct *strange1) { + make_results(strange1); + outlet_anything(strange1 -> search_outlet, gensym("show"), M_search_count, strange1 -> search_out); +} + +static void param(strange1_struct *strange1, t_symbol *s, int argc, t_atom *argv) { + if (argc != 12) { + post("Incorrect number of arguments for strange1 fractal. Expecting 12 arguments."); + return; + } + strange1 -> a0 = (double) atom_getfloatarg(0, argc, argv); + strange1 -> a1 = (double) atom_getfloatarg(1, argc, argv); + strange1 -> a2 = (double) atom_getfloatarg(2, argc, argv); + strange1 -> a3 = (double) atom_getfloatarg(3, argc, argv); + strange1 -> a4 = (double) atom_getfloatarg(4, argc, argv); + strange1 -> a5 = (double) atom_getfloatarg(5, argc, argv); + strange1 -> b0 = (double) atom_getfloatarg(6, argc, argv); + strange1 -> b1 = (double) atom_getfloatarg(7, argc, argv); + strange1 -> b2 = (double) atom_getfloatarg(8, argc, argv); + strange1 -> b3 = (double) atom_getfloatarg(9, argc, argv); + strange1 -> b4 = (double) atom_getfloatarg(10, argc, argv); + strange1 -> b5 = (double) atom_getfloatarg(11, argc, argv); +} + +static void seed(strange1_struct *strange1, t_symbol *s, int argc, t_atom *argv) { + if (argc > 0) { + srand48(((unsigned int)time(0))|1); + } else { + srand48((unsigned int) atom_getfloatarg(0, argc, argv)); + } +} + +static void lyap(strange1_struct *strange1, t_floatarg l, t_floatarg h, t_floatarg lim) { + strange1 -> lyap_lo = l; + strange1 -> lyap_hi = h; + strange1 -> lyap_limit = (double) ((int) lim); +} + +static void elyap(strange1_struct *strange1) { + double results[M_var_count]; + int i; + if (lyapunov_full((void *) strange1, (t_gotfn) calc, M_var_count, strange1 -> vars, results) != NULL) { + post("elyapunov:"); + for(i = 0; i < M_var_count; i++) { post("%d: %3.80f", i, results[i]); } + } +} + +static void limiter(strange1_struct *strange1) { + if (strange1 -> a0_lo < M_a0_lo) { strange1 -> a0_lo = M_a0_lo; } + if (strange1 -> a0_lo > M_a0_hi) { strange1 -> a0_lo = M_a0_hi; } + if (strange1 -> a0_hi < M_a0_lo) { strange1 -> a0_hi = M_a0_lo; } + if (strange1 -> a0_hi > M_a0_hi) { strange1 -> a0_hi = M_a0_hi; } + if (strange1 -> a1_lo < M_a1_lo) { strange1 -> a1_lo = M_a1_lo; } + if (strange1 -> a1_lo > M_a1_hi) { strange1 -> a1_lo = M_a1_hi; } + if (strange1 -> a1_hi < M_a1_lo) { strange1 -> a1_hi = M_a1_lo; } + if (strange1 -> a1_hi > M_a1_hi) { strange1 -> a1_hi = M_a1_hi; } + if (strange1 -> a2_lo < M_a2_lo) { strange1 -> a2_lo = M_a2_lo; } + if (strange1 -> a2_lo > M_a2_hi) { strange1 -> a2_lo = M_a2_hi; } + if (strange1 -> a2_hi < M_a2_lo) { strange1 -> a2_hi = M_a2_lo; } + if (strange1 -> a2_hi > M_a2_hi) { strange1 -> a2_hi = M_a2_hi; } + if (strange1 -> a3_lo < M_a3_lo) { strange1 -> a3_lo = M_a3_lo; } + if (strange1 -> a3_lo > M_a3_hi) { strange1 -> a3_lo = M_a3_hi; } + if (strange1 -> a3_hi < M_a3_lo) { strange1 -> a3_hi = M_a3_lo; } + if (strange1 -> a3_hi > M_a3_hi) { strange1 -> a3_hi = M_a3_hi; } + if (strange1 -> a4_lo < M_a4_lo) { strange1 -> a4_lo = M_a4_lo; } + if (strange1 -> a4_lo > M_a4_hi) { strange1 -> a4_lo = M_a4_hi; } + if (strange1 -> a4_hi < M_a4_lo) { strange1 -> a4_hi = M_a4_lo; } + if (strange1 -> a4_hi > M_a4_hi) { strange1 -> a4_hi = M_a4_hi; } + if (strange1 -> a5_lo < M_a5_lo) { strange1 -> a5_lo = M_a5_lo; } + if (strange1 -> a5_lo > M_a5_hi) { strange1 -> a5_lo = M_a5_hi; } + if (strange1 -> a5_hi < M_a5_lo) { strange1 -> a5_hi = M_a5_lo; } + if (strange1 -> a5_hi > M_a5_hi) { strange1 -> a5_hi = M_a5_hi; } + if (strange1 -> b0_lo < M_b0_lo) { strange1 -> b0_lo = M_b0_lo; } + if (strange1 -> b0_lo > M_b0_hi) { strange1 -> b0_lo = M_b0_hi; } + if (strange1 -> b0_hi < M_b0_lo) { strange1 -> b0_hi = M_b0_lo; } + if (strange1 -> b0_hi > M_b0_hi) { strange1 -> b0_hi = M_b0_hi; } + if (strange1 -> b1_lo < M_b1_lo) { strange1 -> b1_lo = M_b1_lo; } + if (strange1 -> b1_lo > M_b1_hi) { strange1 -> b1_lo = M_b1_hi; } + if (strange1 -> b1_hi < M_b1_lo) { strange1 -> b1_hi = M_b1_lo; } + if (strange1 -> b1_hi > M_b1_hi) { strange1 -> b1_hi = M_b1_hi; } + if (strange1 -> b2_lo < M_b2_lo) { strange1 -> b2_lo = M_b2_lo; } + if (strange1 -> b2_lo > M_b2_hi) { strange1 -> b2_lo = M_b2_hi; } + if (strange1 -> b2_hi < M_b2_lo) { strange1 -> b2_hi = M_b2_lo; } + if (strange1 -> b2_hi > M_b2_hi) { strange1 -> b2_hi = M_b2_hi; } + if (strange1 -> b3_lo < M_b3_lo) { strange1 -> b3_lo = M_b3_lo; } + if (strange1 -> b3_lo > M_b3_hi) { strange1 -> b3_lo = M_b3_hi; } + if (strange1 -> b3_hi < M_b3_lo) { strange1 -> b3_hi = M_b3_lo; } + if (strange1 -> b3_hi > M_b3_hi) { strange1 -> b3_hi = M_b3_hi; } + if (strange1 -> b4_lo < M_b4_lo) { strange1 -> b4_lo = M_b4_lo; } + if (strange1 -> b4_lo > M_b4_hi) { strange1 -> b4_lo = M_b4_hi; } + if (strange1 -> b4_hi < M_b4_lo) { strange1 -> b4_hi = M_b4_lo; } + if (strange1 -> b4_hi > M_b4_hi) { strange1 -> b4_hi = M_b4_hi; } + if (strange1 -> b5_lo < M_b5_lo) { strange1 -> b5_lo = M_b5_lo; } + if (strange1 -> b5_lo > M_b5_hi) { strange1 -> b5_lo = M_b5_hi; } + if (strange1 -> b5_hi < M_b5_lo) { strange1 -> b5_hi = M_b5_lo; } + if (strange1 -> b5_hi > M_b5_hi) { strange1 -> b5_hi = M_b5_hi; } +} + +static void constrain(strange1_struct *strange1, t_symbol *s, int argc, t_atom *argv) { + int i; + t_atom *arg = argv; + if (argc == 0) { + // reset to full limits of search ranges + strange1 -> a0_lo = M_a0_lo; + strange1 -> a0_hi = M_a0_hi; + strange1 -> a1_lo = M_a1_lo; + strange1 -> a1_hi = M_a1_hi; + strange1 -> a2_lo = M_a2_lo; + strange1 -> a2_hi = M_a2_hi; + strange1 -> a3_lo = M_a3_lo; + strange1 -> a3_hi = M_a3_hi; + strange1 -> a4_lo = M_a4_lo; + strange1 -> a4_hi = M_a4_hi; + strange1 -> a5_lo = M_a5_lo; + strange1 -> a5_hi = M_a5_hi; + strange1 -> b0_lo = M_b0_lo; + strange1 -> b0_hi = M_b0_hi; + strange1 -> b1_lo = M_b1_lo; + strange1 -> b1_hi = M_b1_hi; + strange1 -> b2_lo = M_b2_lo; + strange1 -> b2_hi = M_b2_hi; + strange1 -> b3_lo = M_b3_lo; + strange1 -> b3_hi = M_b3_hi; + strange1 -> b4_lo = M_b4_lo; + strange1 -> b4_hi = M_b4_hi; + strange1 -> b5_lo = M_b5_lo; + strange1 -> b5_hi = M_b5_hi; + return; + } + if (argc == 1) { + // set the ranges based on percentage of full range + double percent = atom_getfloat(arg); + double a0_spread = ((M_a0_hi - M_a0_lo) * percent) / 2; + double a1_spread = ((M_a1_hi - M_a1_lo) * percent) / 2; + double a2_spread = ((M_a2_hi - M_a2_lo) * percent) / 2; + double a3_spread = ((M_a3_hi - M_a3_lo) * percent) / 2; + double a4_spread = ((M_a4_hi - M_a4_lo) * percent) / 2; + double a5_spread = ((M_a5_hi - M_a5_lo) * percent) / 2; + double b0_spread = ((M_b0_hi - M_b0_lo) * percent) / 2; + double b1_spread = ((M_b1_hi - M_b1_lo) * percent) / 2; + double b2_spread = ((M_b2_hi - M_b2_lo) * percent) / 2; + double b3_spread = ((M_b3_hi - M_b3_lo) * percent) / 2; + double b4_spread = ((M_b4_hi - M_b4_lo) * percent) / 2; + double b5_spread = ((M_b5_hi - M_b5_lo) * percent) / 2; + strange1 -> a0_lo = strange1 -> a0 - a0_spread; + strange1 -> a0_hi = strange1 -> a0 + a0_spread; + strange1 -> a1_lo = strange1 -> a1 - a1_spread; + strange1 -> a1_hi = strange1 -> a1 + a1_spread; + strange1 -> a2_lo = strange1 -> a2 - a2_spread; + strange1 -> a2_hi = strange1 -> a2 + a2_spread; + strange1 -> a3_lo = strange1 -> a3 - a3_spread; + strange1 -> a3_hi = strange1 -> a3 + a3_spread; + strange1 -> a4_lo = strange1 -> a4 - a4_spread; + strange1 -> a4_hi = strange1 -> a4 + a4_spread; + strange1 -> a5_lo = strange1 -> a5 - a5_spread; + strange1 -> a5_hi = strange1 -> a5 + a5_spread; + strange1 -> b0_lo = strange1 -> b0 - b0_spread; + strange1 -> b0_hi = strange1 -> b0 + b0_spread; + strange1 -> b1_lo = strange1 -> b1 - b1_spread; + strange1 -> b1_hi = strange1 -> b1 + b1_spread; + strange1 -> b2_lo = strange1 -> b2 - b2_spread; + strange1 -> b2_hi = strange1 -> b2 + b2_spread; + strange1 -> b3_lo = strange1 -> b3 - b3_spread; + strange1 -> b3_hi = strange1 -> b3 + b3_spread; + strange1 -> b4_lo = strange1 -> b4 - b4_spread; + strange1 -> b4_hi = strange1 -> b4 + b4_spread; + strange1 -> b5_lo = strange1 -> b5 - b5_spread; + strange1 -> b5_hi = strange1 -> b5 + b5_spread; + limiter(strange1); + return; + } + if (argc != M_param_count * 2) { + post("Invalid number of arguments for strange1 constraints, requires 24 values, got %d", argc); + return; + } + strange1 -> a0_lo = atom_getfloat(arg++); + strange1 -> a0_hi = atom_getfloat(arg++); + strange1 -> a1_lo = atom_getfloat(arg++); + strange1 -> a1_hi = atom_getfloat(arg++); + strange1 -> a2_lo = atom_getfloat(arg++); + strange1 -> a2_hi = atom_getfloat(arg++); + strange1 -> a3_lo = atom_getfloat(arg++); + strange1 -> a3_hi = atom_getfloat(arg++); + strange1 -> a4_lo = atom_getfloat(arg++); + strange1 -> a4_hi = atom_getfloat(arg++); + strange1 -> a5_lo = atom_getfloat(arg++); + strange1 -> a5_hi = atom_getfloat(arg++); + strange1 -> b0_lo = atom_getfloat(arg++); + strange1 -> b0_hi = atom_getfloat(arg++); + strange1 -> b1_lo = atom_getfloat(arg++); + strange1 -> b1_hi = atom_getfloat(arg++); + strange1 -> b2_lo = atom_getfloat(arg++); + strange1 -> b2_hi = atom_getfloat(arg++); + strange1 -> b3_lo = atom_getfloat(arg++); + strange1 -> b3_hi = atom_getfloat(arg++); + strange1 -> b4_lo = atom_getfloat(arg++); + strange1 -> b4_hi = atom_getfloat(arg++); + strange1 -> b5_lo = atom_getfloat(arg++); + strange1 -> b5_hi = atom_getfloat(arg++); + limiter(strange1); +} + +static void search(strange1_struct *strange1, t_symbol *s, int argc, t_atom *argv) { + int not_found, not_expired = strange1 -> lyap_limit; + int jump, i, iterations; + t_atom vars[M_var_count]; + double temp_a0 = strange1 -> a0; + double temp_a1 = strange1 -> a1; + double temp_a2 = strange1 -> a2; + double temp_a3 = strange1 -> a3; + double temp_a4 = strange1 -> a4; + double temp_a5 = strange1 -> a5; + double temp_b0 = strange1 -> b0; + double temp_b1 = strange1 -> b1; + double temp_b2 = strange1 -> b2; + double temp_b3 = strange1 -> b3; + double temp_b4 = strange1 -> b4; + double temp_b5 = strange1 -> b5; + if (argc > 0) { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], atom_getfloatarg(i, argc, argv)); + } + } else { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], strange1 -> vars_init[i]); + } + } + do { + jump = 500; + not_found = 0; + iterations = 10000; + bad_params: + strange1 -> a0 = (drand48() * (strange1 -> a0_hi - strange1 -> a0_lo)) + strange1 -> a0_lo; + strange1 -> a1 = (drand48() * (strange1 -> a1_hi - strange1 -> a1_lo)) + strange1 -> a1_lo; + strange1 -> a2 = (drand48() * (strange1 -> a2_hi - strange1 -> a2_lo)) + strange1 -> a2_lo; + strange1 -> a3 = (drand48() * (strange1 -> a3_hi - strange1 -> a3_lo)) + strange1 -> a3_lo; + strange1 -> a4 = (drand48() * (strange1 -> a4_hi - strange1 -> a4_lo)) + strange1 -> a4_lo; + strange1 -> a5 = (drand48() * (strange1 -> a5_hi - strange1 -> a5_lo)) + strange1 -> a5_lo; + strange1 -> b0 = (drand48() * (strange1 -> b0_hi - strange1 -> b0_lo)) + strange1 -> b0_lo; + strange1 -> b1 = (drand48() * (strange1 -> b1_hi - strange1 -> b1_lo)) + strange1 -> b1_lo; + strange1 -> b2 = (drand48() * (strange1 -> b2_hi - strange1 -> b2_lo)) + strange1 -> b2_lo; + strange1 -> b3 = (drand48() * (strange1 -> b3_hi - strange1 -> b3_lo)) + strange1 -> b3_lo; + strange1 -> b4 = (drand48() * (strange1 -> b4_hi - strange1 -> b4_lo)) + strange1 -> b4_lo; + strange1 -> b5 = (drand48() * (strange1 -> b5_hi - strange1 -> b5_lo)) + strange1 -> b5_lo; + // put any preliminary checks specific to this fractal to eliminate bad_params + + reset(strange1, NULL, argc, vars); + do { calc(strange1, strange1 -> vars); } while(jump--); + strange1 -> lyap_exp = lyapunov((void *) strange1, (t_gotfn) calc, M_var_count, (double *) strange1 -> vars); + if (isnan(strange1 -> lyap_exp)) { not_found = 1; } + if (strange1 -> lyap_exp < strange1 -> lyap_lo || strange1 -> lyap_exp > strange1 -> lyap_hi) { not_found = 1; } + not_expired--; + } while(not_found && not_expired); + reset(strange1, NULL, argc, vars); + if (!not_expired) { + post("Could not find a fractal after %d attempts.", (int) strange1 -> lyap_limit); + post("Try using wider constraints."); + strange1 -> a0 = temp_a0; + strange1 -> a1 = temp_a1; + strange1 -> a2 = temp_a2; + strange1 -> a3 = temp_a3; + strange1 -> a4 = temp_a4; + strange1 -> a5 = temp_a5; + strange1 -> b0 = temp_b0; + strange1 -> b1 = temp_b1; + strange1 -> b2 = temp_b2; + strange1 -> b3 = temp_b3; + strange1 -> b4 = temp_b4; + strange1 -> b5 = temp_b5; + outlet_anything(strange1 -> search_outlet, gensym("invalid"), 0, NULL); + } else { + strange1 -> failure_ratio = (strange1 -> lyap_limit - not_expired) / strange1 -> lyap_limit; + make_results(strange1); + outlet_anything(strange1 -> search_outlet, gensym("search"), M_search_count, strange1 -> search_out); + } +} + +void *strange1_new(t_symbol *s, int argc, t_atom *argv) { + strange1_struct *strange1 = (strange1_struct *) pd_new(strange1_class); + if (strange1 != NULL) { + outlet_new(&strange1 -> x_obj, &s_float); + strange1 -> outlets[0] = outlet_new(&strange1 -> x_obj, &s_float); + strange1 -> search_outlet = outlet_new(&strange1 -> x_obj, &s_list); + strange1 -> vars_outlet = outlet_new(&strange1 -> x_obj, &s_list); + strange1 -> params_outlet = outlet_new(&strange1 -> x_obj, &s_list); + if (argc == M_param_count + M_var_count) { + strange1 -> vars_init[M_x] = strange1 -> vars[M_x] = (double) atom_getfloatarg(0, argc, argv); + strange1 -> vars_init[M_y] = strange1 -> vars[M_y] = (double) atom_getfloatarg(1, argc, argv); + strange1 -> a0 = (double) atom_getfloatarg(2, argc, argv); + strange1 -> a1 = (double) atom_getfloatarg(3, argc, argv); + strange1 -> a2 = (double) atom_getfloatarg(4, argc, argv); + strange1 -> a3 = (double) atom_getfloatarg(5, argc, argv); + strange1 -> a4 = (double) atom_getfloatarg(6, argc, argv); + strange1 -> a5 = (double) atom_getfloatarg(7, argc, argv); + strange1 -> b0 = (double) atom_getfloatarg(8, argc, argv); + strange1 -> b1 = (double) atom_getfloatarg(9, argc, argv); + strange1 -> b2 = (double) atom_getfloatarg(10, argc, argv); + strange1 -> b3 = (double) atom_getfloatarg(11, argc, argv); + strange1 -> b4 = (double) atom_getfloatarg(12, argc, argv); + strange1 -> b5 = (double) atom_getfloatarg(13, argc, argv); + } else { + if (argc != 0 && argc != M_param_count + M_var_count) { + post("Incorrect number of arguments for strange1 fractal. Expecting 14 arguments."); + } + strange1 -> vars_init[M_x] = 0; + strange1 -> vars_init[M_y] = 0; + strange1 -> a0 = 1; + strange1 -> a1 = 1; + strange1 -> a2 = 1; + strange1 -> a3 = 1; + strange1 -> a4 = 1; + strange1 -> a5 = 1; + strange1 -> b0 = 1; + strange1 -> b1 = 1; + strange1 -> b2 = 1; + strange1 -> b3 = 1; + strange1 -> b4 = 1; + strange1 -> b5 = 1; + } + constrain(strange1, NULL, 0, NULL); + lyap(strange1, -1000000.0, 1000000.0, M_failure_limit); + } + return (void *)strange1; +} + +void strange1_setup(void) { + strange1_class = class_new(gensym("strange1"), (t_newmethod) strange1_new, 0, sizeof(strange1_struct), 0, A_GIMME, 0); + class_addbang(strange1_class, (t_method) calculate); + class_addmethod(strange1_class, (t_method) reset, gensym("reset"), A_GIMME, 0); + class_addmethod(strange1_class, (t_method) show, gensym("show"), 0); + class_addmethod(strange1_class, (t_method) param, gensym("param"), A_GIMME, 0); + class_addmethod(strange1_class, (t_method) seed, gensym("seed"), A_GIMME, 0); + class_addmethod(strange1_class, (t_method) lyap, gensym("lyapunov"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(strange1_class, (t_method) elyap, gensym("elyapunov"), 0); + class_addmethod(strange1_class, (t_method) search, gensym("search"), A_GIMME, 0); + class_addmethod(strange1_class, (t_method) constrain, gensym("constrain"), A_GIMME, 0); + class_sethelpsymbol(strange1_class, gensym("help-strange1.pd")); +} + diff --git a/tent.c b/tent.c new file mode 100644 index 0000000..baf7302 --- /dev/null +++ b/tent.c @@ -0,0 +1,247 @@ +/* tent Attractor PD External */ +/* Copyright Michael McGonagle, from Cliff Pickover, 2003 */ +/* This program is distributed under the params of the GNU Public License */ + +/////////////////////////////////////////////////////////////////////////////////// +/* This file is part of Chaos PD Externals. */ +/* */ +/* Chaos PD Externals are free software; you can redistribute them and/or modify */ +/* them under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Chaos PD Externals are distributed in the hope that they will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with the Chaos PD Externals; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "lyapunov.h" + +#define M_r_lo -1000 +#define M_r_hi 1000 + +#define M_r 0 + +#define M_x 0 + +#define M_param_count 1 +#define M_var_count 1 +#define M_search_count 3 +#define M_failure_limit 1000 + +static char *version = "tent v0.0, by Michael McGonagle, from Cliff Pickover, 2003"; + +t_class *tent_class; + +typedef struct tent_struct { + t_object x_obj; + + double vars[M_var_count]; + double vars_init[M_var_count]; + t_atom vars_out[M_var_count]; + t_outlet *vars_outlet; + + t_atom search_out[M_search_count]; + t_outlet *search_outlet; + + double r, r_lo, r_hi; + t_atom params_out[M_param_count]; + t_outlet *params_outlet; + double lyap_exp, lyap_lo, lyap_hi, lyap_limit, failure_ratio; +} tent_struct; + +static void calc(tent_struct *tent, double *vars) { + double x_0; + x_0 =(vars[M_x]<=0.5)?2*tent -> r*vars[M_x]:2*tent -> r*(1.0-vars[M_x]); + vars[M_x] = x_0; +} // end calc + +static void calculate(tent_struct *tent) { + calc(tent, tent -> vars); + outlet_float(tent -> x_obj.ob_outlet, tent -> vars[M_x]); +} // end calculate + +static void reset(tent_struct *tent, t_symbol *s, int argc, t_atom *argv) { + if (argc == M_var_count) { + tent -> vars[M_x] = (double) atom_getfloatarg(M_x, argc, argv); + } else { + tent -> vars[M_x] = tent -> vars_init[M_x]; + } // end if +} // end reset + +static char *classify(tent_struct *tent) { + static char buff[2]; + char *c = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + buff[0] = c[(int) (((tent -> r - M_r_lo) * (1.0 / (M_r_hi - M_r_lo))) * 26)]; + buff[1] = '\0'; + return buff; +} + +static void make_results(tent_struct *tent) { + SETFLOAT(&tent -> search_out[0], tent -> lyap_exp); + SETSYMBOL(&tent -> search_out[1], gensym(classify(tent))); + SETFLOAT(&tent -> search_out[2], tent -> failure_ratio); + SETFLOAT(&tent -> vars_out[M_x], tent -> vars[M_x]); + SETFLOAT(&tent -> params_out[M_r], tent -> r); + outlet_list(tent -> params_outlet, gensym("list"), M_param_count, tent -> params_out); + outlet_list(tent -> vars_outlet, gensym("list"), M_var_count, tent -> vars_out); +} + +static void show(tent_struct *tent) { + make_results(tent); + outlet_anything(tent -> search_outlet, gensym("show"), M_search_count, tent -> search_out); +} + +static void param(tent_struct *tent, t_symbol *s, int argc, t_atom *argv) { + if (argc != 1) { + post("Incorrect number of arguments for tent fractal. Expecting 1 arguments."); + return; + } + tent -> r = (double) atom_getfloatarg(0, argc, argv); +} + +static void seed(tent_struct *tent, t_symbol *s, int argc, t_atom *argv) { + if (argc > 0) { + srand48(((unsigned int)time(0))|1); + } else { + srand48((unsigned int) atom_getfloatarg(0, argc, argv)); + } +} + +static void lyap(tent_struct *tent, t_floatarg l, t_floatarg h, t_floatarg lim) { + tent -> lyap_lo = l; + tent -> lyap_hi = h; + tent -> lyap_limit = (double) ((int) lim); +} + +static void elyap(tent_struct *tent) { + double results[M_var_count]; + int i; + if (lyapunov_full((void *) tent, (t_gotfn) calc, M_var_count, tent -> vars, results) != NULL) { + post("elyapunov:"); + for(i = 0; i < M_var_count; i++) { post("%d: %3.80f", i, results[i]); } + } +} + +static void limiter(tent_struct *tent) { + if (tent -> r_lo < M_r_lo) { tent -> r_lo = M_r_lo; } + if (tent -> r_lo > M_r_hi) { tent -> r_lo = M_r_hi; } + if (tent -> r_hi < M_r_lo) { tent -> r_hi = M_r_lo; } + if (tent -> r_hi > M_r_hi) { tent -> r_hi = M_r_hi; } +} + +static void constrain(tent_struct *tent, t_symbol *s, int argc, t_atom *argv) { + int i; + t_atom *arg = argv; + if (argc == 0) { + // reset to full limits of search ranges + tent -> r_lo = M_r_lo; + tent -> r_hi = M_r_hi; + return; + } + if (argc == 1) { + // set the ranges based on percentage of full range + double percent = atom_getfloat(arg); + double r_spread = ((M_r_hi - M_r_lo) * percent) / 2; + tent -> r_lo = tent -> r - r_spread; + tent -> r_hi = tent -> r + r_spread; + limiter(tent); + return; + } + if (argc != M_param_count * 2) { + post("Invalid number of arguments for tent constraints, requires 2 values, got %d", argc); + return; + } + tent -> r_lo = atom_getfloat(arg++); + tent -> r_hi = atom_getfloat(arg++); + limiter(tent); +} + +static void search(tent_struct *tent, t_symbol *s, int argc, t_atom *argv) { + int not_found, not_expired = tent -> lyap_limit; + int jump, i, iterations; + t_atom vars[M_var_count]; + double temp_r = tent -> r; + if (argc > 0) { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], atom_getfloatarg(i, argc, argv)); + } + } else { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], tent -> vars_init[i]); + } + } + do { + jump = 500; + not_found = 0; + iterations = 10000; + bad_params: + tent -> r = (drand48() * (tent -> r_hi - tent -> r_lo)) + tent -> r_lo; + // put any preliminary checks specific to this fractal to eliminate bad_params + + reset(tent, NULL, argc, vars); + do { calc(tent, tent -> vars); } while(jump--); + tent -> lyap_exp = lyapunov((void *) tent, (t_gotfn) calc, M_var_count, (double *) tent -> vars); + if (isnan(tent -> lyap_exp)) { not_found = 1; } + if (tent -> lyap_exp < tent -> lyap_lo || tent -> lyap_exp > tent -> lyap_hi) { not_found = 1; } + not_expired--; + } while(not_found && not_expired); + reset(tent, NULL, argc, vars); + if (!not_expired) { + post("Could not find a fractal after %d attempts.", (int) tent -> lyap_limit); + post("Try using wider constraints."); + tent -> r = temp_r; + outlet_anything(tent -> search_outlet, gensym("invalid"), 0, NULL); + } else { + tent -> failure_ratio = (tent -> lyap_limit - not_expired) / tent -> lyap_limit; + make_results(tent); + outlet_anything(tent -> search_outlet, gensym("search"), M_search_count, tent -> search_out); + } +} + +void *tent_new(t_symbol *s, int argc, t_atom *argv) { + tent_struct *tent = (tent_struct *) pd_new(tent_class); + if (tent != NULL) { + outlet_new(&tent -> x_obj, &s_float); + tent -> search_outlet = outlet_new(&tent -> x_obj, &s_list); + tent -> vars_outlet = outlet_new(&tent -> x_obj, &s_list); + tent -> params_outlet = outlet_new(&tent -> x_obj, &s_list); + if (argc == M_param_count + M_var_count) { + tent -> vars_init[M_x] = tent -> vars[M_x] = (double) atom_getfloatarg(0, argc, argv); + tent -> r = (double) atom_getfloatarg(1, argc, argv); + } else { + if (argc != 0 && argc != M_param_count + M_var_count) { + post("Incorrect number of arguments for tent fractal. Expecting 2 arguments."); + } + tent -> vars_init[M_x] = 0.1; + tent -> r = 1; + } + constrain(tent, NULL, 0, NULL); + lyap(tent, -1000000.0, 1000000.0, M_failure_limit); + } + return (void *)tent; +} + +void tent_setup(void) { + tent_class = class_new(gensym("tent"), (t_newmethod) tent_new, 0, sizeof(tent_struct), 0, A_GIMME, 0); + class_addbang(tent_class, (t_method) calculate); + class_addmethod(tent_class, (t_method) reset, gensym("reset"), A_GIMME, 0); + class_addmethod(tent_class, (t_method) show, gensym("show"), 0); + class_addmethod(tent_class, (t_method) param, gensym("param"), A_GIMME, 0); + class_addmethod(tent_class, (t_method) seed, gensym("seed"), A_GIMME, 0); + class_addmethod(tent_class, (t_method) lyap, gensym("lyapunov"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(tent_class, (t_method) elyap, gensym("elyapunov"), 0); + class_addmethod(tent_class, (t_method) search, gensym("search"), A_GIMME, 0); + class_addmethod(tent_class, (t_method) constrain, gensym("constrain"), A_GIMME, 0); + class_sethelpsymbol(tent_class, gensym("help-tent.pd")); +} + diff --git a/three_d.c b/three_d.c new file mode 100644 index 0000000..3ba4e7f --- /dev/null +++ b/three_d.c @@ -0,0 +1,357 @@ +/* three_d Attractor PD External */ +/* Copyright Michael McGonagle, from Cliff Pickover, 2003 */ +/* This program is distributed under the params of the GNU Public License */ + +/////////////////////////////////////////////////////////////////////////////////// +/* This file is part of Chaos PD Externals. */ +/* */ +/* Chaos PD Externals are free software; you can redistribute them and/or modify */ +/* them under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Chaos PD Externals are distributed in the hope that they will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with the Chaos PD Externals; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "lyapunov.h" + +#define M_a_lo -1000 +#define M_a_hi 1000 +#define M_b_lo -1000 +#define M_b_hi 1000 +#define M_c_lo -1000 +#define M_c_hi 1000 +#define M_d_lo -1000 +#define M_d_hi 1000 +#define M_e_lo -1000 +#define M_e_hi 1000 + +#define M_a 0 +#define M_b 1 +#define M_c 2 +#define M_d 3 +#define M_e 4 + +#define M_x 0 +#define M_y 1 +#define M_z 2 + +#define M_param_count 5 +#define M_var_count 3 +#define M_search_count 3 +#define M_failure_limit 1000 + +static char *version = "three_d v0.0, by Michael McGonagle, from Cliff Pickover, 2003"; + +t_class *three_d_class; + +typedef struct three_d_struct { + t_object x_obj; + + double vars[M_var_count]; + double vars_init[M_var_count]; + t_atom vars_out[M_var_count]; + t_outlet *vars_outlet; + + t_atom search_out[M_search_count]; + t_outlet *search_outlet; + + double a, a_lo, a_hi, b, b_lo, b_hi, c, c_lo, c_hi, d, d_lo, d_hi, e, e_lo, e_hi; + t_atom params_out[M_param_count]; + t_outlet *params_outlet; + double lyap_exp, lyap_lo, lyap_hi, lyap_limit, failure_ratio; + + t_outlet *outlets[M_var_count - 1]; +} three_d_struct; + +static void calc(three_d_struct *three_d, double *vars) { + double x_0, y_0, z_0; + x_0 =sin(three_d -> a*vars[M_y])-vars[M_z]*cos(three_d -> b*vars[M_x]); + y_0 =vars[M_z]*sin(three_d -> c*vars[M_x])-cos(three_d -> d*vars[M_y]); + z_0 =three_d -> e*sin(vars[M_x]); + vars[M_x] = x_0; + vars[M_y] = y_0; + vars[M_z] = z_0; +} // end calc + +static void calculate(three_d_struct *three_d) { + calc(three_d, three_d -> vars); + outlet_float(three_d -> x_obj.ob_outlet, three_d -> vars[M_x]); + outlet_float(three_d -> outlets[M_y - 1], three_d -> vars[M_y]); + outlet_float(three_d -> outlets[M_z - 1], three_d -> vars[M_z]); +} // end calculate + +static void reset(three_d_struct *three_d, t_symbol *s, int argc, t_atom *argv) { + if (argc == M_var_count) { + three_d -> vars[M_x] = (double) atom_getfloatarg(M_x, argc, argv); + three_d -> vars[M_y] = (double) atom_getfloatarg(M_y, argc, argv); + three_d -> vars[M_z] = (double) atom_getfloatarg(M_z, argc, argv); + } else { + three_d -> vars[M_x] = three_d -> vars_init[M_x]; + three_d -> vars[M_y] = three_d -> vars_init[M_y]; + three_d -> vars[M_z] = three_d -> vars_init[M_z]; + } // end if +} // end reset + +static char *classify(three_d_struct *three_d) { + static char buff[6]; + char *c = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + buff[0] = c[(int) (((three_d -> a - M_a_lo) * (1.0 / (M_a_hi - M_a_lo))) * 26)]; + buff[1] = c[(int) (((three_d -> b - M_b_lo) * (1.0 / (M_b_hi - M_b_lo))) * 26)]; + buff[2] = c[(int) (((three_d -> c - M_c_lo) * (1.0 / (M_c_hi - M_c_lo))) * 26)]; + buff[3] = c[(int) (((three_d -> d - M_d_lo) * (1.0 / (M_d_hi - M_d_lo))) * 26)]; + buff[4] = c[(int) (((three_d -> e - M_e_lo) * (1.0 / (M_e_hi - M_e_lo))) * 26)]; + buff[5] = '\0'; + return buff; +} + +static void make_results(three_d_struct *three_d) { + SETFLOAT(&three_d -> search_out[0], three_d -> lyap_exp); + SETSYMBOL(&three_d -> search_out[1], gensym(classify(three_d))); + SETFLOAT(&three_d -> search_out[2], three_d -> failure_ratio); + SETFLOAT(&three_d -> vars_out[M_x], three_d -> vars[M_x]); + SETFLOAT(&three_d -> vars_out[M_y], three_d -> vars[M_y]); + SETFLOAT(&three_d -> vars_out[M_z], three_d -> vars[M_z]); + SETFLOAT(&three_d -> params_out[M_a], three_d -> a); + SETFLOAT(&three_d -> params_out[M_b], three_d -> b); + SETFLOAT(&three_d -> params_out[M_c], three_d -> c); + SETFLOAT(&three_d -> params_out[M_d], three_d -> d); + SETFLOAT(&three_d -> params_out[M_e], three_d -> e); + outlet_list(three_d -> params_outlet, gensym("list"), M_param_count, three_d -> params_out); + outlet_list(three_d -> vars_outlet, gensym("list"), M_var_count, three_d -> vars_out); +} + +static void show(three_d_struct *three_d) { + make_results(three_d); + outlet_anything(three_d -> search_outlet, gensym("show"), M_search_count, three_d -> search_out); +} + +static void param(three_d_struct *three_d, t_symbol *s, int argc, t_atom *argv) { + if (argc != 5) { + post("Incorrect number of arguments for three_d fractal. Expecting 5 arguments."); + return; + } + three_d -> a = (double) atom_getfloatarg(0, argc, argv); + three_d -> b = (double) atom_getfloatarg(1, argc, argv); + three_d -> c = (double) atom_getfloatarg(2, argc, argv); + three_d -> d = (double) atom_getfloatarg(3, argc, argv); + three_d -> e = (double) atom_getfloatarg(4, argc, argv); +} + +static void seed(three_d_struct *three_d, t_symbol *s, int argc, t_atom *argv) { + if (argc > 0) { + srand48(((unsigned int)time(0))|1); + } else { + srand48((unsigned int) atom_getfloatarg(0, argc, argv)); + } +} + +static void lyap(three_d_struct *three_d, t_floatarg l, t_floatarg h, t_floatarg lim) { + three_d -> lyap_lo = l; + three_d -> lyap_hi = h; + three_d -> lyap_limit = (double) ((int) lim); +} + +static void elyap(three_d_struct *three_d) { + double results[M_var_count]; + int i; + if (lyapunov_full((void *) three_d, (t_gotfn) calc, M_var_count, three_d -> vars, results) != NULL) { + post("elyapunov:"); + for(i = 0; i < M_var_count; i++) { post("%d: %3.80f", i, results[i]); } + } +} + +static void limiter(three_d_struct *three_d) { + if (three_d -> a_lo < M_a_lo) { three_d -> a_lo = M_a_lo; } + if (three_d -> a_lo > M_a_hi) { three_d -> a_lo = M_a_hi; } + if (three_d -> a_hi < M_a_lo) { three_d -> a_hi = M_a_lo; } + if (three_d -> a_hi > M_a_hi) { three_d -> a_hi = M_a_hi; } + if (three_d -> b_lo < M_b_lo) { three_d -> b_lo = M_b_lo; } + if (three_d -> b_lo > M_b_hi) { three_d -> b_lo = M_b_hi; } + if (three_d -> b_hi < M_b_lo) { three_d -> b_hi = M_b_lo; } + if (three_d -> b_hi > M_b_hi) { three_d -> b_hi = M_b_hi; } + if (three_d -> c_lo < M_c_lo) { three_d -> c_lo = M_c_lo; } + if (three_d -> c_lo > M_c_hi) { three_d -> c_lo = M_c_hi; } + if (three_d -> c_hi < M_c_lo) { three_d -> c_hi = M_c_lo; } + if (three_d -> c_hi > M_c_hi) { three_d -> c_hi = M_c_hi; } + if (three_d -> d_lo < M_d_lo) { three_d -> d_lo = M_d_lo; } + if (three_d -> d_lo > M_d_hi) { three_d -> d_lo = M_d_hi; } + if (three_d -> d_hi < M_d_lo) { three_d -> d_hi = M_d_lo; } + if (three_d -> d_hi > M_d_hi) { three_d -> d_hi = M_d_hi; } + if (three_d -> e_lo < M_e_lo) { three_d -> e_lo = M_e_lo; } + if (three_d -> e_lo > M_e_hi) { three_d -> e_lo = M_e_hi; } + if (three_d -> e_hi < M_e_lo) { three_d -> e_hi = M_e_lo; } + if (three_d -> e_hi > M_e_hi) { three_d -> e_hi = M_e_hi; } +} + +static void constrain(three_d_struct *three_d, t_symbol *s, int argc, t_atom *argv) { + int i; + t_atom *arg = argv; + if (argc == 0) { + // reset to full limits of search ranges + three_d -> a_lo = M_a_lo; + three_d -> a_hi = M_a_hi; + three_d -> b_lo = M_b_lo; + three_d -> b_hi = M_b_hi; + three_d -> c_lo = M_c_lo; + three_d -> c_hi = M_c_hi; + three_d -> d_lo = M_d_lo; + three_d -> d_hi = M_d_hi; + three_d -> e_lo = M_e_lo; + three_d -> e_hi = M_e_hi; + return; + } + if (argc == 1) { + // set the ranges based on percentage of full range + double percent = atom_getfloat(arg); + double a_spread = ((M_a_hi - M_a_lo) * percent) / 2; + double b_spread = ((M_b_hi - M_b_lo) * percent) / 2; + double c_spread = ((M_c_hi - M_c_lo) * percent) / 2; + double d_spread = ((M_d_hi - M_d_lo) * percent) / 2; + double e_spread = ((M_e_hi - M_e_lo) * percent) / 2; + three_d -> a_lo = three_d -> a - a_spread; + three_d -> a_hi = three_d -> a + a_spread; + three_d -> b_lo = three_d -> b - b_spread; + three_d -> b_hi = three_d -> b + b_spread; + three_d -> c_lo = three_d -> c - c_spread; + three_d -> c_hi = three_d -> c + c_spread; + three_d -> d_lo = three_d -> d - d_spread; + three_d -> d_hi = three_d -> d + d_spread; + three_d -> e_lo = three_d -> e - e_spread; + three_d -> e_hi = three_d -> e + e_spread; + limiter(three_d); + return; + } + if (argc != M_param_count * 2) { + post("Invalid number of arguments for three_d constraints, requires 10 values, got %d", argc); + return; + } + three_d -> a_lo = atom_getfloat(arg++); + three_d -> a_hi = atom_getfloat(arg++); + three_d -> b_lo = atom_getfloat(arg++); + three_d -> b_hi = atom_getfloat(arg++); + three_d -> c_lo = atom_getfloat(arg++); + three_d -> c_hi = atom_getfloat(arg++); + three_d -> d_lo = atom_getfloat(arg++); + three_d -> d_hi = atom_getfloat(arg++); + three_d -> e_lo = atom_getfloat(arg++); + three_d -> e_hi = atom_getfloat(arg++); + limiter(three_d); +} + +static void search(three_d_struct *three_d, t_symbol *s, int argc, t_atom *argv) { + int not_found, not_expired = three_d -> lyap_limit; + int jump, i, iterations; + t_atom vars[M_var_count]; + double temp_a = three_d -> a; + double temp_b = three_d -> b; + double temp_c = three_d -> c; + double temp_d = three_d -> d; + double temp_e = three_d -> e; + if (argc > 0) { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], atom_getfloatarg(i, argc, argv)); + } + } else { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], three_d -> vars_init[i]); + } + } + do { + jump = 500; + not_found = 0; + iterations = 10000; + bad_params: + three_d -> a = (drand48() * (three_d -> a_hi - three_d -> a_lo)) + three_d -> a_lo; + three_d -> b = (drand48() * (three_d -> b_hi - three_d -> b_lo)) + three_d -> b_lo; + three_d -> c = (drand48() * (three_d -> c_hi - three_d -> c_lo)) + three_d -> c_lo; + three_d -> d = (drand48() * (three_d -> d_hi - three_d -> d_lo)) + three_d -> d_lo; + three_d -> e = (drand48() * (three_d -> e_hi - three_d -> e_lo)) + three_d -> e_lo; + // put any preliminary checks specific to this fractal to eliminate bad_params + + reset(three_d, NULL, argc, vars); + do { calc(three_d, three_d -> vars); } while(jump--); + three_d -> lyap_exp = lyapunov((void *) three_d, (t_gotfn) calc, M_var_count, (double *) three_d -> vars); + if (isnan(three_d -> lyap_exp)) { not_found = 1; } + if (three_d -> lyap_exp < three_d -> lyap_lo || three_d -> lyap_exp > three_d -> lyap_hi) { not_found = 1; } + not_expired--; + } while(not_found && not_expired); + reset(three_d, NULL, argc, vars); + if (!not_expired) { + post("Could not find a fractal after %d attempts.", (int) three_d -> lyap_limit); + post("Try using wider constraints."); + three_d -> a = temp_a; + three_d -> b = temp_b; + three_d -> c = temp_c; + three_d -> d = temp_d; + three_d -> e = temp_e; + outlet_anything(three_d -> search_outlet, gensym("invalid"), 0, NULL); + } else { + three_d -> failure_ratio = (three_d -> lyap_limit - not_expired) / three_d -> lyap_limit; + make_results(three_d); + outlet_anything(three_d -> search_outlet, gensym("search"), M_search_count, three_d -> search_out); + } +} + +void *three_d_new(t_symbol *s, int argc, t_atom *argv) { + three_d_struct *three_d = (three_d_struct *) pd_new(three_d_class); + if (three_d != NULL) { + outlet_new(&three_d -> x_obj, &s_float); + three_d -> outlets[0] = outlet_new(&three_d -> x_obj, &s_float); + three_d -> outlets[1] = outlet_new(&three_d -> x_obj, &s_float); + three_d -> search_outlet = outlet_new(&three_d -> x_obj, &s_list); + three_d -> vars_outlet = outlet_new(&three_d -> x_obj, &s_list); + three_d -> params_outlet = outlet_new(&three_d -> x_obj, &s_list); + if (argc == M_param_count + M_var_count) { + three_d -> vars_init[M_x] = three_d -> vars[M_x] = (double) atom_getfloatarg(0, argc, argv); + three_d -> vars_init[M_y] = three_d -> vars[M_y] = (double) atom_getfloatarg(1, argc, argv); + three_d -> vars_init[M_z] = three_d -> vars[M_z] = (double) atom_getfloatarg(2, argc, argv); + three_d -> a = (double) atom_getfloatarg(3, argc, argv); + three_d -> b = (double) atom_getfloatarg(4, argc, argv); + three_d -> c = (double) atom_getfloatarg(5, argc, argv); + three_d -> d = (double) atom_getfloatarg(6, argc, argv); + three_d -> e = (double) atom_getfloatarg(7, argc, argv); + } else { + if (argc != 0 && argc != M_param_count + M_var_count) { + post("Incorrect number of arguments for three_d fractal. Expecting 8 arguments."); + } + three_d -> vars_init[M_x] = 0; + three_d -> vars_init[M_y] = 0; + three_d -> vars_init[M_z] = 0; + three_d -> a = 2.24; + three_d -> b = 0.43; + three_d -> c = -0.65; + three_d -> d = -2.43; + three_d -> e = 1; + } + constrain(three_d, NULL, 0, NULL); + lyap(three_d, -1000000.0, 1000000.0, M_failure_limit); + } + return (void *)three_d; +} + +void three_d_setup(void) { + three_d_class = class_new(gensym("three_d"), (t_newmethod) three_d_new, 0, sizeof(three_d_struct), 0, A_GIMME, 0); + class_addbang(three_d_class, (t_method) calculate); + class_addmethod(three_d_class, (t_method) reset, gensym("reset"), A_GIMME, 0); + class_addmethod(three_d_class, (t_method) show, gensym("show"), 0); + class_addmethod(three_d_class, (t_method) param, gensym("param"), A_GIMME, 0); + class_addmethod(three_d_class, (t_method) seed, gensym("seed"), A_GIMME, 0); + class_addmethod(three_d_class, (t_method) lyap, gensym("lyapunov"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(three_d_class, (t_method) elyap, gensym("elyapunov"), 0); + class_addmethod(three_d_class, (t_method) search, gensym("search"), A_GIMME, 0); + class_addmethod(three_d_class, (t_method) constrain, gensym("constrain"), A_GIMME, 0); + class_sethelpsymbol(three_d_class, gensym("help-three_d.pd")); +} + diff --git a/threeply.c b/threeply.c new file mode 100644 index 0000000..7618772 --- /dev/null +++ b/threeply.c @@ -0,0 +1,303 @@ +/* threeply Attractor PD External */ +/* Copyright Michael McGonagle, from ??????, 2003 */ +/* This program is distributed under the params of the GNU Public License */ + +/////////////////////////////////////////////////////////////////////////////////// +/* This file is part of Chaos PD Externals. */ +/* */ +/* Chaos PD Externals are free software; you can redistribute them and/or modify */ +/* them under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Chaos PD Externals are distributed in the hope that they will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with the Chaos PD Externals; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "lyapunov.h" + +#define M_a_lo -1000 +#define M_a_hi 1000 +#define M_b_lo -1000 +#define M_b_hi 1000 +#define M_c_lo -1000 +#define M_c_hi 1000 + +#define M_a 0 +#define M_b 1 +#define M_c 2 + +#define M_x 0 +#define M_y 1 + +#define M_param_count 3 +#define M_var_count 2 +#define M_search_count 3 +#define M_failure_limit 1000 + +static char *version = "threeply v0.0, by Michael McGonagle, from ??????, 2003"; + +t_class *threeply_class; + +typedef struct threeply_struct { + t_object x_obj; + + double vars[M_var_count]; + double vars_init[M_var_count]; + t_atom vars_out[M_var_count]; + t_outlet *vars_outlet; + + t_atom search_out[M_search_count]; + t_outlet *search_outlet; + + double a, a_lo, a_hi, b, b_lo, b_hi, c, c_lo, c_hi; + t_atom params_out[M_param_count]; + t_outlet *params_outlet; + double lyap_exp, lyap_lo, lyap_hi, lyap_limit, failure_ratio; + + t_outlet *outlets[M_var_count - 1]; +} threeply_struct; + +static void calc(threeply_struct *threeply, double *vars) { + double x_0, y_0; + x_0 =vars[M_y]-((vars[M_x]<0)?-1:1)*abs(sin(vars[M_x])*cos(threeply -> b)+threeply -> c-vars[M_x]*sin(threeply -> a+threeply -> b+threeply -> c)); + y_0 =threeply -> a-vars[M_x]; + vars[M_x] = x_0; + vars[M_y] = y_0; +} // end calc + +static void calculate(threeply_struct *threeply) { + calc(threeply, threeply -> vars); + outlet_float(threeply -> x_obj.ob_outlet, threeply -> vars[M_x]); + outlet_float(threeply -> outlets[M_y - 1], threeply -> vars[M_y]); +} // end calculate + +static void reset(threeply_struct *threeply, t_symbol *s, int argc, t_atom *argv) { + if (argc == M_var_count) { + threeply -> vars[M_x] = (double) atom_getfloatarg(M_x, argc, argv); + threeply -> vars[M_y] = (double) atom_getfloatarg(M_y, argc, argv); + } else { + threeply -> vars[M_x] = threeply -> vars_init[M_x]; + threeply -> vars[M_y] = threeply -> vars_init[M_y]; + } // end if +} // end reset + +static char *classify(threeply_struct *threeply) { + static char buff[4]; + char *c = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + buff[0] = c[(int) (((threeply -> a - M_a_lo) * (1.0 / (M_a_hi - M_a_lo))) * 26)]; + buff[1] = c[(int) (((threeply -> b - M_b_lo) * (1.0 / (M_b_hi - M_b_lo))) * 26)]; + buff[2] = c[(int) (((threeply -> c - M_c_lo) * (1.0 / (M_c_hi - M_c_lo))) * 26)]; + buff[3] = '\0'; + return buff; +} + +static void make_results(threeply_struct *threeply) { + SETFLOAT(&threeply -> search_out[0], threeply -> lyap_exp); + SETSYMBOL(&threeply -> search_out[1], gensym(classify(threeply))); + SETFLOAT(&threeply -> search_out[2], threeply -> failure_ratio); + SETFLOAT(&threeply -> vars_out[M_x], threeply -> vars[M_x]); + SETFLOAT(&threeply -> vars_out[M_y], threeply -> vars[M_y]); + SETFLOAT(&threeply -> params_out[M_a], threeply -> a); + SETFLOAT(&threeply -> params_out[M_b], threeply -> b); + SETFLOAT(&threeply -> params_out[M_c], threeply -> c); + outlet_list(threeply -> params_outlet, gensym("list"), M_param_count, threeply -> params_out); + outlet_list(threeply -> vars_outlet, gensym("list"), M_var_count, threeply -> vars_out); +} + +static void show(threeply_struct *threeply) { + make_results(threeply); + outlet_anything(threeply -> search_outlet, gensym("show"), M_search_count, threeply -> search_out); +} + +static void param(threeply_struct *threeply, t_symbol *s, int argc, t_atom *argv) { + if (argc != 3) { + post("Incorrect number of arguments for threeply fractal. Expecting 3 arguments."); + return; + } + threeply -> a = (double) atom_getfloatarg(0, argc, argv); + threeply -> b = (double) atom_getfloatarg(1, argc, argv); + threeply -> c = (double) atom_getfloatarg(2, argc, argv); +} + +static void seed(threeply_struct *threeply, t_symbol *s, int argc, t_atom *argv) { + if (argc > 0) { + srand48(((unsigned int)time(0))|1); + } else { + srand48((unsigned int) atom_getfloatarg(0, argc, argv)); + } +} + +static void lyap(threeply_struct *threeply, t_floatarg l, t_floatarg h, t_floatarg lim) { + threeply -> lyap_lo = l; + threeply -> lyap_hi = h; + threeply -> lyap_limit = (double) ((int) lim); +} + +static void elyap(threeply_struct *threeply) { + double results[M_var_count]; + int i; + if (lyapunov_full((void *) threeply, (t_gotfn) calc, M_var_count, threeply -> vars, results) != NULL) { + post("elyapunov:"); + for(i = 0; i < M_var_count; i++) { post("%d: %3.80f", i, results[i]); } + } +} + +static void limiter(threeply_struct *threeply) { + if (threeply -> a_lo < M_a_lo) { threeply -> a_lo = M_a_lo; } + if (threeply -> a_lo > M_a_hi) { threeply -> a_lo = M_a_hi; } + if (threeply -> a_hi < M_a_lo) { threeply -> a_hi = M_a_lo; } + if (threeply -> a_hi > M_a_hi) { threeply -> a_hi = M_a_hi; } + if (threeply -> b_lo < M_b_lo) { threeply -> b_lo = M_b_lo; } + if (threeply -> b_lo > M_b_hi) { threeply -> b_lo = M_b_hi; } + if (threeply -> b_hi < M_b_lo) { threeply -> b_hi = M_b_lo; } + if (threeply -> b_hi > M_b_hi) { threeply -> b_hi = M_b_hi; } + if (threeply -> c_lo < M_c_lo) { threeply -> c_lo = M_c_lo; } + if (threeply -> c_lo > M_c_hi) { threeply -> c_lo = M_c_hi; } + if (threeply -> c_hi < M_c_lo) { threeply -> c_hi = M_c_lo; } + if (threeply -> c_hi > M_c_hi) { threeply -> c_hi = M_c_hi; } +} + +static void constrain(threeply_struct *threeply, t_symbol *s, int argc, t_atom *argv) { + int i; + t_atom *arg = argv; + if (argc == 0) { + // reset to full limits of search ranges + threeply -> a_lo = M_a_lo; + threeply -> a_hi = M_a_hi; + threeply -> b_lo = M_b_lo; + threeply -> b_hi = M_b_hi; + threeply -> c_lo = M_c_lo; + threeply -> c_hi = M_c_hi; + return; + } + if (argc == 1) { + // set the ranges based on percentage of full range + double percent = atom_getfloat(arg); + double a_spread = ((M_a_hi - M_a_lo) * percent) / 2; + double b_spread = ((M_b_hi - M_b_lo) * percent) / 2; + double c_spread = ((M_c_hi - M_c_lo) * percent) / 2; + threeply -> a_lo = threeply -> a - a_spread; + threeply -> a_hi = threeply -> a + a_spread; + threeply -> b_lo = threeply -> b - b_spread; + threeply -> b_hi = threeply -> b + b_spread; + threeply -> c_lo = threeply -> c - c_spread; + threeply -> c_hi = threeply -> c + c_spread; + limiter(threeply); + return; + } + if (argc != M_param_count * 2) { + post("Invalid number of arguments for threeply constraints, requires 6 values, got %d", argc); + return; + } + threeply -> a_lo = atom_getfloat(arg++); + threeply -> a_hi = atom_getfloat(arg++); + threeply -> b_lo = atom_getfloat(arg++); + threeply -> b_hi = atom_getfloat(arg++); + threeply -> c_lo = atom_getfloat(arg++); + threeply -> c_hi = atom_getfloat(arg++); + limiter(threeply); +} + +static void search(threeply_struct *threeply, t_symbol *s, int argc, t_atom *argv) { + int not_found, not_expired = threeply -> lyap_limit; + int jump, i, iterations; + t_atom vars[M_var_count]; + double temp_a = threeply -> a; + double temp_b = threeply -> b; + double temp_c = threeply -> c; + if (argc > 0) { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], atom_getfloatarg(i, argc, argv)); + } + } else { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], threeply -> vars_init[i]); + } + } + do { + jump = 500; + not_found = 0; + iterations = 10000; + bad_params: + threeply -> a = (drand48() * (threeply -> a_hi - threeply -> a_lo)) + threeply -> a_lo; + threeply -> b = (drand48() * (threeply -> b_hi - threeply -> b_lo)) + threeply -> b_lo; + threeply -> c = (drand48() * (threeply -> c_hi - threeply -> c_lo)) + threeply -> c_lo; + // put any preliminary checks specific to this fractal to eliminate bad_params + + reset(threeply, NULL, argc, vars); + do { calc(threeply, threeply -> vars); } while(jump--); + threeply -> lyap_exp = lyapunov((void *) threeply, (t_gotfn) calc, M_var_count, (double *) threeply -> vars); + if (isnan(threeply -> lyap_exp)) { not_found = 1; } + if (threeply -> lyap_exp < threeply -> lyap_lo || threeply -> lyap_exp > threeply -> lyap_hi) { not_found = 1; } + not_expired--; + } while(not_found && not_expired); + reset(threeply, NULL, argc, vars); + if (!not_expired) { + post("Could not find a fractal after %d attempts.", (int) threeply -> lyap_limit); + post("Try using wider constraints."); + threeply -> a = temp_a; + threeply -> b = temp_b; + threeply -> c = temp_c; + outlet_anything(threeply -> search_outlet, gensym("invalid"), 0, NULL); + } else { + threeply -> failure_ratio = (threeply -> lyap_limit - not_expired) / threeply -> lyap_limit; + make_results(threeply); + outlet_anything(threeply -> search_outlet, gensym("search"), M_search_count, threeply -> search_out); + } +} + +void *threeply_new(t_symbol *s, int argc, t_atom *argv) { + threeply_struct *threeply = (threeply_struct *) pd_new(threeply_class); + if (threeply != NULL) { + outlet_new(&threeply -> x_obj, &s_float); + threeply -> outlets[0] = outlet_new(&threeply -> x_obj, &s_float); + threeply -> search_outlet = outlet_new(&threeply -> x_obj, &s_list); + threeply -> vars_outlet = outlet_new(&threeply -> x_obj, &s_list); + threeply -> params_outlet = outlet_new(&threeply -> x_obj, &s_list); + if (argc == M_param_count + M_var_count) { + threeply -> vars_init[M_x] = threeply -> vars[M_x] = (double) atom_getfloatarg(0, argc, argv); + threeply -> vars_init[M_y] = threeply -> vars[M_y] = (double) atom_getfloatarg(1, argc, argv); + threeply -> a = (double) atom_getfloatarg(2, argc, argv); + threeply -> b = (double) atom_getfloatarg(3, argc, argv); + threeply -> c = (double) atom_getfloatarg(4, argc, argv); + } else { + if (argc != 0 && argc != M_param_count + M_var_count) { + post("Incorrect number of arguments for threeply fractal. Expecting 5 arguments."); + } + threeply -> vars_init[M_x] = 0; + threeply -> vars_init[M_y] = 0; + threeply -> a = -55; + threeply -> b = -1; + threeply -> c = -42; + } + constrain(threeply, NULL, 0, NULL); + lyap(threeply, -1000000.0, 1000000.0, M_failure_limit); + } + return (void *)threeply; +} + +void threeply_setup(void) { + threeply_class = class_new(gensym("threeply"), (t_newmethod) threeply_new, 0, sizeof(threeply_struct), 0, A_GIMME, 0); + class_addbang(threeply_class, (t_method) calculate); + class_addmethod(threeply_class, (t_method) reset, gensym("reset"), A_GIMME, 0); + class_addmethod(threeply_class, (t_method) show, gensym("show"), 0); + class_addmethod(threeply_class, (t_method) param, gensym("param"), A_GIMME, 0); + class_addmethod(threeply_class, (t_method) seed, gensym("seed"), A_GIMME, 0); + class_addmethod(threeply_class, (t_method) lyap, gensym("lyapunov"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(threeply_class, (t_method) elyap, gensym("elyapunov"), 0); + class_addmethod(threeply_class, (t_method) search, gensym("search"), A_GIMME, 0); + class_addmethod(threeply_class, (t_method) constrain, gensym("constrain"), A_GIMME, 0); + class_sethelpsymbol(threeply_class, gensym("help-threeply.pd")); +} + diff --git a/tinkerbell.c b/tinkerbell.c new file mode 100644 index 0000000..b934bd9 --- /dev/null +++ b/tinkerbell.c @@ -0,0 +1,325 @@ +/* tinkerbell Attractor PD External */ +/* Copyright Michael McGonagle, from ??????, 2003 */ +/* This program is distributed under the params of the GNU Public License */ + +/////////////////////////////////////////////////////////////////////////////////// +/* This file is part of Chaos PD Externals. */ +/* */ +/* Chaos PD Externals are free software; you can redistribute them and/or modify */ +/* them under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Chaos PD Externals are distributed in the hope that they will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with the Chaos PD Externals; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "lyapunov.h" + +#define M_a_lo -1000 +#define M_a_hi 1000 +#define M_b_lo -1000 +#define M_b_hi 1000 +#define M_c_lo -1000 +#define M_c_hi 1000 +#define M_d_lo -1000 +#define M_d_hi 1000 + +#define M_a 0 +#define M_b 1 +#define M_c 2 +#define M_d 3 + +#define M_x 0 +#define M_y 1 + +#define M_param_count 4 +#define M_var_count 2 +#define M_search_count 3 +#define M_failure_limit 1000 + +static char *version = "tinkerbell v0.0, by Michael McGonagle, from ??????, 2003"; + +t_class *tinkerbell_class; + +typedef struct tinkerbell_struct { + t_object x_obj; + + double vars[M_var_count]; + double vars_init[M_var_count]; + t_atom vars_out[M_var_count]; + t_outlet *vars_outlet; + + t_atom search_out[M_search_count]; + t_outlet *search_outlet; + + double a, a_lo, a_hi, b, b_lo, b_hi, c, c_lo, c_hi, d, d_lo, d_hi; + t_atom params_out[M_param_count]; + t_outlet *params_outlet; + double lyap_exp, lyap_lo, lyap_hi, lyap_limit, failure_ratio; + + t_outlet *outlets[M_var_count - 1]; +} tinkerbell_struct; + +static void calc(tinkerbell_struct *tinkerbell, double *vars) { + double x_0, y_0; + x_0 =vars[M_x]*vars[M_x]-vars[M_y]*vars[M_y]+tinkerbell -> a*vars[M_x]+tinkerbell -> b*vars[M_y]; + y_0 =2*vars[M_x]*vars[M_y]-tinkerbell -> c*vars[M_x]+tinkerbell -> d*vars[M_y]; + vars[M_x] = x_0; + vars[M_y] = y_0; +} // end calc + +static void calculate(tinkerbell_struct *tinkerbell) { + calc(tinkerbell, tinkerbell -> vars); + outlet_float(tinkerbell -> x_obj.ob_outlet, tinkerbell -> vars[M_x]); + outlet_float(tinkerbell -> outlets[M_y - 1], tinkerbell -> vars[M_y]); +} // end calculate + +static void reset(tinkerbell_struct *tinkerbell, t_symbol *s, int argc, t_atom *argv) { + if (argc == M_var_count) { + tinkerbell -> vars[M_x] = (double) atom_getfloatarg(M_x, argc, argv); + tinkerbell -> vars[M_y] = (double) atom_getfloatarg(M_y, argc, argv); + } else { + tinkerbell -> vars[M_x] = tinkerbell -> vars_init[M_x]; + tinkerbell -> vars[M_y] = tinkerbell -> vars_init[M_y]; + } // end if +} // end reset + +static char *classify(tinkerbell_struct *tinkerbell) { + static char buff[5]; + char *c = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + buff[0] = c[(int) (((tinkerbell -> a - M_a_lo) * (1.0 / (M_a_hi - M_a_lo))) * 26)]; + buff[1] = c[(int) (((tinkerbell -> b - M_b_lo) * (1.0 / (M_b_hi - M_b_lo))) * 26)]; + buff[2] = c[(int) (((tinkerbell -> c - M_c_lo) * (1.0 / (M_c_hi - M_c_lo))) * 26)]; + buff[3] = c[(int) (((tinkerbell -> d - M_d_lo) * (1.0 / (M_d_hi - M_d_lo))) * 26)]; + buff[4] = '\0'; + return buff; +} + +static void make_results(tinkerbell_struct *tinkerbell) { + SETFLOAT(&tinkerbell -> search_out[0], tinkerbell -> lyap_exp); + SETSYMBOL(&tinkerbell -> search_out[1], gensym(classify(tinkerbell))); + SETFLOAT(&tinkerbell -> search_out[2], tinkerbell -> failure_ratio); + SETFLOAT(&tinkerbell -> vars_out[M_x], tinkerbell -> vars[M_x]); + SETFLOAT(&tinkerbell -> vars_out[M_y], tinkerbell -> vars[M_y]); + SETFLOAT(&tinkerbell -> params_out[M_a], tinkerbell -> a); + SETFLOAT(&tinkerbell -> params_out[M_b], tinkerbell -> b); + SETFLOAT(&tinkerbell -> params_out[M_c], tinkerbell -> c); + SETFLOAT(&tinkerbell -> params_out[M_d], tinkerbell -> d); + outlet_list(tinkerbell -> params_outlet, gensym("list"), M_param_count, tinkerbell -> params_out); + outlet_list(tinkerbell -> vars_outlet, gensym("list"), M_var_count, tinkerbell -> vars_out); +} + +static void show(tinkerbell_struct *tinkerbell) { + make_results(tinkerbell); + outlet_anything(tinkerbell -> search_outlet, gensym("show"), M_search_count, tinkerbell -> search_out); +} + +static void param(tinkerbell_struct *tinkerbell, t_symbol *s, int argc, t_atom *argv) { + if (argc != 4) { + post("Incorrect number of arguments for tinkerbell fractal. Expecting 4 arguments."); + return; + } + tinkerbell -> a = (double) atom_getfloatarg(0, argc, argv); + tinkerbell -> b = (double) atom_getfloatarg(1, argc, argv); + tinkerbell -> c = (double) atom_getfloatarg(2, argc, argv); + tinkerbell -> d = (double) atom_getfloatarg(3, argc, argv); +} + +static void seed(tinkerbell_struct *tinkerbell, t_symbol *s, int argc, t_atom *argv) { + if (argc > 0) { + srand48(((unsigned int)time(0))|1); + } else { + srand48((unsigned int) atom_getfloatarg(0, argc, argv)); + } +} + +static void lyap(tinkerbell_struct *tinkerbell, t_floatarg l, t_floatarg h, t_floatarg lim) { + tinkerbell -> lyap_lo = l; + tinkerbell -> lyap_hi = h; + tinkerbell -> lyap_limit = (double) ((int) lim); +} + +static void elyap(tinkerbell_struct *tinkerbell) { + double results[M_var_count]; + int i; + if (lyapunov_full((void *) tinkerbell, (t_gotfn) calc, M_var_count, tinkerbell -> vars, results) != NULL) { + post("elyapunov:"); + for(i = 0; i < M_var_count; i++) { post("%d: %3.80f", i, results[i]); } + } +} + +static void limiter(tinkerbell_struct *tinkerbell) { + if (tinkerbell -> a_lo < M_a_lo) { tinkerbell -> a_lo = M_a_lo; } + if (tinkerbell -> a_lo > M_a_hi) { tinkerbell -> a_lo = M_a_hi; } + if (tinkerbell -> a_hi < M_a_lo) { tinkerbell -> a_hi = M_a_lo; } + if (tinkerbell -> a_hi > M_a_hi) { tinkerbell -> a_hi = M_a_hi; } + if (tinkerbell -> b_lo < M_b_lo) { tinkerbell -> b_lo = M_b_lo; } + if (tinkerbell -> b_lo > M_b_hi) { tinkerbell -> b_lo = M_b_hi; } + if (tinkerbell -> b_hi < M_b_lo) { tinkerbell -> b_hi = M_b_lo; } + if (tinkerbell -> b_hi > M_b_hi) { tinkerbell -> b_hi = M_b_hi; } + if (tinkerbell -> c_lo < M_c_lo) { tinkerbell -> c_lo = M_c_lo; } + if (tinkerbell -> c_lo > M_c_hi) { tinkerbell -> c_lo = M_c_hi; } + if (tinkerbell -> c_hi < M_c_lo) { tinkerbell -> c_hi = M_c_lo; } + if (tinkerbell -> c_hi > M_c_hi) { tinkerbell -> c_hi = M_c_hi; } + if (tinkerbell -> d_lo < M_d_lo) { tinkerbell -> d_lo = M_d_lo; } + if (tinkerbell -> d_lo > M_d_hi) { tinkerbell -> d_lo = M_d_hi; } + if (tinkerbell -> d_hi < M_d_lo) { tinkerbell -> d_hi = M_d_lo; } + if (tinkerbell -> d_hi > M_d_hi) { tinkerbell -> d_hi = M_d_hi; } +} + +static void constrain(tinkerbell_struct *tinkerbell, t_symbol *s, int argc, t_atom *argv) { + int i; + t_atom *arg = argv; + if (argc == 0) { + // reset to full limits of search ranges + tinkerbell -> a_lo = M_a_lo; + tinkerbell -> a_hi = M_a_hi; + tinkerbell -> b_lo = M_b_lo; + tinkerbell -> b_hi = M_b_hi; + tinkerbell -> c_lo = M_c_lo; + tinkerbell -> c_hi = M_c_hi; + tinkerbell -> d_lo = M_d_lo; + tinkerbell -> d_hi = M_d_hi; + return; + } + if (argc == 1) { + // set the ranges based on percentage of full range + double percent = atom_getfloat(arg); + double a_spread = ((M_a_hi - M_a_lo) * percent) / 2; + double b_spread = ((M_b_hi - M_b_lo) * percent) / 2; + double c_spread = ((M_c_hi - M_c_lo) * percent) / 2; + double d_spread = ((M_d_hi - M_d_lo) * percent) / 2; + tinkerbell -> a_lo = tinkerbell -> a - a_spread; + tinkerbell -> a_hi = tinkerbell -> a + a_spread; + tinkerbell -> b_lo = tinkerbell -> b - b_spread; + tinkerbell -> b_hi = tinkerbell -> b + b_spread; + tinkerbell -> c_lo = tinkerbell -> c - c_spread; + tinkerbell -> c_hi = tinkerbell -> c + c_spread; + tinkerbell -> d_lo = tinkerbell -> d - d_spread; + tinkerbell -> d_hi = tinkerbell -> d + d_spread; + limiter(tinkerbell); + return; + } + if (argc != M_param_count * 2) { + post("Invalid number of arguments for tinkerbell constraints, requires 8 values, got %d", argc); + return; + } + tinkerbell -> a_lo = atom_getfloat(arg++); + tinkerbell -> a_hi = atom_getfloat(arg++); + tinkerbell -> b_lo = atom_getfloat(arg++); + tinkerbell -> b_hi = atom_getfloat(arg++); + tinkerbell -> c_lo = atom_getfloat(arg++); + tinkerbell -> c_hi = atom_getfloat(arg++); + tinkerbell -> d_lo = atom_getfloat(arg++); + tinkerbell -> d_hi = atom_getfloat(arg++); + limiter(tinkerbell); +} + +static void search(tinkerbell_struct *tinkerbell, t_symbol *s, int argc, t_atom *argv) { + int not_found, not_expired = tinkerbell -> lyap_limit; + int jump, i, iterations; + t_atom vars[M_var_count]; + double temp_a = tinkerbell -> a; + double temp_b = tinkerbell -> b; + double temp_c = tinkerbell -> c; + double temp_d = tinkerbell -> d; + if (argc > 0) { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], atom_getfloatarg(i, argc, argv)); + } + } else { + for (i = 0; i < M_var_count; i++) { + SETFLOAT(&vars[i], tinkerbell -> vars_init[i]); + } + } + do { + jump = 500; + not_found = 0; + iterations = 10000; + bad_params: + tinkerbell -> a = (drand48() * (tinkerbell -> a_hi - tinkerbell -> a_lo)) + tinkerbell -> a_lo; + tinkerbell -> b = (drand48() * (tinkerbell -> b_hi - tinkerbell -> b_lo)) + tinkerbell -> b_lo; + tinkerbell -> c = (drand48() * (tinkerbell -> c_hi - tinkerbell -> c_lo)) + tinkerbell -> c_lo; + tinkerbell -> d = (drand48() * (tinkerbell -> d_hi - tinkerbell -> d_lo)) + tinkerbell -> d_lo; + // put any preliminary checks specific to this fractal to eliminate bad_params + + reset(tinkerbell, NULL, argc, vars); + do { calc(tinkerbell, tinkerbell -> vars); } while(jump--); + tinkerbell -> lyap_exp = lyapunov((void *) tinkerbell, (t_gotfn) calc, M_var_count, (double *) tinkerbell -> vars); + if (isnan(tinkerbell -> lyap_exp)) { not_found = 1; } + if (tinkerbell -> lyap_exp < tinkerbell -> lyap_lo || tinkerbell -> lyap_exp > tinkerbell -> lyap_hi) { not_found = 1; } + not_expired--; + } while(not_found && not_expired); + reset(tinkerbell, NULL, argc, vars); + if (!not_expired) { + post("Could not find a fractal after %d attempts.", (int) tinkerbell -> lyap_limit); + post("Try using wider constraints."); + tinkerbell -> a = temp_a; + tinkerbell -> b = temp_b; + tinkerbell -> c = temp_c; + tinkerbell -> d = temp_d; + outlet_anything(tinkerbell -> search_outlet, gensym("invalid"), 0, NULL); + } else { + tinkerbell -> failure_ratio = (tinkerbell -> lyap_limit - not_expired) / tinkerbell -> lyap_limit; + make_results(tinkerbell); + outlet_anything(tinkerbell -> search_outlet, gensym("search"), M_search_count, tinkerbell -> search_out); + } +} + +void *tinkerbell_new(t_symbol *s, int argc, t_atom *argv) { + tinkerbell_struct *tinkerbell = (tinkerbell_struct *) pd_new(tinkerbell_class); + if (tinkerbell != NULL) { + outlet_new(&tinkerbell -> x_obj, &s_float); + tinkerbell -> outlets[0] = outlet_new(&tinkerbell -> x_obj, &s_float); + tinkerbell -> search_outlet = outlet_new(&tinkerbell -> x_obj, &s_list); + tinkerbell -> vars_outlet = outlet_new(&tinkerbell -> x_obj, &s_list); + tinkerbell -> params_outlet = outlet_new(&tinkerbell -> x_obj, &s_list); + if (argc == M_param_count + M_var_count) { + tinkerbell -> vars_init[M_x] = tinkerbell -> vars[M_x] = (double) atom_getfloatarg(0, argc, argv); + tinkerbell -> vars_init[M_y] = tinkerbell -> vars[M_y] = (double) atom_getfloatarg(1, argc, argv); + tinkerbell -> a = (double) atom_getfloatarg(2, argc, argv); + tinkerbell -> b = (double) atom_getfloatarg(3, argc, argv); + tinkerbell -> c = (double) atom_getfloatarg(4, argc, argv); + tinkerbell -> d = (double) atom_getfloatarg(5, argc, argv); + } else { + if (argc != 0 && argc != M_param_count + M_var_count) { + post("Incorrect number of arguments for tinkerbell fractal. Expecting 6 arguments."); + } + tinkerbell -> vars_init[M_x] = 0.1; + tinkerbell -> vars_init[M_y] = 0.1; + tinkerbell -> a = 0.9; + tinkerbell -> b = 0.6; + tinkerbell -> c = 2; + tinkerbell -> d = 0.5; + } + constrain(tinkerbell, NULL, 0, NULL); + lyap(tinkerbell, -1000000.0, 1000000.0, M_failure_limit); + } + return (void *)tinkerbell; +} + +void tinkerbell_setup(void) { + tinkerbell_class = class_new(gensym("tinkerbell"), (t_newmethod) tinkerbell_new, 0, sizeof(tinkerbell_struct), 0, A_GIMME, 0); + class_addbang(tinkerbell_class, (t_method) calculate); + class_addmethod(tinkerbell_class, (t_method) reset, gensym("reset"), A_GIMME, 0); + class_addmethod(tinkerbell_class, (t_method) show, gensym("show"), 0); + class_addmethod(tinkerbell_class, (t_method) param, gensym("param"), A_GIMME, 0); + class_addmethod(tinkerbell_class, (t_method) seed, gensym("seed"), A_GIMME, 0); + class_addmethod(tinkerbell_class, (t_method) lyap, gensym("lyapunov"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(tinkerbell_class, (t_method) elyap, gensym("elyapunov"), 0); + class_addmethod(tinkerbell_class, (t_method) search, gensym("search"), A_GIMME, 0); + class_addmethod(tinkerbell_class, (t_method) constrain, gensym("constrain"), A_GIMME, 0); + class_sethelpsymbol(tinkerbell_class, gensym("help-tinkerbell.pd")); +} + diff --git a/tools/fractal-tools.pd b/tools/fractal-tools.pd new file mode 100644 index 0000000..2170d6a --- /dev/null +++ b/tools/fractal-tools.pd @@ -0,0 +1,27 @@ +#N canvas 0 22 454 304 10; +#X obj 27 252 outlet; +#X msg 149 80 reset; +#X msg 158 101 show; +#X msg 167 122 param; +#X msg 175 143 lyapunov -100 100 1000; +#X msg 183 164 elyapunov; +#X msg 192 186 constrain; +#X msg 198 208 search; +#X obj 27 23 inlet; +#N canvas 0 22 454 304 iterator-tools 0; +#X obj 17 264 outlet; +#X text 17 19 This abstraction is intended to be used to iterate over +the parameter space. Repeatedly performs the following:; +#X text 46 65 1 'param' to set a centerpoint around which to search +; +#X text 46 80 2 'constrain ' to limit the search area; +#X text 46 95 3 'search' to find a fractal within the area; +#X restore 48 53 pd iterator-tools; +#X connect 1 0 0 0; +#X connect 2 0 0 0; +#X connect 3 0 0 0; +#X connect 4 0 0 0; +#X connect 5 0 0 0; +#X connect 6 0 0 0; +#X connect 7 0 0 0; +#X connect 8 0 0 0; diff --git a/tools/help-attract1.pd b/tools/help-attract1.pd new file mode 100644 index 0000000..cb737b9 --- /dev/null +++ b/tools/help-attract1.pd @@ -0,0 +1,35 @@ +#N canvas 426 137 573 476 10; +#X obj 44 115 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X floatatom 95 116 5 0 0 0 - - -; +#X floatatom 132 393 10 0 0 0 Y - -; +#X floatatom 44 393 10 0 0 0 X - -; +#X text 18 49 (This attractor is not continuous); +#X obj 44 132 metro 50; +#X obj 19 131 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 242 104 readme-fractals; +#X msg 87 245 search; +#X text 138 246 Find a random attractor set; +#X msg 98 266 show; +#X obj 44 316 attract1 0 0 -0.0239362 -0.67834 2.50703 -0.0138538 -1.44072 +2.47917; +#X msg 78 195 param -0.0239362 -0.67834 2.50703 -0.0138538 -1.44072 +2.47917; +#X text 20 18 Attract1 Attractor; +#X text 18 33 Chaos PD Externals - Copyright Michael McGonagle \, 2003 +; +#X obj 278 367 search-tools; +#X connect 0 0 5 0; +#X connect 1 0 5 1; +#X connect 5 0 11 0; +#X connect 6 0 11 0; +#X connect 8 0 11 0; +#X connect 10 0 11 0; +#X connect 11 0 3 0; +#X connect 11 1 2 0; +#X connect 11 2 15 0; +#X connect 11 3 15 1; +#X connect 11 4 15 2; +#X connect 12 0 11 0; +#X connect 15 0 11 0; diff --git a/tools/help-base.pd b/tools/help-base.pd new file mode 100644 index 0000000..bc0fd83 --- /dev/null +++ b/tools/help-base.pd @@ -0,0 +1,28 @@ +#N canvas 680 295 589 492 10; +#X obj 43 134 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X floatatom 94 135 5 0 0 0 - - -; +#X floatatom 43 332 10 0 0 0 X - -; +#X text 19 50 (This attractor is not continuous); +#X text 20 34 Chaos PD Externals - Copyright Michael McGonagle 2003 +; +#X obj 43 151 metro 50; +#X obj 20 154 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 436 18 readme-fractals; +#X text 21 19 Base Attractor; +#X obj 53 262 fractal-tools; +#X obj 43 285 base3 0.1 1.18939 2.24148; +#X msg 61 240 lyapunov 0 100 1000; +#X obj 126 320 search-tools; +#X connect 0 0 5 0; +#X connect 1 0 5 1; +#X connect 5 0 10 0; +#X connect 6 0 10 0; +#X connect 9 0 10 0; +#X connect 10 0 2 0; +#X connect 10 1 12 0; +#X connect 10 2 12 1; +#X connect 10 3 12 2; +#X connect 11 0 9 0; +#X connect 12 0 10 0; diff --git a/tools/help-gingerbreadman.pd b/tools/help-gingerbreadman.pd new file mode 100644 index 0000000..701b33e --- /dev/null +++ b/tools/help-gingerbreadman.pd @@ -0,0 +1,31 @@ +#N canvas 615 23 577 480 10; +#X obj 44 115 tgl 15 0 empty empty empty 0 -6 32 8 -262144 -1 -1 0 +1; +#X floatatom 95 116 5 0 0 0 - - -; +#X floatatom 131 348 10 0 0 0 Y - -; +#X floatatom 44 348 10 0 0 0 X - -; +#X text 17 48 (This attractor is not continuous); +#X obj 44 132 metro 50; +#X obj 19 131 bng 15 250 50 0 empty empty empty 0 -6 32 8 -262144 -1 +-1; +#X obj 242 104 readme-fractals; +#X msg 113 272 show; +#X msg 76 156 reset; +#X text 120 156 Reset to initial state from creation arguments; +#X text 19 33 Chaos PD Externals - Copyright Michael McGonagle \, 2003 +; +#X text 20 18 Gingerbreadman Attractor; +#X obj 44 316 gingerbreadman; +#X text 91 193 This fractal equation does not have any parameters \, +and thus does not allow the messages 'param' or any of the searching +functions.; +#X msg 96 235 param; +#X connect 0 0 5 0; +#X connect 1 0 5 1; +#X connect 5 0 13 0; +#X connect 6 0 13 0; +#X connect 8 0 13 0; +#X connect 9 0 13 0; +#X connect 13 0 3 0; +#X connect 13 1 2 0; +#X connect 15 0 13 0; diff --git a/tools/help-henon.pd b/tools/help-henon.pd new file mode 100644 index 0000000..87b06ce --- /dev/null +++ b/tools/help-henon.pd @@ -0,0 +1,30 @@ +#N canvas 473 208 581 484 10; +#X obj 43 81 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X floatatom 94 82 5 0 0 0 - - -; +#X floatatom 71 372 10 0 0 0 Y - -; +#X floatatom 43 348 10 0 0 0 X - -; +#X text 18 49 (This attractor is not continuous); +#X obj 43 98 metro 50; +#X obj 18 97 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X msg 88 209 param 1.4 0.3; +#X text 19 33 Chaos PD Externals - Copyright Ben Bogart 2002; +#X text 20 17 Henon Attractor; +#X obj 43 294 henon 1 1 1.4 0.3; +#X msg 75 176 reset; +#X text 120 176 Reset to initial state from creation arguments; +#X text 192 209 Modify parameters; +#X obj 90 318 search-tools; +#X connect 0 0 5 0; +#X connect 1 0 5 1; +#X connect 5 0 10 0; +#X connect 6 0 10 0; +#X connect 7 0 10 0; +#X connect 10 0 3 0; +#X connect 10 1 2 0; +#X connect 10 2 14 0; +#X connect 10 3 14 1; +#X connect 10 4 14 2; +#X connect 11 0 10 0; +#X connect 14 0 10 0; diff --git a/tools/help-hopalong.pd b/tools/help-hopalong.pd new file mode 100644 index 0000000..4b6433b --- /dev/null +++ b/tools/help-hopalong.pd @@ -0,0 +1,32 @@ +#N canvas 473 208 581 484 10; +#X obj 43 134 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X floatatom 94 135 5 0 0 0 - - -; +#X text 91 208 Reset To Initial Conditions; +#X text 102 251 Modify Parameters; +#X msg 88 191 reset 0.1 0.1; +#X floatatom 115 419 10 0 0 0 Y - -; +#X floatatom 43 388 10 0 0 0 X - -; +#X text 19 50 (This attractor is not continuous); +#X text 20 34 Chaos PD Externals - Copyright Michael McGonagle 2003 +; +#X obj 43 151 metro 50; +#X obj 18 150 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 25 83 readme-fractals; +#X text 21 19 Hopalong Attractor; +#X msg 99 234 param -639.064 886.792 -150.226; +#X obj 43 348 hopalong 0.1 0.1 -639.064 886.792 -150.226; +#X obj 220 378 search-tools; +#X connect 0 0 9 0; +#X connect 1 0 9 1; +#X connect 4 0 14 0; +#X connect 9 0 14 0; +#X connect 10 0 14 0; +#X connect 13 0 14 0; +#X connect 14 0 6 0; +#X connect 14 1 5 0; +#X connect 14 2 15 0; +#X connect 14 3 15 1; +#X connect 14 4 15 2; +#X connect 15 0 14 0; diff --git a/tools/help-ikeda.pd b/tools/help-ikeda.pd new file mode 100644 index 0000000..b9d009c --- /dev/null +++ b/tools/help-ikeda.pd @@ -0,0 +1,33 @@ +#N canvas 23 245 569 472 10; +#X obj 44 115 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X floatatom 95 116 5 0 0 0 - - -; +#X floatatom 86 379 10 0 0 0 Y - -; +#X floatatom 44 352 10 0 0 0 X - -; +#X text 18 49 (This attractor is not continuous); +#X obj 44 132 metro 50; +#X obj 19 131 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X msg 92 215 param 0.4 0.9 6 1; +#X msg 92 193 param 0.4 0.8 20 1; +#X text 20 18 Ikeda Attractor; +#X text 19 33 Chaos PD Externals - Copyright Ben Bogart 2002; +#X obj 242 104 readme-fractals; +#X obj 44 316 ikeda 0.1 0.1 0.4 0.9 6 1; +#X msg 76 156 reset; +#X text 120 156 Reset to initial state from creation arguments; +#X text 226 193 Modify parameters; +#X obj 156 349 search-tools; +#X connect 0 0 5 0; +#X connect 1 0 5 1; +#X connect 5 0 12 0; +#X connect 6 0 12 0; +#X connect 7 0 12 0; +#X connect 8 0 12 0; +#X connect 12 0 3 0; +#X connect 12 1 2 0; +#X connect 12 2 16 0; +#X connect 12 3 16 1; +#X connect 12 4 16 2; +#X connect 13 0 12 0; +#X connect 16 0 12 0; diff --git a/tools/help-latoocarfian.pd b/tools/help-latoocarfian.pd new file mode 100644 index 0000000..ee592be --- /dev/null +++ b/tools/help-latoocarfian.pd @@ -0,0 +1,35 @@ +#N canvas 527 258 589 492 10; +#X obj 43 134 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X floatatom 94 135 5 0 0 0 - - -; +#X text 91 208 Reset To Initial Conditions; +#X text 114 281 Modify Parameters; +#X msg 88 191 reset 0.1 0.1; +#X msg 111 243 param -0.966918 2.87988 0.756145 0.744728; +#X msg 111 264 param -2.90515 -2.03043 1.44055 0.70307; +#X floatatom 136 407 10 0 0 0 Y - -; +#X floatatom 43 367 10 0 0 0 X - -; +#X text 19 50 (This attractor is not continuous); +#X text 21 19 Latoocarfian Attractor (from Cliff Pickover); +#X text 20 34 Chaos PD Externals - Copyright Michael McGonagle 2003 +; +#X obj 43 151 metro 50; +#X obj 18 150 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 25 83 readme-fractals; +#X obj 43 347 latoocarfian 0.1 0.1 -2.90515 -2.03043 1.44055 0.70307 +; +#X obj 283 376 search-tools; +#X connect 0 0 12 0; +#X connect 1 0 12 1; +#X connect 4 0 15 0; +#X connect 5 0 15 0; +#X connect 6 0 15 0; +#X connect 12 0 15 0; +#X connect 13 0 15 0; +#X connect 15 0 8 0; +#X connect 15 1 7 0; +#X connect 15 2 16 0; +#X connect 15 3 16 1; +#X connect 15 4 16 2; +#X connect 16 0 15 0; diff --git a/tools/help-latoomutalpha.pd b/tools/help-latoomutalpha.pd new file mode 100644 index 0000000..dda50f5 --- /dev/null +++ b/tools/help-latoomutalpha.pd @@ -0,0 +1,35 @@ +#N canvas 487 49 585 488 10; +#X obj 43 134 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X floatatom 94 135 5 0 0 0 - - -; +#X text 91 208 Reset To Initial Conditions; +#X text 114 281 Modify Parameters; +#X msg 88 191 reset 0.1 0.1; +#X msg 111 243 param -0.966918 2.87988 0.756145 0.744728; +#X msg 111 264 param -2.90515 -2.03043 1.44055 0.70307; +#X floatatom 138 404 10 0 0 0 Y - -; +#X floatatom 43 367 10 0 0 0 X - -; +#X text 19 50 (This attractor is not continuous); +#X text 21 19 Latoocarfian Attractor (from Cliff Pickover); +#X text 20 34 Chaos PD Externals - Copyright Michael McGonagle 2003 +; +#X obj 43 151 metro 50; +#X obj 18 150 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 25 83 readme-fractals; +#X obj 43 347 latoomutalpha 0.1 0.1 -2.90515 -2.03043 1.44055 0.70307 +; +#X obj 289 374 search-tools; +#X connect 0 0 12 0; +#X connect 1 0 12 1; +#X connect 4 0 15 0; +#X connect 5 0 15 0; +#X connect 6 0 15 0; +#X connect 12 0 15 0; +#X connect 13 0 15 0; +#X connect 15 0 8 0; +#X connect 15 1 7 0; +#X connect 15 2 16 0; +#X connect 15 3 16 1; +#X connect 15 4 16 2; +#X connect 16 0 15 0; diff --git a/tools/help-latoomutbeta.pd b/tools/help-latoomutbeta.pd new file mode 100644 index 0000000..775b542 --- /dev/null +++ b/tools/help-latoomutbeta.pd @@ -0,0 +1,35 @@ +#N canvas 527 258 585 488 10; +#X obj 43 134 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X floatatom 94 135 5 0 0 0 - - -; +#X text 91 208 Reset To Initial Conditions; +#X text 114 281 Modify Parameters; +#X msg 88 191 reset 0.1 0.1; +#X msg 111 243 param -0.966918 2.87988 0.756145 0.744728; +#X msg 111 264 param -2.90515 -2.03043 1.44055 0.70307; +#X floatatom 136 399 10 0 0 0 Y - -; +#X floatatom 43 367 10 0 0 0 X - -; +#X text 19 50 (This attractor is not continuous); +#X text 21 19 Latoocarfian Attractor (from Cliff Pickover); +#X text 20 34 Chaos PD Externals - Copyright Michael McGonagle 2003 +; +#X obj 43 151 metro 50; +#X obj 18 150 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 25 83 readme-fractals; +#X obj 43 347 latoomutbeta 0.1 0.1 -2.90515 -2.03043 1.44055 0.70307 +; +#X obj 283 373 search-tools; +#X connect 0 0 12 0; +#X connect 1 0 12 1; +#X connect 4 0 15 0; +#X connect 5 0 15 0; +#X connect 6 0 15 0; +#X connect 12 0 15 0; +#X connect 13 0 15 0; +#X connect 15 0 8 0; +#X connect 15 1 7 0; +#X connect 15 2 16 0; +#X connect 15 3 16 1; +#X connect 15 4 16 2; +#X connect 16 0 15 0; diff --git a/tools/help-latoomutgamma.pd b/tools/help-latoomutgamma.pd new file mode 100644 index 0000000..256b795 --- /dev/null +++ b/tools/help-latoomutgamma.pd @@ -0,0 +1,35 @@ +#N canvas 527 258 581 484 10; +#X obj 43 134 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X floatatom 94 135 5 0 0 0 - - -; +#X text 91 208 Reset To Initial Conditions; +#X text 114 281 Modify Parameters; +#X msg 88 191 reset 0.1 0.1; +#X msg 111 243 param -0.966918 2.87988 0.756145 0.744728; +#X msg 111 264 param -2.90515 -2.03043 1.44055 0.70307; +#X floatatom 138 406 10 0 0 0 Y - -; +#X floatatom 43 367 10 0 0 0 X - -; +#X text 19 50 (This attractor is not continuous); +#X text 21 19 Latoocarfian Attractor (from Cliff Pickover); +#X text 20 34 Chaos PD Externals - Copyright Michael McGonagle 2003 +; +#X obj 43 151 metro 50; +#X obj 18 150 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 25 83 readme-fractals; +#X obj 43 347 latoomutgamma 0.1 0.1 -2.90515 -2.03043 1.44055 0.70307 +; +#X obj 289 374 search-tools; +#X connect 0 0 12 0; +#X connect 1 0 12 1; +#X connect 4 0 15 0; +#X connect 5 0 15 0; +#X connect 6 0 15 0; +#X connect 12 0 15 0; +#X connect 13 0 15 0; +#X connect 15 0 8 0; +#X connect 15 1 7 0; +#X connect 15 2 16 0; +#X connect 15 3 16 1; +#X connect 15 4 16 2; +#X connect 16 0 15 0; diff --git a/tools/help-lorenz.pd b/tools/help-lorenz.pd new file mode 100644 index 0000000..0dc9b56 --- /dev/null +++ b/tools/help-lorenz.pd @@ -0,0 +1,32 @@ +#N canvas 683 22 577 480 10; +#X obj 43 105 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X floatatom 94 106 5 0 0 0 - - -; +#X text 132 162 Reset To Initial Conditions; +#X floatatom 88 372 10 0 0 0 Y - -; +#X floatatom 43 350 10 0 0 0 X - -; +#X obj 43 122 metro 50; +#X obj 18 121 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X msg 98 192 param 0.02 10 28 2.66667; +#X floatatom 133 399 10 0 0 0 Z - -; +#X text 20 18 Lorenz Attractor; +#X text 19 33 Chaos PD Externals - Copyright Ben Bogart 2002; +#X obj 20 62 readme-fractals; +#X obj 43 318 lorenz 0.1 0 0 0.02 10 28 2.66667; +#X text 275 194 Modify parameters; +#X msg 88 162 reset; +#X obj 184 345 search-tools; +#X connect 0 0 5 0; +#X connect 1 0 5 1; +#X connect 5 0 12 0; +#X connect 6 0 12 0; +#X connect 7 0 12 0; +#X connect 12 0 4 0; +#X connect 12 1 3 0; +#X connect 12 2 8 0; +#X connect 12 3 15 0; +#X connect 12 4 15 1; +#X connect 12 5 15 2; +#X connect 14 0 12 0; +#X connect 15 0 12 0; diff --git a/tools/help-martin-test.pd b/tools/help-martin-test.pd new file mode 100644 index 0000000..b8f294a --- /dev/null +++ b/tools/help-martin-test.pd @@ -0,0 +1,92 @@ +#N canvas 437 54 668 669 10; +#X obj 35 179 tgl 15 0 empty empty empty 0 -6 32 8 -262144 -1 -1 0 +1; +#X floatatom 86 180 5 0 0 0 - - -; +#X text 81 219 Reset To Initial Conditions; +#X text 94 261 Modify Parameters; +#X msg 80 236 reset 0.1 0.1; +#X floatatom 59 444 10 0 0 0 Y - -; +#X floatatom 32 464 10 0 0 0 X - -; +#X text 19 50 (This attractor is not continuous); +#X text 21 19 Latoocarfian Attractor (from Cliff Pickover); +#X text 20 34 Chaos PD Externals - Copyright Michael McGonagle 2003 +; +#X obj 35 196 metro 50; +#X obj 14 197 bng 15 250 50 0 empty empty empty 0 -6 32 8 -262144 -1 +-1; +#X obj 25 83 readme-fractals; +#X msg 98 307 search; +#X obj 34 392 martin; +#X msg 89 282 param 1; +#X msg 113 330 show; +#X msg 380 144 1000; +#X obj 336 202 until; +#X obj 279 384 route show search invalid; +#X obj 335 441 print search; +#X obj 279 460 print show; +#X obj 392 422 print invalid; +#X obj 449 403 print somethingelse; +#X msg 346 115 100; +#X msg 311 141 10; +#X msg 309 169 1; +#X obj 474 625 qlist; +#X msg 491 567 print; +#X msg 484 547 clear; +#X msg 474 527 rewind; +#N canvas 0 22 458 308 search 1; +#X floatatom 187 89 5 0 0 0 - - -; +#X obj 142 50 bng 15 250 50 0 empty empty empty 0 -6 32 8 -262144 -1 +-1; +#X obj 147 73 loop; +#X floatatom 186 15 5 0 0 0 - - -; +#X floatatom 192 31 5 0 0 0 - - -; +#X floatatom 198 47 5 0 0 0 - - -; +#X obj 31 259 outlet; +#X msg 48 167 param \$1; +#X msg 65 192 constrain 0.01; +#X obj 77 121 t b b f; +#X msg 82 218 search; +#X connect 1 0 2 0; +#X connect 2 0 9 0; +#X connect 2 1 0 0; +#X connect 3 0 2 0; +#X connect 4 0 2 1; +#X connect 5 0 2 2; +#X connect 7 0 6 0; +#X connect 8 0 6 0; +#X connect 9 0 10 0; +#X connect 9 1 8 0; +#X connect 9 2 7 0; +#X connect 10 0 6 0; +#X restore 45 119 pd search; +#X obj 52 146 print sit; +#X msg 136 357 lyapunov 0 10 100; +#X msg 465 504 add martin \$1 \$3 \$6; +#X connect 0 0 10 0; +#X connect 1 0 10 1; +#X connect 4 0 14 0; +#X connect 10 0 14 0; +#X connect 11 0 14 0; +#X connect 13 0 14 0; +#X connect 14 0 6 0; +#X connect 14 1 5 0; +#X connect 14 2 19 0; +#X connect 15 0 14 0; +#X connect 16 0 14 0; +#X connect 17 0 18 0; +#X connect 18 0 13 0; +#X connect 19 0 21 0; +#X connect 19 1 20 0; +#X connect 19 1 34 0; +#X connect 19 2 22 0; +#X connect 19 3 23 0; +#X connect 24 0 18 0; +#X connect 25 0 18 0; +#X connect 26 0 18 0; +#X connect 28 0 27 0; +#X connect 29 0 27 0; +#X connect 30 0 27 0; +#X connect 31 0 32 0; +#X connect 31 0 14 0; +#X connect 33 0 14 0; +#X connect 34 0 27 0; diff --git a/tools/help-martin.pd b/tools/help-martin.pd new file mode 100644 index 0000000..ef12d0d --- /dev/null +++ b/tools/help-martin.pd @@ -0,0 +1,38 @@ +#N canvas 203 283 593 496 10; +#X obj 43 134 tgl 15 0 empty empty empty 0 -6 32 8 -262144 -1 -1 0 +1; +#X floatatom 94 135 5 0 0 0 - - -; +#X text 89 174 Reset To Initial Conditions; +#X text 102 216 Modify Parameters; +#X msg 88 191 reset 0.1 0.1; +#X floatatom 51 451 10 0 0 0 Y - -; +#X floatatom 42 427 10 0 0 0 X - -; +#X text 19 50 (This attractor is not continuous); +#X text 20 34 Chaos PD Externals - Copyright Michael McGonagle 2003 +; +#X obj 43 151 metro 50; +#X obj 18 150 bng 15 250 50 0 empty empty empty 0 -6 32 8 -262144 -1 +-1; +#X obj 25 83 readme-fractals; +#X obj 42 347 martin; +#X text 143 429 This fractal exhibits chaotic tendencies when A (param) +is in the vicinity of an odd multiple of PI.; +#X msg 97 237 param 3.14159; +#X text 21 19 Martin Attractor; +#X obj 68 379 search-tools; +#X obj 204 344 print vars; +#X obj 239 317 print param; +#X connect 0 0 9 0; +#X connect 1 0 9 1; +#X connect 4 0 12 0; +#X connect 9 0 12 0; +#X connect 10 0 12 0; +#X connect 12 0 6 0; +#X connect 12 1 5 0; +#X connect 12 2 16 0; +#X connect 12 3 16 1; +#X connect 12 3 17 0; +#X connect 12 4 16 2; +#X connect 12 4 18 0; +#X connect 14 0 12 0; +#X connect 16 0 12 0; diff --git a/tools/help-popcorn-test.pd b/tools/help-popcorn-test.pd new file mode 100644 index 0000000..cbfdc4b --- /dev/null +++ b/tools/help-popcorn-test.pd @@ -0,0 +1,62 @@ +#N canvas 575 260 589 492 10; +#X obj 43 134 tgl 15 0 empty empty empty 0 -6 160 8 -262144 -1 -1 0 +1; +#X floatatom 94 135 5 0 0 0 - - -; +#X text 79 201 Reset To Initial Conditions; +#X text 99 246 Modify Parameters; +#X msg 76 184 reset 0.1 0.1; +#X floatatom 131 384 10 0 0 0 Y - -; +#X floatatom 43 384 10 0 0 0 X - -; +#X text 19 50 (This attractor is not continuous); +#X text 21 19 Latoocarfian Attractor (from Cliff Pickover); +#X text 20 34 Chaos PD Externals - Copyright Michael McGonagle 2003 +; +#X obj 43 151 metro 50; +#X obj 13 150 bng 15 250 50 0 empty empty empty 0 -6 32 8 -262144 -1 +-1; +#X obj 25 83 readme-fractals; +#X msg 101 266 search; +#X obj 212 381 print; +#X msg 113 294 show; +#X msg 95 226 param 2.35155; +#X obj 43 347 popcorn 0.1 0 2.35155; +#N canvas 83 103 466 316 search 1; +#X floatatom 187 89 5 0 0 0 - - -; +#X obj 142 50 bng 15 250 50 0 empty empty empty 0 -6 32 8 -262144 -1 +-1; +#X obj 147 73 loop; +#X floatatom 186 15 5 0 0 0 - - -; +#X floatatom 192 31 5 0 0 0 - - -; +#X floatatom 198 47 5 0 0 0 - - -; +#X obj 31 259 outlet; +#X msg 48 167 param \$1; +#X obj 77 121 t b b f; +#X msg 82 218 search; +#X msg 65 192 constrain 0.001; +#X connect 1 0 2 0; +#X connect 2 0 8 0; +#X connect 2 1 0 0; +#X connect 3 0 2 0; +#X connect 4 0 2 1; +#X connect 5 0 2 2; +#X connect 7 0 6 0; +#X connect 8 0 9 0; +#X connect 8 1 10 0; +#X connect 8 2 7 0; +#X connect 9 0 6 0; +#X connect 10 0 6 0; +#X restore 229 286 pd search; +#X obj 236 313 print sit; +#X connect 0 0 10 0; +#X connect 1 0 10 1; +#X connect 4 0 17 0; +#X connect 10 0 17 0; +#X connect 11 0 17 0; +#X connect 13 0 17 0; +#X connect 15 0 17 0; +#X connect 16 0 17 0; +#X connect 17 0 6 0; +#X connect 17 1 5 0; +#X connect 17 2 14 0; +#X connect 18 0 19 0; +#X connect 18 0 17 0; diff --git a/tools/help-popcorn.pd b/tools/help-popcorn.pd new file mode 100644 index 0000000..119edea --- /dev/null +++ b/tools/help-popcorn.pd @@ -0,0 +1,35 @@ +#N canvas 492 119 593 496 10; +#X obj 43 134 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X floatatom 94 135 5 0 0 0 - - -; +#X text 79 201 Reset To Initial Conditions; +#X text 99 246 Modify Parameters; +#X msg 76 184 reset 0.1 0.1; +#X floatatom 78 398 10 0 0 0 Y - -; +#X floatatom 43 373 10 0 0 0 X - -; +#X text 19 50 (This attractor is not continuous); +#X text 20 34 Chaos PD Externals - Copyright Michael McGonagle 2003 +; +#X obj 43 151 metro 50; +#X obj 13 150 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 25 83 readme-fractals; +#X msg 95 226 param 2.35155; +#X obj 43 347 popcorn 0.1 0 2.35155; +#X text 98 441 This fractal seems to allow is sole parameter to range +over a large range. As the value of the parameter rises \, so does +the Lyapunov Exponent \, but it does not appear to be linear.; +#X text 21 19 Popcorn Attractor (from Cliff Pickover); +#X obj 126 373 search-tools; +#X connect 0 0 9 0; +#X connect 1 0 9 1; +#X connect 4 0 13 0; +#X connect 9 0 13 0; +#X connect 10 0 13 0; +#X connect 12 0 13 0; +#X connect 13 0 6 0; +#X connect 13 1 5 0; +#X connect 13 2 16 0; +#X connect 13 3 16 1; +#X connect 13 4 16 2; +#X connect 16 0 13 0; diff --git a/tools/help-quaruptwo-test.pd b/tools/help-quaruptwo-test.pd new file mode 100644 index 0000000..4fcc159 --- /dev/null +++ b/tools/help-quaruptwo-test.pd @@ -0,0 +1,69 @@ +#N canvas 559 82 589 492 10; +#X obj 43 134 tgl 15 0 empty empty empty 0 -6 160 8 -262144 -1 -1 0 +1; +#X floatatom 94 135 5 0 0 0 - - -; +#X text 91 208 Reset To Initial Conditions; +#X text 114 281 Modify Parameters; +#X floatatom 197 399 10 0 0 0 Y - -; +#X floatatom 43 399 10 0 0 0 X - -; +#X text 19 50 (This attractor is not continuous); +#X text 20 34 Chaos PD Externals - Copyright Michael McGonagle 2003 +; +#X obj 43 151 metro 50; +#X obj 18 150 bng 15 250 50 0 empty empty empty 0 -6 160 8 -262144 +-1 -1; +#X obj 25 83 readme-fractals; +#X msg 117 303 search; +#X obj 327 394 print; +#X text 21 19 QuadrupTwo Attractor; +#X msg 111 243 param 0 1 2; +#X msg 177 335 show; +#X msg 88 191 reset; +#N canvas 0 22 470 320 search 0; +#X floatatom 187 89 5 0 0 0 - - -; +#X obj 142 50 bng 15 250 50 0 empty empty empty 0 -6 32 8 -262144 -1 +-1; +#X obj 147 73 loop; +#X floatatom 186 15 5 0 0 0 - - -; +#X floatatom 192 31 5 0 0 0 - - -; +#X floatatom 198 47 5 0 0 0 - - -; +#X obj 31 259 outlet; +#X obj 77 121 t b b f; +#X msg 82 218 search; +#X msg 48 167 param 34 1 \$1; +#X msg 65 192 constrain 0.05; +#X msg 190 149 constrain; +#X msg 238 268 elyapunov; +#X msg 198 198 constrain 0 100 0 2 0 100; +#X msg 218 228 lyapunov 0 10 1000; +#X connect 1 0 2 0; +#X connect 2 0 7 0; +#X connect 2 1 0 0; +#X connect 3 0 2 0; +#X connect 4 0 2 1; +#X connect 5 0 2 2; +#X connect 7 0 8 0; +#X connect 7 2 9 0; +#X connect 8 0 6 0; +#X connect 9 0 6 0; +#X connect 10 0 6 0; +#X connect 11 0 6 0; +#X connect 12 0 6 0; +#X connect 13 0 6 0; +#X connect 14 0 6 0; +#X restore 165 96 pd search; +#X obj 172 123 print sit; +#X obj 43 363 quadruptwo 0.1 0.1 34 1 5; +#X connect 0 0 8 0; +#X connect 1 0 8 1; +#X connect 8 0 19 0; +#X connect 9 0 19 0; +#X connect 11 0 19 0; +#X connect 14 0 19 0; +#X connect 15 0 19 0; +#X connect 16 0 19 0; +#X connect 17 0 18 0; +#X connect 17 0 19 0; +#X connect 19 0 5 0; +#X connect 19 1 4 0; +#X connect 19 2 12 0; diff --git a/tools/help-quaruptwo.pd b/tools/help-quaruptwo.pd new file mode 100644 index 0000000..292b46e --- /dev/null +++ b/tools/help-quaruptwo.pd @@ -0,0 +1,32 @@ +#N canvas 527 258 585 488 10; +#X obj 43 134 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X floatatom 94 135 5 0 0 0 - - -; +#X text 91 208 Reset To Initial Conditions; +#X text 114 263 Modify Parameters; +#X floatatom 78 414 10 0 0 0 Y - -; +#X floatatom 43 392 10 0 0 0 X - -; +#X text 19 50 (This attractor is not continuous); +#X text 20 34 Chaos PD Externals - Copyright Michael McGonagle 2003 +; +#X obj 43 151 metro 50; +#X obj 18 150 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 25 83 readme-fractals; +#X text 21 19 QuadrupTwo Attractor; +#X msg 111 243 param 0 1 2; +#X msg 88 191 reset; +#X obj 43 363 quadruptwo 0 0 34 1 5; +#X obj 126 390 search-tools; +#X connect 0 0 8 0; +#X connect 1 0 8 1; +#X connect 8 0 14 0; +#X connect 9 0 14 0; +#X connect 12 0 14 0; +#X connect 13 0 14 0; +#X connect 14 0 5 0; +#X connect 14 1 4 0; +#X connect 14 2 15 0; +#X connect 14 3 15 1; +#X connect 14 4 15 2; +#X connect 15 0 14 0; diff --git a/tools/help-standardmap.pd b/tools/help-standardmap.pd new file mode 100644 index 0000000..02fb992 --- /dev/null +++ b/tools/help-standardmap.pd @@ -0,0 +1,32 @@ +#N canvas 527 258 585 488 10; +#X obj 43 134 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X floatatom 94 135 5 0 0 0 - - -; +#X text 91 208 Reset To Initial Conditions; +#X text 112 265 Modify Parameters; +#X msg 88 191 reset 0.1 0.1; +#X floatatom 61 452 10 0 0 0 Y - -; +#X floatatom 43 427 10 0 0 0 X - -; +#X text 19 50 (This attractor is not continuous); +#X text 20 34 Chaos PD Externals - Copyright Michael McGonagle 2003 +; +#X obj 43 151 metro 50; +#X obj 18 150 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 25 83 readme-fractals; +#X text 21 19 Standard Map; +#X obj 43 369 standardmap; +#X msg 110 242 param 0.89; +#X obj 70 398 search-tools; +#X connect 0 0 9 0; +#X connect 1 0 9 1; +#X connect 4 0 13 0; +#X connect 9 0 13 0; +#X connect 10 0 13 0; +#X connect 13 0 6 0; +#X connect 13 1 5 0; +#X connect 13 2 15 0; +#X connect 13 3 15 1; +#X connect 13 4 15 2; +#X connect 14 0 13 0; +#X connect 15 0 13 0; diff --git a/tools/loop.pd b/tools/loop.pd new file mode 100644 index 0000000..19896ab --- /dev/null +++ b/tools/loop.pd @@ -0,0 +1,43 @@ +#N canvas 640 438 490 340 10; +#X obj 52 26 inlet; +#X obj 93 26 inlet; +#X obj 134 26 inlet; +#X obj 52 262 outlet; +#X obj 52 44 route bang float; +#X obj 74 118 f; +#X obj 74 136 -; +#X obj 74 154 /; +#X obj 74 172 i; +#X obj 74 190 + 1; +#X obj 52 208 f; +#X obj 52 226 until; +#X obj 52 244 f; +#X obj 79 244 +; +#X obj 96 99 f; +#X obj 52 62 t b b b; +#X obj 130 262 outlet; +#X obj 74 81 t b f; +#X connect 0 0 4 0; +#X connect 1 0 5 1; +#X connect 2 0 13 1; +#X connect 2 0 7 1; +#X connect 4 0 15 0; +#X connect 4 1 17 0; +#X connect 5 0 6 0; +#X connect 6 0 7 0; +#X connect 7 0 8 0; +#X connect 8 0 9 0; +#X connect 9 0 10 1; +#X connect 9 0 16 0; +#X connect 10 0 11 0; +#X connect 11 0 12 0; +#X connect 12 0 13 0; +#X connect 12 0 3 0; +#X connect 13 0 12 1; +#X connect 14 0 12 1; +#X connect 15 0 10 0; +#X connect 15 1 5 0; +#X connect 15 2 14 0; +#X connect 17 0 5 0; +#X connect 17 1 14 1; +#X connect 17 1 6 1; diff --git a/tools/readme-frac-format.pd b/tools/readme-frac-format.pd new file mode 100644 index 0000000..950f56c --- /dev/null +++ b/tools/readme-frac-format.pd @@ -0,0 +1,22 @@ +#N canvas 171 208 685 432 10; +#X text 31 36 The format of this file is pretty simple (or tries to +be).; +#X text 55 69 Line 1: name - this is used as the 'c' identifier; +#X text 55 81 Line 2: - integer for each +; +#X text 55 93 Line 3-x: - var name and start state; +#X text 55 105 Line y-z: - param data; +#X text 55 131 Line c: '.' - file must end with a single period '.' +; +#X text 33 180 This file is used by 'gen_fractal_framework' to produce +the 'C' source for the external.; +#X text 62 225 ** - The pseudo-code must not have any spaces. Each +line in the pseudo-code is considered to be a single "assignment" statement. +There is no need to worry about creating storage for any intermediate +(calculated) variables \, as that is done by the translation program. +The pseudo-code represents variables and parameters with a '$' before +the variable name. Locals are allowed \, but are preceded with a '#'. +(Locals are used as 'intermediate' \, computed values that are not +retained from iteration to iteration.); +#X text 55 118 Line a-b: - line(s) of frac 'pseudo-code' +**; diff --git a/tools/readme-fractals.pd b/tools/readme-fractals.pd new file mode 100644 index 0000000..2281c6a --- /dev/null +++ b/tools/readme-fractals.pd @@ -0,0 +1,54 @@ +#N canvas 495 74 487 362 10; +#X obj 56 202 readme-frac-format; +#X obj 56 221 readme-gen-fractal; +#X text 37 183 if you want to add new fractals:; +#X obj 56 144 readme-operation; +#X obj 56 164 readme-searching; +#X text 22 107 Additional Reading \,; +#X text 41 126 if you want to us existing fractals:; +#X obj 56 240 readme-parameter-ranges; +#X text 270 269 Developed using PD 0.36; +#X text 93 295 Copyright 2003 \, Ben Bogart and Michael McGonagle; +#X text 276 282 Released under GNU GPL; +#N canvas 302 96 575 579 available_fractals 0; +#X obj 157 264 henon; +#X obj 157 302 ikeda; +#X obj 157 321 latoocarfian; +#X obj 157 340 latoomutalpha; +#X obj 157 359 latoomutbeta; +#X obj 157 378 latoomutgamma; +#X obj 69 208 logistic; +#X obj 277 208 lorenz; +#X obj 69 227 mlogistic; +#X obj 277 246 rossler; +#X obj 157 473 standardmap; +#X obj 69 246 tent; +#X obj 277 265 three_d; +#X text 57 187 1 variable; +#X text 157 187 2 variables; +#X text 273 187 3 variables; +#X text 24 136 The remaining outputs represent the variables \, corresponding +from left to right as the variables from the '*.frac' data file.; +#X text 24 16 Below \, there is an object for each of the fractals +currently available in the ChaosII collection.; +#X text 23 55 All fractals share the same common structure \, in that +the right-most outlet is used as the "results" outlet. This is used +during the "Searching" operations to return the results of the search +to the user. see 'readme-searching' file for more info on the results +of a search.; +#X obj 157 207 attract1; +#X obj 157 226 dejong; +#X obj 157 245 gingerbreadman; +#X obj 157 283 hopalong; +#X obj 157 416 martin; +#X obj 277 227 pickover; +#X obj 157 435 popcorn; +#X obj 157 454 quadruptwo; +#X obj 157 492 strange1; +#X obj 157 511 tinkerbell; +#X obj 157 530 unity; +#X obj 157 397 lotkavolterra; +#X restore 43 78 pd available_fractals; +#X text 27 28 The Chaos Library provides a means to generate multiple +chaotic datastreams \, as well as the ability to search for new attractor +sets that produce other chaotic datastreams.; diff --git a/tools/readme-gen-fractal.pd b/tools/readme-gen-fractal.pd new file mode 100644 index 0000000..2af4657 --- /dev/null +++ b/tools/readme-gen-fractal.pd @@ -0,0 +1,6 @@ +#N canvas 0 22 478 328 10; +#X text 25 23 This will explain the usage of 'gen_fractal_framework' +\, once the program has become more "stable" and generates what would +be unique to each fractal. Currently \, there is still some redundancy +in the code.; +#X text 282 136 more later...; diff --git a/tools/readme-lyapunov.pd b/tools/readme-lyapunov.pd new file mode 100644 index 0000000..056e6bd --- /dev/null +++ b/tools/readme-lyapunov.pd @@ -0,0 +1,16 @@ +#N canvas 0 22 565 389 10; +#X text 74 61 Lyapunov Exponent; +#X text 25 82 This value is an estimate of the attractors potential +for chaos. It will not necessarily be the same for any given run using +any arbitrary fractal. The description below attempts to put "attractors" +into three catagories.; +#X text 48 262 Don't forget \, just because an "attractor" is not chaotic +\, it does not mean that it will not generate an interesting stream +of number \, if only until they converge.; +#X text 40 151 < 0; +#X text 78 151 These are not chaotic \, may produce a "short-term" +stream of intrest; +#X text 39 179 == 0; +#X text 80 179 Attractors converge to one or more points; +#X text 40 197 > 0; +#X text 80 198 Chaos begins. Higher values indicate "more" chaos.; diff --git a/tools/readme-operation.pd b/tools/readme-operation.pd new file mode 100644 index 0000000..be93969 --- /dev/null +++ b/tools/readme-operation.pd @@ -0,0 +1,34 @@ +#N canvas 159 133 675 651 10; +#X msg 56 219 reset ; +#X msg 56 240 param ; +#X text 36 280 As to the exact variable and parameter ranges to use +\, you will have to consult each fractals help file. You can also use +the "Searching" functions to randomly find a new attractor set \, and +then use those values in either a set of messages to the fractal \, +or in its creation arguments.; +#X msg 56 198 reset; +#X text 98 199 sets the variables back to their initial state **; +#X text 181 221 sets the variables to an explicit state ***; +#X text 195 242 sets parameters to explicit state ****; +#X text 34 26 Create a fractal with or without a set of variables and +parameters \, passed as creation arguments. Without the creation arguments +\, the class defaults will be used for the fractal. With the arguments +\, a new fractal is created using the arguments as the defaults.; +#X text 35 104 To use a fractal \, create the instance \, and optionally +pass it an initial state of variables and a set of parameters. Then +repeatedly 'bang' on the input to iterate thru the fractals variable +states. Using a 'reset' message will return the variables to their +initial state \, or to the explicit values passed.; +#X text 38 369 ** - The initial state can be explicitly set by passing +the arguments at creation time for the fractal \, or (without creation +arguments) the class default value will be used.; +#X text 37 414 *** - When setting the variables to an arbitrary state +\, the stream may not be in a "stable" state. You may need to iterate +the fractal several hundred (or thousand) times to obtain a "stable" +state. If you pass a set of variables that were taken from the 'search' +(or 'show') results \, the values most likely will be in a "stable" +condition.; +#X text 38 500 **** - Do remember that not all combinations of parameters +result in an attractor set.; +#X text 234 577 chaos \, version 2 by Ben Bogart and Michael McGonagle. +Copyright 2003; diff --git a/tools/readme-parameter-ranges.pd b/tools/readme-parameter-ranges.pd new file mode 100644 index 0000000..27fe5f0 --- /dev/null +++ b/tools/readme-parameter-ranges.pd @@ -0,0 +1,23 @@ +#N canvas 0 22 499 399 10; +#X text 33 275 The "classification" of an attractor set uses the full +range of the fractals acceptable parameter ranges. As this method of +"classification" is relative \, it will not describe each fractal uniquely +\, but rather can be used to compare attractor sets that have similar +(closely related) parameter values. NOTE: there needs to be a way to +increase the granularity of the classification system...; +#X text 35 21 Parameter Ranges - Once you have an operational fractal +external \, it is important to make sure that the assigned ranges for +each of the parameters are "optimized" to limit the random number generator +to those ranges. This is important when a variable can only range between +(-1 .. 1) and you have declared that it can range from (-100 .. 100). +Because of the much wider search space \, there is less likelyhood +of finding anything useful \, or at least make the search times longer +due to higher failure rates.; +#X text 35 147 If you are unsure of what the ranges are \, you can +either figure them out mathematically \, or use the "brute-force" method +and iterate over ranges of the defined parameters. The points that +return a fractal (even ones that converge) will give an indication +as to the acceptable ranges for each param. Once you have determined +those ranges \, adjust them in your '*.frac' file and re-make the external +for your fractal. (Or you can just edit the Macros in the C code \, +if you are comfortable with that.); diff --git a/tools/readme-searching.pd b/tools/readme-searching.pd new file mode 100644 index 0000000..0135779 --- /dev/null +++ b/tools/readme-searching.pd @@ -0,0 +1,101 @@ +#N canvas 39 41 1031 669 10; +#X msg 471 344 show; +#X msg 470 295 seed; +#X msg 470 314 seed number; +#X msg 469 234 elyapunov; +#X msg 467 118 constrain; +#X text 601 76 random search for an attractor; +#X text 508 345 displays info on attractor to console; +#X text 543 119 restores full param search area; +#X text 632 138 based on current params \, limits to percentage of +range; +#X msg 465 76 search ; +#X msg 467 137 constrain ; +#X msg 467 156 constrain ; +#X msg 468 200 lyapunov ; +#X msg 465 57 search; +#X text 516 57 random search for an attractor \, variables use defaults +; +#X text 17 403 The search method implemented performs the following: +; +#X text 41 418 1 Set the params randomly based on allowed ranges; +#X text 41 432 2 Calculate the Lyapunov Exponent; +#X text 41 447 3 If the Lyapunov Exponent is within allowed range \, +return the attractor set; +#X text 19 39 Searching for an attractor set can be as simple as sending +a 'search' message to a fractal. This will search the fractals allowable +parameter limits for an attractor set.; +#X text 39 183 arg[1] = Lyapunov Exponent; +#X msg 469 265 classify ; +#X text 591 266 Used to set the "granularity" of the classification +; +#X text 17 323 The Lyapunov Exponent for the attractor set will indicates +one of three states \, (1) Convergence [a negative value] \, (2) Stability +[0 \, of values close to 0] \, and (3) Chaos [a positive value]. Each +class will have different ranges of Lyapunov Exponent.; +#X text 39 196 arg[2] = Classification String ****; +#X text 16 513 **** - The classification method was adopted from Julian +Sprott's method of classification. While it is an arbitrary system +\, and does not "uniquely" identify an attractor set \, it is used +to show a relationship with other attractor sets with similar values. +; +#X text 558 313 seeds search random number generator with number * +; +#X text 507 296 seeds search random number generator with time *; +#X text 543 235 calculates an extended Lyapunov Exponent **; +#X text 648 157 params are limited to explicit ranges ***; +#X text 473 419 * - all fractals of all classes currently share the +same random number generator.; +#X text 473 452 ** - this performs a Lyapunov Exponent calculation +for each variable in the attractor. Ideally \, all results should be +approximately the same. This is an experimental function.; +#X text 473 502 *** - expects there to be a low and high range limit +for each param in the fractal equation.; +#X text 483 217 sets search limits and failure count for Lyapunov Exponent +; +#X text 37 15 Searching - the art of chaos.; +#N canvas 0 22 464 316 simple_example 0; +#X obj 166 106 latoocarfian; +#X msg 173 38 search; +#X text 32 238 This example creates a 'latoocarfian' fractal with the +class defaults. When a search is performed \, the initial state for +the variables are set to the class defaults.; +#X obj 131 14 bng 15 250 50 0 empty empty empty 0 -6 32 8 -262144 -1 +-1; +#X floatatom 166 211 10 0 0 0 X - -; +#X floatatom 185 194 10 0 0 1 Y - -; +#X msg 166 16 reset; +#X msg 183 61 show; +#X obj 205 173 print results; +#X obj 225 152 print vars; +#X obj 245 132 print params; +#X connect 0 0 4 0; +#X connect 0 1 5 0; +#X connect 0 2 8 0; +#X connect 0 3 9 0; +#X connect 0 4 10 0; +#X connect 1 0 0 0; +#X connect 3 0 0 0; +#X connect 6 0 0 0; +#X connect 7 0 0 0; +#X restore 286 18 pd simple_example; +#X text 39 210 arg[3] = failure rate before solution *****; +#X text 16 581 ***** - the failure rate is a percentage of the actual +number of failures until a solution is found over the total number +of times the search algorithm will be executed before giving up. This +limit is set via the 'lyapunov' message. This number will also be influenced +by the 'low' and 'high' ranges set.; +#X text 19 93 The values returned from a 'search' message use the 'search' +outlets. These three outlets encapsulate that three pieces of data +of interest. The first of the 'search' outlets holds a list of the +results. This includes:; +#X text 39 170 arg[0] = 'show' \, 'search' \, or 'invalid'; +#X text 18 269 Most likely \, you won't see any failures ('invalid') +\, unless you mess with the 'constrain' or 'lyapunov' messages. 'show' +is returned when you use the 'show' message.; +#X obj 153 376 readme-lyapunov; +#X text 43 475 4 If the Limit Count has been exceeded \, return 'invalid' +\, else goto 1; +#X text 18 154 Search Outlet 0:; +#X text 18 227 Search Outlet 1: list of current variables; +#X text 18 243 Search Outlet 2: list of parameter set; diff --git a/tools/search-tools.pd b/tools/search-tools.pd new file mode 100644 index 0000000..f00a011 --- /dev/null +++ b/tools/search-tools.pd @@ -0,0 +1,186 @@ +#N canvas 619 310 464 533 10; +#X obj -97 556 outlet; +#X obj -97 2 cnv 15 450 220 empty empty Searching_Commands 2 9 1 10 +-233017 -66577 0; +#X msg 104 83 constrain; +#X msg 104 104 constrain \$1; +#X text -77 104 % Constraint; +#X text -77 82 No Constraint; +#X msg 104 30 search; +#X obj 221 52 nbx 5 17 -1e+37 1e+37 0 0 \$0-search_v2 empty empty 0 +-6 1153 10 -262144 -1 -1 0 256; +#X obj 172 52 nbx 5 17 -1e+37 1e+37 0 0 \$0-search_v1 empty empty 0 +-6 1153 10 -262144 -1 -1 0 256; +#X text -78 48 Search w/ inits; +#X text -78 29 Search w/ default inits; +#X obj 86 143 bng 17 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X text -76 142 Set Lyapunov Limits; +#X obj 287 143 nbx 5 17 -1e+37 1e+37 0 0 \$0-lyapunov_v3 empty failure +0 -6 1153 10 -262144 -1 -1 0 256; +#X obj 238 143 nbx 5 17 -1e+37 1e+37 0 0 \$0-lyapunov_v2 empty high +0 -6 1153 10 -262144 -1 -1 0 256; +#X obj 189 143 nbx 5 17 -1e+37 1e+37 0 0 \$0-lyapunov_v1 empty low +0 -6 1153 10 -262144 -1 -1 0 256; +#N canvas 0 22 509 236 lyapunov 0; +#X obj 42 26 inlet; +#X obj 83 26 r \$0-lyapunov_v1; +#X obj 101 61 pack f f f; +#X obj 203 27 r \$0-lyapunov_v2; +#X obj 320 27 r \$0-lyapunov_v3; +#X msg 101 84 lyapunov \$1 \$2 \$3; +#X obj 101 108 s \$0-outlet; +#X connect 0 0 2 0; +#X connect 1 0 2 0; +#X connect 2 0 5 0; +#X connect 3 0 2 1; +#X connect 4 0 2 2; +#X connect 5 0 6 0; +#X restore 106 143 pd lyapunov; +#X obj 86 52 bng 17 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#N canvas 0 22 374 205 search 0; +#X obj 104 104 pack f f; +#X msg 104 127 search \$1 \$2; +#X obj 83 26 r \$0-search_v1; +#X obj 186 26 r \$0-search_v2; +#X obj 94 63 f; +#X obj 104 151 s \$0-outlet; +#X obj 18 26 inlet; +#X connect 0 0 1 0; +#X connect 1 0 5 0; +#X connect 2 0 4 1; +#X connect 3 0 0 1; +#X connect 4 0 0 0; +#X connect 6 0 4 0; +#X restore 104 52 pd search; +#X text -76 164 Extended Lyapunov; +#X msg 104 165 elyapunov; +#X msg 104 186 show; +#X text -75 198 Get Attractor Info; +#X obj 104 226 s \$0-outlet; +#X obj -97 535 r \$0-outlet; +#X obj -14 535 inlet; +#X obj -14 556 s \$0-inlet; +#X obj -97 226 cnv 15 450 300 empty empty Search_Results 2 9 1 10 -233017 +-66577 0; +#N canvas 48 644 700 296 get_results 0; +#X msg 5 39 set \$1; +#X obj 5 17 symbol; +#X obj 5 61 outlet; +#X obj 150 38 s \$0-lyapunov; +#X obj 190 89 s \$0-failure_rate; +#X obj 319 32 s \$0-v1; +#X obj 343 53 s \$0-v2; +#X obj 367 75 s \$0-v3; +#X obj 473 31 s \$0-p1; +#X obj 497 52 s \$0-p2; +#X obj 521 74 s \$0-p3; +#X obj 170 62 s \$0-classification; +#X obj 44 222 r \$0-classification; +#X msg 44 243 set \$1; +#X obj 44 264 outlet; +#X obj 5 -6 r \$0-inlet; +#X obj 80 117 print debug; +#X obj 131 11 unpack s 0 s 0; +#X obj 319 9 unpack 0 0 0 0 0 0; +#X obj 391 96 s \$0-v4; +#X obj 415 117 s \$0-v5; +#X obj 440 138 s \$0-v6; +#X obj 473 9 unpack 0 0 0 0 0 0; +#X obj 545 96 s \$0-p4; +#X obj 569 117 s \$0-p5; +#X obj 594 137 s \$0-p6; +#X obj 318 -12 r \$0-inlet_var; +#X obj 473 -11 r \$0-inlet_param; +#X connect 0 0 2 0; +#X connect 1 0 0 0; +#X connect 12 0 13 0; +#X connect 13 0 14 0; +#X connect 15 0 1 0; +#X connect 15 0 17 0; +#X connect 17 1 3 0; +#X connect 17 2 11 0; +#X connect 17 3 4 0; +#X connect 18 0 5 0; +#X connect 18 1 6 0; +#X connect 18 2 7 0; +#X connect 18 3 19 0; +#X connect 18 4 20 0; +#X connect 18 5 21 0; +#X connect 22 0 8 0; +#X connect 22 1 9 0; +#X connect 22 2 10 0; +#X connect 22 3 23 0; +#X connect 22 4 24 0; +#X connect 22 5 25 0; +#X connect 26 0 18 0; +#X connect 27 0 22 0; +#X restore -14 267 pd get_results; +#X msg -14 288 search; +#X msg 79 288 NOCBNS; +#X text 184 290 Classification; +#X obj 79 309 nbx 10 17 -1e+37 1e+37 0 0 empty \$0-lyapunov empty 0 +-6 577 10 -262144 -1 -1 -0.482697 256; +#X obj 79 330 nbx 10 17 -1e+37 1e+37 0 0 empty \$0-failure_rate empty +0 -6 577 10 -262144 -1 -1 0.005 256; +#X obj -14 371 nbx 5 17 -1e+37 1e+37 0 0 empty \$0-v1 empty 0 -6 577 +10 -262144 -1 -1 0 256; +#X obj -14 391 nbx 5 17 -1e+37 1e+37 0 0 empty \$0-v2 empty 0 -6 577 +10 -262144 -1 -1 0 256; +#X obj -14 411 nbx 5 17 -1e+37 1e+37 0 0 empty \$0-v3 empty 0 -6 577 +10 -262144 -1 -1 0 256; +#X obj 111 371 nbx 5 17 -1e+37 1e+37 0 0 empty \$0-p1 empty 0 -6 577 +10 -262144 -1 -1 0.17869 256; +#X obj 111 391 nbx 5 17 -1e+37 1e+37 0 0 empty \$0-p2 empty 0 -6 577 +10 -262144 -1 -1 0.437724 256; +#X obj 111 411 nbx 5 17 -1e+37 1e+37 0 0 empty \$0-p3 empty 0 -6 577 +10 -262144 -1 -1 -2.31304 256; +#X text 183 331 Failure Rate; +#X text 184 309 Lyapunov Exponent; +#X text 48 372 Var 1; +#X text 48 392 Var 2; +#X text 48 412 Var 3; +#X text 174 373 Param 1; +#X text 174 393 Param 2; +#X text 174 413 Param 3; +#X obj 188 164 readme-lyapunov; +#X obj 171 29 readme-searching; +#X obj -14 431 nbx 5 17 -1e+37 1e+37 0 0 empty \$0-v4 empty 0 -6 577 +10 -262144 -1 -1 0 256; +#X obj -14 451 nbx 5 17 -1e+37 1e+37 0 0 empty \$0-v5 empty 0 -6 577 +10 -262144 -1 -1 0 256; +#X obj -14 471 nbx 5 17 -1e+37 1e+37 0 0 empty \$0-v6 empty 0 -6 577 +10 -262144 -1 -1 0 256; +#X obj 111 431 nbx 5 17 -1e+37 1e+37 0 0 empty \$0-p4 empty 0 -6 577 +10 -262144 -1 -1 -2.74459 256; +#X obj 111 451 nbx 5 17 -1e+37 1e+37 0 0 empty \$0-p5 empty 0 -6 577 +10 -262144 -1 -1 0.00541449 256; +#X obj 111 471 nbx 5 17 -1e+37 1e+37 0 0 empty \$0-p6 empty 0 -6 577 +10 -262144 -1 -1 1.3485 256; +#X text 48 432 Var 4; +#X text 48 452 Var 5; +#X text 48 472 Var 6; +#X text 174 433 Param 4; +#X text 174 453 Param 5; +#X text 174 473 Param 6; +#X obj 62 535 inlet; +#X obj 166 535 inlet; +#X obj 62 556 s \$0-inlet_var; +#X obj 166 556 s \$0-inlet_param; +#X obj 198 104 nbx 5 17 -1e+37 1e+37 0 0 empty empty % 0 -6 1 10 -262144 +-1 -1 0 256; +#X connect 2 0 23 0; +#X connect 3 0 23 0; +#X connect 6 0 23 0; +#X connect 11 0 16 0; +#X connect 17 0 18 0; +#X connect 20 0 23 0; +#X connect 21 0 23 0; +#X connect 24 0 0 0; +#X connect 25 0 26 0; +#X connect 28 0 29 0; +#X connect 28 1 30 0; +#X connect 62 0 64 0; +#X connect 63 0 65 0; +#X connect 66 0 3 0; diff --git a/unity.c b/unity.c new file mode 100644 index 0000000..21ecc6f --- /dev/null +++ b/unity.c @@ -0,0 +1,102 @@ +/* unity Attractor PD External */ +/* Copyright Michael McGonagle, from ??????, 2003 */ +/* This program is distributed under the params of the GNU Public License */ + +/////////////////////////////////////////////////////////////////////////////////// +/* This file is part of Chaos PD Externals. */ +/* */ +/* Chaos PD Externals are free software; you can redistribute them and/or modify */ +/* them under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Chaos PD Externals are distributed in the hope that they will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with the Chaos PD Externals; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "m_pd.h" + + + +#define M_x 0 +#define M_y 1 + +#define M_param_count 0 +#define M_var_count 2 +#define M_search_count 0 +#define M_failure_limit 1000 + +static char *version = "unity v0.0, by Michael McGonagle, from ??????, 2003"; + +t_class *unity_class; + +typedef struct unity_struct { + t_object x_obj; + + double vars[M_var_count]; + double vars_init[M_var_count]; + + t_outlet *outlets[M_var_count - 1]; +} unity_struct; + +static void calc(unity_struct *unity, double *vars) { + double k, x_0, y_0; + k=(vars[M_x]*vars[M_x])+(vars[M_y]*vars[M_y]); + x_0 =(2-k)*vars[M_y]; + y_0 =(2-k)*vars[M_x]; + vars[M_x] = x_0; + vars[M_y] = y_0; +} // end calc + +static void calculate(unity_struct *unity) { + calc(unity, unity -> vars); + outlet_float(unity -> x_obj.ob_outlet, unity -> vars[M_x]); + outlet_float(unity -> outlets[M_y - 1], unity -> vars[M_y]); +} // end calculate + +static void reset(unity_struct *unity, t_symbol *s, int argc, t_atom *argv) { + if (argc == M_var_count) { + unity -> vars[M_x] = (double) atom_getfloatarg(M_x, argc, argv); + unity -> vars[M_y] = (double) atom_getfloatarg(M_y, argc, argv); + } else { + unity -> vars[M_x] = unity -> vars_init[M_x]; + unity -> vars[M_y] = unity -> vars_init[M_y]; + } // end if +} // end reset + +void *unity_new(t_symbol *s, int argc, t_atom *argv) { + unity_struct *unity = (unity_struct *) pd_new(unity_class); + if (unity != NULL) { + outlet_new(&unity -> x_obj, &s_float); + unity -> outlets[0] = outlet_new(&unity -> x_obj, &s_float); + if (argc == M_param_count + M_var_count) { + unity -> vars_init[M_x] = unity -> vars[M_x] = (double) atom_getfloatarg(0, argc, argv); + unity -> vars_init[M_y] = unity -> vars[M_y] = (double) atom_getfloatarg(1, argc, argv); + } else { + if (argc != 0 && argc != M_param_count + M_var_count) { + post("Incorrect number of arguments for unity fractal. Expecting 2 arguments."); + } + unity -> vars_init[M_x] = 0; + unity -> vars_init[M_y] = 0; + } + } + return (void *)unity; +} + +void unity_setup(void) { + unity_class = class_new(gensym("unity"), (t_newmethod) unity_new, 0, sizeof(unity_struct), 0, A_GIMME, 0); + class_addbang(unity_class, (t_method) calculate); + class_addmethod(unity_class, (t_method) reset, gensym("reset"), A_GIMME, 0); + class_sethelpsymbol(unity_class, gensym("help-unity.pd")); +} + -- cgit v1.2.1