Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – tendra.SVN – Blame – /branches/algol60/src/installers/common/construct/flpt_fns.c – Rev 2

Subversion Repositories tendra.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
2
    		 Crown Copyright (c) 1997
3
 
4
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
12
 
13
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
15
 
16
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
19
 
20
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
22
        these conditions;
23
 
24
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
27
        it may be put.
28
*/
29
 
30
 
31
/**********************************************************************
32
$Author: release $
33
$Date: 1998/01/17 15:55:47 $
34
$Revision: 1.1.1.1 $
35
$Log: flpt_fns.c,v $
36
 * Revision 1.1.1.1  1998/01/17  15:55:47  release
37
 * First version to be checked into rolling release.
38
 *
39
 * Revision 1.1  1997/11/04  18:23:43  pwe
40
 * split install_fns with new flpt_fns
41
 *
42
***********************************************************************/
43
 
44
 
45
 
46
  /* This file consists of the floating point and complex operations
47
     extracted from install_fns.c, to reduce compilation unit sizes
48
  */
49
 
50
#include "config.h"
51
#include <ctype.h>
52
#include <time.h>
53
#include "common_types.h"
54
#include "basicread.h"
55
#include "exp.h"
56
#include "expmacs.h"
57
#include "main_reads.h"
58
#include "tags.h"
59
#include "flags.h"
60
#include "me_fns.h"
61
#include "installglob.h"
62
#include "readglob.h"
63
#include "table_fns.h"
64
#include "flpttypes.h"
65
#include "flpt.h"
66
#include "xalloc.h"
67
#include "shapemacs.h"
68
#include "read_fns.h"
69
#include "sortmacs.h"
70
#include "machine.h"
71
#include "spec.h"
72
#include "check_id.h"
73
#include "check.h"
74
#include "szs_als.h"
75
#include "messages_c.h"
76
#include "natmacs.h"
77
#include "f64.h"
78
#include "readglob.h"
79
#include "case_opt.h"
80
#include "install_fns.h"
81
#include "externs.h"
82
 
83
 
84
extern shape shcomplexsh;
85
extern shape complexsh;
86
extern shape complexdoublesh;
87
exp_list reorder_list PROTO_S ( ( exp_list, int ) ) ;
88
exp me_contents PROTO_S ( ( exp ) ) ;
89
extern int eq_et PROTO_S ( ( error_treatment, error_treatment ) ) ;
90
extern exp TDFcallaux PROTO_S ( ( error_treatment, exp, char *, shape ) ) ;
91
extern exp find_named_tg PROTO_S ( ( char *, shape ) ) ;
92
 
93
static exp me_complete_chain PROTO_S ( ( exp, exp, exp ) ) ;
94
static exp push PROTO_S ( ( exp, exp ) ) ;
95
static void square_x_iy PROTO_S ( ( error_treatment, exp *, exp *, exp ) ) ;
96
static void mult_w_by_z PROTO_S ( ( error_treatment, exp *, exp *, exp, exp, exp ) ) ;
97
static exp make_comp_1_z PROTO_S ( ( floating_variety, error_treatment, exp, exp, exp, exp, exp, exp ) ) ;
98
static exp f_bin_floating_plus PROTO_S ( ( error_treatment, exp, exp ) ) ;
99
static exp f_bin_floating_mult PROTO_S ( ( error_treatment, exp, exp ) ) ;
100
static exp real_power PROTO_S ( ( error_treatment, exp, exp ) ) ;
101
 
102
 
103
 
104
exp f_change_floating_variety
105
    PROTO_N ( (flpt_err, r, arg1) )
106
    PROTO_T ( error_treatment flpt_err X floating_variety r X exp arg1 )
107
{
108
  if (name(sh(arg1)) == bothd)
109
    return arg1;
110
 
111
#if check_shape
112
  if ( ! ( (is_complex(sh(arg1)) && is_complex(f_floating(r)) ) ||
113
	   (is_float(sh(arg1)) && is_float(f_floating(r)) )
114
	 )
115
     )
116
    failer(CHSH_CHFL);
117
#endif
118
 if (eq_shape(f_floating(r), sh(arg1)))		/* i.e. does nothing */
119
    return arg1;	/* Discard the other bits ? */
120
 
121
#if substitute_complex
122
  if (is_complex(sh(arg1)))
123
  {
124
    shape complex_shape = sh(arg1);
125
    floating_variety real_fv = f_float_of_complex (f_floating(r));
126
 
127
    exp c1 = me_startid (complex_shape, arg1, 0);
128
 
129
    exp obtain1_c1 = me_obtain(c1);		/* contents of arg1 */
130
    exp obtain2_c1 = me_obtain(c1);
131
 
132
    exp x = f_real_part      (obtain1_c1);		/* re(arg1) */
133
    exp y = f_imaginary_part (obtain2_c1);		/* im(arg1) */
134
 
135
    exp new_x = f_change_floating_variety (flpt_err, real_fv, x);
136
    exp new_y = f_change_floating_variety (flpt_err, real_fv, y);
137
 
138
    exp make_comp = f_make_complex (r, new_x, new_y);
139
    c1 = me_complete_id (c1, make_comp);		/* Does a 'hold_check' */
140
 
141
    return c1;
142
  };
143
#endif  /* substitute complex */
144
 
145
#if ishppa
146
  {
147
    exp t = me_c1(f_floating(r), flpt_err, arg1, chfl_tag);
148
    if (!optop(t) && name(sh(t))==doublehd) {
149
      exp id = me_startid(sh(t),t,0);
150
      exp tmp = me_complete_id(id,me_obtain(id));
151
      return tmp;
152
     }
153
    else
154
      return t;
155
  }
156
#endif
157
  return me_c1(f_floating(r), flpt_err, arg1, chfl_tag);
158
}
159
 
160
 
161
 
162
exp f_complex_conjugate
163
    PROTO_N ( (arg1) )
164
    PROTO_T ( exp arg1 )
165
{
166
  if (name(sh(arg1)) == bothd)
167
    return arg1;
168
#if check_shape
169
  if (!is_complex(sh(arg1)))
170
    failer(CHSH_CONJUGATE);
171
#endif
172
 
173
#if substitute_complex
174
  {
175
    shape complex_shape = sh(arg1);                     /* shape of our complex numbers */
176
    floating_variety real_fv = f_float_of_complex(complex_shape);
177
    shape real_shape = f_floating(real_fv);
178
    floating_variety complex_fv = f_complex_of_float(real_shape);
179
 
180
    exp c1 = me_startid(complex_shape, arg1, 0);
181
 
182
    exp obtain1_c1 = hold_check(me_obtain(c1));                     /* contents of arg1 */
183
    exp obtain2_c1 = hold_check(me_obtain(c1));
184
 
185
    exp x1 = f_real_part(obtain1_c1);                                       /* re(arg1) */
186
    exp y1 = f_imaginary_part(obtain2_c1);                                  /* im(arg1) */
187
 
188
    exp neg_im = f_floating_negate(f_impossible, y1);                           /* - im(arg1) */
189
    exp make_comp = f_make_complex(complex_fv, x1, neg_im);
190
 
191
    c1 = me_complete_id(c1, make_comp);
192
 
193
    return c1;
194
  }
195
#else
196
  return me_u3(sh(arg1), arg1, conj_tag);
197
#endif
198
}
199
 
200
 
201
 
202
exp f_float_int
203
    PROTO_N ( (flpt_err, f, arg1) )
204
    PROTO_T ( error_treatment flpt_err X floating_variety f X exp arg1 )
205
{
206
  if (name(sh(arg1)) == bothd)
207
    return arg1;
208
 
209
#if check_shape
210
  if (!is_integer(sh(arg1)))
211
    failer(CHSH_FLINT);
212
#endif
213
 
214
    if (is_complex(f_floating(f))) {
215
	flpt fzero_copy = new_flpt();
216
	floating_variety fv = f_float_of_complex(f_floating(f));
217
	shape real_shape = f_floating(fv);
218
	exp zero;
219
	exp res = f_float_int(flpt_err, fv, arg1);
220
	res = hold_check(res);
221
	flt_copy (flptnos[fzero_no], &flptnos[fzero_copy]);
222
	zero = getexp(real_shape, nilexp, 1, nilexp, nilexp, 0,
223
			fzero_copy,  real_tag);
224
	return f_make_complex(f, res, zero);
225
    }
226
#if !has64bits
227
  if ((name(arg1)!=val_tag || flpt_err.err_code > 2)
228
		 && shape_size(sh(arg1))> 32) {
229
#if use_long_double
230
	exp z = TDFcallaux(flpt_err, arg1,
231
		(is_signed(sh(arg1))?"__TDFUs_float":"__TDFUu_float"), doublesh);
232
	z = hold_check(z);
233
	if (f != doublefv) {
234
		z = me_c1(f_floating(f), flpt_err, z, chfl_tag);
235
	}
236
	return z;
237
#else
238
	exp z = TDFcallaux(flpt_err, arg1,
239
		(is_signed(sh(arg1))?"__TDFUs_float":"__TDFUu_float"), realsh);
240
	z = hold_check(z);
241
	if (f != realfv) {
242
		z = me_c1(f_floating(f), flpt_err, z, chfl_tag);
243
	}
244
	return z;
245
#endif
246
    }
247
#endif
248
  return me_c1(f_floating(f), flpt_err, arg1, float_tag);
249
}
250
 
251
 
252
exp f_floating_abs
253
    PROTO_N ( (ov_err, arg1) )
254
    PROTO_T ( error_treatment ov_err X exp arg1 )
255
{
256
  if (name(sh(arg1)) == bothd)
257
    return arg1;
258
 
259
#if check_shape
260
  if (!is_float(sh(arg1)))
261
    failer(CHSH_FLABS);
262
#endif
263
 
264
#if ishppa
265
  {
266
    exp r = me_u1(ov_err, arg1, fabs_tag);
267
    if (!optop(r) && name(sh(r))==doublehd) {
268
      exp id = me_startid(sh(r),r,0);
269
      exp tmp = me_complete_id(id,me_obtain(id));
270
      return tmp;
271
     }
272
    else
273
      return r;
274
  }
275
#endif
276
  return me_u1(ov_err, arg1, fabs_tag);
277
}
278
 
279
 
280
exp f_floating_div
281
    PROTO_N ( (ov_err, arg1, arg2) )
282
    PROTO_T ( error_treatment ov_err X exp arg1 X exp arg2 )
