Skip to content

Instantly share code, notes, and snippets.

@etale
Created October 14, 2013 13:56
Show Gist options
  • Save etale/6976058 to your computer and use it in GitHub Desktop.
Save etale/6976058 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>
html, body {
width: 100%;
height: 100%;
padding: 0;
border: 0;
margin: 0;
font-size: 1.5rem;
font-family: serif;
background-color: transparent;
-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;
}
div {
width: 100%;
height: 100%;
}
table {
width: 100%;
border-collapse: collapse;
}
#display {
background-color: #eee;
}
#display input {
width: 100%;
font-family: none;
font-size: 1.5rem;
color: #aaa;
background-color: transparent;
border: 0;
}
#display td {
text-align: right;
padding: 0 0.5rem;
}
#keypad {
position: fixed;
bottom: 0;
}
#keypad td {
width: 16.6667%;
text-align: center;
color: #eee;
padding: 0.5rem;
}
</style>
<script>
var pi2 = Math.PI * 2, nil = 'nil'
var equal = function(a, b) {
return a.ord === b.ord && a.arg === b.arg
}
var shift = function(a) {
return (a === 0) ? 0 : {ord: a.ord + 1, arg: a.arg}
}
var succ = function(a) {
return log(shift(exp(a)))
}
var 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)))
}
var 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}
}
var minus = function(a) {
return (a === nil) ? nil :
(a === 0 ) ? 0 :
{ord: a.ord, arg: (a.arg + 0.5) % 1}
}
var inverse = function(a) {
return (a === nil) ? nil :
(a === 0 ) ? nil :
{ord: - a.ord, arg: (a.arg === 0) ? 0 : (1 - a.arg)}
}
var _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}
}
var log = function(a) {
return (a === nil || a === 0) ? nil :
(a.ord === 0 && a.arg === 0) ? 0 :
_log(a)
}
var _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}
}
var exp = function(a) {
return (a === nil) ? nil :
(a === 0 ) ? {ord: 0, arg: 0} :
_exp(a)
}
var e, touch
var isFixed = function() {
return e.hasOwnProperty('value')
}
var 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}))
}
var 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})
}
}
var moveFocus = function() {
e.classList.remove('focus')
this.cell.classList.add('focus')
e = this.cell
// alert(keypad.offsetTop)
scrollTo(0,
e.offsetTop + e.offsetParent.offsetTop -
keypad.offsetTop + 70)
}
var 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
}
var push = function() {
display.insertBefore(makeCell(), e.nextSibling)
e.nextSibling.data[touch]()
}
var pop = function() {
var value = e.value
if (!e.previousSibling) {
return
}
e.previousSibling.data[touch]()
display.removeChild(e.nextSibling)
return value
}
var 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(8).split('.')
aarg = a.arg.toFixed(8).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'
}
}
var 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
}
}
}
var
c = Math.log(2.997924580e+08),
h = Math.log(1.054571726e-31),
G = Math.log(6.673840000e-14),
g = (- h + G - c)/2,
m = (- h - G + 3 * c)/2,
s = (- h - G + 5 * c)/2
var 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: g, arg: 0})
},
'm': function() {
isFixed() && push(); set({ord: m, arg: 0})
},
's': function() {
isFixed() && push(); set({ord: s, 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')
var 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]
_.classList.add('button')
tr.appendChild(_)
})
keypad.appendChild(tr)
})
keypad.setAttribute('id', 'keypad')
onload = function() {
document.body.appendChild(document.createElement('div'))
document.body.appendChild(display)
document.body.appendChild(keypad)
document.body.appendChild(document.createElement('div'))
e.data[touch]()
}
</script>
</head>
<body></body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment