1 /*
2 * Calcoo: c_main.c
3 *
4 * Copyright (C) 2001, 2002, 2003 Alexei Kaminski
5 *
6 * creates and initializes cpu
7 *
8 * also handles "clear all" and RPN toggles
9 */
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <math.h>
14 #include <float.h>
15
16 #include "codes.h"
17 #include "const.h"
18 #include "defaults.h"
19 #include "cpu.h"
20 #include "c_headers.h"
21 #include "io_headers.h"
22 #include "aux_headers.h"
23
24 t_calcoo_cpu *cpu;
25
26 void reset_stack(void);
27
init_cpu(void)28 void init_cpu(void)
29 /* mallocs and initializes cpu variables;
30 * runs once, after calcoo is started */
31 {
32 int i;
33
34 cpu = (t_calcoo_cpu*) malloc (sizeof(t_calcoo_cpu));
35 if(cpu == NULL)
36 error_occured("malloc in init_cpu() failed", TRUE);
37 cpu->d = (t_cpu_display*) malloc (sizeof(t_cpu_display));
38 if(cpu->d == NULL)
39 error_occured("malloc in init_cpu() failed", TRUE);
40
41 cpu->stack_head = NULL;
42
43 for(i = 0; i < NUMBER_OF_MEMS; i++)
44 {
45 cpu->mem[i] = 0.0;
46 cpu->mem_d[i] =
47 (t_cpu_display*) malloc (sizeof(t_cpu_display));
48 }
49 for(i = 0; i < NUMBER_OF_REG_DISPLAYS; i++)
50 {
51 cpu->reg_d[i] =
52 (t_cpu_display*) malloc (sizeof(t_cpu_display));
53 if(cpu->reg_d[i] == NULL)
54 error_occured("malloc in init_cpu() failed", TRUE);
55
56 cpu->op_d[i] = (t_cpu_operation_display*)
57 malloc (sizeof(t_cpu_operation_display));
58 if(cpu->op_d[i] == NULL)
59 error_occured("malloc in init_cpu() failed", TRUE);
60 }
61
62 reset_registers();
63 cpu->prescribed_format = DEFAULT_DISPLAY_FORMAT;
64 cpu->curr_mem = 0;
65 cpu->rpn_mode = FALSE ; /* It is a kluge. We need it to have proper
66 * (to display nothing) initialization of the operation
67 * displays. The reason is that cpu->rpn_mode is used in
68 * cpu_to_output(), and if it turns out to be set to TRUE
69 * after having been malloc'ed, cpu_to_output() does not
70 * reset operation displays. If these displays contain
71 * some garbage after having been malloc'ed, it will lead to
72 * weird stuff displayed in the operation displays in the
73 * algebraic mode from after initialization until the next
74 * call to cpu_to_output */
75
76 if (MAXIMIZE_PRECISION)
77 cpu->precision = pow(10, -floor(fabs(log10(DBL_EPSILON))) + 1);
78 /* "+1" is just in case, to underestimate precision;
79 * as for -floor(fabs()), it is just me being paranoid,
80 * since I am not sure wether the behavior of floor()
81 * of a negative number is universal */
82 else
83 cpu->precision = pow(10, -INPUT_LENGTH - 1);
84 /* it is going to be used in evaluation of
85 * trigonometric functions to get sin PI == 0
86 * rather than 10^-17 and also in subtraction/addition
87 * to have 100.1 - 100 - 0.1 == 0 rather than 1e-15 */
88
89 cpu_to_output();
90 init_undo_stack();
91 refresh_body();
92 }
93
aftermath(void)94 void aftermath(void)
95 {
96 cpu_to_output();
97 save_for_undo();
98 refresh_body();
99 }
100
reset_registers(void)101 void reset_registers(void)
102 /* the function called by the "C" button" */
103 {
104 cpu->x = 0.0;
105 cpu->y = 0.0;
106 cpu->z = 0.0;
107 cpu->t = 0.0;
108
109 cpu->op = CODE_NO_OPERATION;
110 cpu->number_of_parens = 0;
111
112 reset_stack();
113 cpu->last_action = ACTION_CLEAR;
114 cpu->x_overflow = FALSE;
115
116 cpu->d->input_field = INPUT_FIELD_INT;
117 cpu->d->sign = SIGN_PLUS;
118 cpu->d->exp_sign = SIGN_PLUS;
119 cpu->d->format = FORMAT_FIX;
120 cpu->d->display_overflow = FALSE;
121 cpu->d->n_int = 0;
122 cpu->d->n_frac = 0;
123 }
124
reset_stack(void)125 void reset_stack(void)
126 {
127 t_stack_element *to_remove;
128
129 while (cpu->stack_head != NULL)
130 {
131 to_remove = cpu->stack_head;
132 cpu->stack_head = cpu->stack_head->next;
133 free(to_remove);
134 }
135 }
136
call_set_rpn_mode(int a)137 void call_set_rpn_mode(int a)
138 {
139 double tmp;
140
141 if (a != cpu->rpn_mode)
142 {
143 if (cpu->last_action == ACTION_INPUT)
144 input_to_x();
145 tmp = cpu->x;
146 reset_undo_stack();
147 reset_registers();
148 cpu->x = tmp;
149
150 if (a)
151 {
152 cpu->rpn_mode = TRUE;
153 } else {
154 cpu->rpn_mode = FALSE;
155 } /* why not just "cpu->rpn_mode = a;"? I don't remember why */
156
157 cpu_to_output();
158 save_for_undo();
159 refresh_body();
160 }
161 }
162
call_get_rpn_mode(void)163 int call_get_rpn_mode(void)
164 {
165 return cpu->rpn_mode;
166 }
167
call_set_enter_mode(int new_mode)168 void call_set_enter_mode(int new_mode)
169 {
170 cpu->enter_mode = new_mode;
171 }
172
call_get_enter_mode(void)173 int call_get_enter_mode(void)
174 {
175 return cpu->enter_mode;
176 }
177
call_set_rounding_mode(int a)178 void call_set_rounding_mode(int a)
179 {
180 if (cpu->last_action == ACTION_INPUT) {
181 input_to_x();
182 cpu->last_action = ACTION_ENTER;
183 }
184
185 if (a > 0 )
186 {
187 cpu->rounding = TRUE;
188 cpu->digits_to_keep = a;
189 } else {
190 cpu->rounding = FALSE;
191 cpu->digits_to_keep = -a;
192 }
193 cpu_to_output();
194 refresh_body();
195 }
196
call_get_rounding_mode(void)197 int call_get_rounding_mode(void)
198 {
199 if (cpu->rounding)
200 return cpu->digits_to_keep;
201 else
202 return -cpu->digits_to_keep;
203 }
204
call_set_trunc_zeros_mode(int a)205 void call_set_trunc_zeros_mode(int a)
206 {
207 if(cpu->rounding){
208 if (cpu->last_action == ACTION_INPUT) {
209 input_to_x();
210 cpu->last_action = ACTION_ENTER;
211 }
212
213 cpu->trunc_zeros = a;
214 cpu_to_output();
215 refresh_body();
216 } else {
217 /* to ensure proper loading of options */
218 cpu->trunc_zeros = a;
219 }
220 }
221
call_get_trunc_zeros_mode(void)222 int call_get_trunc_zeros_mode(void)
223 {
224 return cpu->trunc_zeros;
225 }
226
227
call_set_stack_mode(int new_mode)228 void call_set_stack_mode(int new_mode)
229 {
230 cpu->stack_mode = new_mode;
231 if (new_mode == STACK_MODE_XYZT)
232 reset_stack(); /* resets stack only beyond T */
233 }
234
call_get_stack_mode(void)235 int call_get_stack_mode(void)
236 {
237 return cpu->stack_mode;
238 }
239
call_get_angle_units(void)240 int call_get_angle_units(void)
241 {
242 return cpu->angle_units;
243 }
244
call_change_angle_units(void)245 void call_change_angle_units(void)
246 {
247 if (cpu->angle_units == CODE_DEG)
248 cpu->angle_units = CODE_RAD;
249 else
250 cpu->angle_units = CODE_DEG;
251
252 save_for_undo();
253 refresh_body();
254 }
255
call_set_angle_units(int a)256 void call_set_angle_units(int a)
257 {
258 cpu->angle_units = a;
259 refresh_body();
260 }
261
262