283
{
284
  if (name(sh(arg1)) == bothd)
285
    { kill_exp(arg2,arg2); return arg1; }
286
  if (name(sh(arg2)) == bothd)
287
    { kill_exp(arg1,arg1); return arg2; }
288
 
289
#if check_shape
290
  if (! ((is_float(sh(arg1)) || is_complex(sh(arg1))) && eq_shape(sh(arg1), sh(arg2))) )
291
    failer(CHSH_FLDIV);
292
#endif
293
 
294
/* PAB changes - 21 October 1994 */
295
#if substitute_complex
296
  if (is_complex(sh(arg1))) {
297
 
298
      shape complex_shape = sh(arg1);                     /* shape of our complex numbers */
299
      floating_variety real_fv = f_float_of_complex(complex_shape);
300
      shape real_shape = f_floating(real_fv);
301
      floating_variety complex_fv = f_complex_of_float(real_shape);
302
 
303
      exp z1 = me_startid(complex_shape, arg1, 0);
304
      exp z2 = me_startid(complex_shape, arg2, 0);
305
 
306
      exp obtain1_z1 = hold_check(me_obtain(z1));                     /* contents of arg1 */
307
      exp obtain2_z1 = hold_check(me_obtain(z1));
308
      exp obtain1_z2 = hold_check(me_obtain(z2));                     /* contents of arg2 */
309
      exp obtain2_z2 = hold_check(me_obtain(z2));
310
 
311
      exp z1_re = f_real_part(obtain1_z1);                           /* re(arg1) */
312
      exp z2_re = f_real_part(obtain1_z2);                           /* re(arg2) */
313
      exp z1_im = f_imaginary_part(obtain2_z1);                      /* im(arg1) */
314
      exp z2_im = f_imaginary_part(obtain2_z2);                      /* im(arg2) */
315
 
316
      exp x1 = me_startid(real_shape, z1_re, 0);
317
      exp x2 = me_startid(real_shape, z2_re, 0);
318
      exp y1 = me_startid(real_shape, z1_im, 0);
319
      exp y2 = me_startid(real_shape, z2_im, 0);
320
 
321
      exp obtain1_x1 = hold_check(me_obtain(x1));                     /* x1 is used twice */
322
      exp obtain2_x1 = hold_check(me_obtain(x1));
323
      exp obtain1_y1 = hold_check(me_obtain(y1));                     /* y1 is used twice */
324
      exp obtain2_y1 = hold_check(me_obtain(y1));
325
 
326
      exp obtain1_x2 = hold_check(me_obtain(x2));                /* x2 is used four times */
327
      exp obtain2_x2 = hold_check(me_obtain(x2));
328
      exp obtain3_x2 = hold_check(me_obtain(x2));
329
      exp obtain4_x2 = hold_check(me_obtain(x2));
330
      exp obtain1_y2 = hold_check(me_obtain(y2));                /* y2 is used four times */
331
      exp obtain2_y2 = hold_check(me_obtain(y2));
332
      exp obtain3_y2 = hold_check(me_obtain(y2));
333
      exp obtain4_y2 = hold_check(me_obtain(y2));
334
 
335
      exp mult_x2_x2 = f_bin_floating_mult(ov_err, obtain1_x2, obtain2_x2);
336
      exp mult_y2_y2 = f_bin_floating_mult(ov_err, obtain1_y2, obtain2_y2);
337
      exp mult_x1_x2 = f_bin_floating_mult(ov_err, obtain1_x1, obtain3_x2);
338
      exp mult_y1_y2 = f_bin_floating_mult(ov_err, obtain1_y1, obtain3_y2);
339
      exp mult_y1_x2 = f_bin_floating_mult(ov_err, obtain2_y1, obtain4_x2);
340
      exp mult_x1_y2 = f_bin_floating_mult(ov_err, obtain2_x1, obtain4_y2);
341
 
342
      exp plus1  = f_bin_floating_plus(ov_err, mult_x2_x2, mult_y2_y2);
343
      exp plus2  = f_bin_floating_plus(ov_err, mult_x1_x2, mult_y1_y2);
344
      exp minus1 = f_floating_minus(ov_err, mult_y1_x2, mult_x1_y2);
345
 
346
      exp denom = me_startid(real_shape, plus1, 0);
347
 
348
      exp obtain_denom1 = hold_check(me_obtain(denom));
349
      exp obtain_denom2 = hold_check(me_obtain(denom));
350
 
351
      exp answer_re = f_floating_div(ov_err, plus2,  obtain_denom1);
352
      exp answer_im = f_floating_div(ov_err, minus1, obtain_denom2);
353
      exp make_comp = f_make_complex(complex_fv, answer_re, answer_im);
354
 
355
      denom = me_complete_id(denom, make_comp);
356
      y2 = me_complete_id(y2, denom);
357
      y1 = me_complete_id(y1, y2);
358
      x2 = me_complete_id(x2, y1);
359
      x1 = me_complete_id(x1, x2);
360
      z2 = me_complete_id(z2, x1);
361
      z1 = me_complete_id(z1, z2);
362
 
363
      return z1;
364
  };
365
#endif
366
#if ishppa
367
  {
368
    exp r = hold_check(me_b1(ov_err, arg1, arg2, fdiv_tag));
369
    if (!optop(r) && name(sh(r))==doublehd) {
370
      exp id = me_startid(sh(r),r,0);
371
      exp tmp = me_complete_id(id,me_obtain(id));
372
      return tmp;
373
     }
374
    else
375
      return r;
376
  }
377
#endif
378
  return  hold_check(me_b1(ov_err, arg1, arg2, fdiv_tag));
379
}
380
 
381
 
382
exp f_floating_maximum
383
    PROTO_N ( (flpt_err, arg1, arg2) )
384
    PROTO_T ( error_treatment flpt_err X exp arg1 X exp arg2 )
385
{
386
  if (name(sh(arg1)) == bothd)
387
    { kill_exp(arg2,arg2); return arg1; }
388
  if (name(sh(arg2)) == bothd)
389
    { kill_exp(arg1,arg1); return arg2; }
390
 
391
#if check_shape
392
  if (!is_float(sh(arg1)) || !eq_shape(sh(arg1), sh(arg2)))
393
    failer(CHSH_FLMAX);
394
#endif
395
  return  hold_check(me_b1(flpt_err, arg1, arg2, fmax_tag));
396
}
397
 
398
 
399
exp f_floating_minimum
400
    PROTO_N ( (flpt_err, arg1, arg2) )
401
    PROTO_T ( error_treatment flpt_err X exp arg1 X exp arg2 )
402
{
403
  if (name(sh(arg1)) == bothd)
404
    { kill_exp(arg2,arg2); return arg1; }
405
  if (name(sh(arg2)) == bothd)
406
    { kill_exp(arg1,arg1); return arg2; }
407
 
408
 
409
#if check_shape
410
  if (!is_float(sh(arg1)) || !eq_shape(sh(arg1), sh(arg2)))
411
    failer(CHSH_FLMIN);
412
#endif
413
  return  hold_check(me_b1(flpt_err, arg1, arg2, fmin_tag));
414
}
415
 
416
 
417
 
418
 
419
/****************************************************************/
420
/*  The following code needs to generate labels for use with    */
421
/*  'cond_tag'.  This is currently implemented using the        */
422
/*  knowledge that a label can be obtained by taking a pointer  */
423
/*  to an EXP - a hack which was introduced because of the      */
424
/*  need to use 'f_integer_test' with 64-bit integers.  This    */
425
/*  hack is performed exclusively by the MACRO 'make_label'     */
426
/****************************************************************/
427
 
428
#define make_label(EXP) &EXP
429
 
430
 
431
/************************************************/
432
/*  'is_constant_arg' checks to see if E1 is    */
433
/*   a constant that will fit into type 'int'.  */
434
/************************************************/
435
 
436
#define is_constant_arg(E1) \
437
	((name(E1) == val_tag) && !isbigval(E1) && \
438
	(is_signed(sh(E1)) || (no(E1) >> 31 == 0)))
439
 
440
 
441
 
442
exp f_floating_power
443
    PROTO_N ( (ov_err, arg1, arg2) )
444
    PROTO_T ( error_treatment ov_err X exp arg1 X exp arg2 )
