From c24f86500eeb8de950a3d35edfd49190fc95d053 Mon Sep 17 00:00:00 2001 From: wan-may Date: Sat, 7 Oct 2023 16:38:00 -0300 Subject: [PATCH] Fix infinite loop bug, add FFI enum test, add moving camera --- enumerations.lua | 36 +++++++++++++++++++- main.lua | 86 +++++++++++++++++++++++++++--------------------- twintree.lua | 2 ++ 3 files changed, 86 insertions(+), 38 deletions(-) diff --git a/enumerations.lua b/enumerations.lua index 1c20993..4157127 100644 --- a/enumerations.lua +++ b/enumerations.lua @@ -1,4 +1,27 @@ local enum = require 'enumeration' +local ffi = require 'ffi' + +local function NadFFI( p ) + local rmt = { + __lt = function(a, b) return a.n / a.d < b.n / b.d end, + __eq = function(a, b) return a.n == b.n and a.d == b.d end, + __call = function(t) return t.n / t.d end, + __tostring = function(t) return string.format( "<%d/%d>", t.n, t.d ) end + } + ffi.cdef "typedef struct { uint32_t n, d; } rational;" + ffi.metatype( "rational", rmt ) + local list = ffi.new( "rational[?]", 123456 ) + local d, i = 1, 1 + repeat + d = d * p + for n = d - 1, 1, -p do + list[i].n = n + list[i].d = d + i = i + 1 + end + until i > 123456 / p + return list +end local function CalkinWilf() local n, d = 1, 1 @@ -79,8 +102,19 @@ local function Dyad() end ) end +local function Nad( p ) + local n, d = -1, p + return enum( function() + n = n + p + if n > d then n, d = 1, d * p end + return n / d + end ) +end + return { - Dyad = Dyad, + Dyad = Dyad, + NadFFI = NadFFI, + Nad = Nad, SternBrocot = SternBrocot, CalkinWilf = CalkinWilf, Random = Random, diff --git a/main.lua b/main.lua index 8d037d3..49a825b 100644 --- a/main.lua +++ b/main.lua @@ -1,8 +1,8 @@ local enumerations = require 'enumerations' local twintree = require 'twintree' local step = coroutine.wrap( twintree.buildIncremental ) -local a = enumerations.Dyad() -local b = enumerations.Random() +local a = enumerations.NadFFI( 2 ) +local b = enumerations.SternBrocot() step( a, b ) --Use LOVE for plotting. @@ -11,36 +11,28 @@ local love = assert( love ) local canvas = love.graphics.newCanvas() local numMapped, pointList = 0 -local function swap( i, j ) - b[i], b[j] = b[j], b[i] -end - -local function reset() - print( "changing coroutine" ) - step = coroutine.wrap( twintree.buildIncremental ) - print( "swapping" ) - for i = 1, 10000 do - swap( i, math.random( 1, 10000 ) ) - end - - pointList = nil - numMapped = 0 - print( "step" ) - step( a, b ) -end - local function new() pointList = step() - numMapped = numMapped + 1 + numMapped = #pointList / 2 +end + +local cx, cy = 0.0, 0.0 +local zoomFactor = 1 +local function zoom( out ) + cx = cx + 0.5 * ( out - 1 ) / ( out * zoomFactor ) + cy = cy + 0.5 * ( out - 1 ) / ( out * zoomFactor ) + zoomFactor = zoomFactor * out + love.graphics.setLineWidth( 0.005 / zoomFactor ) end local function paint() + if not pointList then return end local type = type --Make sure the whole point list consists of numbers! --We use the __call metamethod in non-number elements to coerce to numbers. --TODO: make this more generic, maybe amenable to FFI types. for i = 1, #pointList do - if type( pointList[i] ) ~= 'number' then pointList[i] = pointList[i]() end + if type( pointList[i] ) ~= 'number' then pointList[i] = pointList[i]( pointList[i] ) end end --print( "Points: " ) @@ -50,30 +42,34 @@ local function paint() love.graphics.setCanvas( canvas ) love.graphics.clear() - love.graphics.setColor( 1, 1, 1, 0.5 ) - love.graphics.print( numMapped ) + love.graphics.print( ("%d\n%4.2f\n%4.2f\n%4.2f"):format( numMapped, cx, cy, zoomFactor ) ) love.graphics.push() love.graphics.scale( love.graphics.getWidth(), love.graphics.getHeight() ) love.graphics.translate( 0, 1 ) love.graphics.scale( 1, -1 ) - love.graphics.points( pointList ) + love.graphics.scale( zoomFactor, zoomFactor ) + love.graphics.translate( -cx, -cy ) + + love.graphics.setColor( 1, 1, 1, 0.3 ) + love.graphics.line( 0,0, 1,0 ) + love.graphics.line( 0,0, 0,1 ) + love.graphics.line( 0, 0, 1, 1 ) love.graphics.line( pointList ) + love.graphics.setColor( 1, 0, 0, 0.1 * zoomFactor ) + love.graphics.points( pointList ) love.graphics.pop() love.graphics.setCanvas() end -function love.wheelmoved() - for i = 1, 3 do new() end +function love.wheelmoved( x, y ) + zoom( ( y > 0 ) and 1.01 or 0.99 ) paint() - --[[ for i = 1, #sb do - print( i, sb[i], dy[i] ) - end]] end function love.mousepressed() - --[[for i = 1, #sb do - print( i, sb[i] ) - end]] + --pointList = twintree.flat( twintree.build( 10000, a, b ) ) + --numMapped = #pointList / 2 + paint() end function love.draw() @@ -82,11 +78,27 @@ function love.draw() love.graphics.draw( canvas ) end -function love.keypressed() - print( "pressed key!" ) - return reset() and love.wheelmoved() +function love.update( dt ) + local repaint = false + if love.keyboard.isScancodeDown "r" then repaint = true; new() end + if love.keyboard.isScancodeDown "a" then repaint = true; cx = cx - dt * 0.1 / math.sqrt( zoomFactor ) end + if love.keyboard.isScancodeDown "d" then repaint = true; cx = cx + dt * 0.1 / math.sqrt( zoomFactor ) end + if love.keyboard.isScancodeDown "w" then repaint = true; cy = cy + dt * 0.1 / math.sqrt( zoomFactor ) end + if love.keyboard.isScancodeDown "s" then repaint = true; cy = cy - dt * 0.1 / math.sqrt( zoomFactor ) end + if love.keyboard.isScancodeDown "q" then repaint = true; zoom( 1 + dt ) end + if love.keyboard.isScancodeDown "e" then repaint = true; zoom( 1 - dt ) end + if repaint then return paint() end +end + +function love.keypressed( key, code, isrepeat) + return paint() end function love.load() - love.graphics.setLineWidth( 0.001 ) + --pointList = twintree.flat( twintree.build( 10000, a, b ) ) + --numMapped = #pointList / 2 + new() + love.graphics.setPointSize( 3 ) + love.graphics.setLineWidth( 0.005 ) + paint() end \ No newline at end of file diff --git a/twintree.lua b/twintree.lua index 7fd95c3..b81dc51 100644 --- a/twintree.lua +++ b/twintree.lua @@ -46,6 +46,8 @@ local function insert( aTree, aSeq, aVals, bTree, bSeq, bVals ) newCandidate = true end end + + --print( "Inserting element in tree:", aIdx, aVal, bIdx, bVal ) --Insert elements into tree. aTree[treeIdx], bTree[treeIdx] = aVal, bVal