@@ -18,21 +18,28 @@ extern "C" {
1818 fuzz * \
1919 ABS (v)) // used when v is known to be exact integer. It's close enough, maybe ULP too small on the high end
2020
21- static B
22- jtC1fromC2(J jt, A w, void *yv) {
23- UC *x;
24- US c, *v;
25- v = USAV (w);
26- x = (C *)yv;
27- DQ (AN (w), c = *v++; if (!(256 > c)) return 0 ; *x++ = (UC)c;);
28- return 1 ;
21+ template <typename T, typename V>
22+ [[nodiscard]] static constexpr auto
23+ in_range(V value) -> bool {
24+ return std::numeric_limits<T>::min () <= value && value <= std::numeric_limits<T>::max ();
25+ }
26+
27+ template <typename T, typename V>
28+ [[nodiscard]] static constexpr auto
29+ in_range () -> bool {
30+ return in_range<T>(std::numeric_limits<V>::min ()) && in_range<T>(std::numeric_limits<V>::max ());
2931}
3032
3133template <typename From, typename To>
3234[[nodiscard]] static auto
3335convert (J jt, array w, void *yv) -> bool {
34- From *v = reinterpret_cast <From*>(UAV (w));
35- std::copy (v, v + AN (w), static_cast <To*>(yv));
36+ From *v = reinterpret_cast <From *>(UAV (w));
37+ if constexpr (!in_range<To, From>()) {
38+ // TODO: replace with short circuiting solution
39+ auto out = static_cast <To *>(yv);
40+ return out + AN (w) == std::copy_if (v, v + AN (w), out, [](auto v) { return in_range<To>(v); });
41+ }
42+ std::copy (v, v + AN (w), static_cast <To *>(yv));
3643 return 1 ;
3744}
3845
@@ -44,37 +51,6 @@ convert(J jt, array w, void *yv, Transform t) -> bool {
4451 return 1 ;
4552}
4653
47- static B
48- jtC1fromC4 (J jt, A w, void *yv) {
49- UC *x;
50- C4 c, *v;
51- v = C4AV (w);
52- x = (C *)yv;
53- DQ (AN (w), c = *v++; if (!(256 > c)) return 0 ; *x++ = (UC)c;);
54- return 1 ;
55- }
56-
57- static B
58- jtC2fromC4 (J jt, A w, void *yv) {
59- US *x;
60- C4 c, *v;
61- v = C4AV (w);
62- x = (US *)yv;
63- DQ (AN (w), c = *v++; if (!(65536 > c)) return 0 ; *x++ = (US)c;);
64- return 1 ;
65- }
66-
67- static B
68- jtBfromI (J jt, A w, void *yv) {
69- B *x;
70- I n, p, *v;
71- n = AN (w);
72- v = AV (w);
73- x = (B *)yv;
74- DQ (n, p = *v++; *x++ = (B)p; if (p & -2 ) return 0 ;);
75- return 1 ;
76- }
77-
7854static B
7955jtBfromD (J jt, A w, void *yv, D fuzz) {
8056 B *x;
@@ -451,7 +427,6 @@ jtccvt(J jt, I tflagged, A w, A *y) {
451427 RZ (*y = jtca (jt, w));
452428 return 1 ;
453429 }
454- // else if(n&&t&JCHAR){ASSERT(HOMO(t,wt),EVDOMAIN); RZ(*y=jtuco1(jt,w)); return 1;}
455430 // Kludge on behalf of result assembly: we want to be able to stop converting after the valid cells. If
456431 // NOUNCVTVALIDCT is set in the type, we use the input *y as as override on the # cells to convert. We use it to
457432 // replace n (for use here) and yv, and AK(w) and AN(w) for the subroutines. If NOUNCVTVALIDCT is set, w is
@@ -480,50 +455,41 @@ jtccvt(J jt, I tflagged, A w, A *y) {
480455 // Perform the conversion based on data types
481456 // For branch-table efficiency, we split the C2T and C4T and BIT conversions into one block, and
482457 // the rest in another
483- if ((t | wt) &
484- (C2T + C4T + BIT + SBT)) { // there are no SBT conversions, but we have to show domain error
485- // we must account for all NOUN types. Low 8 bits have most of them, and we know type can't be sparse. This
486- // picks up the others
458+ if ((t | wt) & (C2T + C4T + BIT + SBT)) {
459+ // there are no SBT conversions, but we have to show domain error we
460+ // must account for all NOUN types. Low 8 bits have most of them, and
461+ // we know type can't be sparse. This picks up the others
487462 ASSERT (!((t | wt) & SBT), EVDOMAIN); // No conversions for these types
488463 switch (CVCASE (CTTZ (t), CTTZ (wt))) {
489- case CVCASE (LITX, C2TX): return jtC1fromC2 (jt, w, yv);
490- case CVCASE (LITX, C4TX): return jtC1fromC4 (jt, w, yv);
464+ case CVCASE (LITX, C2TX): return convert<US, UC> (jt, w, yv);
465+ case CVCASE (LITX, C4TX): return convert<C4, UC> (jt, w, yv);
491466 case CVCASE (C2TX, LITX): return convert<UC, US>(jt, w, yv);
492- case CVCASE (C2TX, C4TX): return jtC2fromC4 (jt, w, yv);
467+ case CVCASE (C2TX, C4TX): return convert<C4, US> (jt, w, yv);
493468 case CVCASE (C4TX, LITX): return convert<UC, C4>(jt, w, yv);
494469 case CVCASE (C4TX, C2TX): return convert<US, C4>(jt, w, yv);
495470 default : ASSERT (0 , EVDOMAIN);
496471 }
497472 }
498473 switch (CVCASE (CTTZ (t), CTTZ (wt))) {
499- case CVCASE (INTX, B01X): {
500- I *x = static_cast <I*>(yv);
501- B *v = (B *)wv;
502- DQ (n, *x++ = *v++;);
503- }
474+ case CVCASE (INTX, B01X):
475+ std::copy_n (static_cast <B*>(wv), n, static_cast <I*>(yv));
504476 return 1 ;
505477 case CVCASE (XNUMX, B01X): return jtXfromB (jt, w, yv);
506478 case CVCASE (RATX, B01X): GATV (d, XNUM, n, r, s); return jtXfromB (jt, w, AV (d)) && jtQfromX (jt, d, yv);
507- case CVCASE (FLX, B01X): {
508- D *x = (D *)yv;
509- B *v = (B *)wv;
510- DQ (n, *x++ = *v++;);
511- }
479+ case CVCASE (FLX, B01X):
480+ std::copy_n (static_cast <B*>(wv), n, static_cast <D*>(yv));
512481 return 1 ;
513482 case CVCASE (CMPXX, B01X): {
514483 Z *x = (Z *)yv;
515484 B *v = (B *)wv;
516485 DQ (n, x++->re = *v++;);
517486 }
518487 return 1 ;
519- case CVCASE (B01X, INTX): return jtBfromI (jt, w, yv);
488+ case CVCASE (B01X, INTX): return convert<I, bool > (jt, w, yv);
520489 case CVCASE (XNUMX, INTX): return jtXfromI (jt, w, yv);
521490 case CVCASE (RATX, INTX): GATV (d, XNUM, n, r, s); return jtXfromI (jt, w, AV (d)) && jtQfromX (jt, d, yv);
522- case CVCASE (FLX, INTX): {
523- D *x = (D *)yv;
524- I *v = static_cast <I*>(wv);
525- DQ (n, *x++ = (D)*v++;);
526- }
491+ case CVCASE (FLX, INTX):
492+ std::copy_n (static_cast <I*>(wv), n, static_cast <D*>(yv));
527493 return 1 ;
528494 case CVCASE (CMPXX, INTX): {
529495 Z *x = (Z *)yv;
0 commit comments