445
{
446
  if (name(sh(arg1)) == bothd)
447
    { kill_exp(arg2,arg2); return arg1; }
448
  if (name(sh(arg2)) == bothd)
449
    { kill_exp(arg1,arg1); return arg2; }
450
 
451
#if check_shape
452
  if (!( (is_float(sh(arg1)) || is_complex(sh(arg1))) && is_integer(sh(arg2)) ))
453
    failer(CHSH_FLPOWER);
454
#endif
455
 
456
/* PAB changes - 31 October 1994 */
457
 
458
  /* Gives shorter .s file if n<10 and arg1 is unknown */
459
 
460
  if (is_complex(sh(arg1))) {
461
 
462
      shape integer_shape = sh(arg2);
463
      shape complex_shape = sh(arg1);                     /* shape of our complex numbers */
464
      floating_variety real_fv = f_float_of_complex(complex_shape);
465
      shape real_shape = f_floating(real_fv);
466
      floating_variety complex_fv = f_complex_of_float(real_shape);
467
 
468
      exp sn = me_startid(integer_shape, arg2, 0);
469
 
470
      if (is_constant_arg(arg2) ||
471
	((name(arg2) == name_tag) && (name(son(arg2)) == ident_tag)
472
	   && !isvar(son(arg2)) && is_constant_arg(son(son(arg2)))))
473
      {                                                              /* we know the power */
474
	  int n;
475
	  int exponent;
476
	  exp z = push (sn, me_startid(complex_shape, arg1, 0));
477
 
478
	  if (is_constant_arg(arg2)) {
479
	      exponent = no(arg2);	/* arg2 is a constant */
480
	  }
481
	  else {
482
	      exponent = no(son(son(arg2)));
483
		  /* arg2 identifies a constant */
484
	  }
485
 
486
	  n = abs(exponent);
487
	  if (n == 0) {
488
 
489
	      exp  answer_re, answer_im, make_comp;
490
 
491
	      flpt fzero_copy = new_flpt();
492
	      flpt fone_copy  = new_flpt();
493
 
494
	      flt_copy (flptnos[fzero_no], &flptnos[fzero_copy]);
495
	      flt_copy (flptnos[fone_no],  &flptnos[fone_copy]);
496
 
497
	      answer_re = getexp(real_shape, nilexp, 1, nilexp, nilexp, 0, fone_copy,  real_tag);
498
	      answer_im = getexp(real_shape, nilexp, 1, nilexp, nilexp, 0, fzero_copy, real_tag);
499
 
500
	      make_comp = f_make_complex(complex_fv, answer_re, answer_im);
501
	      return  me_complete_chain(z, arg2, make_comp);
502
 
503
	  } else {
504
 
505
	      exp link_next;
506
 
507
	      exp z_re = f_real_part     (me_obtain(z));
508
	      exp z_im = f_imaginary_part(me_obtain(z));
509
 
510
	      exp x = push (z, me_startid(real_shape, z_re, 0));
511
	      exp y = push (x, me_startid(real_shape, z_im, 0));
512
 
513
	      exp u, v, mylast;;
514
 
515
	      while ((n % 2) == 0) {
516
		  mylast = y;
517
		  square_x_iy(ov_err, &x, &y, mylast);
518
		  n = n / 2;
519
	      }
520
 
521
	      if (n == 1) {                                                   /* return z */
522
 
523
		  if (exponent < 0) {
524
		      link_next = make_comp_1_z(complex_fv, ov_err,
525
						me_obtain(x), me_obtain(x), me_obtain(x),
526
						me_obtain(y), me_obtain(y), me_obtain(y));
527
		  } else {
528
		      link_next = f_make_complex(complex_fv, me_obtain(x), me_obtain(y));
529
		  }
530
 
531
		  return me_complete_chain(y, arg2, link_next);             /*  return z  */
532
 
533
	      } else {                           	                       /*  w = z  */
534
 
535
		  u = push (y, me_startid(real_shape, me_obtain(x), 0));
536
		  v = push (u, me_startid(real_shape, me_obtain(y), 0));
537
		  mylast = v;
538
	      }
539
 
540
	      while (n != 1) {
541
		  square_x_iy(ov_err, &x, &y, mylast);                         /*  z = z*z  */
542
		  mylast = y;
543
		  n = n / 2;
544
		  if ((n % 2) == 1) {
545
		      mult_w_by_z (ov_err, &u, &v, x, y, mylast);              /*  w = w*z  */
546
		      mylast = v;
547
		  }
548
	      }
549
 
550
	      if (exponent < 0) {
551
		  link_next = make_comp_1_z(complex_fv, ov_err,
552
					    me_obtain(u), me_obtain(u), me_obtain(u),
553
					    me_obtain(v), me_obtain(v), me_obtain(v));
554
	      } else {
555
		  link_next = f_make_complex(complex_fv, me_obtain(u), me_obtain(v));
556
	      }
557
	      return me_complete_chain(v, arg2, link_next);                /*  return w  */
558
	  }
559
 
560
      } else {
561
 
562
	  exp  reinitialise_w, main_loop, make_comp;              /* main building blocks */
563
	  exp  square_z, mult_z_w, half_n, update_w, repeat_body;
564
	  exp  seq, seq_zero, make_comp1, make_comp2;
565
	  exp  real0, real1, x, y, u, v;
566
 
567
	  exp z  = me_startid(complex_shape, arg1, 0);
568
 
569
	  exp abs_val_sn = f_abs(ov_err, me_obtain(sn));
570
	  exp n = me_startid(sh(sn), abs_val_sn, 1);
571
 
572
	  exp z_re = f_real_part     (me_obtain(z));
573
	  exp z_im = f_imaginary_part(me_obtain(z));
574
 
575
	  flpt fzero_copy = new_flpt();
576
	  flpt fone_copy  = new_flpt();
577
 
578
	  flt_copy (flptnos[fzero_no], &flptnos[fzero_copy]);
579
	  flt_copy (flptnos[fone_no],  &flptnos[fone_copy]);
580
 
581
	  real0 = getexp(real_shape, nilexp, 1, nilexp, nilexp, 0, fzero_copy, real_tag);
582
	  real1 = getexp(real_shape, nilexp, 1, nilexp, nilexp, 0, fone_copy,  real_tag);
583
 
584
	  x = me_startid(real_shape, z_re, 1);                                /* re(arg1) */
585
	  y = me_startid(real_shape, z_im, 1);                                /* re(arg2) */
586
 
587
	  u = me_startid(real_shape, real1, 1);                            /* re(w) = 1.0 */
588
	  v = me_startid(real_shape, real0, 1);                            /* im(w) = 0.0 */
589
 
590
 
591
	  /*  change value of w to z if n is odd  */
592
 
593
	  {
594
	      exp constant1  = me_shint(integer_shape, 1);
595
	      exp constant2  = me_shint(integer_shape, 2);
596
 
597
	      exp rem_n_2    = f_rem0 (f_impossible, f_impossible,
598
				       me_contents(n), constant2);
599
 
600
	      exp assign_u = hold_check(me_b3(f_top, me_obtain(u), me_contents(x), ass_tag));
601
	      exp assign_v = hold_check(me_b3(f_top, me_obtain(v), me_contents(y), ass_tag));
602
 
603
	      exp top_cell  = me_l1(f_top, top_tag);
604
	      exp alt_labst = hold_check(me_b3(sh(top_cell), me_null(f_top,0,clear_tag),
605
					       top_cell, labst_tag));
606
 
607
	      exp is_n_odd = f_integer_test (no_nat_option, f_equal,
608
					     make_label(alt_labst), rem_n_2, constant1);
609
 
610
	      exp seq_zero = hold_check(me_b2(is_n_odd, assign_u, 0));
611
	      exp seq = hold_check(me_b3(sh(assign_v), seq_zero, assign_v, seq_tag));
612
 
613
	      reinitialise_w = hold_check(me_b3(lub_shape(sh(seq),sh(alt_labst)),
614
						seq, alt_labst, cond_tag));
615
	  }
616
 
617
 
618
	  /*  z=z*z  */
619
 
620
	  {
621
	      exp minus_x_y = f_floating_minus(ov_err, me_contents(x), me_contents(y));
622
	      exp  plus_x_y = f_bin_floating_plus(ov_err, me_contents(x), me_contents(y));
623
	      exp  mult_x_y = f_bin_floating_mult(ov_err, me_contents(x), me_contents(y));
624
 
625
	      exp tmp = me_startid(real_shape, mult_x_y, 0);
626
 
627
	      exp answer_re  = f_bin_floating_mult(ov_err, minus_x_y, plus_x_y);
628
	      exp answer_im  = f_bin_floating_plus(ov_err, me_obtain(tmp), me_obtain(tmp));
629
 
630
	      exp assign_x = hold_check(me_b3(f_top, me_obtain(x), answer_re, ass_tag));
631
	      exp assign_y = hold_check(me_b3(f_top, me_obtain(y), answer_im, ass_tag));
632
 
633
	      exp seq_zero = hold_check(me_u2(assign_x, 0));
634
	      exp seq      = hold_check(me_b3(sh(assign_y), seq_zero, assign_y, seq_tag));
635
 
636
	      square_z = me_complete_id(tmp, seq);
637
	  }
638
 
639
 
640
	  /*  w=z*w  */
641
 
642
	  {
643
	      exp mult_x_u = f_bin_floating_mult(ov_err, me_contents(x), me_contents(u));
644
	      exp mult_x_v = f_bin_floating_mult(ov_err, me_contents(x), me_contents(v));
645
	      exp mult_y_u = f_bin_floating_mult(ov_err, me_contents(y), me_contents(u));
646
	      exp mult_y_v = f_bin_floating_mult(ov_err, me_contents(y), me_contents(v));
647
 
648
	      exp tmp = me_startid(real_shape, mult_y_u, 0);
649
 
650
	      exp answer_re  = f_floating_minus(ov_err, mult_x_u, mult_y_v);
651
	      exp answer_im  = f_bin_floating_plus(ov_err, mult_x_v, me_obtain(tmp));
652
 
653
	      exp assign_u = hold_check(me_b3(f_top, me_obtain(u), answer_re, ass_tag));
654
	      exp assign_v = hold_check(me_b3(f_top, me_obtain(v), answer_im, ass_tag));
655
 
656
	      exp seq_zero = hold_check(me_u2(assign_u, 0));
657
	      exp seq      = hold_check(me_b3(sh(assign_v), seq_zero, assign_v, seq_tag));
658
 
659
	      mult_z_w = me_complete_id(tmp, seq);
660
	  }
661
 
662
 
663
	  /*  n=n/2  */
664
 
665
	  {
666
	      exp constant2  = me_shint(integer_shape, 2);
667
 
668
	      exp answer = f_div0 (f_impossible, f_impossible,
669
				   me_contents(n), constant2);
670
	      half_n = hold_check(me_b3(f_top, me_obtain(n), answer, ass_tag));
671
	  }
672
 
673
 
674
	  /*  if n is odd then w = z*w  */
675
 
676
	  {
677
	      exp constant1  = me_shint(integer_shape, 1);
678
	      exp constant2  = me_shint(integer_shape, 2);
679
 
680
	      exp rem_n_2    = f_rem0 (f_impossible, f_impossible,
681
				       me_contents(n), constant2);
682
 
683
	      exp top_cell  = me_l1(f_top, top_tag);
684
	      exp alt_labst = hold_check(me_b3(f_top, me_null(f_top,0,clear_tag),
685
					       top_cell, labst_tag));
686
 
687
	      exp is_n_odd = f_integer_test (no_nat_option, f_equal,
688
					     make_label(alt_labst), rem_n_2, constant1);
689
	      exp seq_zero = hold_check(me_u2(is_n_odd, 0));
690
	      exp seq = hold_check(me_b3(sh(mult_z_w), seq_zero, mult_z_w, seq_tag));
691
 
692
	      update_w = hold_check(me_b3(lub_shape(sh(seq),sh(alt_labst)),
693
					  seq, alt_labst, cond_tag));
694
	  }
695
 
696
 
697
	  /*  repeat + body  */
698
 
699
	  {
700
	      exp if_n_equals_1, seq_zero, seq, body_labst;
701
 
702
	      exp constant1  = me_shint(integer_shape, 1);
703
	      exp top_cell   = me_l1(f_top, top_tag);
704
 
705
	      body_labst = hold_check(me_b3(sh(top_cell), me_null(f_top,0,clear_tag),
706
                                            top_cell, labst_tag));
707
 
708
	      if_n_equals_1 = f_integer_test (no_nat_option, f_equal, make_label(body_labst),
709
					      me_contents(n), constant1);
710
 
711
	      seq_zero = me_b2(square_z, update_w, 0);
712
	      setbro (square_z, half_n);                   /*  insert half_n between   */
713
	      setbro (half_n, update_w);                   /*  square_x and update_w   */
714
	      clearlast (half_n);
715
	      seq_zero = hold_check(seq_zero);
716
 
717
	      seq = hold_check(me_b3(sh(if_n_equals_1), seq_zero, if_n_equals_1, seq_tag));
718
 
719
	      setbro(son(body_labst), seq);
720
	      clearlast(son(body_labst));
721
	      setfather(body_labst, seq);
722
 
723
	      repeat_body = hold_check(me_b3(sh(seq), top_cell, body_labst, rep_tag));
724
	      note_repeat(repeat_body);
725
	  }
726
 
727
 
728
	  /*  make loop - only done if  mod(n) > 1  */
729
 
730
	  {
731
	      exp constant1  = me_shint(integer_shape, 1);
732
 
733
	      exp top_cell  = me_l1(f_top, top_tag);
734
	      exp alt_labst = hold_check(me_b3(f_top, me_null(f_top,0,clear_tag),
735
					       top_cell, labst_tag));
736
 
737
	      exp is_n_gt_1 = f_integer_test (no_nat_option, f_greater_than,
738
					      make_label(alt_labst), me_contents(n), constant1);
739
 
740
	      exp seq_zero = hold_check(me_u2(is_n_gt_1, 0));
741
	      exp seq = hold_check(me_b3(sh(repeat_body), seq_zero, repeat_body, seq_tag));
742
 
743
	      main_loop = hold_check(me_b3(lub_shape(sh(seq),sh(alt_labst)),
744
					   seq, alt_labst, cond_tag));
745
	  }
746
 
747
	  make_comp1 = f_make_complex(complex_fv, me_contents(u), me_contents(v));
748
	  make_comp2 = make_comp_1_z(complex_fv, ov_err,
749
                                     me_contents(u), me_contents(u), me_contents(u),
750
                                     me_contents(v), me_contents(v), me_contents(v));
751
 
752
 
753
	  /* if arg2 is negative then make_comp2 else make_comp1 */
754
 
755
	  {
756
	      exp constant0 = me_shint(integer_shape, 0);
757
 
758
	      exp alt_labst = hold_check(me_b3(sh(make_comp1),
759
					       me_null(f_top,0,clear_tag),
760
					       make_comp1, labst_tag));
761
 
762
	      exp is_arg2_negative = f_integer_test (no_nat_option, f_less_than,
763
						     make_label(alt_labst),
764
						     me_obtain(sn), constant0);
765
 
766
	      exp seq_zero = hold_check(me_u2(is_arg2_negative, 0));
767
	      exp seq = hold_check(me_b3(sh(make_comp2), seq_zero, make_comp2, seq_tag));
768
 
769
	      make_comp = hold_check(me_b3(lub_shape(sh(seq),sh(alt_labst)),
770
					   seq, alt_labst, cond_tag));
771
	  }
772
 
773
      seq_zero = hold_check(me_b2(reinitialise_w, main_loop, 0));
774
      seq      = hold_check(me_b3(sh(make_comp), seq_zero, make_comp, seq_tag));
775
 
776
 
777
      v  = me_complete_id(v, seq);
778
      u  = me_complete_id(u, v);
779
      y  = me_complete_id(y, u);
780
      x  = me_complete_id(x, y);
781
      n  = me_complete_id(n, x);
782
      sn = me_complete_id(sn, n);
783
      z  = me_complete_id(z, sn);
784
 
785
      return z;
786
      }
787
  }
788
 
789
  return  real_power(ov_err, arg1, arg2);
790
}
791
 
792
 
793
exp f_floating_minus
794
    PROTO_N ( (ov_err, arg1, arg2) )
795
    PROTO_T ( error_treatment ov_err X exp arg1 X exp arg2 )
796
{
797
  if (name(sh(arg1)) == bothd)
798
    { kill_exp(arg2,arg2); return arg1; }
799
  if (name(sh(arg2)) == bothd)
800
    { kill_exp(arg1,arg1); return arg2; }
801
 
802
#if check_shape
803
  if (! ((is_float(sh(arg1)) || is_complex(sh(arg1))) && eq_shape(sh(arg1), sh(arg2))) )
804
    failer(CHSH_FLMINUS);
805
#endif
806
 
807
/* PAB changes - 18 October 1994 */
808
#if substitute_complex
809
  if (is_complex(sh(arg1))) {
810
 
811
      shape complex_shape = sh(arg1);                     /* shape of our complex numbers */
812
      floating_variety real_fv = f_float_of_complex(complex_shape);
813
      shape real_shape = f_floating(real_fv);
814
      floating_variety complex_fv = f_complex_of_float(real_shape);
815
 
816
      exp z1 = me_startid(complex_shape, arg1, 0);
817
      exp z2 = me_startid(complex_shape, arg2, 0);
818
 
819
      exp x1 = f_real_part     (me_obtain(z1));                      /* re(arg1) */
820
      exp x2 = f_real_part     (me_obtain(z2));                      /* re(arg2) */
821
      exp y1 = f_imaginary_part(me_obtain(z1));                      /* im(arg1) */
822
      exp y2 = f_imaginary_part(me_obtain(z2));                      /* im(arg2) */
823
 
824
      exp minus_re  = f_floating_minus(ov_err, x1, x2);
825
      exp minus_im  = f_floating_minus(ov_err, y1, y2);
826
      exp make_comp = f_make_complex(complex_fv, minus_re, minus_im);
827
 
828
      z2 = me_complete_id(z2, make_comp);
829
      z1 = me_complete_id(z1, z2);
830
 
831
      return z1;
832
  };
833
#endif
834
#if ishppa
835
  {
836
    exp r = hold_check(me_b1(ov_err, arg1, arg2, fminus_tag));
837
    if (!optop(r) && name(sh(r))==doublehd) {
838
      exp id = me_startid(sh(r),r,0);
839
      exp tmp = me_complete_id(id,me_obtain(id));
840
      return tmp;
841
     }
842
    else
843
      return r;
844
  }
845
#endif
846
  return  hold_check(me_b1(ov_err, arg1, arg2, fminus_tag));
847
}
848
 
