Asked by:
Small Basic Subroutine Library Project

I sometimes use same subroutines in different programs. For example, I used Math_CartesianToPolar() in a new program today. Actually I used this subroutine in several programs.
My suggestion is to collect these kind of useful subroutines here and if possible with test code like below.
' Math_CartesianToPolar Test Program GraphicsWindow.Title = "Test  Cartesian to Polar" gw = 598 gh = 428 GraphicsWindow.Width = gw GraphicsWindow.Height = gh color = "LightGray" dx = 10 dy = 10 x1 = Math.Remainder(gw / 2, dx)  dx x2 = gw  x1 y1 = Math.Remainder(gh / 2, dy)  dy y2 = gh  y1 DrawGrid() color = "Gray" dx = 100 dy = 100 x1 = Math.Remainder(gw / 2, dx)  dx x2 = gw  x1 y1 = Math.Remainder(gh / 2, dy)  dy y2 = gh  y1 DrawGrid() GraphicsWindow.BrushColor = "Black" xText = Shapes.AddText("") Shapes.Move(xText, 10, 20) yText = Shapes.AddText("") Shapes.Move(yText, 10, 40) rText = Shapes.AddText("") Shapes.Move(rText, 10, 60) aText = Shapes.AddText("") Shapes.Move(aText, 10, 80) x2Text = Shapes.AddText("") Shapes.Move(x2Text, 10, 100) y2Text = Shapes.AddText("") Shapes.Move(y2Text, 10, 120) GraphicsWindow.MouseMove = OnMouseMove While "True" If mouseMove Then x = mx  gw / 2 y = my  gh / 2 Math_CartesianToPolar() Shapes.SetText(xText, "x=" + x) Shapes.SetText(yText, "y=" + y) Shapes.SetText(aText, "a=" + a) Shapes.SetText(rText, "r=" + r) Math_PolarToCartesian() Shapes.SetText(x2Text, "x=" + x) Shapes.SetText(y2Text, "y=" + y) If mx <> mxLast Or my <> myLast Then If line <> "" Then Shapes.Remove(line) EndIf GraphicsWindow.PenColor = "Red" line = Shapes.AddLine(gw / 2, gh / 2, mx, my) mxLast = mx myLast = my EndIf EndIf EndWhile Sub OnMouseMove mx = GraphicsWindow.MouseX my = GraphicsWindow.MouseY mouseMove = "True" EndSub Sub DrawGrid ' param x1, x2  x range ' param dx  delta x ' param y1, y2  y range ' param dy  delta y ' param color  color for grid GraphicsWindow.PenColor = color For x = x1 To x2 Step dx GraphicsWindow.DrawLine(x, y1, x, y2) EndFor For y = y1 To y2 Step dy GraphicsWindow.DrawLine(x1, y, x2, y) EndFor EndSub Sub Math_PolarToCartesian ' Math  convert Cartesian coodinate to polar coordinate ' param r, a  polar Coordinate ' return x, y  Cartesian coordinate _a = Math.GetRadians(a) x = r * Math.Cos(_a) y = r * Math.Sin(_a) EndSub Sub Math_CartesianToPolar ' Math  convert Cartesian coodinate to polar coordinate ' param x, y  Cartesian coordinate ' return r, a  polar Coordinate (0<=a<360) r = Math.SquareRoot(x * x + y * y) If x = 0 And y > 0 Then a = 90 ' [degree] ElseIf x = 0 And y < 0 Then a = 90 Else a = Math.ArcTan(y / x) * 180 / Math.Pi EndIf ' at this point 90<=a<=90 If x < 0 Then a = a + 180 ElseIf x >= 0 And y < 0 Then a = a + 360 EndIf ' at this point 0<=a<360 EndSub
Subroutines introduced in this thread:
 Color_Blacken
 Color_ColorToRGB
 Color_NameToColor
 Colors_Init
 Math_CartesianToPolar
 Math_Hex2Dec
 Math_PolarToCartesian
 bubblesort (by litdev)
 shellsort (by litdev)
 Text_Compare
 Text_Split
 TW_DrawLineWithChar
Nonki Takahashi
 Edited by Nonki TakahashiModerator Monday, March 13, 2017 1:39 AM updated sub list
General discussion
All replies


I wrote a TechNet Wiki article about this program.
Small Basic Sample: Math.Sin, Math.Cos and Math.Tan
Nonki Takahashi

Hello NonkiVery interesting program. However could you explain to me why, in the example below, when I point the mouse to the Cartesian coordinates x = and y = 100, in your JXB040 program it returns y =100.
Off, if I base myself on this Wikipedia article about Cartesian coordinates system, the upper right quadrant is always positive + x and y +. so why use a negative value for y?
https://en.wikipedia.org/wiki/Cartesian_coordinate_system
 Edited by YLedEditor Friday, March 03, 2017 2:20 PM


