@@ -561,48 +561,48 @@ jtcvt(J jt, I t, A w) {
561561A
562562jtbcvt (J jt, C mode, A w) {
563563 FPREFIP;
564- A y, z = w;
565564 if (!w) return 0 ;
565+
566+ auto const as_integer = [](auto const &v) { return *(I *)&v; };
567+ auto const isflag = [&](auto const &z) { return as_integer (z.im ) == NANFLAG; };
568+
566569 // there may be values (especially b types) that were nominally CMPX but might actually be integers. Those were
567570 // stored with the real part being the actual integer value and the imaginary part as the special 'flag' value. We
568571 // handle those here. If all the imaginary parts were flags, we accept all the integer parts and change the type
569572 // to integer. If none of the imaginary parts were flags, we leave the input unchanged. If some were flags, we
570573 // convert the flagged values to float and keep the result as complex
574+ array result = w;
571575 if ((((AN (w) - 1 ) | (AT (w) & CMPX) - 1 )) >= 0 ) { // not empty AND complex
572- I allflag = 1 , anyflag = 0 ;
573- Z *wv = ZAV (w);
574- DO (AN (w), I isflag = *(I *)&wv[i].im == NANFLAG; allflag &= isflag; anyflag |= isflag;)
575- if (anyflag) {
576+ Z *wv = ZAV (w);
577+ auto flags = std::transform_reduce (wv, wv + AN (w), int64_t {}, std::plus{}, isflag);
578+ if (flags) {
576579 I ipok = SGNIF (jtinplace, JTINPLACEWX) & AC (w); // both sign bits set (<0) if inplaceable
577- if (allflag) {
578- if (ipok >= 0 ) GATV (z, INT, AN (w), AR (w), AS (w));
579- I *zv = IAV (z); // output area
580- DO (AN (w), zv[i] = *(I *)&wv[i].re ;) // copy the results as integers
580+ if (flags == AN (w)) {
581+ if (ipok >= 0 ) GATV (result, INT, AN (w), AR (w), AS (w));
582+ std::transform (wv, wv + AN (w), IAV (result), [&](auto const &z) { return as_integer (z.re ); });
581583 } else {
582- if (ipok >= 0 ) GATV (z, CMPX, AN (w), AR (w), AS (w));
583- Z *zv = ZAV (z); // output area
584- DO (
585- AN (w),
586- if (*(I *)&wv[i].im == NANFLAG) {
587- zv[i].re = (D) * (I *)&wv[i].re ;
588- zv[i].im = 0.0 ;
589- } else { zv[i] = wv[i]; }) // copy floats, and converts any integers back to float
584+ if (ipok >= 0 ) GATV (result, CMPX, AN (w), AR (w), AS (w));
585+ std::transform (wv, wv + AN (w), ZAV (result), [&](auto const &z) -> Z {
586+ if (isflag (z)) return {.re = (D)as_integer (z.re ), .im = 0.0 };
587+ return z; // copy floats, and converts any integers back to float
588+ });
590589 }
591- w = z ; // this result is now eligible for further demotion
590+ w = result ; // this result is now eligible for further demotion
592591 }
593592 }
594593 // for all numerics, try Boolean/int/float in order, stopping when we find one that holds the data
595594 if (mode & 1 || !(AT (w) & XNUM + RAT)) { // if we are not stopping at XNUM/RAT
596595 // To avoid a needless copy, suppress conversion to B01 if type is B01, to INT if type is INT, etc
597596 // set the NOFUZZ flag in jt to insist on an exact match so we won't lose precision
597+ array y;
598598 jtinplace = (J)((I)jt + JTNOFUZZ); // demand exact match
599- z = !(mode & 14 ) && jtccvt (jtinplace, B01, w, &y) ? y
599+ result = !(mode & 14 ) && jtccvt (jtinplace, B01, w, &y) ? y
600600 : (y = w, AT (w) & INT || (!(mode & 12 ) && jtccvt (jtinplace, INT, w, &y))) ? y
601601 : (y = w, AT (w) & FL || (!(mode & 8 ) && jtccvt (jtinplace, FL, w, &y)))
602602 ? y
603603 : w; // convert to enabled modes one by one, stopping when one works
604604 }
605- RNE (z );
605+ RNE (result );
606606} /* convert to lowest type. 0=mode: don't convert XNUM/RAT to other types */
607607
608608A
0 commit comments