849
 
850
exp f_floating_mult
851
    PROTO_N ( (ov_err, arg1) )
852
    PROTO_T ( error_treatment ov_err X exp_list arg1 )
853
{
854
  exp first = arg1.start;
855
  exp r = getexp (sh(first), nilexp, 0, first,
856
                  nilexp,
857
                  0, 0, fmult_tag);
858
  if (name(sh(first)) == bothd || arg1.number == 1)
859
    return first;
860
  clear_exp_list(arg1);
861
  seterrhandle(r, ov_err.err_code);
862
  if (isov(r))
863
   setjmp_dest(r, get_lab(ov_err.jmp_dest));
864
 
865
#if check_shape
866
  {exp t = first;
867
   while (1)
868
     {
869
       if (! ((is_float(sh(t)) || is_complex(sh(t))) && eq_shape(sh(t), sh(first))) )
870
         failer(CHSH_FLMULT);
871
       if (t == arg1.end)
872
         break;
873
       t = bro(t);
874
       if (name(sh(t)) == bothd)
875
         return t;
876
     };
877
  };
878
#endif
879
 
880
/* PAB changes - 19 October 1994 */
881
#if substitute_complex
882
  if (is_complex(sh(arg1.start))) {
883
 
884
      shape complex_shape = sh(arg1.start);            /* shape of our complex numbers */
885
      floating_variety real_fv = f_float_of_complex(complex_shape);
886
      shape real_shape = f_floating(real_fv);
887
      floating_variety complex_fv = f_complex_of_float(real_shape);
888
 
889
      exp  x1, y1, x2, y2, z1, z1_re, z1_im, t, link_next, prod_re, prod_im;
890
 
891
#if 0
892
      arg1 = reorder_list(arg1, 1);              /* reorder so constants are at the front */
893
#endif
894
 
895
      z1 = me_startid(complex_shape, arg1.start, 0);
896
 
897
      z1_re = f_real_part     (me_obtain(z1));                 /* re(arg1.first) */
898
      z1_im = f_imaginary_part(me_obtain(z1));                 /* im(arg1.first) */
899
 
900
      x1 = push(z1, me_startid(real_shape, z1_re, 0));
901
      y1 = push(x1, me_startid(real_shape, z1_im, 0));
902
 
903
      t = arg1.start;
904
 
905
      while (t != arg1.end) {
906
 
907
	  t = bro(t);
908
	  z1 = push(y1, me_startid(complex_shape, t, 0));
909
 
910
	  z1_re = f_real_part     (me_obtain(z1));    /* contents of next */
911
	  z1_im = f_imaginary_part(me_obtain(z1));    /* list element     */
912
 
913
	  x2 = push(z1, me_startid(real_shape, z1_re, 0));
914
	  y2 = push(x2, me_startid(real_shape, z1_im, 0));
915
 
916
	  if (eq_exp(x1,x2) && eq_exp(y1,y2)) {
917
 
918
	      exp minus_x1_x2 = f_floating_minus(ov_err, me_obtain(x1), me_obtain(x2));
919
	      exp  plus_x1_x2 = f_bin_floating_plus(ov_err, me_obtain(x1), me_obtain(x2));
920
	      exp  mult_x1_y1 = f_bin_floating_mult(ov_err, me_obtain(x1), me_obtain(y1));
921
 
922
	      prod_re = f_bin_floating_mult(ov_err, minus_x1_x2, plus_x1_x2);
923
	      prod_im = f_bin_floating_plus(ov_err,  mult_x1_y1, mult_x1_y1);
924
	  }
925
 
926
	  else
927
 
928
	  {
929
	      exp mult_x1_x2 = f_bin_floating_mult(ov_err, me_obtain(x1), me_obtain(x2));
930
	      exp mult_y1_y2 = f_bin_floating_mult(ov_err, me_obtain(y1), me_obtain(y2));
931
	      exp mult_x1_y2 = f_bin_floating_mult(ov_err, me_obtain(x1), me_obtain(y2));
932
	      exp mult_x2_y1 = f_bin_floating_mult(ov_err, me_obtain(x2), me_obtain(y1));
933
 
934
	      prod_re = f_floating_minus(ov_err, mult_x1_x2, mult_y1_y2);
935
	      prod_im = f_bin_floating_plus(ov_err, mult_x1_y2, mult_x2_y1);
936
	  }
937
 
938
	  x1 = push(y2, me_startid(real_shape, prod_re, 0));
939
	  y1 = push(x1, me_startid(real_shape, prod_im, 0));
940
      }
941
 
942
      link_next = f_make_complex(complex_fv, me_obtain(x1), me_obtain(y1));
943
 
944
      return  me_complete_chain(y1, arg1.start, link_next);
945
  }
946
#endif
947
  setfather (r, arg1.end);
948
#if ishppa
949
  if (!optop(r) && name(sh(r))==doublehd) {
950
    exp id = me_startid(sh(r),r,0);
951
    exp tmp = me_complete_id(id,me_obtain(id));
952
    return tmp;
953
   }
954
  else
955
#endif
956
  return r;
957
}
958
 
959
 
960
exp f_floating_negate
961
    PROTO_N ( (ov_err, arg1) )
962
    PROTO_T ( error_treatment ov_err X exp arg1 )
963
{
964
  if (name(sh(arg1)) == bothd)
965
    return arg1;
966
 
967
#if check_shape
968
  if (!is_float(sh(arg1)) && !is_complex(sh(arg1)))
969
    failer(CHSH_FLNEGATE);
970
#endif
971
 
972
/* PAB changes - 18 October 1994 */
973
#if substitute_complex
974
  if (is_complex(sh(arg1))) {
975
 
976
      shape complex_shape = sh(arg1);                     /* shape of our complex numbers */
977
      floating_variety real_fv = f_float_of_complex(complex_shape);
978
      shape real_shape = f_floating(real_fv);
979
      floating_variety complex_fv = f_complex_of_float(real_shape);
980
 
981
      exp c1 = me_startid(complex_shape, arg1, 0);
982
 
983
      exp obtain1_c1 = hold_check(me_obtain(c1));                     /* contents of arg1 */
984
      exp obtain2_c1 = hold_check(me_obtain(c1));
985
 
986
      exp x1 = f_real_part(obtain1_c1);                              /* re(arg1) */
987
      exp y1 = f_imaginary_part(obtain2_c1);                         /* im(arg1) */
988
 
989
      exp neg_re = f_floating_negate(ov_err, x1);                           /* - re(arg1) */
990
      exp neg_im = f_floating_negate(ov_err, y1);                           /* - im(arg1) */
991
      exp make_comp = f_make_complex(complex_fv, neg_re, neg_im);
992
 
993
      c1 = me_complete_id(c1, make_comp);
994
 
995
      return c1;
996
  };
997
#endif
998
#if ishppa
999
  {
1000
    exp r = hold_check(me_u1(ov_err, arg1, fneg_tag));
1001
    if (!optop(r) && name(sh(r))==doublehd) {
1002
      exp id = me_startid(sh(r),r,0);
1003
      exp tmp = me_complete_id(id,me_obtain(id));
1004
      return tmp;
1005
     }
1006
    else
1007
      return r;
1008
  }
1009
#endif
1010
  return  hold_check(me_u1(ov_err, arg1, fneg_tag));
1011
}
1012
 
1013
 
1014
exp f_floating_plus
1015
    PROTO_N ( (ov_err, arg1) )
1016
    PROTO_T ( error_treatment ov_err X exp_list arg1 )
1017
{
1018
  exp first = arg1.start;
1019
  exp r = getexp (sh(first), nilexp, 0, first,
1020
                  nilexp, 0, 0, fplus_tag);
1021
  if (name(sh(first)) == bothd || arg1.number == 1)
1022
    return first;
1023
  clear_exp_list(arg1);
1024
  seterrhandle(r, ov_err.err_code);
1025
  if (isov(r))
1026
    setjmp_dest(r, get_lab(ov_err.jmp_dest));
1027
 
1028
#if check_shape
1029
  {exp t = first;
1030
   while (1)
1031
     {
1032
       if (! ((is_float(sh(t)) || is_complex(sh(t))) && eq_shape(sh(t), sh(first))) )
1033
         failer(CHSH_FLPLUS);
1034
       if (t == arg1.end)
1035
         break;
1036
       t = bro(t);
1037
       if (name(sh(t)) == bothd)
1038
         return t;
1039
     };
1040
  };
1041
#endif
1042
 
1043
/* PAB changes - 18 October 1994 */
1044
#if substitute_complex
1045
  if (is_complex(sh(arg1.start))) {
1046
 
1047
      exp z1, z2, x1, y1, x2, y2, make_comp, t;
1048
 
1049
      shape complex_shape = sh(arg1.start);               /* shape of our complex numbers */
1050
      floating_variety real_fv = f_float_of_complex(complex_shape);
1051
      shape real_shape = f_floating(real_fv);
1052
      floating_variety complex_fv = f_complex_of_float(real_shape);
1053
 
1054
#if 0
1055
      arg1 = reorder_list(arg1, 1);              /* reorder so constants are at the front */
1056
#endif
1057
 
1058
      z1 = me_startid(complex_shape, arg1.start, 0);
1059
 
1060
      x1 = f_real_part     (me_obtain(z1));                    /* re(arg1.first) */
1061
      y1 = f_imaginary_part(me_obtain(z1));                    /* im(arg1.first) */
1062
 
1063
      t=arg1.start;
1064
      z2 = z1;                                                   /* start chain of idents */
1065
 
1066
      while (t != arg1.end) {
1067
 
1068
	  t = bro(t);
1069
	  z2 = push(z2, me_startid(complex_shape, t, 0));
1070
 
1071
	  x2 = f_real_part     (me_obtain(z2));              /* contents of next */
1072
	  y2 = f_imaginary_part(me_obtain(z2));              /*   list element   */
1073
 
1074
	  x1 = f_bin_floating_plus(ov_err, x1, x2);                    /* pass it this on */
1075
	  y1 = f_bin_floating_plus(ov_err, y1, y2);                    /*  as new result  */
1076
      }
1077
 
1078
      make_comp = f_make_complex(complex_fv, x1, y1);
1079
 
1080
      return me_complete_chain(z2, arg1.start, make_comp);
1081
  }
1082
#endif
1083
  setfather (r, arg1.end);
1084
#if ishppa
1085
  if (!optop(r) && name(sh(r))==doublehd) {
1086
    exp id = me_startid(sh(r),r,0);
1087
    exp tmp = me_complete_id(id,me_obtain(id));
1088
    return tmp;
1089
   }
1090
  else
1091
#endif
1092
  return r;
1093
}
1094
 
1095
 
1096
exp f_floating_test
1097
    PROTO_N ( (prob, flpt_err, nt, dest, arg1, arg2) )
1098
    PROTO_T ( nat_option prob X error_treatment flpt_err X ntest nt X label dest X exp arg1 X exp arg2 )
