Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
| Author |
Topic |
|
Onamuji
Aged Yak Warrior
504 Posts |
Posted - 2002-09-04 : 21:42:57
|
Ok so I'm bored and I came up with this wacky idea to convert my C++ program that generates Mandlebrot sets (wrote it for a chaos theory class back in college) into T-SQL, just for kicks to see if I could do it set-based rather than using loops. So here's what I have so far: SET NOCOUNT ONIF ISNULL(OBJECTPROPERTY(OBJECT_ID(N'MBS_Sequences'), N'IsTable'), 0) = 0 BEGIN CREATE TABLE MBS_Sequences (Value INT NOT NULL PRIMARY KEY) WHILE (SELECT ISNULL(MAX(Value), -1) FROM MBS_Sequences) < 8192 INSERT INTO MBS_Sequences SELECT ISNULL(MAX(Value), -1) + 1 FROM MBS_Sequences ENDIF OBJECTPROPERTY(OBJECT_ID(N'MBS_Calculate'), N'IsProcedure') = 1 DROP PROCEDURE MBS_CalculateGOCREATE PROCEDURE MBS_Calculate( @OffsetX DECIMAL(38, 10), @OffsetY DECIMAL(38, 10), @ScalePercent DECIMAL(38, 10), @EscapeValue DECIMAL(38, 10), @Iterations INT, @Width INT, @Height INT) AS SET NOCOUNT ON DECLARE @x INT, @y INT, @i INT, @CX DECIMAL(38, 10), @CY DECIMAL(38, 10), @X1 DECIMAL(38, 10), @X2 DECIMAL(38, 10), @Y1 DECIMAL(38, 10), @Y2 DECIMAL(38, 10), @Value DECIMAL(38, 10) CREATE TABLE #Mandlebrot (X INT, Y INT, I INT) SET @x = 0 WHILE @x < @Width BEGIN SET @y = 0 WHILE @y < @Height BEGIN SET @CX = (CAST(@x AS DECIMAL(38, 10)) - @OffsetX) / @ScalePercent SET @CY = (@OffsetY - CAST(@y AS DECIMAL(38, 10))) / @ScalePercent SET @X1 = @CX SET @Y1 = @CY SET @i = 0 WHILE @i < @Iterations AND @i <> -1 BEGIN SET @X2 = POWER(@X1, 2) - POWER(@Y1, 2) + @CX SET @Y2 = 2.0 * @X1 * @Y1 + @CY SET @Value = POWER(@X2, 2) + POWER(@Y2, 2) SET @X1 = @X2 SET @Y1 = @Y2 IF @Value > @EscapeValue BEGIN INSERT INTO #Mandlebrot (X, Y, I) VALUES (@x, @y, @i + 1) SET @i = -1 END ELSE SET @i = @i + 1 END SET @Value = POWER(@X2, 2) + POWER(@Y2, 2) IF @Value < @EscapeValue INSERT INTO #Mandlebrot (X, Y, I) VALUES (@x, @y, 0) SET @y = @y + 1 END SET @x = @x + 1 END SELECT * FROM #Mandlebrot WHERE I > 1/* -- Generic Algorithm for x = 0; x < @Width for y = 0; y < @Height cy = (@OffsetY - y.Value) / @ScalePercent cx = (x.Value - @OffsetX) / @ScalePercent x = cx y = cy for each k.Value x1 = x * x - y * y + cx y1 = 2.0 * x * y + cy r = x1 * x1 + y1 * y1 x = x1 y = y1 if r > @EscapeValue then k.Value + 1 for x,y end if (x1 * x1 + y1 * y1) < @EscapeValue then -1 end end -- I was thinking something like SELECT x.Value AS x, y.Value AS y, CASE ... SOMETHING ... END AS i FROM (SELECT Value FROM MBS_Sequences WHERE Value BETWEEN 0 AND @Width - 1) AS x, (SELECT Value FROM MBS_Sequences WHERE Value BETWEEN 0 AND @Height - 1) AS y, (SELECT Value FROM MBS_Sequences WHERE Value BETWEEN 0 AND @Iterations - 1) AS i, -- But I couldn't figure out how to sum X1 and X2 when looping through i*/GOEXEC MBS_Calculate 250, 200, 100, 4.0, 100, 320, 240 That will work ... it generates the correct values except its super slow for one but it will probably be slow no matter what ... I just want to see a set-based version of it... I think this would be a great reader challenge If you want to see the C++ code for it and/or the program just email me. Good luck all... I'm gonna be up all night working on this Edited by - onamuji on 09/06/2002 12:16:50 |
|
|
Arnold Fribble
Yak-finder General
1961 Posts |
Posted - 2002-09-05 : 15:40:31
|
I don't think you can make it completely set-based because you fundamentally cannot replace the recurrence z -> z^2 + c with something that doesn't require a loop.You can use a UDF to return the count for a point:CREATE FUNCTION MandPoint(@cx float, @cy float, @imax int)RETURNS INTASBEGIN DECLARE @i int, @x float, @y float, @t float SET @i = 0 SET @x = 0.0 SET @y = 0.0 WHILE @i < @imax BEGIN SET @t = @x*@x - @y*@y + @cx SET @y = 2*@x*@y + @cy SET @x = @t IF (@x*@x + @y*@y) > 4.0 BREAK SET @i = @i + 1 END RETURN CASE WHEN @i = @imax THEN -1 ELSE @i ENDEND and write the rest in a set-based way generating the x and y coordinates from tally tables, but that's about it.Edited by - Arnold Fribble on 09/05/2002 15:50:33 |
 |
|
|
Onamuji
Aged Yak Warrior
504 Posts |
Posted - 2002-09-06 : 10:13:02
|
That's such a bummer ... I'm 60% sure it can be done with multiple UPDATE's and SELECT statements |
 |
|
|
Arnold Fribble
Yak-finder General
1961 Posts |
Posted - 2002-09-06 : 10:30:32
|
| Yes, ok, you could generate a temporary table with xpoints*ypoints*maxit rows so that all the rows for a point are 'consecutive' (in the sense that UPDATE sees them together), and use an UPDATE with a few variables to construct each Z(i), and then get the largest iteration for each point. But I wouldn't consider this use of UPDATE to be set-based. And the size of the temporary table will be truly huge! |
 |
|
|
|
|
|
|
|