aboutsummaryrefslogtreecommitdiff
path: root/src/symtodp.c
blob: 9b889f76871edba9e6e302aad993aa34d89a92a0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution.

iem_dp written by IOhannes m zmoelnig, Thomas Musil, Copyright (c) IEM KUG Graz Austria 1999 - 2013 */
/* double precision library */

#include "m_pd.h"
#include "iemlib.h"
#include "iem_dp.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* -------------------------- symtodp ------------------------------ */
/* symbol double precision number to double float converter */

/* double float is only internal used */
/* to transfer this value, we divide this double value into use one float casted value */
/* and into the difference to the accurate double value. */

/* double float (sign_1 + exp_12 + mant_51) */

static t_class *symtodp_class;

typedef struct _symtodp
{
  t_object  x_obj;
  double    x_inner_double_value;
  t_outlet  *x_out_floatcasted;
  t_outlet  *x_out_residual;
} t_symtodp;

static double symtodp_calc_list_sum(int ac, t_atom *av)
{
  int i;
  char str[1000], buf[100], *dummy;
  
  str[0] = 0;
  for(i=0; i<ac; i++)
  {
    if(IS_A_FLOAT(av, i))
    {
      sprintf(buf, "%g", (float)atom_getfloatarg(i, ac, av));
      strcat(str, buf);
    }
  }
  //  post("listtodp string: %s", str);
  
  return(strtod(str, &dummy));
}

static void symtodp_bang(t_symtodp *x)
{
  t_float float_casted_value;
  
  float_casted_value = iem_dp_cast_to_float(x->x_inner_double_value);
  outlet_float(x->x_out_residual, iem_dp_calc_residual(x->x_inner_double_value, float_casted_value));
  outlet_float(x->x_out_floatcasted, float_casted_value);
}

static void symtodp_float(t_symtodp *x, t_floatarg f)
{
  x->x_inner_double_value = (double)f;
  symtodp_bang(x);
}

static void symtodp_symbol(t_symtodp *x, t_symbol *s)
{
  char *dummy;
  
  if((s->s_name[0] == '"') && (s->s_name[1]))
  {
    if((s->s_name[1] == '.') || (s->s_name[1] == '+') || (s->s_name[1] == '-') || ((s->s_name[1] >= '0') && (s->s_name[1] <= '9')))
    {
      x->x_inner_double_value = strtod(s->s_name+1, &dummy);
      symtodp_bang(x);
    }
  }
  else if((s->s_name[0] == '.') || (s->s_name[0] == '+') || (s->s_name[0] == '-') || ((s->s_name[0] >= '0') && (s->s_name[0] <= '9')))
  {
    x->x_inner_double_value = strtod(s->s_name, &dummy);
    symtodp_bang(x);
  }
}

static void symtodp_list(t_symtodp *x, t_symbol *s, int ac, t_atom *av)
{
  if(ac > 0)
  {
    x->x_inner_double_value = symtodp_calc_list_sum(ac, av);
    //    post("listtodp double: %.18g", x->x_inner_double_value);
    symtodp_bang(x);
  }
}

static void symtodp_anything(t_symtodp *x, t_symbol *s, int ac, t_atom *av)
{
  char *dummy;
  
  if((s->s_name[0] == '"') && (s->s_name[1]))
  {
    if((s->s_name[1] == '.') || (s->s_name[1] == '+') || (s->s_name[1] == '-') || ((s->s_name[1] >= '0') && (s->s_name[1] <= '9')))
    {
      x->x_inner_double_value = strtod(s->s_name+1, &dummy);
      symtodp_bang(x);
    }
  }
}

static void *symtodp_new(void)
{
  t_symtodp *x = (t_symtodp *)pd_new(symtodp_class);
 
  x->x_inner_double_value = 0.0;
  x->x_out_floatcasted = outlet_new(&x->x_obj, &s_float);
  x->x_out_residual = outlet_new(&x->x_obj, &s_float);
  return (x);
}

static void symtodp_free(t_symtodp *x)
{
}

void symtodp_setup(void)
{
  symtodp_class = class_new(gensym("symtodp"),
    (t_newmethod)symtodp_new, (t_method)symtodp_free, sizeof(t_symtodp), 0, 0);
  class_addbang(symtodp_class, symtodp_bang);
  class_addfloat(symtodp_class, symtodp_float);
  class_addsymbol(symtodp_class, symtodp_symbol);
  class_addlist(symtodp_class, symtodp_list);
  class_addanything(symtodp_class, symtodp_anything);
}