1099
{
1100
  if (name(sh(arg1)) == bothd)
1101
    { kill_exp(arg2,arg2); return arg1; }
1102
  if (name(sh(arg2)) == bothd)
1103
    { kill_exp(arg1,arg1); return arg2; }
1104
 
1105
#if check_shape
1106
  if (! ((is_float(sh(arg1)) || is_complex(sh(arg1))) && eq_shape(sh(arg1), sh(arg2))) )
1107
    failer(CHSH_FLTEST);
1108
#endif
1109
 
1110
/* PAB changes - 18 October 1994 */
1111
#if substitute_complex
1112
  if (is_complex(sh(arg1))) {                               /* is arg1 a complex number ? */
1113
 
1114
      shape complex_shape = sh(arg1);                     /* shape of our complex numbers */
1115
      exp z1 = me_startid(complex_shape, arg1, 0);
1116
      exp z2 = me_startid(complex_shape, arg2, 0);
1117
 
1118
      exp obtain1_z1 = hold_check(me_obtain(z1));                     /* contents of arg1 */
1119
      exp obtain2_z1 = hold_check(me_obtain(z1));
1120
      exp obtain1_z2 = hold_check(me_obtain(z2));                     /* contents of arg2 */
1121
      exp obtain2_z2 = hold_check(me_obtain(z2));
1122
 
1123
      exp x1 = f_real_part     (obtain1_z1);                         /* re(arg1) */
1124
      exp x2 = f_real_part     (obtain1_z2);                         /* re(arg2) */
1125
      exp y1 = f_imaginary_part(obtain2_z1);                         /* im(arg1) */
1126
      exp y2 = f_imaginary_part(obtain2_z2);                         /* im(arg2) */
1127
 
1128
#if check_shape
1129
      if ((nt != f_equal) && (nt != f_not_equal))
1130
	  failer(CHSH_FLTEST);
1131
#endif
1132
 
1133
      if (nt == f_equal) {                                       /* equality of z1 and z2 */
1134
 
1135
	  exp test1 = f_floating_test (prob, flpt_err, f_equal, dest, x1, x2);
1136
	  exp test2 = f_floating_test (prob, flpt_err, f_equal, dest, y1, y2);
1137
 
1138
	  exp seq_zero = hold_check(me_u2(test1, 0));
1139
	  exp seq      = hold_check(me_b3(sh(test2), seq_zero, test2, seq_tag));
1140
	  z2           = me_complete_id(z2, seq);
1141
 
1142
      } else {                                                 /* inequality of z1 and z2 */
1143
 
1144
	  exp seq, conditional;
1145
 
1146
	  exp top_cell = me_l1(f_top, top_tag);
1147
	  exp alt_labst = hold_check(me_b3(f_top, me_null(f_top,0,clear_tag),
1148
                                                          top_cell, labst_tag));
1149
 
1150
	  exp test1 = f_floating_test (prob, flpt_err, f_equal,
1151
				       make_label(alt_labst), x1, x2);
1152
	  exp test2 = f_floating_test (prob, flpt_err, f_not_equal,
1153
				       dest, y1, y2);
1154
      	  exp seq_zero = hold_check(me_b2(test1, test2, 0));
1155
 
1156
	  seq = hold_check(me_b3(f_bottom, seq_zero, f_make_top(), seq_tag));
1157
 
1158
	  conditional = hold_check(me_b3(f_top,
1159
					 seq, alt_labst, cond_tag));
1160
 
1161
	  z2 = me_complete_id(z2, conditional);
1162
      }
1163
      z1 = me_complete_id(z1, z2);
1164
 
1165
      return z1;
1166
  }
1167
#endif
1168
  return me_q2(prob, flpt_err, nt, dest, arg1, arg2, test_tag);
1169
}
1170
 
1171
 
1172
 
1173
exp f_imaginary_part
1174
    PROTO_N ( (arg1) )
1175
    PROTO_T ( exp arg1 )
1176
{
1177
  shape real_shape;
1178
 
1179
  if (name(sh(arg1)) == bothd)
1180
    return arg1;
1181
#if check_shape
1182
  if (!is_complex(sh(arg1)))
1183
    failer(CHSH_IMAG);
1184
#endif
1185
 
1186
/* PAB changes - 25 May 1995 */
1187
  real_shape = f_floating(f_float_of_complex(sh(arg1)));
1188
#if substitute_complex
1189
  {
1190
    exp t = me_u3(real_shape, arg1, field_tag);
1191
    no(t) = shape_size(real_shape);
1192
    return hold_check(t);
1193
  }
1194
#else
1195
  return me_u3(real_shape, arg1, imag_tag);
1196
#endif
1197
}
1198
 
1199
 
1200
exp f_real_part
1201
    PROTO_N ( (arg1) )
1202
    PROTO_T ( exp arg1 )
1203
{
1204
  shape real_shape;
1205
 
1206
  if (name(sh(arg1)) == bothd)
1207
    return arg1;
1208
#if check_shape
1209
  if (!is_complex(sh(arg1)))
1210
    failer(CHSH_REAL);
1211
#endif
1212
 
1213
/* PAB changes - 25 May 1995 */
1214
  real_shape = f_floating(f_float_of_complex(sh(arg1)));
1215
#if substitute_complex
1216
  {
1217
    exp t = me_u3(real_shape, arg1, field_tag);
1218
    no(t) = 0;
1219
    return hold_check(t);
1220
  }
1221
#else
1222
  return me_u3(real_shape, arg1, realpart_tag);
1223
#endif
1224
}
1225
 
1226
 
1227
 
1228
exp f_make_complex
1229
    PROTO_N ( (f, arg1, arg2) )
1230
    PROTO_T ( floating_variety f X exp arg1 X exp arg2 )
1231
{
1232
  if (name(sh(arg1)) == bothd)
1233
    { kill_exp(arg2,arg2); return arg1; }
1234
  if (name(sh(arg2)) == bothd)
1235
    { kill_exp(arg1,arg1); return arg2; }
1236
 
1237
#if check_shape
1238
  if (!is_float(sh(arg1)) || !is_float(sh(arg2)) ||
1239
	!eq_shape(sh(arg1), sh(arg2)) || f != f_complex_of_float(sh(arg1)))
1240
    failer(CHSH_MAKE_COMPLEX);
1241
#endif
1242
 
1243
 
1244
/* PAB changes - 19 October 1994 */
1245
#if substitute_complex
1246
  switch (f) {
1247
     case shcomplexfv:
1248
        {
1249
	 shape off_set = f_offset(SHREAL_ALIGN, SHREAL_ALIGN);
1250
	 exp val1 = me_shint(off_set, 0);
1251
	 exp val2 = me_shint(off_set, SHREAL_SZ);
1252
	 exp sz = me_shint(off_set, SHREAL_SZ + SHREAL_SZ);
1253
	 exp r = getexp(f_compound(sz), nilexp, 0, val1, nilexp, 0, 0, compound_tag);
1254
 
1255
	 setbro(val1, arg1);
1256
	 clearlast(val1);
1257
	 setbro(arg1, val2);
1258
	 clearlast(arg1);
1259
	 setbro(val2, arg2);
1260
	 clearlast(val2);
1261
	 setfather(r, arg2);
1262
	 return hold_check(r);
1263
       }
1264
     case complexfv:
1265
       {
1266
	 shape off_set = f_offset(REAL_ALIGN, REAL_ALIGN);
1267
	 exp val1 = me_shint(off_set, 0);
1268
	 exp val2 = me_shint(off_set, REAL_SZ);
1269
	 exp sz = me_shint(off_set, REAL_SZ + REAL_SZ);
1270
	 exp r = getexp(f_compound(sz), nilexp, 0, val1, nilexp, 0, 0, compound_tag);
1271
 
1272
	 setbro(val1, arg1);
1273
	 clearlast(val1);
1274
	 setbro(arg1, val2);
1275
	 clearlast(arg1);
1276
	 setbro(val2, arg2);
1277
	 clearlast(val2);
1278
	 setfather(r, arg2);
1279
	 return hold_check(r);
1280
       }
1281
     case complexdoublefv:
1282
       {
1283
	 shape off_set = f_offset(DOUBLE_ALIGN, DOUBLE_ALIGN);
1284
	 exp val1 = me_shint(off_set, 0);
1285
	 exp val2 = me_shint(off_set, DOUBLE_SZ);
1286
	 exp sz = me_shint(off_set, DOUBLE_SZ + DOUBLE_SZ);
1287
	 exp r = getexp(f_compound(sz), nilexp, 0, val1, nilexp, 0, 0, compound_tag);
1288
 
1289
	 setbro(val1, arg1);
1290
	 clearlast(val1);
1291
	 setbro(arg1, val2);
1292
	 clearlast(arg1);
1293
	 setbro(val2, arg2);
1294
	 clearlast(val2);
1295
	 setfather(r, arg2);
1296
	 return hold_check(r);
1297
       }
1298
     default:
1299
       {
1300
	 failer("Illegal floating_variety for make_complex_tag\n");
1301
       }
1302
  }
1303
#endif
1304
  return me_b3(f_floating(f), arg1, arg2,
1305
		 make_complex_tag);
1306
}
1307
 
1308
 
1309
#if FBASE == 10
1310
 
1311
exp f_make_floating
1312
    PROTO_N ( (fv, rm, sign, mantissa, base, expo) )
1313
    PROTO_T ( floating_variety fv X rounding_mode rm X bool sign X string mantissa X nat base X signed_nat expo )
1314
{
1315
  int ignore_zero = 1;
1316
  int lg = mantissa.number;
1317
  flpt f = new_flpt ();
1318
  int  sig_digs = 0;
1319
  int  i;
1320
  int point = 0;
1321
  char ch;
1322
  int exponent = snatint(expo);
1323
 
1324
  if (PIC_code)
1325
    proc_externs = 1;
1326
 
1327
  if (snatneg(expo))
1328
    exponent = - exponent;
1329
 
1330
  if (natint(base) != 10)
1331
    failer (BASE_NOT_10);
1332
  for (i = 0; i < MANT_SIZE; ++i)
1333
    (flptnos[f].mant)[i] = 0;
1334
 
1335
  for (i = 0; i < lg; ++i) {
1336
    ch = mantissa.ints.chars[i];
1337
    if (ch == '0' && ignore_zero) {
1338
      if (point)
1339
	--exponent;
1340
    }
1341
    else {
1342
      if (ch == '.')
1343
	point = 1;
1344
      else {
1345
	ignore_zero = 0;
1346
	if (!point)
1347
	  ++exponent;
1348
	if (sig_digs < MANT_SIZE)
1349
	  (flptnos[f].mant)[sig_digs++] = ch - '0';
1350
      };
1351
    };
1352
  };
1353
 
1354
  if (ignore_zero) {
1355
    flptnos[f].exp = 0;
1356
    flptnos[f].sign = 0;
1357
  }
1358
  else {
1359
    flptnos[f].exp = exponent - 1;
1360
    flptnos[f].sign = (sign ? -1 : 1);
1361
  };
1362
 
1363
  if (flptnos[f].exp > target_dbl_maxexp)
1364
    failer (BIG_FLPT);
1365
 
1366
  return (getexp (f_floating(fv), nilexp, 0, nilexp, nilexp,
1367
             0, f, real_tag));
1368
 
1369
}
1370
 
1371
#else
1372
 
1373
exp f_make_floating
1374
    PROTO_N ( (fv, rm, sign, mantissa, natbase, expo) )
1375
    PROTO_T ( floating_variety fv X rounding_mode rm X bool sign X string mantissa X nat natbase X signed_nat expo )
