Re: does GtkD (win7) support opengl?
10.04.2013 3:48, Mike Wey пишет: I was able to build gtkglext3 on windows, and i've uploaded a zip file containing the dll's. http://gtkd.org/Downloads/GtkDGL.zip I've also included the static libs for GtkDGL and for 32bits windows two import libraries for opengl and glu, for win64 these are included in the Windows SDK. Thank you very much, Mike! now I have a little time to try gtk again and your help lets me build my SimpleGL demo. But I was forced use my own version of GtkDGL - your' doesn't work. I built it simple just running this from srcgl folder: cd glgdk dmd -lib -ofGlGdk.lib GLConfig.d GLContext.d GLdInit.d GLDrawable.d GLDrawableIF.d GLDrawableT.d GLQuery.d GLWindow.d -I.. -I..\..\src cd .. cd glgtk dmd -lib -ofGlGtk.lib GLCapability.d GLtInit.d GLWidget.d -I.. -I..\..\src cd .. cd gtkglc dmd -lib -ofGtkGlc.lib gl.d glgdk.d glgdktypes.d glgtk.d glgtktypes.d glu.d -I.. -I..\..\src cd .. it created three other libs and these I linked against. Also I was forced to rename: libgdkglext-3.0-0.dll to libgdkglext-win32-3.0-0.dll libgtkglext-3.0-0.dll to libgtkglext-win32-3.0-0.dll Now simplegl building and running but failed with the following: (SimpleGL.exe:4668): GLib-GObject-WARNING **: cannot register existing type `GdkGLConfig' (SimpleGL.exe:4668): GLib-CRITICAL **: g_once_init_leave: assertion `result != 0' failed (SimpleGL.exe:4668): GtkGLExt-CRITICAL **: gtk_widget_set_gl_capability: assertion `GDK_IS_GL_CONFIG (glconfig)' failed object.Error: Access Violation 0x0059ADDC 0x0059AC67 0x77B1B459 in LdrRemoveLoadAsDataTable 0x77B1B42B in LdrRemoveLoadAsDataTable 0x77AD0133 in KiUserExceptionDispatcher 0x004E5E73 0x665228B6 in gtk_main_do_event 0x6860BBCC in g_slice_free1 0x63A45E36 in g_closure_invoke 0x77AEE0F2 in RtlAllocateHeap I think it relevant to Gtk, not GtkD, but it would be very nice if you could help with it too. Google says nothing about it and simplegl.d has only 150 lines, where should I look for 4668th line?
Re: Quadratic time to sort in a simple case?
On 4/22/13 5:52 PM, bearophile wrote: Andrei Alexandrescu: c) add introspection to the algorithm, i.e. if an attempt to partition hits the worst case or near worst case, just try another pivot instead of moving forward with the sorting stage. Or switch to a sort that is guaranteed to have a pseudo-linear complexity. I am not sure, but I think the C++ STL sort does this. There's not the C++ STL sort. Any implementation is fine as long as it has O(n log n) expected run time. TimSort is slower on average. Here it's not easy to define what average is. Python devs think that a common case is an array with mostly sorted data with unsorted data at the end. Note that in this case it's sorted data followed by its smallest element. (Changing the value does improve sped.) This is hitting a corner case: median of 3 will pick the smallest element, which will lead to an inefficient partition. I haven't looked at the code, but it seems the smallest element again makes it to the beginning and the end of the array so it's again picked etc. One simple solution to this (which I forgot to mention) is picking a pivot at random. Andrei
Re: Quadratic time to sort in a simple case?
Andrei Alexandrescu: There's not the C++ STL sort. Any implementation is fine as long as it has O(n log n) expected run time. This seems to use the Introsort: http://www.sgi.com/tech/stl/sort.html I don't know if Xinok has tested a 2-pivot quicksort (called by the usual Introsort setting). Bye, bearophile
Random double
I want to generate a random double value, excluding wierdos like NaN and Infinity. However, std.random.uniform seems to be useless. I tried things like std.random.uniform( double.min, double.max); std.random.uniform(-double.max, double.max); std.random.uniform(0.0, double.max); However, I just get Inf values. :( I assume this is due to floating point computation within uniform, which easily becomes Inf, if you come near the double.max boundary. Should that be considered a bug? Nevertheless, any ideas how to work around that issue?
Re: Win32 + OpenGL bindings
On 2013-04-22 14:54, Diggory wrote: OK, I had seen that but earlier in this thread evilrat said it didn't work in GDC so I assumed it was a DMD only feature. That's true as well. GDC won't/can't implement it because of how the architecture looks like in GCC. The compiler cannot access the driver. As I understand it the driver chooses the linker flags. -- /Jacob Carlborg
Re: Random double
On 04/23/2013 07:43 AM, qznc wrote: I want to generate a random double value, excluding wierdos like NaN and Infinity. However, std.random.uniform seems to be useless. I tried things like std.random.uniform( double.min, double.max); std.random.uniform(-double.max, double.max); std.random.uniform(0.0, double.max); Since double.max is a valid double value, you may want to call uniform with a closed range: uniform![](-double.max, double.max) However, that still produces double.inf. :) Should that be considered a bug? I would say yes, it is a bug. Nevertheless, any ideas how to work around that issue? Floating point numbers have this interesting property where the number of representable values in the range [double.min_normal, 1) is equal to the number of representable values in the range [1, double.max]. The number line on this article should help with what I am trying to say: http://dlang.org/d-floating-point.html So, to workaround this problem I would suggest simply using the following range: uniform(-1.0, 1.0); One benefit is, now the range is open ended: You don't need to provide ![) to leave 1 out, because it is the default. On the other hand, the width of the range is now 2.0 so you must keep that in mind when you scale the value: Additionally, note that the random numbers in the range between [-double.min_normal, double.min_normal] and outside of those may have a different distribution. Test before using. :) (I have no experience with floating point random numbers.) Ali
Re: Quadratic time to sort in a simple case?
On Tuesday, 23 April 2013 at 14:12:01 UTC, bearophile wrote: Andrei Alexandrescu: There's not the C++ STL sort. Any implementation is fine as long as it has O(n log n) expected run time. This seems to use the Introsort: http://www.sgi.com/tech/stl/sort.html I don't know if Xinok has tested a 2-pivot quicksort (called by the usual Introsort setting). Bye, bearophile On an average case, two-pivot quick sort will increase the number of comparisons by about 50%, reason being that about half the elements will be greater than the first pivot and have to he compared to the second pivot. There's also a greater complexity given there are three partitions rather than two, increasing the amount of I/O necessary. Introsort is simply a quick sort which falls back to a heap sort after so many recursions to guarantee O(n log n) performance. I've implemented this using a median of five and it works excellent. This is what I plan to contribute to Phobos. Choosing a random pivot will always invoke average performance where as finding the median of N elements usually achieves better performance on sorted lists. You also have to be careful that equal elements are distributed equally among both partitions, else a list with many elements equal to the pivot will still achieve poor performance. (equal elements would all fall onto one side of the pivot)
Re: Random double
Tue, 23 Apr 2013 16:43:14 +0200: qznc wrote I want to generate a random double value, excluding wierdos like NaN and Infinity. However, std.random.uniform seems to be useless. I tried things like std.random.uniform( double.min, double.max); std.random.uniform(-double.max, double.max); std.random.uniform(0.0, double.max); However, I just get Inf values. :( I assume this is due to floating point computation within uniform, which easily becomes Inf, if you come near the double.max boundary. Should that be considered a bug? Nevertheless, any ideas how to work around that issue? Using a union seems to be a good workaround: union foo { ulong input; double output; } foo val = void; do { val.input = uniform(ulong.min, ulong.max); } while (val.output == double.infinity || val.output == -double.infinity || val.output != val.output); return val.output; Maybe the implementation of uniform should use a similar trick?
GtkD DLL issues
Trying out GtkD for the first time today, compiled one of the sample applications and when I try to run it, it instantly crashes with the following error message: The image file C:\Program Files\Intel\WiFi\bin\zlib1.dll is valid, but is for a machine type other than that current machine. Select OK to continue, or CANCEL to fail the DLL load. I've looked around and found people with similar problems, but nothing that seems to solve my problem. Using: Windows 8 (64 bit) DMD v2.062 GtkD v2.1.1 Code: import gtk.MainWindow; import gtk.Label; import gtk.Main; void main(string[] args) { Main.init(args); MainWindow win = new MainWindow(Hello World); win.setDefaultSize(200, 100); win.add(new Label(Hello World)); win.showAll(); Main.run(); } Any help would be much appreciated.
Re: GtkD DLL issues
On 04/23/2013 09:00 PM, Jeff wrote: Trying out GtkD for the first time today, compiled one of the sample applications and when I try to run it, it instantly crashes with the following error message: The image file C:\Program Files\Intel\WiFi\bin\zlib1.dll is valid, but is for a machine type other than that current machine. Select OK to continue, or CANCEL to fail the DLL load. I've looked around and found people with similar problems, but nothing that seems to solve my problem. Using: Windows 8 (64 bit) DMD v2.062 GtkD v2.1.1 Code: import gtk.MainWindow; import gtk.Label; import gtk.Main; void main(string[] args) { Main.init(args); MainWindow win = new MainWindow(Hello World); win.setDefaultSize(200, 100); win.add(new Label(Hello World)); win.showAll(); Main.run(); } Any help would be much appreciated. Are you compiling gtkD and the app as 32 or 64 bit? Did you install the matching Gtk+ runtime 32 or 64 bits? I looks like its pikking up a different version of a dll used by Gtk+ and apperantly the Intel WiFi tools. But think it should loadthe right one if ist just 32 vs 64 bits. -- Mike Wey
Re: GtkD DLL issues
On Tuesday, 23 April 2013 at 20:21:51 UTC, Mike Wey wrote: On 04/23/2013 09:00 PM, Jeff wrote: Trying out GtkD for the first time today, compiled one of the sample applications and when I try to run it, it instantly crashes with the following error message: The image file C:\Program Files\Intel\WiFi\bin\zlib1.dll is valid, but is for a machine type other than that current machine. Select OK to continue, or CANCEL to fail the DLL load. I've looked around and found people with similar problems, but nothing that seems to solve my problem. Using: Windows 8 (64 bit) DMD v2.062 GtkD v2.1.1 Code: import gtk.MainWindow; import gtk.Label; import gtk.Main; void main(string[] args) { Main.init(args); MainWindow win = new MainWindow(Hello World); win.setDefaultSize(200, 100); win.add(new Label(Hello World)); win.showAll(); Main.run(); } Any help would be much appreciated. Are you compiling gtkD and the app as 32 or 64 bit? Did you install the matching Gtk+ runtime 32 or 64 bits? I looks like its pikking up a different version of a dll used by Gtk+ and apperantly the Intel WiFi tools. But think it should loadthe right one if ist just 32 vs 64 bits. Both as 32.
Re: GtkD DLL issues
On Tuesday, 23 April 2013 at 20:24:33 UTC, Jeff wrote: On Tuesday, 23 April 2013 at 20:21:51 UTC, Mike Wey wrote: On 04/23/2013 09:00 PM, Jeff wrote: Trying out GtkD for the first time today, compiled one of the sample applications and when I try to run it, it instantly crashes with the following error message: The image file C:\Program Files\Intel\WiFi\bin\zlib1.dll is valid, but is for a machine type other than that current machine. Select OK to continue, or CANCEL to fail the DLL load. I've looked around and found people with similar problems, but nothing that seems to solve my problem. Using: Windows 8 (64 bit) DMD v2.062 GtkD v2.1.1 Code: import gtk.MainWindow; import gtk.Label; import gtk.Main; void main(string[] args) { Main.init(args); MainWindow win = new MainWindow(Hello World); win.setDefaultSize(200, 100); win.add(new Label(Hello World)); win.showAll(); Main.run(); } Any help would be much appreciated. Are you compiling gtkD and the app as 32 or 64 bit? Did you install the matching Gtk+ runtime 32 or 64 bits? I looks like its pikking up a different version of a dll used by Gtk+ and apperantly the Intel WiFi tools. But think it should loadthe right one if ist just 32 vs 64 bits. Both as 32. Oh, and using the 32-bit runtime as well.
Re: GtkD DLL issues
On 04/23/2013 10:26 PM, Jeff wrote: On Tuesday, 23 April 2013 at 20:24:33 UTC, Jeff wrote: On Tuesday, 23 April 2013 at 20:21:51 UTC, Mike Wey wrote: On 04/23/2013 09:00 PM, Jeff wrote: Trying out GtkD for the first time today, compiled one of the sample applications and when I try to run it, it instantly crashes with the following error message: The image file C:\Program Files\Intel\WiFi\bin\zlib1.dll is valid, but is for a machine type other than that current machine. Select OK to continue, or CANCEL to fail the DLL load. I've looked around and found people with similar problems, but nothing that seems to solve my problem. Using: Windows 8 (64 bit) DMD v2.062 GtkD v2.1.1 Code: import gtk.MainWindow; import gtk.Label; import gtk.Main; void main(string[] args) { Main.init(args); MainWindow win = new MainWindow(Hello World); win.setDefaultSize(200, 100); win.add(new Label(Hello World)); win.showAll(); Main.run(); } Any help would be much appreciated. Are you compiling gtkD and the app as 32 or 64 bit? Did you install the matching Gtk+ runtime 32 or 64 bits? I looks like its pikking up a different version of a dll used by Gtk+ and apperantly the Intel WiFi tools. But think it should loadthe right one if ist just 32 vs 64 bits. Both as 32. Oh, and using the 32-bit runtime as well. Then it's indeed picing up the copy of zlib1.dll installed with the Intel WiFi tools instead of the one installed with Gtk+. But i don't know what could be done about that. -- Mike Wey
Re: Random double
qznc: I want to generate a random double value, excluding wierdos like NaN and Infinity. However, std.random.uniform seems to be useless. Can you explain why you need uniform doubles in their whole range? I think I have never had to generate them so far. Maybe for a unittest? Also note by their nature doubles are not equally spread across the line of Reals, so getting a truly uniform distribution is hard or impossible. Bye, bearophile
Re: does GtkD (win7) support opengl?
On 04/23/2013 10:59 AM, Alexandr Druzhinin wrote: 10.04.2013 3:48, Mike Wey пишет: I was able to build gtkglext3 on windows, and i've uploaded a zip file containing the dll's. http://gtkd.org/Downloads/GtkDGL.zip I've also included the static libs for GtkDGL and for 32bits windows two import libraries for opengl and glu, for win64 these are included in the Windows SDK. Thank you very much, Mike! now I have a little time to try gtk again and your help lets me build my SimpleGL demo. But I was forced use my own version of GtkDGL - your' doesn't work. I built it simple just running this from srcgl folder: cd glgdk dmd -lib -ofGlGdk.lib GLConfig.d GLContext.d GLdInit.d GLDrawable.d GLDrawableIF.d GLDrawableT.d GLQuery.d GLWindow.d -I.. -I..\..\src cd .. cd glgtk dmd -lib -ofGlGtk.lib GLCapability.d GLtInit.d GLWidget.d -I.. -I..\..\src cd .. cd gtkglc dmd -lib -ofGtkGlc.lib gl.d glgdk.d glgdktypes.d glgtk.d glgtktypes.d glu.d -I.. -I..\..\src cd .. I probably used a different version of dmd to create the libs. it created three other libs and these I linked against. Also I was forced to rename: libgdkglext-3.0-0.dll to libgdkglext-win32-3.0-0.dll libgtkglext-3.0-0.dll to libgtkglext-win32-3.0-0.dll This is a bug already fixed in git, has got the dll names wrong. Now simplegl building and running but failed with the following: (SimpleGL.exe:4668): GLib-GObject-WARNING **: cannot register existing type `GdkGLConfig' (SimpleGL.exe:4668): GLib-CRITICAL **: g_once_init_leave: assertion `result != 0' failed (SimpleGL.exe:4668): GtkGLExt-CRITICAL **: gtk_widget_set_gl_capability: assertion `GDK_IS_GL_CONFIG (glconfig)' failed object.Error: Access Violation 0x0059ADDC 0x0059AC67 0x77B1B459 in LdrRemoveLoadAsDataTable 0x77B1B42B in LdrRemoveLoadAsDataTable 0x77AD0133 in KiUserExceptionDispatcher 0x004E5E73 0x665228B6 in gtk_main_do_event 0x6860BBCC in g_slice_free1 0x63A45E36 in g_closure_invoke 0x77AEE0F2 in RtlAllocateHeap I think it relevant to Gtk, not GtkD, but it would be very nice if you could help with it too. Google says nothing about it and simplegl.d has only 150 lines, where should I look for 4668th line? I don't think it's the line number. I think i may have this error on my machine once, but not since then. And i can't reproduce it. -- Mike Wey
Re: Quadratic time to sort in a simple case?
On Monday, 22 April 2013 at 21:34:47 UTC, Andrei Alexandrescu wrote: a) choose median of five Sounds like it could decrease speed on average, and still perhaps fail on a simple case like [0, 1, 2, 3, ..., 999, 0, 0] or something? Didn't test it though. b) if the array is large, sort a stride of it first (e.g. 1%) then choose the pivot as the median point of that stride A bad case would be, e.g., the array containing almost sorted parts, and the stride getting taken from the part where lowest or highest elements reside. c) add introspection to the algorithm, i.e. if an attempt to partition hits the worst case or near worst case, just try another pivot instead of moving forward with the sorting stage. Now, trying another pivot again and again could give the same O(n^2) in a bad case. One simple solution to this (which I forgot to mention) is picking a pivot at random. But it would again mean that the sort function depends on global state (RNG state). And if it doesn't (a local RNG is initialized somehow each time), an adversary would just have to hardcode it once to get the same O(n^2) worst case anytime he wants. And on Tuesday, 23 April 2013 at 01:10:26 UTC, Xinok wrote: I filed a bug report for this issue a year ago: http://d.puremagic.com/issues/show_bug.cgi?id=7767 I've been meaning to fix this issue myself. Time allowing, I'll do it soon. What I wonder now, what would be the goal of such a fix? One possible goal would be to have an O(n log n) worst case sort. And that would perhaps cost some speed and/or memory on average. Besides, such a sort function is already implemented (TimSort), so it's just a matter of setting the default then. Another goal would be to have O(n^2) only for cases which don't have a reasonable chance to occur in real world, but could still be constructed artificially by an adversary. And that could perhaps be done by just changing the getPivot implementation. Other languages' experience may be useful here: 1. GNU C++ 4.x std::sort implementation is IntroSort [1]. 2. Microsoft .NET used Quicksort up to version 4.0 [2]. Now in .NET 4.5 they use Introsort too [3]. 3. For primitive types, Java 6 used a tuned QuickSort [4]. The current Java 7 uses Dual-Pivot QuickSort [5]. Java uses TimSort for Objects [6]. 4. Python uses TimSort since version 2.3 [7]. In any case, there are techniques to construct a bad case given a QuickSort implementation. One of them is described by M. Douglas McIlroy in A Killer Adversary for Quicksort [8]. We run QuickSort on a would-be-array a controlling the a[i] a[j] predicate, and, using only certain assumptions (not looking at the code!), we build a killer-case array on the fly. Given some thought, the technique could perhaps be extended to Dual-Pivot QuickSort too. As long as some flavor of QuickSort (and topN) is in Phobos, such a unittest would fit the sort implementation nicely, if only to show just how bad it can get. Ivan Kazmenko. - References: [1] http://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.4/a01027.html#g152148508b4a39e15ffbfbc987ab653a [2] http://msdn.microsoft.com/en-us/library/6tf1f0bc%28v=vs.100%29.aspx [3] http://msdn.microsoft.com/en-us/library/6tf1f0bc%28v=vs.110%29.aspx [4] http://docs.oracle.com/javase/6/docs/api/java/util/Arrays.html#sort%28int[]%29 [5] http://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html#sort%28int[]%29 [6] http://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html#sort%28java.lang.Object[]%29 [7] http://en.wikipedia.org/wiki/Timsort [8] http://www.cs.dartmouth.edu/~doug/mdmspe.pdf
Re: GtkD DLL issues
Then it's indeed picing up the copy of zlib1.dll installed with the Intel WiFi tools instead of the one installed with Gtk+. But i don't know what could be done about that. Try opening a command prompt (cmd.exe) and setting the path of the gtk runtime before the Intel Wifi tools. set PATH=C:\Path\To\GtkRuntime\bin;%PATH% This will use the gtk runtime zlib1.dll first. If that works and doesn't mess up your intel wifi program, you can make that a global path setting.
WinAPI callbacks and GC
I'm writing Ctrl-C handler for console application for Windows: extern(Windows) { int CtrlHandler(uint flag) nothrow { auto tmp = new SomeClass; // is it safe? ... return true; } } ... SetConsoleCtrlHandler(CtrlHandler, true); ... According WinAPI documentation, CtrlHandler will be called in new additional thread. Is it safe to allocate GC memory in NOT Phobos threads? If not, how to make it safe? I'm trying call thread_attachThis() at the beginning of CtrlHandler fucntion, but it doesn't compile because thread_attachThis() is not nothrow.
Re: Quadratic time to sort in a simple case?
On Tuesday, 23 April 2013 at 17:42:08 UTC, Xinok wrote: Choosing a random pivot will always invoke average performance where as finding the median of N elements usually achieves better performance on sorted lists. You also have to be careful that equal elements are distributed equally among both partitions, else a list with many elements equal to the pivot will still achieve poor performance. (equal elements would all fall onto one side of the pivot) Introsort is simply a quick sort which falls back to a heap sort after so many recursions to guarantee O(n log n) performance. I've implemented this using a median of five and it works excellent. This is what I plan to contribute to Phobos. I like the sound of that! Regarding my previous post, it's perhaps worth mentioning Go in the comparison, it uses QuickSort with median-of-three for small sizes and median of medians-of-three for larger sizes [1]. And it actually sorts the three medians in median-of-three, which sounds like a good thing to do. They cite Engineering a Sort Function (1993) by Bentley and McIlroy as inspiration [2]. Ivan Kazmenko. - [1] http://golang.org/src/pkg/sort/sort.go#L104 [2] http://www.enseignement.polytechnique.fr/informatique/profs/Luc.Maranget/421/09/bentley93engineering.pdf
Re: GtkD DLL issues
On Tuesday, 23 April 2013 at 21:16:03 UTC, ollie wrote: Then it's indeed picing up the copy of zlib1.dll installed with the Intel WiFi tools instead of the one installed with Gtk+. But i don't know what could be done about that. Try opening a command prompt (cmd.exe) and setting the path of the gtk runtime before the Intel Wifi tools. set PATH=C:\Path\To\GtkRuntime\bin;%PATH% This will use the gtk runtime zlib1.dll first. If that works and doesn't mess up your intel wifi program, you can make that a global path setting. Thanks, that did the trick. Should've know it was just a %PATH% issue.
Re: WinAPI callbacks and GC
On Tuesday, 23 April 2013 at 21:21:28 UTC, Jack Applegame wrote: I'm writing Ctrl-C handler for console application for Windows: extern(Windows) { int CtrlHandler(uint flag) nothrow { auto tmp = new SomeClass; // is it safe? ... return true; } } ... SetConsoleCtrlHandler(CtrlHandler, true); ... According WinAPI documentation, CtrlHandler will be called in new additional thread. Is it safe to allocate GC memory in NOT Phobos threads? If not, how to make it safe? I'm trying call thread_attachThis() at the beginning of CtrlHandler fucntion, but it doesn't compile because thread_attachThis() is not nothrow. i guess it call ur callback(enters D code, so GC is in), alloc new instance, and after callback return it should collect it, but there is no such thing like guessing, just try it and see if it works correctly. also there is an option without using GC at all, use struct instead of class if you don't need polymorphism(for most tasks structs is really enough, they are as powerful as c++ class just without polymorphism and other nasties) also if you really need class or whole program lifetime memory, you may declare instance in module level with __gshared(__gshared SomeClass tmp;, don't forget to alloc if is class) so gc won't touch it. also it may be better to read related docs in language reference on this site for more info, since i'm somehow bad with remembering all the details.
Re: WinAPI callbacks and GC
On Tuesday, 23 April 2013 at 21:21:28 UTC, Jack Applegame wrote: If not, how to make it safe? I'm trying call thread_attachThis() at the beginning of CtrlHandler fucntion, but it doesn't compile because thread_attachThis() is not nothrow. what stops you from calling normal functions in nothrow one? use try-catch inside nothrow. nothrow means that function doesn't throw, not it can call only nothrow. also if another func is C language func, you may try to add nothrow to it's signature since it's anyway can't throw anything. --- example: void doWithThrow() { int x = 1; x++; } nothrow void doStuff() { try { doWithThrow(); } catch ( Exception e ) { // your handling code here... } } void main() { doStuff(); } --- i hope i don't learn people to do bad or stupid things :(