Nice idea Nonli,
Here are some array sort methods.
'Example of efficient ShellSort algorithm to sort a list, comparing with BubbleSort 'Create a random 500 element array numVal = 500 For i = 1 To numVal val[i] = Math.GetRandomNumber(numVal) EndFor valStore = val 'ShellSort it TextWindow.Write("ShellSort ") val = valStore start = Clock.ElapsedMilliseconds shellsort() timing = 0.001*Math.Floor(0.5+(Clock.ElapsedMillisecondsstart)) 'Nearest 1000th of a second TextWindow.WriteLine(timing+" sec") 'BubbleSort it TextWindow.Write("BubbleSort ") val = valStore start = Clock.ElapsedMilliseconds bubblesort() timing = 0.001*Math.Floor(0.5+(Clock.ElapsedMillisecondsstart)) TextWindow.WriteLine(timing+" sec") Sub shellsort inc = Math.Round(numVal/2) While inc > 0 For i = inc To numVal temp = val[i] j = i while (j >= inc) and (val[jinc] > temp) val[j] = val[jinc] j = j  inc EndWhile val[j] = temp EndFor inc = Math.Round(inc/2.2) Endwhile Endsub Sub bubblesort For i = 1 To numVal For j = i+1 To numVal If (val[j] < val[i]) Then temp = val[i] val[i] = val[j] val[j] = temp EndIf EndFor EndFor EndSub

YLed, I just would liked to use the subroutines for graphics window coordinate. But if the origin is at the top left corner, x and y must be positive to see. So I move the origin to the center of the graphics window.
Subroutines themselves are not depend on coordinate systems.
Nonki Takahashi
 Edited by Nonki TakahashiModerator Sunday, March 12, 2017 2:20 PM added a sentence

I wrote a bowling game program (GRT7323) for Challenge of the Month  March 2017.
In the program, I used following subroutines.
 Color_Blacken  blacken given color
 Color_ColorToRGB  convert color to RGB values
 Color_NameToColor  convert color name to color
 Colors_Init  initialize 140 colors array
 Math_Hex2Dec  convert hexadecimal to decimal
 Text_Split  split text to array by delimiter
Nonki Takahashi
 Edited by Nonki TakahashiModerator Wednesday, March 15, 2017 7:53 AM corrected program id



This a really good idea but you need to be careful with variable names. For example, x and y are pretty generic names that might be used somewhere else in the program. If you then call a subroutine that uses x or y,its value maybe overridden. You need to be very disciplined in the use of variables. I can think of two solutions to this. The first is that you publish a dictionary of variable names and what they are used for (so they don't get used for something inappropriate) or change the names in the subroutines to be unique by, for example, prefixing them with the subroutine name.
The problem occurs, of course, because SB doesn't support local variables or subroutine parameters.

This a really good idea but you need to be careful with variable names. For example, x and y are pretty generic names that might be used somewhere else in the program. If you then call a subroutine that uses x or y,its value maybe overridden. You need to be very disciplined in the use of variables. I can think of two solutions to this. The first is that you publish a dictionary of variable names and what they are used for (so they don't get used for something inappropriate) or change the names in the subroutines to be unique by, for example, prefixing them with the subroutine name.
The problem occurs, of course, because SB doesn't support local variables or subroutine parameters.
Good point, parhaps start all local variables in subroutines with _, eg _x, _y etc. This kind of discipline can help to create good reusable code. 
Yes, that is better, litdev, but still has potential for overwriting of one 'local' variable by one in another subroutine. I was thinking that if you had, say, a subroutine called 'add', then its local variables could be called add_x, add_y, etc. This way if the subroutine names are unique then the variables will be, too.

It is also possible to push all local variables on a stack at the start of the Sub and pop them at the end
Edit: added c ( unused in the main program)a=1 b=2 s="stack1" s() TextWindow.WriteLine("A = "+a) TextWindow.WriteLine("B = "+b)
TextWindow.WriteLine("C = "+c)TextWindow.Pause() Sub s Stack.PushValue(s,a) Stack.PushValue(s,b) a=101 b=102
c=103 TextWindow.WriteLine("in sub A = "+a) TextWindow.WriteLine("in sub B = "+b) TextWindow.WriteLine("in sub C = "+c) c=stack.PopValue(s) b=stack.PopValue(s) a=stack.PopValue(s) EndSub
Jan [ WhTurner ] The Netherlands
 Edited by WhTurner33Editor Sunday, March 19, 2017 2:25 PM

Good thinking, Jan, in principle it's a good idea, though to be safe you would need to push an pop every variable from the main program, which could be tedious.
Another good use of the stack would be to pass parameters to a subroutine by pushing values before the call and popping them into local variables inside the subroutine.
 Edited by outbyone Tuesday, March 21, 2017 9:33 AM typo

I've put a short tutorial about how you can implement local variables, as well as parameters and return values, on my blog here: http://programmingprof.blogspot.com.es