Files
cell/internal/number.cm
2025-12-18 18:43:23 -06:00

170 lines
4.2 KiB
Plaintext

/* number.cm - number conversion and math utilities */
var _floor = Math.floor
var _ceil = Math.ceil
var _round = Math.round
var _abs = Math.abs
var _trunc = Math.trunc
var _min = Math.min
var _max = Math.max
var _pow = Math.pow
var _parseInt = parseInt
var _parseFloat = parseFloat
function number(val, format) {
if (val == true) return 1
if (val == false) return 0
if (typeof val == 'number') return val
if (typeof val == 'string') {
if (typeof format == 'number') {
// radix conversion
if (format < 2 || format > 36) return null
var result = _parseInt(val, format)
if (isNaN(result)) return null
return result
}
if (typeof format == 'string') {
return parse_formatted(val, format)
}
// default: parse as decimal
var result = _parseFloat(val)
if (!isa(result, number)) return null
return result
}
return null
}
function parse_formatted(str, format) {
if (!format || format == "" || format == "n") {
var result = _parseFloat(str)
if (isNaN(result)) return null
return result
}
switch (format) {
case "u": // underbar separator
str = str.split('_').join('')
break
case "d": // comma separator
str = str.split(',').join('')
break
case "s": // space separator
str = str.split(' ').join('')
break
case "v": // European style: period separator, comma decimal
str = str.split('.').join('')
str = str.replace(',', '.')
break
case "l": // locale - treat like 'd' for now
str = str.split(',').join('')
break
case "i": // integer with underbar
str = str.split('_').join('')
break
case "b": // binary
return _parseInt(str, 2)
case "o": // octal
return _parseInt(str, 8)
case "h": // hex
return _parseInt(str, 16)
case "t": // base32
return _parseInt(str, 32)
case "j": // JavaScript style prefix
if (str.startsWith('0x') || str.startsWith('0X'))
return _parseInt(str.slice(2), 16)
if (str.startsWith('0o') || str.startsWith('0O'))
return _parseInt(str.slice(2), 8)
if (str.startsWith('0b') || str.startsWith('0B'))
return _parseInt(str.slice(2), 2)
return _parseFloat(str)
default:
return null
}
var result = _parseFloat(str)
if (isNaN(result)) return null
return result
}
number.whole = function(n) {
if (typeof n != 'number') return null
return _trunc(n)
}
number.fraction = function(n) {
if (typeof n != 'number') return null
return n - _trunc(n)
}
number.floor = function(n, place) {
if (typeof n != 'number') return null
if (place == null || place == 0) return _floor(n)
var mult = _pow(10, place)
return _floor(n * mult) / mult
}
number.ceiling = function(n, place) {
if (typeof n != 'number') return null
if (place == null || place == 0) return _ceil(n)
var mult = _pow(10, place)
return _ceil(n * mult) / mult
}
number.abs = function(n) {
if (typeof n != 'number') return null
return _abs(n)
}
number.round = function(n, place) {
if (typeof n != 'number') return null
if (place == null || place == 0) return _round(n)
var mult = _pow(10, place)
return _round(n * mult) / mult
}
number.sign = function(n) {
if (typeof n != 'number') return null
if (n < 0) return -1
if (n > 0) return 1
return 0
}
number.trunc = function(n, place) {
if (typeof n != 'number') return null
if (place == null || place == 0) return _trunc(n)
var mult = _pow(10, place)
return _trunc(n * mult) / mult
}
number.min = function(...vals) {
if (vals.length == 0) return null
var result = vals[0]
for (var i = 1; i < vals.length; i++) {
if (typeof vals[i] != 'number') return null
if (vals[i] < result) result = vals[i]
}
return result
}
number.max = function(...vals) {
if (vals.length == 0) return null
var result = vals[0]
for (var i = 1; i < vals.length; i++) {
if (typeof vals[i] != 'number') return null
if (vals[i] > result) result = vals[i]
}
return result
}
number.remainder = function(dividend, divisor) {
if (typeof dividend != 'number' || typeof divisor != 'number') return null
if (divisor == 0) return null
return dividend - (_trunc(dividend / divisor) * divisor)
}
return number