1376
{
1377
  int ignore_zero = 1;
1378
  int lg = mantissa.number;
1379
  flpt f = new_flpt ();
1380
  int  has_sig_digs = 0;
1381
  int  i;
1382
  int point = 0;
1383
  int exponent = snatint(expo);
1384
  flt fr;
1385
  int base = natint(natbase);
1386
 
1387
 
1388
  flt_zero(&fr);
1389
 
1390
  if (PIC_code)
1391
    proc_externs = 1;
1392
 
1393
  if (base != 10 && base != 16 && base !=8 && base != 2 && base != 4)
1394
    failer (BAD_BASE);
1395
 
1396
  if (snatneg(expo))
1397
    exponent = - exponent;
1398
 
1399
  for (i = 0; i < lg; ++i) {
1400
    char c = mantissa.ints.chars[i];
1401
    if (c != '0' || !ignore_zero) {
1402
      ignore_zero = 0;
1403
      if (c == '.')
1404
	point = 1;
1405
      else {
1406
	c = c - '0';
1407
	if (c != 0)
1408
	  has_sig_digs = 1;
1409
        exponent -= point;
1410
	flpt_newdig((unsigned int)c, &fr, base);
1411
      };
1412
    };
1413
  };
1414
 
1415
  if (ignore_zero) {
1416
    fr.exp = 0;
1417
    fr.sign = 0;
1418
  }
1419
  else {
1420
    if (has_sig_digs)
1421
      fr.sign = (sign ? -1 : 1);
1422
    else
1423
      fr.sign = 0;
1424
    flpt_scale(exponent, &fr, base);
1425
  };
1426
 
1427
 
1428
  flpt_round((int)rm, flpt_bits((floating_variety)fv), &fr);
1429
 
1430
  if (flpt_const_overflow_fail) {
1431
    r2l r;
1432
    r = real2longs_IEEE(&fr, fv);
1433
    UNUSED(r);
1434
  };
1435
 
1436
  flptnos[f] = fr;
1437
 
1438
  return (getexp (f_floating(fv), nilexp, 0, nilexp, nilexp,
1439
             0, f, real_tag));
1440
 
1441
}
1442
 
1443
#endif
1444
 
1445
 
1446
 
1447
exp f_power
1448
    PROTO_N ( (ov_err, arg1, arg2) )
1449
    PROTO_T ( error_treatment ov_err X exp arg1 X exp arg2 )
1450
{
1451
  if (name(sh(arg1)) == bothd)
1452
    { kill_exp(arg2,arg2); return arg1; }
1453
  if (name(sh(arg2)) == bothd)
1454
    { kill_exp(arg1,arg1); return arg2; }
1455
#if check_shape
1456
  if (!is_integer(sh(arg1)) || !is_integer(sh(arg2)))
1457
    failer(CHSH_POWER);
1458
#endif
1459
 
1460
  return  real_power(ov_err, arg1, arg2);
1461
}
1462
 
1463
 
1464
exp f_round_with_mode
1465
    PROTO_N ( (flpt_err, mode, r, arg1) )
1466
    PROTO_T ( error_treatment flpt_err X rounding_mode mode X variety r X exp arg1 )
1467
{
1468
  exp res;
1469
  if (name(sh(arg1)) == bothd)
1470
    return arg1;
1471
  if (is_complex(sh(arg1))) {
1472
	arg1 = f_real_part(arg1);
1473
  }
1474
#if check_shape
1475
  if (!is_float(sh(arg1)))
1476
    failer(CHSH_ROUND);
1477
#endif
1478
#if !has64bits
1479
	if ( shape_size(r)>32 && (name(arg1) != real_tag || flpt_err.err_code>=4)   ) {
1480
		int s = is_signed(r);
1481
		char * fn;
1482
		exp e;
1483
#if use_long_double
1484
	        arg1 = hold_check(
1485
		  f_change_floating_variety(f_impossible, 2, arg1));
1486
#else
1487
	        arg1 = hold_check(
1488
		  f_change_floating_variety(f_impossible, 1, arg1));
1489
#endif
1490
		switch(mode) {
1491
		case R2NEAR: fn = (s)?"__TDFUs_R2NEAR":"__TDFUu_R2NEAR"; break;
1492
		case R2PINF: fn = (s)?"__TDFUs_R2PINF":"__TDFUu_R2PINF"; break;
1493
		case R2NINF: fn = (s)?"__TDFUs_R2NINF":"__TDFUu_R2NINF"; break;
1494
		case R2ZERO: fn = (s)?"__TDFUs_R2ZERO":"__TDFUu_R2ZERO"; break;
1495
		default: fn = (s)?"__TDFUs_ASSTATE":"__TDFUu_R2ASSTATE";
1496
		}
1497
		e = TDFcallaux(flpt_err, arg1, fn, r);
1498
		return (hold_check(e));
1499
	}
1500
#endif
1501
#if ismips
1502
	/* mips does not seem to get float->unsigned long right -
1503
		so convert to signed long and adjust if too big*/
1504
	else
1505
	if (name(arg1)!=real_tag && shape_size(r)==32 && !is_signed(r) ) {
1506
		floating_variety fa = (shape_size(sh(arg1))==32)?0:1;
1507
		exp_list st;
1508
		exp z;
1509
		exp d1 = me_startid(r, arg1, 0);
1510
		exp hldr = getexp(f_top, nilexp, 0, nilexp, nilexp, 0, 0, 0);
1511
		exp lb = getexp(f_top, nilexp, 0, hldr, nilexp, 0, 0, labst_tag);
1512
 
1513
		exp fmax = hold_check(f_float_int(f_impossible, fa,
1514
					me_shint(ulongsh,0x80000000 )));
1515
		exp d2 = me_startid(r, fmax, 0);
1516
		exp tst =  f_floating_test(no_nat_option,
1517
				f_impossible, f_less_than, &lb,
1518
				me_obtain(d1), me_obtain(d2));
1519
		exp nconv = f_round_with_mode(flpt_err, mode, slongsh,
1520
					me_obtain(d1));
1521
		exp first; exp alt; exp cnd;
1522
		st = new_exp_list(1);
1523
		st = add_exp_list(st, tst, 0);
1524
		first = f_sequence(st, f_change_variety(flpt_err, r, nconv));
1525
		z = f_round_with_mode(flpt_err, mode, slongsh,
1526
			f_floating_minus(f_impossible, me_obtain(d1), me_obtain(d2)));
1527
		alt = f_plus(f_impossible,
1528
		   f_change_variety(f_impossible, r, z), me_shint(r, 0x80000000));
1529
		cnd = f_conditional(&lb, first, alt);
1530
		return me_complete_id(d1, me_complete_id(d2, cnd));
1531
 
1532
	}
1533
#endif
1534
#if ispower
1535
 if (name(arg1)!=real_tag || flpt_err.err_code>2) {
1536
  if (architecture!=POWERPC_CODE)
1537
  {
1538
    exp id;
1539
    exp apply1;
1540
    exp apply2;
1541
    long shp_sze = shape_size(f_integer(r));
1542
    bool sgned = is_signed(f_integer(r));
1543
    bool err = (flpt_err.err_code>2);
1544
    char *nm ;
1545
    char *nm_err;
1546
    int power_mode;
1547
 
1548
    /* Set up ident to hold arg1 */
1549
    if (name(sh(arg1))==shrealhd)
1550
    {
1551
      arg1 = f_change_floating_variety(f_impossible,realfv,arg1);
1552
    }
1553
    id = me_startid(f_top,arg1,0);
1554
 
1555
  /* Set up power_mode */
1556
    switch (mode)
1557
    {
1558
 
1559
      case R2ZERO: power_mode = 0;break;
1560
      case R2NEAR: power_mode = 1;break;
1561
      case R2PINF: power_mode = 2;break;
1562
      case R2NINF: power_mode = 3;break;
1563
      default:power_mode = 1;break;
1564
    }
1565
 
1566
    /* Work out which functions to call */
1567
    if (sgned)
1568
    {
1569
      nm = "__TDFrnd_sgned";
1570
      nm_err = "__TDFerr_rnd_sgned";
1571
    }
1572
    else
1573
    {
1574
      nm = "__TDFrnd_unsgned";
1575
      nm_err = "__TDFerr_rnd_unsgned";
1576
    }
1577
 
1578
    {
1579
      exp_list pars2;
1580
      exp_option no_var ;
1581
      pars2 = new_exp_list(2);
1582
      no_var.present = 0;
1583
      pars2 = add_exp_list(pars2,me_obtain(id),0);
1584
      pars2 = add_exp_list(pars2,me_shint(uwordsh,power_mode),1);
1585
      apply2 = f_apply_proc(sgned?slongsh:ulongsh,me_obtain(find_named_tg(nm,f_proc)),pars2,no_var);
1586
    }
1587
 
1588
    if (err)
1589
    {
1590
      exp_list st;
1591
      exp seq;
1592
      exp pl;
1593
      exp_list pars1;
1594
      exp_option no_var;
1595
      no_var.present = 0;
1596
 
1597
      pars1 = new_exp_list(2);
1598
      pars1 = add_exp_list(pars1,me_obtain(id),0);
1599
      pars1 = add_exp_list(pars1,me_shint(uwordsh,power_mode),1);
1600
      apply1 = f_apply_proc(f_top,me_obtain(find_named_tg(nm_err,f_proc)),pars1,no_var);
1601
 
1602
      pl = f_plus(flpt_err,me_shint(slongsh,INT_MAX),me_obtain(find_named_tg("__TDFrnd_error",slongsh)));
1603
      st = new_exp_list(2);
1604
      st = add_exp_list(st,apply1,0);
1605
      st = add_exp_list(st,pl,1);
1606
      seq = f_sequence(st,apply2);
1607
      id = me_complete_id(id,seq);
1608
    }
1609
    else
1610
    {
1611
      id = me_complete_id(id,apply2);
1612
    }
1613
    if (shp_sze <32)
1614
    {
1615
      id = f_change_variety(flpt_err,f_integer(r),id);
1616
    }
1617
    return id;
1618
  }/*end ispower */
1619
 }
1620
  /* FALL THROUGH */
1621
#endif
1622
 
1623
  res = getexp (f_integer(r), nilexp, 0, arg1, nilexp,
1624
           0, 0, round_tag);
1625
  setround_number(res, mode);
1626
  seterrhandle(res, flpt_err.err_code);
1627
  if (flpt_err.err_code ==  4)
1628
    setjmp_dest(res, get_lab(flpt_err.jmp_dest));
1629
  setfather (res, arg1);
1630
  return res;
1631
}
1632
 
1633
 
1634
 
1635
floating_variety f_flvar_parms
1636
    PROTO_N ( (base, mantissa_digits, minimum_exponent, maximum_exponent) )
1637
    PROTO_T ( nat base X nat mantissa_digits X nat minimum_exponent X nat maximum_exponent )
1638
{
1639
  int b = natint(base);
1640
  int mantdig = natint(mantissa_digits);
1641
  int neg_minexp = natint(minimum_exponent);
1642
  int maxexp = natint(maximum_exponent);
1643
 
1644
  while (b !=2) {
1645
	if ((b & 1) != 0) {
1646
		failer("base in flvar_parms must be a power of 2");
1647
	}
1648
	mantdig+=mantdig;
1649
	neg_minexp+=neg_minexp;
1650
	maxexp+=maxexp;
1651
	b = (b>>1);
1652
  }
1653
 
1654
	if (mantdig <= 24 && neg_minexp <= 126 &&
1655
                 maxexp <= 127)
1656
	  return (0);
1657
	if (mantdig <= 53 && neg_minexp <= 1022 &&
1658
                 maxexp <= 1023)
1659
	  return (1);
1660
 
1661
#if use_long_double
1662
	if (mantdig <= 64 && neg_minexp <= 16382 &&
1663
                 maxexp <= 16383)
1664
	  return (2);
1665
	return (2);
1666
#else
1667
        return 1;
1668
#endif
1669
}
1670
 
1671
 
1672
floating_variety f_complex_parms
1673
    PROTO_N ( (base, mantissa_digits, minimum_exponent, maximum_exponent) )
1674
    PROTO_T ( nat base X nat mantissa_digits X nat minimum_exponent X nat maximum_exponent )
1675
{
1676
  return float_to_complex_var(f_flvar_parms(base, mantissa_digits,
1677
			 minimum_exponent, maximum_exponent));
1678
}
1679
 
1680
 
1681
void init_floating_variety
1682
    PROTO_Z ()
