@@ -163,7 +163,10 @@ export const ARITHMETIC_LIBRARY: IdentifierDefinitions[] = [
163163type :( [ x ] ) => x . type ,
164164sgn :( [ x ] ) => {
165165if ( x . is ( 0 ) ) return 'zero' ;
166- return x . isNumberLiteral ?'positive' :'non-negative' ;
166+ if ( x . isNumberLiteral ) {
167+ return 'positive' ;
168+ }
169+ return x . isNumberLiteral ?'positive' :'non-negative' ; //|x^2+1| fails
167170} ,
168171evaluate :( [ x ] ) => evaluateAbs ( x ) ,
169172} ,
@@ -183,13 +186,12 @@ export const ARITHMETIC_LIBRARY: IdentifierDefinitions[] = [
183186type :addType ,
184187
185188sgn :( ops ) => {
186- if ( ops . some ( ( x ) => x . isReal === false || x . isNaN ) ) return 'unsigned' ;
189+ if ( ops . some ( ( x ) => x . isNaN ) ) return 'unsigned' ;
187190if ( ops . every ( ( x ) => x . is ( 0 ) ) ) return 'zero' ;
188191if ( ops . every ( ( x ) => x . isNonNegative ) )
189192return ops . some ( ( x ) => x . isPositive ) ?'positive' :'non-negative' ;
190193if ( ops . every ( ( x ) => x . isNonPositive ) )
191194return ops . some ( ( x ) => x . isNegative ) ?'negative' :'non-positive' ;
192- if ( ops . every ( ( x ) => x . isReal ) ) return 'real' ;
193195return undefined ;
194196} ,
195197
@@ -273,12 +275,14 @@ export const ARITHMETIC_LIBRARY: IdentifierDefinitions[] = [
273275
274276sgn :( ops ) => {
275277const [ n , d ] = [ ops [ 0 ] , ops [ 1 ] ] ;
278+ const s = d . sgn ;
279+ const s1 = n . sgn ;
276280if ( d . is ( 0 ) ) return 'unsigned' ;
277- if ( d . is ( 0 ) === false && n . is ( 0 ) ) return 'zero' ;
278- if ( d . isPositive ) return n . sgn ;
279- if ( d . isNegative ) return oppositeSgn ( n . sgn ) ;
280- if ( n . is ( 0 ) || ( n . isFinite && d . isInfinity ) ) return 'zero' ;
281- if ( ! n . is ( 0 ) && ! d . is ( 0 ) ) return 'not-zero' ;
281+ if ( d . isPositive ) return s1 ;
282+ if ( d . isNegative ) return oppositeSgn ( s1 ) ;
283+ if ( ( n . is ( 0 ) && s === 'not-zero' ) || ( n . isFinite && d . isInfinity ) )
284+ return 'zero' ;
285+ if ( s1 === 'not-zero' && s === 'not-zero' ) return 'not-zero' ;
282286return undefined ;
283287} ,
284288
@@ -653,7 +657,10 @@ export const ARITHMETIC_LIBRARY: IdentifierDefinitions[] = [
653657 :undefined ;
654658if (
655659ops . some ( ( x ) => x . isFinite === false || x . isFinite === undefined ) &&
656- ops . some ( ( x ) => x . is ( 0 ) === undefined )
660+ ops . some ( ( x ) => {
661+ const s = x . sgn ;
662+ s !== 'positive' && s !== 'negative' && s !== 'not-zero' ;
663+ } )
657664)
658665return undefined ;
659666if ( ops . every ( ( x ) => x . isPositive || x . isNegative ) ) {
@@ -670,11 +677,17 @@ export const ARITHMETIC_LIBRARY: IdentifierDefinitions[] = [
670677} ) ;
671678return sumNeg % 2 === 0 ?'non-positive' :'non-negative' ;
672679}
673- if ( ops . every ( ( x ) => ! x . is ( 0 ) ) ) return 'not-zero' ;
674- if ( ops . every ( ( x ) => x . isReal ) ) return 'real' ;
680+ if (
681+ ops . every (
682+ ( x ) =>
683+ x . sgn === 'not-zero' ||
684+ x . sgn === 'positive' ||
685+ x . sgn === 'negative'
686+ )
687+ )
688+ return 'not-zero' ;
675689return undefined ;
676690} ,
677-
678691evaluate :( ops , { numericApproximation} ) =>
679692// Use evaluate i both cases: do not introduce premature rounding errors
680693numericApproximation
@@ -756,9 +769,13 @@ export const ARITHMETIC_LIBRARY: IdentifierDefinitions[] = [
756769return a . sgn ;
757770
758771if ( b . numerator . isEven && b . denominator . isOdd ) {
759- if ( a . isReal ) return ! a . is ( 0 ) ?'positive' :'non-negative' ;
772+ if ( a . isReal ) {
773+ let s = a . sgn ;
774+ return s === 'positive' || s === 'not-zero' || s === 'negative'
775+ ?'positive'
776+ :'non-negative' ;
777+ }
760778if ( a . type === 'imaginary' ) return 'negative' ;
761- return ! a . is ( 0 ) ?'not-zero' :undefined ; //already accounted for a.is(0)
762779}
763780
764781if (
@@ -847,19 +864,26 @@ export const ARITHMETIC_LIBRARY: IdentifierDefinitions[] = [
847864sgn :( [ x , n ] ) => {
848865// Note: we can't simplify this to a power, then get the sgn of that because this may cause an infinite loop
849866if ( x . isReal === false || n . isReal === false ) return 'unsigned' ;
850- if ( x . is ( 0 ) ) return n . is ( 0 ) ?'unsigned' :'zero' ;
867+ if ( x . is ( 0 ) ) {
868+ if ( n . isNonPositive ) {
869+ return 'unsigned' ;
870+ }
871+ if ( n . isPositive ) return 'zero' ;
872+ }
851873if ( x . isPositive === true ) return 'positive' ;
852- if ( n . isOdd === true ) return 'negative' ;
853- if ( n . isEven === true ) return 'unsigned' ;
874+ if ( x . isNonNegative === true ) return 'non-negative' ;
875+ if ( n . isOdd === true || ( n . numerator . isOdd && n . denominator . isOdd ) ) {
876+ return x . sgn ;
877+ }
878+ if ( x . isNegative && n . isOdd === false ) return 'unsigned' ;
854879return undefined ;
855880} ,
856881canonical :( args , { engine} ) => {
857882args = checkNumericArgs ( engine , args , 2 ) ;
858883const [ base , exp ] = args ;
859884return canonicalRoot ( base , exp ) ;
860885} ,
861- evaluate :( [ x , n ] , { numericApproximation} ) =>
862- root ( x , n , { numericApproximation} ) ,
886+ evaluate :( [ x , n ] , { numericApproximation} ) => x . root ( n ) ,
863887} ,
864888
865889Round :{
@@ -882,7 +906,6 @@ export const ARITHMETIC_LIBRARY: IdentifierDefinitions[] = [
882906if ( x . isLess ( 0.5 ) && x . isGreater ( - 0.5 ) ) return 'zero' ;
883907if ( x . isNonNegative ) return 'non-negative' ;
884908if ( x . isNonPositive ) return 'non-positive' ;
885- if ( x . isReal ) return 'real' ;
886909return undefined ;
887910} ,
888911evaluate :( [ x ] ) =>
@@ -958,7 +981,7 @@ export const ARITHMETIC_LIBRARY: IdentifierDefinitions[] = [
958981if ( x . isPositive ) return 'positive' ;
959982if ( x . isNegative ) return 'unsigned' ;
960983if ( x . isNonNegative ) return 'non-negative' ;
961- if ( ! x . is ( 0 ) ) return 'not-zero' ;
984+ if ( x . sgn === 'not-zero' ) return 'not-zero' ;
962985return undefined ;
963986} ,
964987evaluate :( [ x ] , { numericApproximation, engine} ) => {
@@ -979,8 +1002,13 @@ export const ARITHMETIC_LIBRARY: IdentifierDefinitions[] = [
9791002signature :'number -> number' ,
9801003sgn :( [ x ] ) => {
9811004if ( x . is ( 0 ) ) return 'zero' ;
982- if ( x . isReal ) return ! x . is ( 0 ) ?'positive' :'non-negative' ;
983- if ( x . type === 'imaginary' || x . type === 'complex' ) return 'negative' ;
1005+ if ( x . isReal ) {
1006+ let s = x . sgn ;
1007+ return s === 'not-zero' || s === 'positive' || s === 'negative'
1008+ ?'positive'
1009+ :'non-negative' ;
1010+ }
1011+ if ( x . type === 'imaginary' ) return 'negative' ;
9841012if ( x . isReal == false || x . isNaN ) return 'unsigned' ;
9851013return undefined ;
9861014} ,