XNS Utility Script

The XNS_Utility.js file defines several basic functions and values used and/or available for use with the XNS suite. The idea is to simplify certain basic operations of the suite.

isNegative() functions

The returnTrue function unconditionally returns true. The returnFalse function unconditionally returns false. The returnFalseIfNaN function returns true if and only if this is not an XNS number. Typically, these functions are assigned directly as the isNegative method of an XNS constructor's prototype property.

var returnTrue = function() {
   return true
   }

var returnFalse = function() {
   return false
   }

var returnFalseIfNaN = function() {
   return (this.compareTo(0) < 2)
// Numbers will always return -1, 0, or 1 for compareTo, so for numbers this returns true.
// NaN is not less than 2, so for NaN this returns false.
// It is inadvisable to use this function outside of the Number XNS type.
   }

isXNSNaN()

This function returns true if the this object is not recognized as an XNS number. It also returns true for any XNS number constructed with the XNS_NaN() function, or for any number or string value which is not a number in JavaScript. Absent any of these conditions, the function returns false.

function isXNSNaN(arg) {
   var type = typeof arg
   switch (type) {
      case "number":
      case "string":
      return isNaN(arg)

      case "object":
      return ((typeof XNS_Types[arg.xnsType] != "boolean")||(XNS_Types[arg.xnsType] != true))
/*  The first checks to see if that type has been registered.  The second checks to see if that type is active.  The third 
checks a specific property of the number which the script has set.

There are three special xnsType reserved values:  "+Infinity", "-Infinity", and "NaN".  For the first two, XNS_Types = true.
For the last, XNS_Types = false.
*/
      break;

      default:
      }
   return true
   }

toLiteralString()

XNS provides the ability to retrieve a literal notation for an XNS number. To do so correctly, XNS must extend the current JavaScript implementation with a few methods for core JavaScript constructors.

Each of these functions (with the exception of Number) returns "new constructorName(value)".

String.prototype.toLiteralString = function() {
   var response = this.replace(/\\/g, "\\\\")
   response = response.replace(/\"/g, '\\"')
   response = response.replace(/\'/g, "\\'")
   return "'" + response + "'"
   }

Array.prototype.toLiteralString = function() {
   var args = []
   for (var property in this) {
      if (typeof this[property].toLiteralString == "function") {
         args[property] = this[property].toLiteralString()
         } else {
         args[property] = this[property]
         }
      }
   return "[" + args.join(",") + "]"
   }

Date.prototype.toLiteralString = function() {
   return "new Date(" + this * 1 + ")"
   }

Error.prototype.toLiteralString = function() {
   return "new Error('" + this.message.toLiteralString() + "')"
   }

Number.prototype.toLiteralString = Number.prototype.toString

XNS_Types

This is an array intended for storing an order of preference for XNS number types. Currently, it stores true and false values, though these values I expect to replace with number values in the near future.

var XNS_Types = []
XNS_Types["+Infinity"] = true
XNS_Types["-Infinity"] = true
XNS_Types["NaN"] = false

MathML Namespace

For the toMathML() functions, we need a common variable referencing the MathML namespace.

const xmlns_math = "http://www.w3.org/1998/Math/MathML"

Compound Inequalities And Logical Operators

One weakness of JavaScript in terms of conditional statements is the inability to succinctly declare a compound inequality such as "3 < x < 5". For JavaScript number types, this statement would typically be:

if ((3 < x) && (x < 5)) { /* statements */ }

But, using the compareTo() methods as most XNS numbers will require, it would actually be:

if (((3).compareTo(x) == -1) && (x.compareTo(5) == -1)) { /* statements */ }

XNS provides a function to simplify this expression:

if (ineq(3, LT, x, LT, 5)) { /* statements */ }

There are eight unique top-level objects XNS_Utility.js creates:

const LT = {}, LTE = {}, EQ = {}, LGT = {}, GT = {}, GTE = {}
const AND = {}, OR = {}

These indicate the following:

XNS Top-Level Comparison Objects
LT The argument preceding LT must be less than the argument following LT.
LTE The argument preceding LTE must be less than or equal to the argument following LTE.
EQ The argument preceding EQ must be equal to the argument following EQ.
LGT The argument preceding LGT must be less than or greater than the argument following LGT.
GT The argument preceding GT must be greater than the argument following GT.
GTE The argument preceding GTE must be greater than or equal to the argument following GTE.
AND Both the conditions immediately preceding AND and the conditions immediately following AND must be true.
OR Either the conditions immediately preceding OR or the conditions immediately following OR must be true.

The ineq() function requires an odd number of arguments, at least 3. Each even argument must be one of these eight constant values, and each odd argument must be a variable or XNS number you wish to compare.

function ineq(num0, comp0, num1) {
   var in_flag = 1
   /* 
   in_flag == 2:  unconditionally true
   in_flag == 1:  true so far, unconfirmed
   in_flag == 0:  false so far, unconfirmed
   in_flag == -1:  unconditionally false
   */
   var in_loop = 0
   var left = null, right = null, op = null, result = null
   for (in_loop = 1; (in_loop < arguments.length)&&(in_flag < 2)&&(in_flag > -1); in_loop+=2) {
      left = arguments[in_loop - 1]
      right = arguments[in_loop + 1]
      op = arguments[in_loop]
      result = left.compareTo(right)

      switch (true) {
/* The goal of each loop through is to find a condition which returns false.  In this situation, 
   we can set the in_flag to 0.

An OR condition means we can add one to in_flag.  An AND condition means that if it is currently 
   false, we must end our search.

Because NaN does not compare well to other numbers, I explicitly must state conditions which 
   would pass LTE, LGT and GTE, and then negate those results.

*/

         case ((op == LT)&&(result != -1)):
         case ((op == LTE)&&( !((result == 0)||(result == -1)) )):
         case ((op == EQ)&&(result != 0)):
         case ((op == LGT)&&( !((result == -1)||(result == 1)) )):
         case ((op == GT)&&(result != 1)):
         case ((op == GTE)&&( !((result == 0)||(result == 1)) )):
         in_flag = 0
         break;

         case (op == OR):
         in_flag++
         break;

         case (op == AND):
         if (in_flag < 1) {
            in_flag = -1
            }
         break;

         default:
         }

      }
   var response = false
   if (in_flag > 0) {
      response =  true
      }
   return response
   }

Back to the Main Page.

docs/Utility.html created May 23, 2002.