@@ -167,7 +167,8 @@ export const ARITHMETIC_LIBRARY: IdentifierDefinitions[] = [
167167type :( [ x ] ) => x . type ,
168168sgn :( [ x ] ) => {
169169if ( x . is ( 0 ) ) return 'zero' ;
170- return x . isNumberLiteral ?'positive' :'non-negative' ;
170+ if ( x . isNumberLiteral ) return 'positive' ;
171+ return 'non-negative' ; //|x^2+1| fails
171172} ,
172173evaluate :( [ x ] ) => evaluateAbs ( x ) ,
173174} ,
@@ -187,14 +188,12 @@ export const ARITHMETIC_LIBRARY: IdentifierDefinitions[] = [
187188type :addType ,
188189
189190sgn :( ops ) => {
190- if ( ops . some ( ( x ) => x . isNaN ) ) return 'nan' ;
191- if ( ops . some ( ( x ) => x . isReal === false ) ) return 'unsigned' ;
191+ if ( ops . some ( ( x ) => x . isNaN ) ) return 'unsigned' ;
192192if ( ops . every ( ( x ) => x . is ( 0 ) ) ) return 'zero' ;
193193if ( ops . every ( ( x ) => x . isNonNegative ) )
194194return ops . some ( ( x ) => x . isPositive ) ?'positive' :'non-negative' ;
195195if ( ops . every ( ( x ) => x . isNonPositive ) )
196196return ops . some ( ( x ) => x . isNegative ) ?'negative' :'non-positive' ;
197- if ( ops . every ( ( x ) => x . isReal ) ) return 'real' ;
198197return undefined ;
199198} ,
200199
@@ -280,11 +279,12 @@ export const ARITHMETIC_LIBRARY: IdentifierDefinitions[] = [
280279sgn :( ops ) => {
281280const [ n , d ] = [ ops [ 0 ] , ops [ 1 ] ] ;
282281if ( d . is ( 0 ) ) return 'unsigned' ;
283- if ( d . is ( 0 ) === false && n . is ( 0 ) ) return 'zero' ;
284282if ( d . isPositive ) return n . sgn ;
285283if ( d . isNegative ) return oppositeSgn ( n . sgn ) ;
286- if ( n . is ( 0 ) || ( n . isFinite && d . isInfinity ) ) return 'zero' ;
287- if ( ! n . is ( 0 ) && ! d . is ( 0 ) ) return 'not-zero' ;
284+ const s = d . sgn ;
285+ if ( ( n . is ( 0 ) && s === 'not-zero' ) || ( n . isFinite && d . isInfinity ) )
286+ return 'zero' ;
287+ if ( n . sgn === 'not-zero' && s === 'not-zero' ) return 'not-zero' ;
288288return undefined ;
289289} ,
290290
@@ -669,7 +669,10 @@ export const ARITHMETIC_LIBRARY: IdentifierDefinitions[] = [
669669 :undefined ;
670670if (
671671ops . some ( ( x ) => x . isFinite === false || x . isFinite === undefined ) &&
672- ops . some ( ( x ) => x . is ( 0 ) === undefined )
672+ ops . some ( ( x ) => {
673+ const s = x . sgn ;
674+ s !== 'positive' && s !== 'negative' && s !== 'not-zero' ;
675+ } )
673676)
674677return undefined ;
675678if ( ops . every ( ( x ) => x . isPositive || x . isNegative ) ) {
@@ -686,11 +689,17 @@ export const ARITHMETIC_LIBRARY: IdentifierDefinitions[] = [
686689} ) ;
687690return sumNeg % 2 === 0 ?'non-positive' :'non-negative' ;
688691}
689- if ( ops . every ( ( x ) => ! x . is ( 0 ) ) ) return 'not-zero' ;
690- if ( ops . every ( ( x ) => x . isReal ) ) return 'real' ;
692+ if (
693+ ops . every (
694+ ( x ) =>
695+ x . sgn === 'not-zero' ||
696+ x . sgn === 'positive' ||
697+ x . sgn === 'negative'
698+ )
699+ )
700+ return 'not-zero' ;
691701return undefined ;
692702} ,
693-
694703evaluate :( ops , { numericApproximation} ) =>
695704// Use evaluate i both cases: do not introduce premature rounding errors
696705numericApproximation
@@ -776,8 +785,13 @@ export const ARITHMETIC_LIBRARY: IdentifierDefinitions[] = [
776785return a . sgn ;
777786
778787if ( b . numerator . isEven && b . denominator . isOdd ) {
779- if ( a . isReal ) return ! a . is ( 0 ) ?'positive' :'non-negative' ;
780- if ( a . type . is ( 'imaginary' ) ) return 'negative' ;
788+ if ( a . isReal ) {
789+ let s = a . sgn ;
790+ return s === 'positive' || s === 'not-zero' || s === 'negative'
791+ ?'positive'
792+ :'non-negative' ;
793+ }
794+ if ( a . type . matches ( 'complex' ) ) return 'negative' ;
781795return ! a . is ( 0 ) ?'not-zero' :undefined ; //already accounted for a.is(0)
782796}
783797
@@ -868,10 +882,18 @@ export const ARITHMETIC_LIBRARY: IdentifierDefinitions[] = [
868882sgn :( [ x , n ] ) => {
869883// Note: we can't simplify this to a power, then get the sgn of that because this may cause an infinite loop
870884if ( x . isReal === false || n . isReal === false ) return 'unsigned' ;
871- if ( x . is ( 0 ) ) return n . is ( 0 ) ?'unsigned' :'zero' ;
885+ if ( x . is ( 0 ) ) {
886+ if ( n . isNonPositive ) {
887+ return 'unsigned' ;
888+ }
889+ if ( n . isPositive ) return 'zero' ;
890+ }
872891if ( x . isPositive === true ) return 'positive' ;
873- if ( n . isOdd === true ) return 'negative' ;
874- if ( n . isEven === true ) return 'unsigned' ;
892+ if ( x . isNonNegative === true ) return 'non-negative' ;
893+ if ( n . isOdd === true || ( n . numerator . isOdd && n . denominator . isOdd ) ) {
894+ return x . sgn ;
895+ }
896+ if ( x . isNegative && n . isOdd === false ) return 'unsigned' ;
875897return undefined ;
876898} ,
877899canonical :( args , { engine} ) => {
@@ -905,7 +927,6 @@ export const ARITHMETIC_LIBRARY: IdentifierDefinitions[] = [
905927if ( x . isLess ( 0.5 ) && x . isGreater ( - 0.5 ) ) return 'zero' ;
906928if ( x . isNonNegative ) return 'non-negative' ;
907929if ( x . isNonPositive ) return 'non-positive' ;
908- if ( x . isReal ) return 'real' ;
909930return undefined ;
910931} ,
911932evaluate :( [ x ] ) =>
@@ -982,7 +1003,7 @@ export const ARITHMETIC_LIBRARY: IdentifierDefinitions[] = [
9821003if ( x . isPositive ) return 'positive' ;
9831004if ( x . isNegative ) return 'unsigned' ;
9841005if ( x . isNonNegative ) return 'non-negative' ;
985- if ( ! x . is ( 0 ) ) return 'not-zero' ;
1006+ if ( x . sgn === 'not-zero' ) return 'not-zero' ;
9861007return undefined ;
9871008} ,
9881009evaluate :( [ x ] , { numericApproximation, engine} ) => {
@@ -1003,9 +1024,14 @@ export const ARITHMETIC_LIBRARY: IdentifierDefinitions[] = [
10031024signature :'number -> number' ,
10041025sgn :( [ x ] ) => {
10051026if ( x . is ( 0 ) ) return 'zero' ;
1006- if ( x . isReal ) return ! x . is ( 0 ) ?'positive' :'non-negative' ;
1027+ if ( x . isReal ) {
1028+ let s = x . sgn ;
1029+ return s === 'not-zero' || s === 'positive' || s === 'negative'
1030+ ?'positive'
1031+ :'non-negative' ;
1032+ }
10071033if ( x . type . matches ( 'complex' ) ) return 'negative' ;
1008- if ( x . isReal === false || x . isNaN ) return 'unsigned' ;
1034+ if ( x . isReal == false || x . isNaN ) return 'unsigned' ;
10091035return undefined ;
10101036} ,
10111037canonical :( args , { engine} ) => {