1 /*
2     This file is part of GNU APL, a free implementation of the
3     ISO/IEC Standard 13751, "Programming Language APL, Extended"
4 
5     Copyright (C) 2008-2015  Dr. Jürgen Sauermann
6 
7     This program is free software: you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation, either version 3 of the License, or
10     (at your option) any later version.
11 
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16 
17     You should have received a copy of the GNU General Public License
18     along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #include <stdio.h>
22 #include <string.h>
23 #include <math.h>
24 
25 #include <complex>
26 
27 #include "Common.hh"
28 #include "ComplexCell.hh"
29 #include "Error.hh"
30 #include "FloatCell.hh"
31 #include "IntCell.hh"
32 #include "UTF8_string.hh"
33 #include "Workspace.hh"
34 
35 #include "Cell.icc"
36 #include "Value.hh"
37 
38 //-----------------------------------------------------------------------------
39 bool
equal(const Cell & A,double qct) const40 FloatCell::equal(const Cell & A, double qct) const
41 {
42    if (!A.is_numeric())       return false;
43    if (A.is_complex_cell())   return A.equal(*this, qct);
44    return tolerantly_equal(A.get_real_value(), get_real_value(), qct);
45 }
46 //-----------------------------------------------------------------------------
47 bool
greater(const Cell & other) const48 FloatCell::greater(const Cell & other) const
49 {
50 const APL_Float this_val  = get_real_value();
51 
52    switch(other.get_cell_type())
53       {
54         case CT_INT:
55              {
56                const APL_Float other_val(other.get_int_value());
57                if (this_val == other_val)   return this > &other;
58                return this_val > other_val;
59              }
60 
61         case CT_FLOAT:
62              {
63                const APL_Float other_val = other.get_real_value();
64                if (this_val == other_val)   return this > &other;
65                return this_val > other_val;
66              }
67 
68         case CT_CHAR:    return true;
69         case CT_COMPLEX: break;
70         case CT_POINTER: return false;
71         case CT_CELLREF: DOMAIN_ERROR;
72         default:         Assert(0 && "Bad celltype");
73       }
74 
75 const Comp_result comp = compare(other);
76    if (comp == COMP_EQ)   return this > &other;
77    return (comp == COMP_GT);
78 }
79 //-----------------------------------------------------------------------------
80 bool
get_near_bool() const81 FloatCell::get_near_bool()  const
82 {
83    if (dfval() > INTEGER_TOLERANCE)   // maybe 1
84       {
85         if (dfval() > (1.0 + INTEGER_TOLERANCE))   DOMAIN_ERROR;
86         if (dfval() < (1.0 - INTEGER_TOLERANCE))   DOMAIN_ERROR;
87         return true;
88       }
89 
90    // maybe 0. We already know that dfval() ≤ qct
91    //
92    if (dfval() < -INTEGER_TOLERANCE)   DOMAIN_ERROR;
93    return false;
94 }
95 //-----------------------------------------------------------------------------
96 Comp_result
compare(const Cell & other) const97 FloatCell::compare(const Cell & other) const
98 {
99    if (other.is_integer_cell())   // integer
100       {
101         const double qct = Workspace::get_CT();
102         if (equal(other, qct))   return COMP_EQ;
103         return (dfval() <= other.get_int_value())  ? COMP_LT : COMP_GT;
104       }
105 
106    if (other.is_float_cell())
107       {
108         const double qct = Workspace::get_CT();
109         if (equal(other, qct))   return COMP_EQ;
110         return (dfval() <= other.get_real_value()) ? COMP_LT : COMP_GT;
111       }
112 
113    if (other.is_complex_cell())   return Comp_result(-other.compare(*this));
114 
115    DOMAIN_ERROR;
116 }
117 //-----------------------------------------------------------------------------
118 // monadic built-in functions...
119 //-----------------------------------------------------------------------------
120 ErrorCode
bif_near_int64_t(Cell * Z) const121 FloatCell::bif_near_int64_t(Cell * Z) const
122 {
123    if (!is_near_int64_t())       return E_DOMAIN_ERROR;
124 
125    return IntCell::zv(Z, get_near_int());
126 }
127 //-----------------------------------------------------------------------------
128 ErrorCode
bif_within_quad_CT(Cell * Z) const129 FloatCell::bif_within_quad_CT(Cell * Z) const
130 {
131 const double val = dfval();
132    if (val > LARGE_INT)   return E_DOMAIN_ERROR;
133    if (val < SMALL_INT)   return E_DOMAIN_ERROR;
134 
135 const double max_diff = Workspace::get_CT() * val;   // scale ⎕CT
136 
137 const APL_Float val_dn = floor(val);
138    if (val < (val_dn + max_diff))   return IntCell::zv(Z, val_dn);
139 
140 const APL_Float val_up = ceil(val);
141    if (val > (val_up - max_diff))   return IntCell::zv(Z, val_up);
142 
143    return E_DOMAIN_ERROR;
144 }
145 //-----------------------------------------------------------------------------
146 ErrorCode
bif_factorial(Cell * Z) const147 FloatCell::bif_factorial(Cell * Z) const
148 {
149    // max N! that fits into double is about 170
150    //
151    if (dfval() > 170.0)   return E_DOMAIN_ERROR;
152 
153 const APL_Float arg = dfval() + 1.0;
154    return FloatCell::zv(Z, tgamma(arg));
155 }
156 //-----------------------------------------------------------------------------
157 ErrorCode
bif_conjugate(Cell * Z) const158 FloatCell::bif_conjugate(Cell * Z) const
159 {
160    // convert quotients (if any) to double
161    return zv(Z, dfval());
162 }
163 //-----------------------------------------------------------------------------
164 ErrorCode
bif_negative(Cell * Z) const165 FloatCell::bif_negative(Cell * Z) const
166 {
167 #ifdef RATIONAL_NUMBERS_WANTED
168    if (const APL_Integer denom = get_denominator())
169       return zv(Z, -get_numerator(), denom);
170 #endif
171 
172    return zv(Z, - dfval());
173 }
174 //-----------------------------------------------------------------------------
175 ErrorCode
bif_direction(Cell * Z) const176 FloatCell::bif_direction(Cell * Z) const
177 {
178    // Note: bif_direction does NOT use ⎕CT
179    //
180 #ifdef RATIONAL_NUMBERS_WANTED
181    if (const APL_Integer denom = get_denominator())
182       {
183         if (get_numerator() > 0)   return IntCell::zv(Z,  1);
184         if (get_numerator() < 0)   return IntCell::zv(Z, -1);
185         return IntCell::zv(Z, 0);
186       }
187 #endif
188 
189    if (dfval() > 0.0)   return IntCell::zv(Z,  1);
190    if (dfval() < 0.0)   return IntCell::zv(Z, -1);
191    return IntCell::zv(Z, 0);
192 }
193 //-----------------------------------------------------------------------------
194 ErrorCode
bif_magnitude(Cell * Z) const195 FloatCell::bif_magnitude(Cell * Z) const
196 {
197 #ifdef RATIONAL_NUMBERS_WANTED
198    if (const APL_Integer denom = get_denominator())
199       {
200         const APL_Integer numer = get_numerator();
201         return FloatCell::zv(Z, numer < 0 ? -numer : numer, denom);
202       }
203 #endif
204 
205    if (dfval() < 0.0)   return FloatCell::zv(Z, -dfval());
206    else                return FloatCell::zv(Z, dfval());
207 }
208 //-----------------------------------------------------------------------------
209 ErrorCode
bif_reciprocal(Cell * Z) const210 FloatCell::bif_reciprocal(Cell * Z) const
211 {
212 #ifdef RATIONAL_NUMBERS_WANTED
213    if (const APL_Integer denom = get_denominator())
214       {
215         if (uint64_t(denom) < 0x8000000000000000ULL)   // small enough for int32
216            {
217              const APL_Integer numer = get_numerator();
218              // simply exchange numerator and denominator, but make sure that
219              // the denominator is positive
220              //
221              if (numer == 1)    return IntCell::zv(Z,  denom);
222              if (numer == -1)   return IntCell::zv(Z, -denom);
223              if (numer < 0)     return FloatCell::zv(Z, -denom, -numer);
224              else               return FloatCell::zv(Z, denom, numer);
225            }
226 
227         // at this point denom does not fit into numer. Fall through
228       }
229 #endif
230 
231 const APL_Float z = 1.0/dfval();
232    if (!isfinite(z))   return E_DOMAIN_ERROR;
233 
234    return FloatCell::zv(Z, 1.0/dfval());
235 }
236 //-----------------------------------------------------------------------------
237 ErrorCode
bif_roll(Cell * Z) const238 FloatCell::bif_roll(Cell * Z) const
239 {
240    if (!is_near_int())   return E_DOMAIN_ERROR;
241 
242 const APL_Integer set_size = get_checked_near_int();
243    if (set_size <= 0)   return E_DOMAIN_ERROR;
244 
245 const uint64_t rnd = Workspace::get_RL(set_size);
246    return IntCell::zv(Z, Workspace::get_IO() + (rnd % set_size));
247 }
248 //-----------------------------------------------------------------------------
249 ErrorCode
bif_pi_times(Cell * Z) const250 FloatCell::bif_pi_times(Cell * Z) const
251 {
252    return zv(Z, dfval() * M_PI);
253 }
254 //-----------------------------------------------------------------------------
255 ErrorCode
bif_pi_times_inverse(Cell * Z) const256 FloatCell::bif_pi_times_inverse(Cell * Z) const
257 {
258    return zv(Z, dfval() / M_PI);
259 }
260 //-----------------------------------------------------------------------------
261 ErrorCode
bif_ceiling(Cell * Z) const262 FloatCell::bif_ceiling(Cell * Z) const
263 {
264 #ifdef RATIONAL_NUMBERS_WANTED
265    if (const APL_Integer denom = get_denominator())
266       {
267         // since the quotient is exact, we ignore ⎕CT
268         //
269         const APL_Integer numer = get_numerator();
270         APL_Integer quotient = numer / denom;
271         if (numer > (quotient * denom))   ++quotient;
272         return IntCell::zv(Z, quotient);
273       }
274 #endif
275 
276    // see comments for bif_floor below.
277 
278 const APL_Float b = dfval();
279    // if b is large then return it as is.
280    //
281    if (b >= LARGE_INT)   return zv(Z, b);
282    if (b <= SMALL_INT)   return zv(Z, b);
283 
284 APL_Integer bi = b;
285    while (bi < b)         ++bi;
286    while ((bi - 1) > b)   --bi;
287    if (bi == b)   return IntCell::zv(Z, bi);   // b already equal to its floor
288 
289 const APL_Float D = bi - b;
290 
291    if (D >= (1.0 - Workspace::get_CT()))   --bi;
292    return IntCell::zv(Z, bi);
293 }
294 //-----------------------------------------------------------------------------
295 ErrorCode
bif_floor(Cell * Z) const296 FloatCell::bif_floor(Cell * Z) const
297 {
298 #ifdef RATIONAL_NUMBERS_WANTED
299    if (const APL_Integer denom = get_denominator())
300       {
301         // since the quotient is exact, we ignore ⎕CT
302         //
303         const APL_Integer numer = get_numerator();
304         APL_Integer quotient = numer / denom;
305         if (numer < (quotient * denom))   --quotient;
306         return IntCell::zv(Z, quotient);
307       }
308 #endif
309 
310 /* Informal description (iso p. 78):
311    For real-numbers, Z is the greatest integer tolerantly less than
312    or equal to B. Uses comparison-tolerance.
313 
314    Formal description:
315    Return the tolerant-floor of B within comparison-tolerance.
316 
317    tolerant-floor (p.19) is defined for complex A:
318    Let A be a member of the set of numbers in the unit-square at the
319    complex-integer C, and let D be A minus C.
320    If the sum of the real and imaginary parts of D is tolerantly-less-than
321    one within B, then Z is C.
322    Otherwise, if the imaginary-part of D is greater-than the real-part of D,
323    then Z is C plus imaginary-one.
324    Otherwise, Z is C plus one.
325 
326    Unfortunately tolerantly-less-than is not defined in the standard. We
327    interpret it as meaning 'less than and not tolerrantly-equal'.
328 
329    Replacing B with ⎕CT, and A with B, and considering that the imaginary
330    part of B is always 0 if B is real this becomes:
331 
332    tolerant-floor of (real) B within ⎕CT:
333    Let B be a member of the set of numbers in the hals-open interval [C, C+1),
334    and let D be B minus C.
335    If D is tolerantly-less-than one within ⎕CT, then Z is C.
336    Otherwise, Z is C plus one.
337 
338    In other word, Let RB be B rounded down. Then Z is RB if B < RB + 1 - ⎕CT
339    and RB+1 otherwise.
340 
341    Note: if B cannot fit into int64_t then, due to the smaller precision
342    of double, it is already equal to its floor and we return it unchanged.
343 */
344 
345 const APL_Float b = dfval();
346    // if b is large then return it as is.
347    //
348    if (b >= LARGE_INT)   return zv(Z, b);
349    if (b <= SMALL_INT)   return zv(Z, b);
350 
351 APL_Integer bi = b;
352    while (bi > b)         --bi;
353    while ((bi + 1) < b)   ++bi;
354    if (bi == b)   return IntCell::zv(Z, bi);   // b already equal to its floor
355 
356 const APL_Float D = b - bi;
357 
358    if (D >= (1.0 - Workspace::get_CT()))   ++bi;
359    return IntCell::zv(Z, bi);
360 }
361 //-----------------------------------------------------------------------------
362 ErrorCode
bif_exponential(Cell * Z) const363 FloatCell::bif_exponential(Cell * Z) const
364 {
365    // e to the B-th power
366    //
367    return FloatCell::zv(Z, exp(dfval()));
368 }
369 //-----------------------------------------------------------------------------
370 ErrorCode
bif_nat_log(Cell * Z) const371 FloatCell::bif_nat_log(Cell * Z) const
372 {
373 const APL_Float val = dfval();
374    if (val == 0.0)     return E_DOMAIN_ERROR;
375 
376    if (val > 0.0)   // real result
377       {
378         return FloatCell::zv(Z, log(val));
379       }
380 
381 const APL_Complex bb(val, 0);
382    return ComplexCell::zv(Z, log(bb));
383 }
384 //-----------------------------------------------------------------------------
385 // dyadic built-in functions...
386 //
387 // where possible a function with non-real A is delegated to the corresponding
388 // member function of A. For numeric cells that is the ComplexCell function
389 // and otherwise the default function (that returns E_DOMAIN_ERROR.
390 //
391 //-----------------------------------------------------------------------------
392 ErrorCode
bif_add(Cell * Z,const Cell * A) const393 FloatCell::bif_add(Cell * Z, const Cell * A) const
394 {
395    if (A->is_real_cell())
396       {
397 #ifdef RATIONAL_NUMBERS_WANTED
398    if (const APL_Integer denom_B = get_denominator())
399    if (const APL_Integer denom_A = A->get_denominator())
400       {
401         // both A and B are rational
402         //
403         if (Cell::prod_overflow(denom_A, denom_B))   goto big;
404 
405         // compute common denominator...
406         const APL_Integer gcd_AB   = gcd(denom_A, denom_B);
407         const APL_Integer mult_A  = denom_A / gcd_AB;
408         const APL_Integer mult_B  = denom_B / gcd_AB;
409         const APL_Integer denom_AB = denom_A * mult_B;
410         if (Cell::prod_overflow(denom_AB, mult_B))                goto big;
411 
412         // compute numerators...
413         const APL_Integer numer_A = A->get_numerator();
414         if (Cell::prod_overflow(numer_A, mult_B))                goto big;
415         const APL_Integer numer_A1 = numer_A * mult_B;
416         const APL_Integer numer_B = get_numerator();
417         if (Cell::prod_overflow(numer_B, mult_A))                goto big;
418         const APL_Integer numer_B1 = numer_B * mult_A;
419 
420         const APL_Integer sum_AB = numer_A1 + numer_B1;
421         if (Cell::sum_overflow(sum_AB, numer_A1, numer_B1))      goto big;
422         const APL_Integer sum_gcd = gcd(sum_AB, denom_AB);
423         if (sum_gcd == denom_AB)   return IntCell::zv(Z, sum_AB / denom_AB);
424         if (sum_gcd == 1)   return FloatCell::zv(Z, sum_AB, denom_AB);
425         return FloatCell::zv(Z, sum_AB/sum_gcd, denom_AB/sum_gcd);
426       }
427       big:
428 
429 #endif
430 
431         return FloatCell::zv(Z, A->get_real_value() + get_real_value());
432       }
433 
434    // delegate to A
435    //
436    return A->bif_add(Z, this);
437 }
438 //-----------------------------------------------------------------------------
439 ErrorCode
bif_add_inverse(Cell * Z,const Cell * A) const440 FloatCell::bif_add_inverse(Cell * Z, const Cell * A) const
441 {
442    return A->bif_subtract(Z, this);
443 }
444 //-----------------------------------------------------------------------------
445 ErrorCode
bif_subtract(Cell * Z,const Cell * A) const446 FloatCell::bif_subtract(Cell * Z, const Cell * A) const
447 {
448    if (A->is_real_cell())   // real result
449       {
450 #ifdef RATIONAL_NUMBERS_WANTED
451    if (const APL_Integer denom_B = get_denominator())
452    if (const APL_Integer denom_A = A->get_denominator())
453       {
454         // both A and B are rational
455         //
456         if (Cell::prod_overflow(denom_A, denom_B))   goto big;
457 
458         // compute common denominator...
459         const APL_Integer gcd_AB   = gcd(denom_A, denom_B);
460         const APL_Integer mult_A  = denom_A / gcd_AB;
461         const APL_Integer mult_B  = denom_B / gcd_AB;
462         const APL_Integer denom_AB = denom_A * mult_B;
463 
464         // compute numerators...
465         const APL_Integer numer_A = A->get_numerator();
466         if (Cell::prod_overflow(numer_A, mult_B))                goto big;
467         const APL_Integer numer_A1 = numer_A * mult_B;
468         const APL_Integer numer_B = get_numerator();
469         if (Cell::prod_overflow(numer_B, mult_A))                goto big;
470         const APL_Integer numer_B1 = numer_B * mult_A;
471 
472         const APL_Integer diff_AB = numer_A1 - numer_B1;
473         if (Cell::diff_overflow(diff_AB, numer_A1, numer_B1))    goto big;
474         const APL_Integer diff_gcd = gcd(diff_AB, denom_AB);
475         if (diff_gcd == denom_AB)   return IntCell::zv(Z, diff_AB / denom_AB);
476         if (diff_gcd == 1)   return FloatCell::zv(Z, diff_AB, denom_AB);
477         return FloatCell::zv(Z, diff_AB/diff_gcd, denom_AB/diff_gcd);
478       }
479       big:
480 
481 #endif
482 
483        return zv(Z, A->get_real_value() - get_real_value());
484       }
485 
486    if (A->is_complex_cell())   // complex result
487       {
488        return ComplexCell::zv(Z, A->get_real_value() - get_real_value(),
489                                  A->get_imag_value());
490       }
491 
492    return E_DOMAIN_ERROR;
493 }
494 //-----------------------------------------------------------------------------
495 ErrorCode
bif_multiply(Cell * Z,const Cell * A) const496 FloatCell::bif_multiply(Cell * Z, const Cell * A) const
497 {
498 #ifdef RATIONAL_NUMBERS_WANTED
499    if (APL_Integer denom_B = get_denominator())
500    if (APL_Integer denom_A = A->get_denominator())
501       {
502         // both A and B are rational
503         //
504         APL_Integer numer_A = A->get_numerator();
505         APL_Integer numer_B = get_numerator();
506         const APL_Integer gcd_A_B = gcd(numer_A, denom_B);
507          if (gcd_A_B > 1)   { numer_A /= gcd_A_B;   denom_B /= gcd_A_B; }
508 
509         const APL_Integer gcd_B_A = gcd(numer_B, denom_A);
510          if (gcd_B_A > 1)   { numer_B /= gcd_B_A;   denom_A /= gcd_B_A; }
511 
512         if (Cell::prod_overflow(numer_A, numer_B))   goto big;
513         if (Cell::prod_overflow(denom_A, denom_B))   goto big;
514 
515         const APL_Integer numer = numer_A * numer_B;
516         const APL_Integer denom = denom_A * denom_B;
517         const APL_Integer prod_gcd = gcd(numer, denom);
518         if (prod_gcd == denom)   return IntCell::zv(Z, numer / denom);
519         if (prod_gcd == 1)       return FloatCell::zv(Z, numer, denom);
520         return FloatCell::zv(Z, numer/prod_gcd, denom/prod_gcd);
521       }
522       big:
523 
524 #endif
525 
526    if (!A->is_numeric())   return E_DOMAIN_ERROR;
527 
528 const APL_Float ar = A->get_real_value();
529 const APL_Float ai = A->get_imag_value();
530 
531    if (ai == 0.0)   // real result
532       {
533         const APL_Float z = ar * dfval();
534         if (!isfinite(z))   return E_DOMAIN_ERROR;
535         return FloatCell::zv(Z, z);
536       }
537 
538    // complex result
539    //
540 const double zr = ar * dfval();
541 const double zi = ai * dfval();
542    if (!isfinite(zr))   return E_DOMAIN_ERROR;
543    if (!isfinite(zi))   return E_DOMAIN_ERROR;
544    return ComplexCell::zv(Z, zr, zi);
545 }
546 //-----------------------------------------------------------------------------
547 ErrorCode
bif_multiply_inverse(Cell * Z,const Cell * A) const548 FloatCell::bif_multiply_inverse(Cell * Z, const Cell * A) const
549 {
550    return A->bif_divide(Z, this);
551 }
552 //-----------------------------------------------------------------------------
553 ErrorCode
bif_divide(Cell * Z,const Cell * A) const554 FloatCell::bif_divide(Cell * Z, const Cell * A) const
555 {
556 #ifdef RATIONAL_NUMBERS_WANTED
557    if (const APL_Integer B_denom = get_denominator())  // B is rational
558       {
559         const APL_Integer B_numer = get_numerator();
560         if (B_numer == 0)   // A ÷ 0
561            {
562              if (A->is_near_zero())   return IntCell::z1(Z);   // 0÷0 is 1
563              return E_DOMAIN_ERROR;
564            }
565         const FloatCell inv_B(B_denom, B_numer);
566         return inv_B.bif_multiply(Z, A);
567       }
568 #endif
569 
570    if (!A->is_numeric())   return E_DOMAIN_ERROR;
571 
572 const APL_Float ar = A->get_real_value();
573 const APL_Float ai = A->get_imag_value();
574 
575    if (dfval() == 0.0)   // A ÷ 0
576       {
577          if (ar != 0.0)   return E_DOMAIN_ERROR;
578          if (ai != 0.0)   return E_DOMAIN_ERROR;
579 
580          return IntCell::z1(Z);   // 0÷0 is 1 in APL
581       }
582 
583 
584    if (ai == 0.0)   // real result
585       {
586         const APL_Float real = ar / dfval() ;
587         if (isfinite(real))   return FloatCell::zv(Z, real);
588         return E_DOMAIN_ERROR;
589       }
590 
591    // complex result
592    //
593 const double zar = ar / dfval();
594 const double zai = ai / dfval();
595    if (!isfinite(zar))   return E_DOMAIN_ERROR;
596    if (!isfinite(zai))   return E_DOMAIN_ERROR;
597    return ComplexCell::zv(Z, zar, zai);
598 }
599 //-----------------------------------------------------------------------------
600 ErrorCode
bif_power(Cell * Z,const Cell * A) const601 FloatCell::bif_power(Cell * Z, const Cell * A) const
602 {
603    // some A to the real B-th power
604    //
605    if (!A->is_numeric())   return E_DOMAIN_ERROR;
606 
607 const APL_Float ar = A->get_real_value();
608 const APL_Float ai = A->get_imag_value();
609 
610    // 1. A == 0
611    //
612    if (ar == 0.0 && ai == 0.0)
613        {
614          if (dfval() == 0.0)   return IntCell::z1(Z);   // 0⋆0 is 1
615          if (dfval()  > 0.0)   return IntCell::z0(Z);   // 0⋆N is 0
616          return E_DOMAIN_ERROR;                        // 0⋆¯N = 1÷0
617        }
618 
619    // 2. real A > 0   (real result)
620    //
621    if (ai == 0.0)
622       {
623         if (ar  == 1.0)   return IntCell::z1(Z);   // 1⋆b = 1
624         const APL_Float z = pow(ar, dfval());
625         if (isfinite(z)) return zv(Z, z);
626 
627         /* fall through */
628       }
629 
630    // 3. complex result
631    //
632 const APL_Complex a(ar, ai);
633 const APL_Complex z = complex_power(a, dfval());
634    if (!isfinite(z.real()))   return E_DOMAIN_ERROR;
635    if (!isfinite(z.imag()))   return E_DOMAIN_ERROR;
636 
637    return ComplexCell::zv(Z, z);
638 }
639 //-----------------------------------------------------------------------------
640 inline double
p_modulo_q(double P,double Q)641 p_modulo_q(double P, double Q)
642 {
643   // return R ← P - (×P) ⌊ | Q × ⌊ | P ÷ Q as described in ISO p. 89
644   //            │   │    │ │ │   │ │ │
645   //            │   │    │ │ │   │ │ └──────── quotient
646   //            │   │    │ │ │   │ └────────── abs_quotient
647   //            │   │    │ │ │   └──────────── floor_quotient
648   //            │   │    │ │ └──────────────── floor_quotient
649   //            │   │    │ └────────────────── prod
650   //            │   │    └──────────────────── abs_prod
651   //            │   └───────────────────────── prod2
652   //            └───────────────────────────── r
653   //
654 
655 const APL_Float quotient = P / Q;   // quotient←b÷a and check overflows
656    if (!isfinite(quotient))   return 0.0;   // exponent overflow
657 
658    if (!isfinite(Q / P))   // exponent underflow
659       return ((P < 0) == (Q < 0)) ? P : 0.0;
660 
661    {
662      const double qct = Workspace::get_CT();
663      if ((qct != 0) && Cell::integral_within(quotient, qct))   return 0.0;
664    }
665 
666 const APL_Float null(0.0);
667 const APL_Float abs_quotient = quotient < null ? -quotient : quotient;
668    if (abs_quotient > 4.5E15)
669       {
670         // if "| P ÷ Q" is too large then 'abs_quotient' is not exact any more.
671         // In this case, for every R with 0 ≤ R < Q there ie an A such that
672         // A has the same floating point representation as 'abs_quotient' and
673         // (P - R) is an integer multiple of Q.
674         //
675         // Normally we would raise a DOMAIN ERROR to inform the user about the
676         // problem, but the ISO standard does not allow that. We therefore
677         // return 0 which is a valid remainder (although not the only one).
678         //
679         return 0.0;
680       }
681 
682    if (abs_quotient < 1.0)
683       {
684         // P is smaller in magnitude than Q. If P and Q have the same sign then
685         // P mod Q is P, otherwise Q - P.
686         //
687         return (P < null) == (Q < null) ? P : Q + P;
688       }
689 
690 const APL_Float floor_quotient = floor(abs_quotient);
691 const APL_Float prod           = Q * floor_quotient;
692 const APL_Float abs_prod       = prod < null ? -prod : prod;
693 const APL_Float prod2          = P < 0 ? -abs_prod : abs_prod;
694 const APL_Float r              = P - prod2;
695 
696    return r;
697 
698 /*
699 // Q(P)
700 // Q(Q)
701 // Q(quotient)
702 // Q(abs_quotient)
703 // Q(floor_quotient)
704 // Q(abs_prod)
705 // Q(prod2)
706 // Q(r)
707 
708 Assert(isnormal(abs_quotient)   || abs_quotient   == 0.0);
709 Assert(isnormal(floor_quotient) || floor_quotient == 0.0);
710 Assert(isnormal(abs_prod)       || abs_prod       == 0.0);
711 Assert(isnormal(prod2)          || prod2          == 0.0);
712 Assert(isnormal(r)              || r              == 0.0);
713 
714    return r;
715 */
716 }
717 //-----------------------------------------------------------------------------
718 ErrorCode
bif_residue(Cell * Z,const Cell * A) const719 FloatCell::bif_residue(Cell * Z, const Cell * A) const
720 {
721    if (!A->is_numeric())   return E_DOMAIN_ERROR;
722 
723    if (A->get_imag_value() != 0.0)   // complex A
724       {
725         ComplexCell B(get_real_value());
726         return B.bif_residue(Z, A);
727       }
728 
729 const APL_Float a = A->get_real_value();
730 const APL_Float b = dfval();
731 
732    // if A is zero, return B
733    //
734    if (a == 0.0)   return zv(Z, b);
735 
736    // IBM: if B is zero , return 0
737    //
738    if (b == 0.0)   return IntCell::z0(Z);
739 
740    // if ⎕CT != 0 and B ÷ A is close to an integer within ⎕CT then return 0.
741    //
742    // Note: In that case, the integer to which A ÷ B is close is either
743    // floor(A ÷ B) or ceil(A ÷ B).
744    //
745 const APL_Float null(0.0);
746 const APL_Float z = p_modulo_q(b, a);
747 Assert(isnormal(z) || z == null);
748 
749 APL_Float r2;
750    if      (z < null && a < null)   r2 = z;     // (×R) = ×Q)
751    else if (z > null && a > null)   r2 = z;     // (×R) = ×Q)
752    else                       r2 = z + a;       // (×R) ≠ ×Q)
753 Assert(isnormal(r2) || r2 == null);
754 
755    if (r2 == null)   return IntCell::z0(Z);
756    if (r2 == a)      return IntCell::z0(Z);
757    else              return zv(Z, r2);
758 }
759 //-----------------------------------------------------------------------------
760 ErrorCode
bif_maximum(Cell * Z,const Cell * A) const761 FloatCell::bif_maximum(Cell * Z, const Cell * A) const
762 {
763    if (A->is_integer_cell())
764       {
765          const APL_Integer a = A->get_int_value();
766          if (a >= dfval())   return IntCell::zv(Z, a);
767          else                          return this->zv(Z);    // copy as is
768       }
769 
770    if (A->is_float_cell())
771       {
772          const APL_Float a = A->get_real_value();
773          if (a >= dfval())
774             return reinterpret_cast<const FloatCell *>(A)->zv(Z);  // copy as is
775          else               return this->zv(Z);               // copy as is
776       }
777 
778    // delegate to A
779    //
780    return A->bif_maximum(Z, this);
781 }
782 //-----------------------------------------------------------------------------
783 ErrorCode
bif_minimum(Cell * Z,const Cell * A) const784 FloatCell::bif_minimum(Cell * Z, const Cell * A) const
785 {
786    if (A->is_integer_cell())
787       {
788          const APL_Integer a = A->get_int_value();
789          if (a <= dfval())   return IntCell::zv(Z, a);
790          else                          return this->zv(Z);    // copy as is
791       }
792 
793    if (A->is_float_cell())
794       {
795          const APL_Float a = A->get_real_value();
796          if (a <= dfval())
797             return reinterpret_cast<const FloatCell *>(A)->zv(Z);  // copy as is
798          else               return this->zv(Z);               // copy as is
799       }
800 
801    // delegate to A
802    //
803    return A->bif_minimum(Z, this);
804 }
805 //=============================================================================
806 // throw/nothrow boundary. Functions above MUST NOT (directly or indirectly)
807 // throw while funcions below MAY throw.
808 //=============================================================================
809 PrintBuffer
character_representation(const PrintContext & pctx) const810 FloatCell::character_representation(const PrintContext & pctx) const
811 {
812 #ifdef RATIONAL_NUMBERS_WANTED
813    if (const APL_Integer denom = get_denominator())
814       {
815         if (Workspace::get_v_Quad_PS().get_print_quotients())   // show A÷B
816            {
817              ColInfo info;
818              info.flags |= CT_FLOAT;
819 
820              UCS_string ucs;
821              APL_Integer numer = get_numerator();
822              if (numer < 0)
823                 {
824                   ucs.append(UNI_OVERBAR);
825                   numer = -numer;
826                 }
827              ucs.append(UCS_string::from_uint(numer));
828              info.int_len = ucs.size();
829 
830              ucs.append(UNI_DIVIDE);
831 
832              ucs.append(UCS_string::from_uint(denom));
833              info.denom_len = ucs.size() - info.int_len;
834              info.real_len = ucs.size();
835              return PrintBuffer(ucs, info);
836            }
837       }
838 #endif
839 
840 bool scaled = pctx.get_scaled();   // may be changed by print function
841 UCS_string ucs = UCS_string(dfval(), scaled, pctx);
842 
843 ColInfo info;
844    info.flags |= CT_FLOAT;
845    if (scaled)   info.flags |= real_has_E;
846 
847    // assume integer.
848    //
849 int int_fract = ucs.size();
850    info.real_len = ucs.size();
851    info.int_len = ucs.size();
852    loop(u, ucs.size())
853       {
854         if (ucs[u] == UNI_ASCII_FULLSTOP)
855            {
856              info.int_len = u;
857              if (!pctx.get_scaled())   break;
858              continue;
859            }
860 
861         if (ucs[u] == UNI_ASCII_E)
862            {
863              if (info.int_len > u)   info.int_len = u;
864              int_fract = u;
865              break;
866            }
867       }
868 
869    info.fract_len = int_fract - info.int_len;
870 
871    return PrintBuffer(ucs, info);
872 }
873 //-----------------------------------------------------------------------------
874 bool
is_big(APL_Float val,int quad_pp)875 FloatCell::is_big(APL_Float val, int quad_pp)
876 {
877 static const APL_Float big[MAX_Quad_PP + 1] =
878 {
879                   1ULL, // not used since MIN_Quad_PP == 1
880                  10ULL,
881                 100ULL,
882                1000ULL,
883               10000ULL,
884              100000ULL,
885             1000000ULL,
886            10000000ULL,
887           100000000ULL,
888          1000000000ULL,
889         10000000000ULL,
890        100000000000ULL,
891       1000000000000ULL,
892      10000000000000ULL,
893     100000000000000ULL,
894    1000000000000000ULL,
895   10000000000000000ULL,
896  1000000000000000000ULL,
897 };
898 
899    return val >= big[quad_pp] || val <= -big[quad_pp];
900 }
901 //-----------------------------------------------------------------------------
902 bool
need_scaling(APL_Float val,int quad_pp)903 FloatCell::need_scaling(APL_Float val, int quad_pp)
904 {
905    // A number is printed in scaled format if (see lrm pp. 11-13) either:
906    //
907    // (1) its integer part is longer that quad-PP, or
908 
909    // (2a) is non-zero, and
910    // (2b) its integer part is 0, and
911    // (2c) its fractional part starts with at least 5 zeroes.
912    //
913    if (val < 0.0)   val = - val;   // simplify comparisons
914 
915    if (is_big(val, quad_pp))        return true;    // case 1.
916 
917    if (val == 0.0)                  return false;   // not 2a.
918 
919    if (val < 0.000001)              return true;    // case 2
920 
921    return false;
922 }
923 //-----------------------------------------------------------------------------
924 void
map_FC(UCS_string & ucs)925 FloatCell::map_FC(UCS_string & ucs)
926 {
927    loop(u, ucs.size())
928       {
929         switch(ucs[u])
930            {
931              case UNI_ASCII_FULLSTOP: ucs[u] = Workspace::get_FC(0);   break;
932              case UNI_ASCII_COMMA:    ucs[u] = Workspace::get_FC(1);   break;
933              case UNI_OVERBAR:        ucs[u] = Workspace::get_FC(5);   break;
934              default:                 break;
935            }
936       }
937 }
938 //-----------------------------------------------------------------------------
939