Skip to content

Commit 116346f

Browse files
committed
Make the type of empty arithmetic result the natural type given the arguments (instead of the type for boolean args)
1 parent 7bf4b2e commit 116346f

4 files changed

Lines changed: 56 additions & 10 deletions

File tree

jsrc/ca.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ static UI imodpow(UI x,I n,UI m){
5959
if(unlikely(m==1))R 0; UI z=1; // if n=0 result is 1 unless m=1, then 0
6060
UI mrecip=((UI)(-IMIN)/m); mrecip=(mrecip<<1)+((((UI)(-IMIN)-mrecip*m)<<1)>=m); // 2^64%m, possibly low by as much as 2^-64
6161
#define modm(x) ({UI t; doubletype tt; tt=(doubletype)(x)*(doubletype)mrecip; t=tt>>BW; t=(x)-t*m; if(unlikely(t>=m))t-=m; t;})
62-
// x%m using mrecip. mrecip may be low by 2^-64; x*mrecip is truncated. Resulting modulus may be high by at most m
62+
// x%m using mrecip. x*mrecip is truncated, which gives the remainder. mrecip may be 2^-64 low, so the remainder may be x*m/2^64 high. This is never more than m too high, so a single correction suffices
63+
// we expect the correction to be rare so we use a branch
6364
// #define modm(x) (x)%m
6465
while(n){UI zz=z*x; zz=modm(zz); x=x*x; x=modm(x); z=n&1?zz:z; n>>=1;} // repeated square/mod
6566
R z;

jsrc/va2.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -476,22 +476,29 @@ static A jtva2(J jt,AD * RESTRICT a,AD * RESTRICT w,AD * RESTRICT self,UI allran
476476
aadocv=&vainfo->p2[(at>>(INTX-1))+((at+wt)>>INTX)];
477477
}else{
478478

479-
// If an operand is empty, turn it to Boolean, and if the OTHER operand is non-numeric, turn that to Boolean too (leaving
480-
// rank and shape untouched). This change to the other operand is notional only - we won't actually convert
481-
// when there is an empty - but it guarantees that execution on an empty never fails.
482479
// If we switch a sparse nonnumeric matrix to boolean, that may be a space problem; but we don't
483480
// support nonnumeric sparse now
484481
// if an operand is sparse, replace its type with the corresponding non-sparse type, for purposes of testing operand precisions
485482
if(unlikely(ISSPARSE(at|wt))){
486483
at&=~SPARSE; wt&=~SPARSE;
487484
jtinplace=0; // We use jtinplace==0 as a flag meaning 'sparse'
488485
}
486+
// Get the result type and routine
487+
adocv=var(self,at,wt);
488+
if(unlikely(adocv.f==0)){
489+
// There is no routine for these argument types.
490+
// If an operand is empty, turn it to Boolean, and if the OTHER operand is non-numeric, turn that to Boolean too (leaving
491+
// rank and shape untouched). This change to the other operand is notional only - we won't actually convert
492+
// when there is an empty - but it guarantees that execution on an empty never fails.
493+
at=((-AN(a)&(-AN(w)|-(at&NUMERIC)))>=0)?B01:at;
494+
wt=((-AN(w)&(-AN(a)|-(wt&NUMERIC)))>=0)?B01:wt;
495+
// obsolete if(AN(a)==0){at=B01;if(!(wt&NUMERIC))wt=B01;} // switch empty arg to Boolean & ensure compatibility with other arg
496+
// obsolete if(AN(w)==0){wt=B01;if(!(at&NUMERIC))at=B01;}
497+
adocv=var(self,at,wt); // rerun the decode with safer types
498+
}
499+
aadocv=&adocv; // we save the address of the struct
489500
// We could allocate the result block here & avoid the test after the allocation later. But we would have to check for agreement etc
490-
if(AN(a)==0){at=B01;if(!(wt&NUMERIC))wt=B01;} // switch empty arg to Boolean & ensure compatibility with other arg
491-
if(AN(w)==0){wt=B01;if(!(at&NUMERIC))at=B01;}
492-
493-
// Figure out the result type. Don't signal the error from it yet, because domain has lower priority than agreement
494-
adocv=var(self,at,wt); aadocv=&adocv;
501+
// Don't signal domain error on the types yet, because domain has lower priority than agreement
495502
}
496503
}
497504

