Run Code
|
API
|
Code Wall
|
Misc
|
Feedback
|
Login
|
Theme
|
Privacy
|
Patreon
Ducktype
/* ducktype.h * * * * * * * * * * * * * * * * * * * * * * * * * * * * \ * * * Copyright (C) 2016 by Henry Kroll III, www.thenerdshow.com * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see <http://www.gnu.org/licenses/>.* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef _DUCKTYPE #include <stdio.h> #include <stdlib.h> #include <stddef.h> #include <stdarg.h> #include <string.h> //strcmp() #include <math.h> //exp() -lm #include <alloca.h> //defines #define _DEBUG 0 #define TYPE_MAX 20 #if !defined(MAX_ROWS) || !defined(MAX_COLS) #define MAX_ROWS 1024 #define MAX_COLS 1024 #endif //cross compile #if defined(_WIN32) || defined(_WIN64) //if windows #define DLL_EXPORT __declspec(dllexport) //make DLL #else #define DLL_EXPORT #endif //error handling #define _STR(a) #a #define STR(a) _STR(a) #define TRY(a) if (!(a)){ \ perror(__FILE__":"STR(__LINE__));exit(1);} #define ERR(...) fprintf (stderr, STR(__FILE__)" "STR(__LINE__) \ ": " __VA_ARGS__);exit (1) #define INFO(...) if(_DEBUG) fprintf (stderr, STR(__FILE__)" " \ STR(__LINE__) ": " __VA_ARGS__) #define OPERATIONS_LIST \ F(addn, +=n) /* array + number operations */ \ F(subn, -=n) \ F(divn, /=n) \ F(muln, *=n) \ F(setn, =n) \ F(square, =x*x) /* one-argument operations */ \ F(sigmoid, =1/(1+exp(-x))) \ F(derivative, =x*(1-x)) \ F(addx, +=n) /* array + array operations */ \ F(subx, -=n) \ F(divx, /=n) \ F(mulx, *=n) \ F(dupx, =n) \ //types < 3 are int types #define TYPE_LIST \ X(char , 0, %c) \ X(int , 1, %i) \ X(long , 2, %li) \ X(double, 3, %6.3f) \ X(float , 4, %5.2f) //enumerate the types #define X(a, c, d) a##_type=c, typedef enum TYPES{TYPE_LIST} e_types; e_types Type; #undef X //structify the types typedef struct { size_t rows, cols; char *name; e_types type; union { #define X(a, c, d) \ a *p_##a; TYPE_LIST #undef X }; char mem; } dm, *pdm; //name the types #define X(a, c, d) #a, char *type_name[]={TYPE_LIST}; #undef X #define F(a, b) a, typedef enum {OPERATIONS_LIST} e_ops; #undef F #define F( a, b) #b, char *operations[]={OPERATIONS_LIST}; #undef F //forward declarations pdm print_r (pdm, ...); pdm fn (e_ops, ...); pdm dot_product (pdm, pdm, pdm); //check for bad array #define CHECK_pdm(X) \ if ((X)->rows > MAX_ROWS || (X)->cols > MAX_COLS \ || (X)->rows < 1 || (X)->cols < 1) { \ ERR ("Array size not recognized.\n" \ "Try &p dereference or NULL."); \ } if (!(X)->name || strlen((X)->name) > TYPE_MAX) { \ ERR ("Array name too long.\n" \ "Try &p dereference or NULL.");} //definition macros take a type as 1st arg #define NEW(TYPE, NAME, ROWS, COLS, ...) \ TYPE NAME##_2d[ROWS][COLS] = { __VA_ARGS__ }; \ dm NAME; NAME.p_##TYPE = (TYPE*)NAME##_2d; \ NAME.rows = ROWS; NAME.cols = COLS; NAME.name = #NAME; \ NAME.type = TYPE##_type #define DUP(TYPE, NAME, A) \ TYPE NAME##_2d [A.rows][A.cols]; \ dm NAME; NAME.p_##TYPE = (TYPE*)NAME##_2d; \ NAME.rows = (A).rows; NAME.cols = (A).cols; NAME.name = #NAME; \ NAME.type = TYPE##_type; \ memcpy((NAME).p_##TYPE, (A).p_##TYPE, (A).rows*(A).cols*sizeof(TYPE)); \ #define DBL(NAME, A) \ double NAME##_2d [(A)->rows][(A)->cols]; \ dm NAME; NAME.p_double = (double*)NAME##_2d; \ NAME.rows = (A)->rows; NAME.cols = (A)->cols; \ NAME.name = #NAME; NAME.type = double_type; \ #define DOT(TYPE, NAME, A, B) \ TYPE NAME##_2d[(A).rows][(B).cols]; \ dm NAME; NAME.p_##TYPE = (TYPE*)NAME##_2d; \ NAME.rows = (A).rows; NAME.cols = (B).cols; NAME.name = #NAME; \ NAME.type = (A).type; dot_product((&NAME), (&A), (&B)) #define CAST2D(A, TYPE) \ (*(TYPE (*)[(A)->rows][(A)->cols])(A)->p_##TYPE) #define GET2D(A, TYPE) \ (*(TYPE (*)[(A).rows][(A).cols])(A).p_##TYPE) // a random integer within specified range (MSDN) #define getrandom(min, max) \ ((rand()%(int)(((max) + 1)-(min)))+ (min)) #endif //_DUCKTYPE /* ducktype.c * * * * * * * * * * * * * * * * * * * * * * * * * * * * \ * * * Copyright (C) 2016 by Henry Kroll III, www.thenerdshow.com * * * ` * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //#include "ducktype.h" //internal function selection inline double _func (e_ops f, double x, double n) { switch (f) { #define F(a, fn) \ case a: x fn; break; OPERATIONS_LIST; //formulas declared in ducktype.h } #undef F return x; } //The fn function accepts multiple types, converts them to double //performs the selected formula, and modifies 1st input array pdm fn (e_ops f, ...) { double x, n = x = 0.0; //initialize variables va_list ap; va_start (ap, f); pdm A, B = NULL; //signal that we have no 2nd array A = va_arg (ap, pdm) ;CHECK_pdm (A); DBL(tmp, A); //declare a temporary double array like A //get more args for operations that need them if (f < square) { //array + number operations n = va_arg (ap, double); } if (f >= addx) { //array + array operations B = va_arg (ap, pdm) ;CHECK_pdm (B); if (B->rows != A->rows || B->cols != A->cols) { ERR ("Can't work on different size arrays.\n"); } if (B->type != double_type) { INFO ("Converting %s to double for calculation.\n", B->name); switch (B->type) { #define X(TYPE, num, fmt) \ case TYPE##_type: { \ for (int i=A->rows*A->cols;i--;) { \ tmp.p_double[i] = B->p_##TYPE[i]; \ } break; \ } TYPE_LIST; //types declared in ducktype.h } #undef X B = &tmp; } } INFO ("%s %s\n", A->name, operations[f]); //else one-argument functions (default) size_t rc = A->rows * A->cols; switch (A->type) { #define X(TYPE, num, fmt) \ case TYPE##_type: { \ for (;rc--;) { \ if (B) n = B->p_double[rc]; \ x = A->p_##TYPE[rc]; \ A->p_##TYPE[rc] = _func(f, x, n); \ } break; \ } TYPE_LIST; //types declared in ducktype.h } #undef X va_end (ap); return A; } //compute the dot product of A and B, store in C //use DOT macro instead: it declares C of the correct size //Arrays A, B and C must be compatible types. pdm dot_product (pdm C, pdm A, pdm B) { size_t r, c; CHECK_pdm (A) ;CHECK_pdm (B); if ((B->type != A->type) || (A->type != C->type)) { ERR ("Arrays A, B and C must be compatible types.\n"); } switch (A->type) { #define X(type, num, fmt) \ case type##_type: { \ for (r=0; r < A->rows; r++) { \ for (c=0; c < B->cols; c++) { \ type sum = 0.0; \ for (size_t i=0; i < A->cols; i++) { \ sum+=CAST2D(A, type)[r][i] \ *CAST2D(B, type)[i][c]; \ } CAST2D(C, type)[r][c] = sum; \ } \ } break; \ } TYPE_LIST; //types declared in ducktype.h } #undef X return C; } //print contents of various types of arrays pdm print_r (pdm X, ...) { va_list ap; va_start (ap, X); int r, c; do { CHECK_pdm (X); printf ("%s %s [%lu][%lu] =\n{", type_name[X->type], X->name, X->rows, X->cols); switch (X->type) { #define X(type, num, fmt) \ case type##_type: { \ for (r=0;r < X->rows;r++) { \ printf ("%c{", r?' ':'\0'); \ for (c=0;c < X->cols;c++) { \ char p = c < X->cols-1?',':'\0'; \ printf (#fmt "%c ", CAST2D(X, type)[r][c], p); \ } printf ("}%c\n", r < X->rows - 1?',':'}'); \ } break; \ } TYPE_LIST; //types declared in ducktype.h } #undef X puts (""); } while ((X = va_arg(ap, pdm))); va_end (ap); return X; } //usr/local/bin/anch -std=c99 -Llibs -lducktype -lm -keep -run "$0" "$@" ; exit 0 /* ducktype_test.c * * * * * * * * * * * * * * * * * * * * * * * * * * \ * * * Copyright (C) 2016 by Henry Kroll III, www.thenerdshow.com * * * ` * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //#include "ducktype.h" int main (void) { //definition macros take a type as 1st arg NEW (double, i0, 2, 3, {0,1,2},{3,4,5}); NEW (double, i1, 3, 2, {0,1}, {2,3}, {4,5}); printf ("Define a couple of 2d %s arrays.\n\n", type_name[i0.type]); print_r (&i0, &i1, NULL); //print_r can figure out the type printf ("Calculate the dot product.\n\n"); DOT (double, i2, i0, i1); //NEW i2 = dotprodut i0, i1 print_r (&i2, NULL); //try the same thing with int NEW (int, d0, 2, 3, {4,5,6},{7,8,9}); NEW (int, d1, 3, 2, {0,1}, {2,3}, {4,5}); printf ("Define a couple of 2d %s arrays.\n\n", type_name[d0.type]); print_r (&d0, &d1, NULL); //print_r can figure out the type printf ("Calculate the dot product.\n\n"); DOT (int, d2, d0, d1); //DOT works as long as types are uniform print_r (&d2, NULL); printf ("In order to perform math on arrays of different types\n"); printf ("The fn function internally converts the 2nd array to double.\n\n"); printf ("Add double array to int array.\n"); //The fn function accepts multiple types, converts them to double //performs the selected formula, and modifies 1st input array fn (addx, &i2, &d2); print_r (&i2, NULL); //no cleanup necessary return 0; }
run
|
edit
|
history
|
help
0
interestCalculationSample
UDP - Pytagorova veta
definice funkce
VKI_Mihalyk_3_2
Bucles: Suma de n números tecleados por el usuario
Vectores: Mayor lista numeros al azar
Bucles: Múltiplos de 4 hasta N tecleado por el usuario
Euclides 2
Cviceni 7 1 uloha ++upper,isupper
Herout (67) - 3