1683
{
1684
  shrealsh = getshape(0, const_al1, const_al1, SHREAL_ALIGN,
1685
			 SHREAL_SZ, shrealhd);
1686
  realsh = getshape(0, const_al1, const_al1, REAL_ALIGN, REAL_SZ, realhd);
1687
  doublesh = getshape(0, const_al1, const_al1, DOUBLE_ALIGN,
1688
			 DOUBLE_SZ, doublehd);
1689
#if substitute_complex
1690
  shcomplexsh = getshape(0, const_al1, const_al1, SHREAL_ALIGN,
1691
			 2*SHREAL_SZ, cpdhd);
1692
  complexsh = getshape(0, const_al1, const_al1, REAL_ALIGN,
1693
			 2*REAL_SZ, cpdhd);
1694
  complexdoublesh = getshape(0, const_al1, const_al1, DOUBLE_ALIGN,
1695
			 2*DOUBLE_SZ, cpdhd);
1696
#else
1697
  shcomplexsh = getshape(0, const_al1, const_al1, SHREAL_ALIGN,
1698
			 2*SHREAL_SZ, shcomplexhd);
1699
  complexsh = getshape(0, const_al1, const_al1, REAL_ALIGN,
1700
			 2*REAL_SZ, complexhd);
1701
  complexdoublesh = getshape(0, const_al1, const_al1, DOUBLE_ALIGN,
1702
			 2*DOUBLE_SZ, complexdoublehd);
1703
#endif
1704
  return;
1705
}
1706
 
1707
 
1708
 
1709
floating_variety f_dummy_floating_variety;
1710
 
1711
floating_variety f_float_of_complex
1712
    PROTO_N ( (sha) )
1713
    PROTO_T ( shape sha )
1714
{
1715
	int s = shape_size(sha)/2;
1716
	if (s==SHREAL_SZ) return shrealfv;
1717
	if (s==REAL_SZ) return realfv;
1718
	if (s==DOUBLE_SZ) return doublefv;
1719
	failer("Expecting a complex shape");
1720
 
1721
	return f_dummy_floating_variety;
1722
}
1723
 
1724
floating_variety f_complex_of_float
1725
    PROTO_N ( (sha) )
1726
    PROTO_T ( shape sha )
1727
{
1728
	int s = shape_size(sha);
1729
	if (s==SHREAL_SZ) return shcomplexfv;
1730
	if (s==REAL_SZ) return complexfv;
1731
	if (s==DOUBLE_SZ) return complexdoublefv;
1732
	failer("Expecting a floating shape");
1733
	return f_dummy_floating_variety;
1734
}
1735
 
1736
floating_variety fv_of_shape
1737
    PROTO_N ( (sha) )
1738
    PROTO_T ( shape sha )
1739
{
1740
	int s = shape_size(sha);
1741
	if (s==SHREAL_SZ) return shrealfv;
1742
	if (s==REAL_SZ) return realfv;
1743
	if (s==DOUBLE_SZ) return doublefv;
1744
	failer("Expecting a complex shape");
1745
 
1746
	return f_dummy_floating_variety;
1747
}
1748
 
1749
 
1750
 
1751
static void square_x_iy
1752
    PROTO_N ( (ov_err, arg1, arg2, arg3) )
1753
    PROTO_T ( error_treatment ov_err X exp *arg1 X exp *arg2 X exp arg3 )
1754
{
1755
    exp x = *arg1;
1756
    exp y = *arg2;
1757
 
1758
    exp obtain1_x = me_obtain(x);
1759
    exp obtain2_x = me_obtain(x);
1760
    exp obtain3_x = me_obtain(x);
1761
    exp obtain1_y = me_obtain(y);
1762
    exp obtain2_y = me_obtain(y);
1763
    exp obtain3_y = me_obtain(y);
1764
 
1765
    exp minus_x_y = f_floating_minus(ov_err, obtain1_x, obtain1_y);
1766
    exp  plus_x_y = f_bin_floating_plus(ov_err, obtain2_x, obtain2_y);
1767
    exp  mult_x_y = f_bin_floating_mult(ov_err, obtain3_x, obtain3_y);
1768
 
1769
    exp tmp = push(arg3, me_startid(sh(x), mult_x_y, 0));
1770
 
1771
    exp obtain1_tmp = hold_check(me_obtain(tmp));
1772
    exp obtain2_tmp = hold_check(me_obtain(tmp));
1773
 
1774
    exp answer_re  = f_bin_floating_mult(ov_err, minus_x_y, plus_x_y);
1775
    exp answer_im  = f_bin_floating_plus(ov_err, obtain1_tmp, obtain2_tmp);
1776
 
1777
    x = push(tmp, me_startid(sh(x), answer_re, 0));
1778
    y = push(x, me_startid(sh(x), answer_im, 0));
1779
 
1780
    *arg1 = x;
1781
    *arg2 = y;
1782
 
1783
    return;
1784
}
1785
 
1786
 
1787
static void mult_w_by_z
1788
    PROTO_N ( (ov_err, arg1, arg2, arg3, arg4, arg5) )
1789
    PROTO_T ( error_treatment ov_err X exp *arg1 X exp *arg2 X exp arg3 X exp arg4 X exp arg5 )
1790
{
1791
    exp u = *arg1;
1792
    exp v = *arg2;
1793
    exp x =  arg3;
1794
    exp y =  arg4;
1795
 
1796
    exp obtain1_x = me_obtain(x);
1797
    exp obtain2_x = me_obtain(x);
1798
    exp obtain1_y = me_obtain(y);
1799
    exp obtain2_y = me_obtain(y);
1800
 
1801
    exp obtain1_u = me_obtain(u);
1802
    exp obtain2_u = me_obtain(u);
1803
    exp obtain1_v = me_obtain(v);
1804
    exp obtain2_v = me_obtain(v);
1805
 
1806
    exp mult_x_u = f_bin_floating_mult(ov_err, obtain1_x, obtain1_u);
1807
    exp mult_x_v = f_bin_floating_mult(ov_err, obtain2_x, obtain1_v);
1808
    exp mult_y_u = f_bin_floating_mult(ov_err, obtain1_y, obtain2_u);
1809
    exp mult_y_v = f_bin_floating_mult(ov_err, obtain2_y, obtain2_v);
1810
 
1811
    exp tmp = push(arg5, me_startid(sh(x), mult_y_u, 0));
1812
    exp obtain_tmp = hold_check(me_obtain(tmp));
1813
 
1814
    exp answer_re  = f_floating_minus(ov_err, mult_x_u, mult_y_v);
1815
    exp answer_im  = f_bin_floating_plus(ov_err, mult_x_v, obtain_tmp);
1816
 
1817
    u = push(tmp, me_startid(sh(x), answer_re, 0));
1818
    v = push(u, me_startid(sh(x), answer_im, 0));
1819
 
1820
    *arg1 = u;
1821
    *arg2 = v;
1822
 
1823
    return;
1824
}
1825
 
1826
 
1827
static exp make_comp_1_z
1828
    PROTO_N ( (complex_fv, ov_err, contents1_u, contents2_u, contents3_u,
1829
	       contents1_v, contents2_v, contents3_v) )
1830
    PROTO_T ( floating_variety complex_fv X error_treatment ov_err X
1831
	      exp contents1_u X exp contents2_u X exp contents3_u X
1832
	      exp contents1_v X exp contents2_v X exp contents3_v )
1833
{
1834
    exp mult_u_u    = f_bin_floating_mult(ov_err, contents1_u, contents2_u);
1835
    exp mult_v_v    = f_bin_floating_mult(ov_err, contents1_v, contents2_v);
1836
    exp mod_squared = f_bin_floating_plus(ov_err, mult_u_u, mult_v_v);
1837
    exp mod_sq      = me_startid(sh(contents1_u), mod_squared, 0);
1838
 
1839
    exp obtain1_mod_sq = me_obtain(mod_sq);
1840
    exp obtain2_mod_sq = me_obtain(mod_sq);
1841
 
1842
    exp v_div_mod_sq = f_floating_div(ov_err, contents3_v, obtain2_mod_sq);
1843
 
1844
    exp answer_re = f_floating_div(ov_err, contents3_u, obtain1_mod_sq);
1845
    exp answer_im = f_floating_negate(ov_err, v_div_mod_sq);
1846
 
1847
    exp make_comp = f_make_complex(complex_fv, answer_re, answer_im);
1848
    return  me_complete_id(mod_sq, make_comp);
1849
}
1850
 
1851
 
1852
#define is_const(X)  (name(X) != ident_tag)
1853
 
1854
exp_list reorder_list
1855
    PROTO_N ( (arg1, consts_first) )
1856
    PROTO_T ( exp_list arg1 X int consts_first )
1857
{
1858
    exp type1_start, type1_end, type2_start, type2_end, t;
1859
 
1860
    type1_start = type1_end = type2_start = type2_end = nilexp;
1861
    setbro(arg1.end, nilexp);
1862
    for (t = arg1.start; t != arg1.end; t=bro(t)) {
1863
	if ((is_const(t) && consts_first) || !(is_const(t) || consts_first)) {
1864
	    if (type1_start == nilexp) {
1865
		type1_start = type1_end = t;                          /* first of type 1 */
1866
	    } else {
1867
		setbro(type1_end, t);                        /* add to existing type 1's */
1868
		type1_end = t;
1869
	    }
1870
	} else {
1871
	    if (type2_start == nilexp) {
1872
		type2_start = type2_end = t;                          /* first of type 2 */
1873
	    } else {
1874
		setbro(type2_end, t);                        /* add to existing type 2's */
1875
		type2_end = t;
1876
	    }
1877
	}
1878
    }
1879
 
1880
    if ((type1_start != nilexp) && (type2_start != nilexp)) {
1881
	arg1.start = type1_start;
1882
        setbro(type1_end, type2_start);                      /* if list is not a mixture */
1883
	arg1.end = type2_end;                            /* no reordering has to be done */
1884
    }
1885
 
1886
    return arg1;
1887
}
1888
 
1889
 
1890
exp me_contents
1891
    PROTO_N ( (arg1) )
1892
    PROTO_T ( exp arg1 )
1893
{
1894
  exp r = me_u3(sh(arg1), me_obtain(arg1), cont_tag);
1895
 
1896
  return hold_check(r);
1897
}
1898
 
1899
 
1900
 
1901
  /* Used in conjunction with the function "me_complete_chain",
1902
     this function is used to push "ident_tag" declarations
1903
     onto a "stack" so that they can be linked up later.  It is
1904
     used in loops where the number of "ident_tag"s is unknown
1905
     and they need to be bound together in a "first-used last-
1906
     bound" order - hence the stack.
1907
 
1908
     arg1 is the new element
1909
     arg2 is the top element on the stack
1910
 */
1911
 
1912
static exp push
1913
    PROTO_N ( (arg1, arg2) )
1914
    PROTO_T ( exp arg1 X exp arg2 )
1915
{
1916
    setbro(arg2, arg1);
1917
    return arg2;
1918
}
1919
 
1920
 
1921
  /* Take the stack full of "ident_tag" declarations and link them
1922
     together with the last element in the list being "last_link"
1923
     and the body around which the declarations are put be "link_to".
1924
  */
1925
 
1926
static exp me_complete_chain
1927
    PROTO_N ( (ident_chain, last_link, link_to) )
1928
    PROTO_T ( exp ident_chain X exp last_link X exp link_to )
1929
{
1930
    exp remove_link;
1931
 
1932
    while (son(ident_chain) != last_link) {
1933
	remove_link = bro(ident_chain);
1934
	link_to = me_complete_id(ident_chain, link_to);
1935
	ident_chain = remove_link;
1936
    };
1937
 
1938
    return me_complete_id(ident_chain, link_to);
1939
}
1940
 
1941
 
1942
 
1943
/* Binary version of 'f_floating_plus' */
1944
 
1945
static exp f_bin_floating_plus
1946
    PROTO_N ( (ov_err, arg1, arg2) )
1947
    PROTO_T ( error_treatment ov_err X exp arg1 X exp arg2 )
1948
{
1949
  exp_list el;
1950
  el = new_exp_list(2);
1951
  el = add_exp_list(el, arg1, 0);
1952
  el = add_exp_list(el, arg2, 1);
1953
  return f_floating_plus (ov_err,el);
1954
}
1955
 
1956
 
1957
/* Binary version of 'f_floating_mult' */
1958
 
1959
static exp f_bin_floating_mult
1960
    PROTO_N ( (ov_err, arg1, arg2) )
1961
    PROTO_T ( error_treatment ov_err X exp arg1 X exp arg2 )