test/g0a.ijs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,41 @@ NB. handling empty arrays -----------------------------------------------
5656
(":0 2 3$s:@<"0 'a') -: ":0 2 3$s:@<"0&.> <'a'
5757
(":0 2 3$s:@<"0 'a') -: ":0 2 3$<"0@s: <'a'
5858

59-
4!:55 ;:'n'
59+
NB. type of empty arithmetic arrays
60+
empties =. (0$0);'';(0$00);(0$0.);(0$0.j0.);(0$a:);(0$1x);(0$1r2)
61+
nonempties =. 0;' ';00;0.;0.j0.;a:;1x;1r2
62+
(".;._2 (0 : 0)) -: empties 3!:0@:+&>/ nonempties
63+
4 4 4 8 16 4 64 128
64+
4 4 4 8 16 4 64 128
65+
4 4 4 8 16 4 64 128
66+
8 4 8 8 16 4 8 8
67+
16 4 16 16 16 4 16 16
68+
4 4 4 8 16 4 64 128
69+
64 4 64 8 16 4 64 128
70+
128 4 128 8 16 4 128 128
71+
)
72+
(".;._2 (0 : 0)) -: empties 3!:0@:*&>/ nonempties
73+
1 1 4 8 16 1 64 128
74+
1 1 4 8 16 1 64 128
75+
4 1 4 8 16 1 64 128
76+
8 1 8 8 16 1 8 8
77+
16 1 16 16 16 1 16 16
78+
1 1 4 8 16 1 64 128
79+
64 1 64 8 16 1 64 128
80+
128 1 128 8 16 1 128 128
81+
)
82+
(".;._2 (0 : 0)) -: empties 3!:0@:-&>/ nonempties
83+
4 4 4 8 16 4 64 128
84+
4 4 4 8 16 4 64 128
85+
4 4 4 8 16 4 64 128
86+
8 4 8 8 16 4 8 8
87+
16 4 16 16 16 4 16 16
88+
4 4 4 8 16 4 64 128
89+
64 4 64 8 16 4 64 128
90+
128 4 128 8 16 4 128 128
91+
)
92+
93+
4!:55 ;:'n empties nonempties'
6094

6195

6296

test/g520.ijs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ for_t. i. 4 do.
137137
assert. (_6 ]\ 0 0 1 0 0 0 0 0 2e_20 0 0 0) ('' run128_9) 2;(,."1 (_2) ]\ 00 0);(0$00);(0$0.0);M;0.0;Yt
138138
assert. (_6 ]\ 1 2 0 0 0 0 0 2e_20 0 0 0 0) ('' run128_9) 6;(,."1 (_2) ]\ 0 2);(00 1);(1. 2.);M;0.0;Yt
139139
assert. (_6 ]\ 0 0 1 2 0 3 0 0 2e_20 6e_20 0 15e_20) ('' run128_9) 8;(,."1 (_2) ]\ (4$0) , 3 3);((3$0) , 2 3 5);((3$0), 1. 2. 3.);M;0.0;Yt
140+
NB. change sign of result when Yt = 8 & fetch is from a Slack
141+
assert. (- _6 ]\ 1 0 0 0 0 0 0 0 0 0 0 0) ('' run128_9) 00;(,."1 (_2) ]\ 00 0);(0$00);(0$0.0);M;0.0;(8 (0}) Yt)
142+
assert. (- _6 ]\ 0 0 1 0 0 0 0 0 2e_20 0 0 0) ('' run128_9) 2;(,."1 (_2) ]\ 00 0);(0$00);(0$0.0);M;0.0;(8 (2}) Yt)
143+
assert. (_6 ]\ 1 2 0 0 0 0 0 2e_20 0 0 0 0) ('' run128_9) 6;(,."1 (_2) ]\ 0 2);(00 1);(1. 2.);M;0.0;(8 (6}) Yt)
140144
NB. clamping to threshold
141145
M =. 1 1e_20 (<1;3;2 3)} 2 {. ,: |: _4 ]\ _1. 0 1 2 _1e_5 _2e_9 0 1e_9 0 0 0 0 0 0 0 1e_10 NB. input by columns
142146
assert. (2 {. ,: _1. 0 1 2) ('' run128_9) 00;(,."1 (_2) ]\ 00 0);(0$00);(0$0.0);M;0.5;Yt

0 commit comments

Comments
 (0)