diff options
author | B. Bogart <bbogart@users.sourceforge.net> | 2003-09-30 16:04:40 +0000 |
---|---|---|
committer | B. Bogart <bbogart@users.sourceforge.net> | 2003-09-30 16:04:40 +0000 |
commit | 705f8dee50e2073a3aba60b03e5c9b86672abd4c (patch) | |
tree | b3ec18787ac0687df3f2de109eff4d840a679996 | |
parent | 8890d81285fc713353a00d7d149fb02e6b00b3b5 (diff) |
Opps - forgot to add the files that did not exist in chaosI!
svn path=/trunk/externals/bbogart/chaos/; revision=1052
49 files changed, 7407 insertions, 0 deletions
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 <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <time.h> +#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")); +} + @@ -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 <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <time.h> +#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")); +} + @@ -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 <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <time.h> +#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 <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <time.h> +#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 <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <time.h> +#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 <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <time.h> +#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 <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <time.h> +#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 <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <time.h> +#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 <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <time.h> +#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 <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <time.h> +#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 <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <time.h> +#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 <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <time.h> +#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 <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <time.h> +#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 <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <time.h> +#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 <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <time.h> +#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 <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <time.h> +#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")); +} + @@ -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 <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <time.h> +#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 <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <time.h> +#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 <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <time.h> +#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 <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <time.h> +#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 <percent>' 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: <var_count> <param_count> - integer for each +; +#X text 55 93 Line 3-x: <name> <init> - var name and start state; +#X text 55 105 Line y-z: <name> <low> <high> <init> - 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: <code_fragment> - 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 <var-init>; +#X msg 56 240 param <param-data>; +#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 <var-inits>; +#X msg 467 137 constrain <percentage>; +#X msg 467 156 constrain <param-limits>; +#X msg 468 200 lyapunov <low> <high> <failure>; +#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 <units>; +#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; @@ -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 <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <time.h> +#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")); +} + |