1962
{
1963
  exp_list el;
1964
  el = new_exp_list(2);
1965
  el = add_exp_list(el, arg1, 0);
1966
  el = add_exp_list(el, arg2, 1);
1967
  return f_floating_mult (ov_err,el);
1968
}
1969
 
1970
static exp optimise_with_wrap
1971
    PROTO_N ( (arg, shape1, shape2) )
1972
    PROTO_T ( exp arg X shape shape1 X shape shape2 )
1973
{
1974
  if (! eq_shape(shape1,shape2))
1975
    return  f_change_variety (f_wrap, shape2, arg);
1976
 
1977
  return (arg);
1978
}
1979
 
1980
static exp real_power
1981
    PROTO_N ( (ov_err, arg1, arg2) )
1982
    PROTO_T ( error_treatment ov_err X exp arg1 X exp arg2 )
1983
{
1984
 
1985
    /* Gives shorter .s file if n<10 and arg1 is unknown */
1986
 
1987
    exp real1, sn;
1988
    exp (*f_real_mult) PROTO_S ((error_treatment, exp, exp));
1989
    shape real_shape, integer_shape, tmp_shape;
1990
 
1991
 
1992
/* With wrap, we may as well work with 'int's and change back after */
1993
 
1994
    tmp_shape = sh(arg1);
1995
    if (is_integer(tmp_shape) && !is_signed(tmp_shape) &&
1996
	shape_size(sh(arg1)) < 32 &&
1997
	eq_et(ov_err, f_wrap))
1998
    {
1999
	arg1 = hold_check (f_change_variety (f_impossible, ulongsh, arg1));
2000
    }
2001
 
2002
 
2003
/* Widen to 'int' if necessary - guarantees negate will work */
2004
 
2005
    if (shape_size(sh(arg2)) < 32) {
2006
	arg2 = hold_check (f_change_variety (f_impossible, slongsh, arg2));
2007
    }
2008
 
2009
    real_shape = sh(arg1);                       /* shape of the result */
2010
    integer_shape = sh(arg2);
2011
    sn = me_startid(integer_shape, arg2, 0);
2012
 
2013
 
2014
/* Identify an exp which represents the value 1 (or 1.0) */
2015
 
2016
    if (is_integer(real_shape)) {
2017
	real1 = me_shint(real_shape,1);
2018
    }
2019
    else {
2020
	real1 = me_shint(integer_shape,1);
2021
	real1 = f_float_int (f_impossible, fv_of_shape(real_shape), real1);
2022
	real1 = hold_check (real1);		/* This should be reduced to 1.0 */
2023
    }
2024
    real1 = push (sn, me_startid(real_shape, real1, 0));
2025
 
2026
 
2027
/* Decide which is the suitable function for multiplying two numbers */
2028
 
2029
    f_real_mult = (is_integer(real_shape) ? f_mult : f_bin_floating_mult);
2030
 
2031
    if (is_constant_arg(arg2) ||
2032
	((name(arg2) == name_tag) && (name(son(arg2)) == ident_tag)
2033
	   && !isvar(son(arg2)) && is_constant_arg(son(son(arg2)))))
2034
    {                                                                /* we know the power */
2035
	int exponent;
2036
	exp x;
2037
 
2038
	if (is_constant_arg(arg2)) {
2039
	    exponent = no(arg2);	/* arg2 is a constant */
2040
	}
2041
	else {
2042
	    exponent = no(son(son(arg2)));
2043
		/* arg2 identifies a constant */
2044
	}
2045
 
2046
	if (exponent < 0) {
2047
	    if (is_integer(real_shape)) {
2048
		failer("constant value out of range: power: must be non-negative");
2049
	    }
2050
	    else {        	/* take reciprocal */
2051
		arg1 = hold_check (f_floating_div (ov_err, me_obtain(real1), arg1));
2052
	    }
2053
	}
2054
	x = push (real1, me_startid(real_shape, arg1, 0));
2055
 
2056
	if (exponent == 0) {
2057
	    return  me_complete_chain (x, arg2, optimise_with_wrap (
2058
			   me_obtain(real1), real_shape, tmp_shape));
2059
	}
2060
 
2061
	{
2062
	    exp  w, mylast = x;
2063
	    int n = abs(exponent);
2064
 
2065
	    while ((n % 2) == 0) {
2066
		exp mult_x_x;
2067
		mult_x_x = (*f_real_mult)(ov_err, me_obtain(x), me_obtain(x));
2068
		mylast = x = push (mylast,
2069
			 me_startid(real_shape, hold_check(mult_x_x), 0));
2070
		n = n / 2;
2071
	    }
2072
 
2073
	    if (n == 1) {
2074
		return  me_complete_chain (x, arg2, optimise_with_wrap (
2075
				me_obtain(x), real_shape, tmp_shape));        /* return x  */
2076
	    }
2077
	    else {                      	                             /*  w = x  */
2078
		mylast = w = push (x, me_startid(real_shape, me_obtain(x), 0));
2079
	    }
2080
 
2081
	    while (n != 1) {
2082
		exp mult_x_x;
2083
		mult_x_x = (*f_real_mult)(ov_err, me_obtain(x), me_obtain(x));
2084
		mylast = x = push (mylast,
2085
			me_startid(real_shape, hold_check(mult_x_x), 0));
2086
		n = n / 2;
2087
		if ((n % 2) == 1) {
2088
		    exp mult_w_x;
2089
		    mult_w_x = (*f_real_mult)(ov_err, me_obtain(w), me_obtain(x));
2090
		    mylast = w = push (mylast,
2091
			me_startid(real_shape, hold_check(mult_w_x), 0));
2092
		}
2093
	    }
2094
 
2095
	    return  me_complete_chain (w, arg2, optimise_with_wrap (
2096
				me_obtain(w), real_shape, tmp_shape));    /*  return w  */
2097
	}
2098
 
2099
    } else {
2100
 
2101
	exp  reinitialise_w, main_loop, make_comp;              /* main building blocks */
2102
	exp  square_x, mult_x_w, half_n, update_w, repeat_body;
2103
	exp  seq, w, x, n;
2104
 
2105
	n = me_obtain(sn);
2106
	if (!is_integer(real_shape)) {	/* Must be positive for integer powers */
2107
	    n = f_abs (f_impossible, n);
2108
	}
2109
 
2110
	n = push (real1, me_startid (integer_shape, n, 1));
2111
	w = push (n, me_startid(real_shape, me_obtain(real1), 1));
2112
	x = push (w, me_startid(real_shape, arg1, 1));
2113
 
2114
 
2115
	/*  change value of w to z if n is odd  */
2116
 
2117
	{
2118
	    exp rem_n_2 = f_and (me_contents(n), me_shint(integer_shape, 1));
2119
	    exp assign_w = f_assign (me_obtain(w), me_contents(x));
2120
	    exp alt_labst = hold_check(me_b3(f_top, f_make_value(f_top),
2121
					       f_make_top(), labst_tag));
2122
	    exp is_n_odd = f_integer_test (no_nat_option, f_equal, make_label(alt_labst),
2123
				rem_n_2, me_shint(integer_shape, 1));
2124
	    exp seq = f_sequence (add_exp_list(new_exp_list(1), is_n_odd, 0), assign_w);
2125
	    reinitialise_w = hold_check(me_b3(lub_shape(sh(seq),sh(alt_labst)),
2126
					      seq, alt_labst, cond_tag));
2127
	}
2128
 
2129
	/*  x=x*x  */
2130
	{
2131
	    exp mult_x_x;
2132
	    mult_x_x = (*f_real_mult) (ov_err, me_contents(x), me_contents(x));
2133
	    square_x = f_assign (me_obtain(x), mult_x_x);
2134
	}
2135
 
2136
	/*  w=x*w  */
2137
	{
2138
	    exp answer;
2139
	    answer = (*f_real_mult)(ov_err, me_contents(x), me_contents(w));
2140
	    mult_x_w = f_assign (me_obtain(w), answer);
2141
	}
2142
 
2143
	/*  n=n/2  */
2144
	{
2145
	    exp answer = f_shift_right (me_contents(n), me_shint(integer_shape, 1));
2146
	    half_n = f_assign (me_obtain(n), answer);
2147
	}
2148
 
2149
	/*  if n is odd then w = z*w  */
2150
	{
2151
	    exp rem_n_2 = f_and (me_contents(n), me_shint(integer_shape, 1));
2152
	    exp alt_labst = hold_check(me_b3(f_top, f_make_value(f_top),
2153
					     f_make_top(), labst_tag));
2154
	    exp is_n_odd = f_integer_test (no_nat_option, f_equal, make_label(alt_labst),
2155
					   rem_n_2, me_shint(integer_shape, 1));
2156
	    exp seq = f_sequence (add_exp_list(new_exp_list(1),
2157
					is_n_odd, 0), mult_x_w);
2158
	    update_w = hold_check(me_b3(lub_shape(sh(seq),sh(alt_labst)),
2159
					seq, alt_labst, cond_tag));
2160
	}
2161
 
2162
	/*  repeat + body  */
2163
	{
2164
	    exp body_labst, if_n_equals_1;
2165
	    exp_list st;
2166
 
2167
	    body_labst = hold_check(me_b3(f_top, f_make_value(f_top), f_make_top(), labst_tag));
2168
 
2169
	    if_n_equals_1 = f_integer_test (no_nat_option, f_equal, make_label(body_labst),
2170
					    me_contents(n), me_shint(integer_shape, 1));
2171
 
2172
	    st = new_exp_list(1);
2173
	    st = add_exp_list(st, square_x, 0);
2174
	    st = add_exp_list(st, half_n, 1);
2175
	    st = add_exp_list(st, update_w, 2);
2176
	    seq = f_sequence (st, if_n_equals_1);
2177
 
2178
	    setbro (son(body_labst), seq);
2179
	    setsh (body_labst, sh (seq));                    /*  put seq into the body  */
2180
	    clearlast (son(body_labst));                     /*  of the labst           */
2181
	    setfather (body_labst, seq);
2182
 
2183
	    repeat_body = hold_check(me_b3(sh(body_labst), f_make_top(), body_labst, rep_tag));
2184
	    note_repeat(repeat_body);
2185
	}
2186
 
2187
	/*  make loop - only done if  mod(n) > 1  */
2188
	{
2189
	    exp alt_labst = hold_check(me_b3(f_top, f_make_value(f_top),
2190
					   f_make_top(), labst_tag));
2191
	    exp is_n_gt_1 = f_integer_test (no_nat_option, f_greater_than, make_label(alt_labst),
2192
					    me_contents(n), me_shint(integer_shape, 1));
2193
	    exp seq = f_sequence (add_exp_list(new_exp_list(1),
2194
					 is_n_gt_1, 0), repeat_body);
2195
	    main_loop = hold_check(me_b3(lub_shape(sh(seq),sh(alt_labst)),
2196
					 seq, alt_labst, cond_tag));
2197
	}
2198
 
2199
	if (is_integer(real_shape)) {
2200
	    make_comp = me_contents(w);
2201
	}
2202
	else {
2203
	    exp make_comp2 = f_floating_div(ov_err, me_obtain(real1), me_contents(w));
2204
	    exp alt_labst = hold_check(me_b3(real_shape, f_make_value(f_top),
2205
					     make_comp2, labst_tag));
2206
	    exp is_arg2_positive = f_integer_test (no_nat_option, f_greater_than_or_equal,
2207
					       make_label(alt_labst), me_obtain(sn),
2208
					       me_shint(integer_shape, 0));
2209
	    exp seq = f_sequence (add_exp_list(new_exp_list(1),
2210
			       	is_arg2_positive, 0), me_contents(w));
2211
 
2212
	    make_comp = hold_check(me_b3(lub_shape(sh(seq),sh(alt_labst)),
2213
					 seq, alt_labst, cond_tag));
2214
	}
2215
 
2216
	seq = f_sequence (add_exp_list (add_exp_list(new_exp_list(1),
2217
				reinitialise_w, 0), main_loop, 1), make_comp);
2218
	seq = optimise_with_wrap (seq, real_shape, tmp_shape);
2219
	return  me_complete_chain(x, arg2, seq);
2220
    }
2221
}