Skip to content

Instantly share code, notes, and snippets.

@etale
Last active December 23, 2015 21:39
Show Gist options
  • Save etale/6698339 to your computer and use it in GitHub Desktop.
Save etale/6698339 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, user-scalable=no">
<meta charset="UTF-8">
<title>Natural Calc</title>
<style>
body {
width: 100%;
position: fixed;
bottom: 0;
overflow: auto;
display: -webkit-box;
-webkit-box-orient: vertical;
margin: 0;
font-size: 1.5rem;
font-family: serif;
-webkit-text-size-adjust: 100%;
-moz-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
-o-text-size-adjust: 100%;
text-size-adjust: 100%;
}
.focus {
background-color: #fff;
}
.button {
color: #eee;
background-color: #444;
}
table {
width: 100%;
border-collapse: collapse;
}
#display {
background-color: #eee;
border: 0;
border-collapse: collapse;
}
#display input {
width: 100%;
font-family: serif;
font-size: 1.5rem;
color: #aaa;
background-color: transparent;
margin: 0;
border: 0;
}
#display td {
text-align: right;
background-color: transparent;
padding: 0 10px;
margin: 0;
border: 0;
}
#keypad td {
width: 16.6667%;
text-align: center;
color: #eee;
background-color: #444;
padding: 0.75rem;
border: 0;
}
</style>
<script>
var
pi2 = Math.PI * 2, nil = 'nil',
equal = function(a, b) {
return a.ord === b.ord && a.arg === b.arg
},
shift = function(a) {
return (a === 0) ? 0 : {ord: a.ord + 1, arg: a.arg}
},
succ = function(a) {
return log(shift(exp(a)))
},
add = function(a, b) {
return (a === nil || b === nil) ? nil :
(a === 0 ) ? b :
(b === 0 ) ? a :
equal(a, minus(b)) ? 0 :
(a.ord < b.ord) ? add(b, a) :
mul(a, succ(mul(inverse(a), b)))
},
mul = function(a, b) {
return (a === nil || b === nil) ? nil :
(a === 0 || b === 0 ) ? 0 :
{ord: a.ord + b.ord, arg: (a.arg + b.arg) % 1}
},
minus = function(a) {
return (a === nil) ? nil :
(a === 0 ) ? 0 :
{ord: a.ord, arg: (a.arg + 0.5) % 1}
},
inverse = function(a) {
return (a === nil) ? nil :
(a === 0 ) ? nil :
{ord: - a.ord, arg: (a.arg === 0) ? 0 : (1 - a.arg)}
},
_log = function(a) {
var ord, arg
if (a.arg >= 0.5) a.arg -= 1
a.arg *= pi2
ord = Math.log(a.ord * a.ord + a.arg * a.arg) * 0.5
arg = Math.atan2(a.arg, a.ord) / pi2
if (arg < 0) arg += 1
return {ord: ord, arg: arg}
},
log = function(a) {
return (a === nil || a === 0) ? nil :
(a.ord === 0 && a.arg === 0) ? 0 :
_log(a)
},
_exp = function(a) {
var ord, arg
if (a.arg >= 0.5) a.arg -= 1
a.arg *= pi2
ord = Math.exp(a.ord) * Math.cos(a.arg)
arg = (Math.exp(a.ord) * Math.sin(a.arg) / pi2) % 1
if (arg < 0) arg += 1
return {ord: ord, arg: arg}
},
exp = function(a) {
return (a === nil) ? nil :
(a === 0 ) ? {ord: 0, arg: 0} :
_exp(a)
}
var
e, touch,
isFixed = function() {
return e.hasOwnProperty('value')
},
fix = function() {
var _, ord, arg
if (isFixed()) return
_ = e.data.textContent.split('.')
_ = [0, 1, 2].map(function(i) {
return _[i] ? _[i] : '0'
})
ord = parseFloat(_[0] + '.' + _[1])
arg = parseFloat( '0.' + _[2])
set(log({ord: ord, arg: arg}))
},
fixAsIs = function() {
var _, ord, arg
if (isFixed()) {
set(exp(e.value))
} else
{
_ = e.data.textContent.split('.')
_ = [0, 1, 2].map(function(i) {
return _[i] ? _[i] : '0'
})
ord = parseFloat(_[0] + '.' + _[1])
arg = parseFloat( '0.' + _[2])
set({ord: ord, arg: arg})
}
},
moveFocus = function() {
e.classList.remove('focus')
this.cell.classList.add('focus')
e = this.cell
},
makeCell = function() {
var cell = document.createElement('tr')
var label = document.createElement('td')
var input = document.createElement('input')
var data = document.createElement('td')
label.appendChild(input)
cell.appendChild(label)
cell.appendChild(data)
cell.label = input
cell.data = data
input.cell = cell
input.onchange = function() {
if (this.value === '') {
this.cell.data[touch] = moveFocus
while (this.cell.previousSibling.label.value !== '') {
display.insertBefore(this.cell, this.cell.previousSibling)
}
this.cell.classList.remove('button')
} else
{
this.cell.data[touch] = function() {
isFixed() && push(); set(this.cell.value)
}
if (e === this.cell) {
fix()
e.previousSibling ? e.previousSibling.data[touch]() : push()
}
this.cell.classList.add('button')
while (this.cell.nextSibling && this.cell.nextSibling.label.value === '') {
display.insertBefore(this.cell, this.cell.nextSibling.nextSibling)
}
while (this.cell.nextSibling && this.cell.nextSibling.value.ord < this.cell.value.ord) {
display.insertBefore(this.cell, this.cell.nextSibling.nextSibling)
}
}
}
data.cell = cell
data.textContent = '0'
data[touch] = moveFocus
return cell
},
push = function() {
display.insertBefore(makeCell(), e.nextSibling)
e.nextSibling.data[touch]()
},
pop = function() {
var value = e.value
if (!e.previousSibling) {
return
}
e.previousSibling.data[touch]()
display.removeChild(e.nextSibling)
return value
},
set = function(a) {
var aord, aarg
e.value = a
if (a === nil) {
e.data.textContent = nil
} else
if (a === 0) {
e.data.textContent = '0'
} else
{
aord = a.ord.toFixed(6).split('.')
aarg = a.arg.toFixed(6).split('.')
aord[1] = aord[1] ? aord[1] : '0'
aarg[1] = aarg[1] ? aarg[1] : '0'
e.data.textContent = aord[0] + '.' + aord[1] + '.' + aarg[1] + 'X'
}
},
numeric = function() {
var label = this.textContent
if (isFixed()) {
push(); e.data.textContent = label
} else
{
if (e.data.textContent === '0') {
e.data.textContent = label
} else
{
e.data.textContent += label
}
}
},
keys = {
'0': numeric,
'1': numeric,
'2': numeric, '3': numeric, '4': numeric, '5': numeric,
'6': numeric, '7': numeric, '8': numeric, '9': numeric,
'.': function() {
isFixed() && push()
e.data.textContent += '.'
},
'↑': function() {
if (isFixed()) {
push(); set(e.previousSibling.value)
} else
{
fix()
}
},
'↓': function() {
if (e.previousSibling) {
pop()
} else
{
delete e.value
e.data.textContent = '0'
}
},
'←': function() {
if (isFixed()) {
delete e.value
e.data.textContent = '0'
} else
{
e.data.textContent = e.data.textContent.slice(0, -1)
if (e.data.textContent === '') {
e.data.textContent = '0'
}
}
},
'g': function() {
isFixed() && push(); set({ord: 10.7352, arg: 0})
},
'm': function() {
isFixed() && push(); set({ord: 80.1104, arg: 0})
},
's': function() {
isFixed() && push(); set({ord: 99.6290, arg: 0})
},
'exp': function() {
fixAsIs()
},
'log': function() {
fix(); set(log(e.value))
},
'/': function() {
fix(); set(inverse(e.value))
},
'−': function() {
fix(); set(minus(e.value))
},
'\\': function() {
alert('Not Implemented')
},
' ': function() {
if (e.previousSibling) {
fix(); _ = pop(); set(mul(e.value, _))
}
},
'+': function() {
if (e.previousSibling) {
fix(); _ = pop(); set(add(e.value, _))
}
}
}
touch = document.createElement('div')
.hasOwnProperty('ontouchend') ? 'ontouchend' : 'onmouseup';
var
display = document.createElement('table'),
keypad = document.createElement('table')
e = makeCell()
display.appendChild(e)
display.setAttribute('id', 'display');
[
['↑' , '↓', '←', '7', '8', '9'],
['g' , 'm', 's', '4', '5', '6'],
['log', ' ', '/', '1', '2', '3'],
['exp', '+', '−', '0', '.', '\\']
].forEach(function(tds) {
var tr = document.createElement('tr')
tds.forEach(function(td) {
var _ = document.createElement('td')
_.textContent = td
_[touch] = keys[td]
tr.appendChild(_)
})
keypad.appendChild(tr)
})
keypad.setAttribute('id', 'keypad')
onload = function() {
document.body.appendChild(display)
document.body.appendChild(keypad)
}
</script>
</head>
<body></body>
</html>
@etale
Copy link
Author

etale commented Dec 25, 2013

calc.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment