RSS

Classificação K-nn rápida como the flash

Artist: Christopher Moeller

O método dos k vizinhos mais próximos (k-NN, do inglês k nearest neighbors) é um dos métodos de classificação automática mais usados na industria. Entretanto é comum problemas de performance com K-NN em linguagens interpretadas isso porque é tudo feito de forma genérica sem otimizações na parte da algebra linear(calma já explico), embora clusterizar seja interessante nestes casos no final torna-se um grande desperdício de energia e tempo.(deixe apra casos extremos)

Muitos processadores modernos tem recursos que não são usados por programadores comuns, fazer uso de um registrador RAX, no caso estaria usando apenas 64bits sendo que alguns processadores tem registradores de 128bits, 256bits e até 512bits, tais como XMM, YMM e ZMM(pensando em AVX).

“Se você pagou por uma ferrari, um dia você deve pensar em passar dos 60km/h”

Destravando todo esse poder dos registradores e instruções, podemos chegar a ter até 200% a mais de performance na algebra linear ou mais dependendo do contexto. O problema é que para programar usando intrinsics ou inline assembly pode ser tanto difícil, já que não é algo comum de se ver em cursos acadêmicos(comum para programadores de games ou aqueles que trabalham com criptografia).

Até aqui alguns devem de se perguntar, “há mas o GCC otimiza basta usar aquele argumento -Os, O3…” mesmo otimizando não é melhor(mais rápido) do que algumas implementações do Agner Fog por exemplo. Para ter algo empírico basta fazer benchmark e comparar as duas formas…

Apresento aqui uma solução para o problema de classificação usando K-NN em alta performance, existe uma biblioteca para linguagem C++ chamada armadillo, internamente essa bibliotéca tem recursos para usar o BLAS, LAPACK, SIMD otimizando assim a parte de algebra linear.

Desenvolvi uma biblioteca usando armadillo para classificar classes usando método K-NN, acabei testando no linux em uma distribuição debian, caso queira testar siga os passos:

1- Instale a lib do armadillo seguinto o comando:

$ apt-get install libarmadillo-dev

2- Configure o armadillo conforme sua necessidade seguindo o site oficial. http://arma.sourceforge.net/docs.html#config_hpp

3- Obtenha repositório do projeto, compile e faça um teste seguindo os comandos:

cooler@Nepal:/codes$ git clone https://github.com/CoolerVoid/libfast_knn
cooler@Nepal:~/codes/libfast_knn$ make
g++ -Wall -O3 -larmadillo -fstack-protector-all -D_FORTIFY_SOURCE=2 -c src/*.cpp -c lib/*.h -c lib/*.cpp
g++ -o bin/knn_test *.o -Wl,-z,relro,-z,now 
rm *.o

cooler@Nepal:~/codes/libfast_knn$ bin/knn_test 
Test Manhattan:
1:    5.0000   3.0000   1.6000   0.2000
	Result: 1
2:    1.0000   2.0000   1.6000   2.2000
	Result: 1
3:    6.0000   4.0000   4.6000   3.2000
	Result: 3
4:    0.9000   1.0000   2.6000   2.2000
	Result: 1
5:    9.0000   7.0000   4.6000   4.2000
	Result: 3

Test Euclidean:
1:    5.0000   3.0000   1.6000   0.2000
	Result: 1
2:    1.0000   2.0000   1.6000   2.2000
	Result: 2
3:    6.0000   4.0000   4.6000   3.2000
	Result: 3
4:    0.9000   1.0000   2.6000   2.2000
	Result: 2
5:    9.0000   7.0000   4.6000   4.2000
	Result: 3

Para aprender como usar a biblioteca basta ler o código no arquivo “src/main.c“.

Até o momento não existe implementação em Java, Python ou R que tenha maior performance, o consagrado MLpack usado até mesmo pelo google faz uso do armadillo, veja seus resultados em benchmarks.

Por que você implementou já que o Mlpack também faz K-nn ?

Mlpack é muito bom entretanto se precisa fazer uso de apenas de uma função K-nn, pode ficar triste quando notar a instalação do mlpack pedindo mais de 300mb de dependências. A curva de aprendizado é lenta já que a documentação do Mlpack é gigantesca. No meu código foi implementado algo simples a bala de prata certa para um problema específico, encontrei nada falando de classificação usando K-nn no MLpack, nem mesmo na sua documentação(logo a lib apresentada neste post é muito útil).

Para quem gostou do assunto e quer saber outras formas de ganhar performance fica uma dica tente usar GPU: https://github.com/vincentfpgarcia/kNN-CUDA

Referências:

https://en.wikipedia.org/wiki/K-nearest_neighbors_algorithm

http://www.mlpack.org/benchmarks.html

http://arma.sourceforge.net/speed.htm

Livro – Machine Learning in Action – Peter Harrington April 2012 ISBN 9781617290183 (embora seja em python os exemplos, aprendi muito).

 
Deixe um comentário

Publicado por em julho 9, 2017 em Linguagem C, Machine Learning

 

Um pouco de Assembly com linguagem C

Anos que digo para mim que vou escrever algo de “Assembly” vai ano e passa, acabo deixando
de lado, já algum tempo ando estudando fazendo coisas simples bem devagar, isso tem me ajudado a depurar meus programas em linguagem C, claro que também me ajuda nos skills de hacking seja com engenharia reversa ou para entender problemas que tenham  overflow, programar para um microcontrolador etc…

Se assembly fosse banda seria uma banda de heavy metal... rsrs

Se assembly fosse banda seria uma banda de heavy metal… rsrs

Antes de começar queria agradecer de coração “sigsegv“,”m0nad“,”iak“,”kov”,”__i”,”MySoft”,”muzgo”
por terem me influenciado em Assembly e ter me ajudado por muitas vezes e até hoje…
irc.freenode.net nos canais #asm,#c-br,#lisp-br,#cogubin.

“antes que me esqueça feliz pascoa caros leitores desse blog…”
Read the rest of this entry »

 
1 comentário

Publicado por em abril 7, 2012 em Assembly, Linguagem C

 

Biblioteca para Thread Pool

Tempos que não público nada, já algum tempo escrevi uma biblioteca em C
para piscinas de conexões,obtive dicas de amigos como Muzgo,
conto com a contribuição do Marcelo M. Fleury aka MarceloMF. se mais
gente poder ajudar seria legal, mesmo por que sou noob e preciso ter
uma visão de terceiros para evoluir….

Por que eu tive ideia de fazer ?
muito chato ficar fazendo malabarismo com mutex, queria algo tão simples
quanto o OpenMPI, algo que só apontando a função,número de threads a
usar e o número de vezes que os dados iriam rolar e pronto.
realmente tem me poupado horas a fio nos meus códigos com
programação concorrente.

Outra sou a favor do “tabula rasa” só faço abstração
quando tenho atitude a respeito(talvez por ter dislexia etc…),
ato de compartilhar não é por orgulho,vaidade e sim
pela sede de melhorar ,poderia ter deixado numa gaveta,
mas não !, deixo para todos só assim para ter esperança
de chegar a uma boa refatoração.

veja URL do PROJETO Aqui

Sem mais palavras “show me the code

$ wget http://tombpool.googlecode.com/files/tombpool02.tar.gz
$ tar zxvf tombpool02.tar.gz
$ cd tombpool02
$ mkdir pack; cd pack;
$ cmake ../; make; cd .. ; cp tombpool.h pack; cp test.c pack; cd pack
# cp libtombpool.so /lib
$ gcc -o test test.c -lpthread -ltombpool
$ ./test

olhando o código do test

/*
example how too use TombPool
 mkdir pack
 cmake ../; make; cd .. ; cp tombpool.h pack; cp test.c pack; cd pack
 sudo cp libtombpool.so /lib
 gcc -o test test.c -lpthread -ltombpool
 ./test

What this it ?
Just another thread pool simple api to work with double linked queue

Author:Antonio Costa aka " Cooler_ "
contact: c00f3r[at]gmail[dot]com
contributor: MarceloMF - Marcelo M. Fleury
email: marcelo.fleury[at]4linux[dot]com[dot]

    Copyright (C) 2012 tombpool authors,
    
    This file is part of tombpool
    
    tombpool is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    tombpool 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 Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include "tombpool.h"

void tarefa(int a)
{
 fprintf(stdout,"%d\n", a);
}


int main()
{
 int count=0;
// the pool struct	
 piscina* threadpool;
// init pool, to fill the pool, alloc heap ,4 thread per time            
 threadpool=Dig_TombPool(4);       

 while(count<10)
 {
// add task in pool and queue...
  Add_Corpse(threadpool, (void*)tarefa, (void*)count);
  count++;
 }	

// exec all and clear process, clear the heap,close semafores...
 Cover_TombPool(threadpool,10);
	
 return 0;
}

Por que tudo inglês ?
inglês é a lingua mais falada isso é clichê,e cai para nós
pessoal de portugal e brasileiro em geral tão nem ai para o
que ocorre em volta, já a 4 anos escrevo códigos OpenSource,
só escrevendo inglês para receber e-mails
de pessoas dando commit, dando dicas… mesmo meu inglês sendo fail 😉

você deve ter pensado por que estas funções
tem nome macabro
tipo “Add_Corpse()” ,” Cover_TombPool()
na verdade é um jargão ao tema de terror a imagem
do projeto também…
entomb

quando eu estiver de boa, vou fazer uma documentação
com doxygen se bem que para algo simples que não tem tanta função…
mas para ajudar a ficar sério ^^

 
1 comentário

Publicado por em março 17, 2012 em Linguagem C

 

Trabalhando com BigInt

Aloha queridos leitores, firmes como geleia ?! , hoje vou
tentar explanar algo comum, pode ser útil para quem trabalha com
estatística,física,aritmética pesada em geral ou desafios
Eulerianos” aqueles problemas com sigma com valores
com fatoriais monstros,acumulativos e recursivos,onde seu
computador pediria água de tanto serviço.

Quando você tem um número muito grande que ultrapassa a cota de uma
variável “int“, variável muda a casaca para negativo,não tem para
onde mais correr, e agora ? uso “long” certo e se o long virar casaca
também , e se o “long long” não der e nem com “unsigned“, Ho Ho parece
um dragão daqueles de múltiplas cabeças bem como Tiamat do D&D,
tiamat😀
bom obviamente você chegou a epifania de usar “char *“,usar alocação
dinâmica e já veio uma utopia na cabeça,uma possível solução para
nosso paradoxo, então você já sabe o que é um “BigInt“.

#include <stdio.h>

int main()
{
//tente concatenar mais alguns algarismos em X e compile e analise os resultados
 unsigned long long X=1844674407370955161;
 fprintf(stdout,"%lld",X);
 return 0;
}

Não vale o fardo seguir com a insanidade de como fazer do zero,
ainda mais mundo moderno onde muitos problemas já foram solucionados,
olhando em volta tocando uns livros e batendo uma busca no
Google a 2 anos atrás, encontrei o GMPGNU Multiple Precision
Arithmetic Library
“, uma API bem madura que proporciona o trabalho
com uma gamma de funções aritméticas, seja com variáveis integer,float
ou número racional, também conheci a lib para BigInt do OpenSSL mas
achei tão lenta que resolvi não escrever sobre. Quanto a otimização ?
GMP tem várias otimizações em ASM de acordo com a arquitetura do seu
computador, código fonte do GMP assusta até o Chuck Norris

Instalando:
# apt-get install libgmp-dev gmp-doc

Lendo o manual:
$ info gmp

agora que temos material em mãos

bom para usar a lib gmp usamos “gmp.h” e na hora de compilar usamos
o argumento “-lgmp“,vou explanar em algo empírico.

// exemplo by Cooler_
#include <stdio.h>
#include <gmp.h>

int main()
{
// var do gmp para trabalhar com signed int
 mpz_t X;
 unsigned int Y=512;
// inciando
 mpz_init(X);
// mnemônico para atribuição x=y
 mpz_set_ui(X,Y);
// mnemônico para soma x+=y
 mpz_add_ui(X,X,Y);
// 1024^512 qual seria o resultado ?
 mpz_pow_ui (X,X,Y);

 gmp_fprintf(stdout,"%Zd  %s\n",X,"legal");
/*
gmp tem um próprio método de OUTPUT
explicando o format string

     F         mpf_t, float conversions
     Q         mpq_t, integer conversions
     M         mp_limb_t, integer conversions
     N         mp_limb_t array, integer conversions
     Z         mpz_t, integer conversion

para INPUT use o gmp_scanf() e gmp_sscanf()
*/


/*
expoente
mpz_pow (mpz_t ROP, mpz_t BASE, mpz_t EXP)

resto
mpz_mod (mpz_t R, mpz_t N, mpz_t D)

testa se é divisível
int mpz_divisible_p (mpz_t N, mpz_t D)

adição
void mpz_add (mpz_t ROP, mpz_t OP1, mpz_t OP2)

subtração
void mpz_sub (mpz_t ROP, mpz_t OP1, mpz_t OP2)

produto
void mpz_mul (mpz_t ROP, mpz_t OP1, mpz_t OP2)

divisão
void mpz_div (mpz_t ROP, mpz_t OP1, mpz_t OP2)

raiz quadrada
void mpz_sqrt (mpz_t ROP, mpz_t OP)

comparar dois números
int mpz_cmp (mpz_t OP1, mpz_t OP2)
...

OBS: usamos "_ui" com nome da função quando precisamos usar "unsigned int"

*/


// limpando a bagunça
 mpz_clear(X);

 return 0;
}

Agora você pode ficar orgulhoso de conseguir fazer contas que uma calculadora
de mão não conseguiria fazer, evidente que todo conhecimento abre portas…

vamos a um desafio do project euler,algo bem easy
http://projecteuler.net/problem=48

vendo enunciado:
sequência , 1^1 + 2^2 + 3^3 + … 10^10 = 10405071317.
quanto seria até 1000^1000 ops apenas os últimos 10 dígitos

parece ser simples vamos fazer até 10 e pegar os últimos 5 dígitos

#include <stdio.h>
#include <math.h>
//coded by Cooler_
int main()
{
 unsigned long long sum=0;
// agora troque o count por 1000, e o digitos para 10
 short count=10,digitos=5;

 while(count)
 {
  sum+=pow(count,count);
  count--;
 }

 fprintf(stdout,"%lld ,last %d digits is %d\n",sum,digitos,(int)fmod(sum,pow(10,digitos)) );
 return 0;
}

compile e rode o programa e depois modifique como no comentário,
pensou em usar GMP ? e se você fazer de 10000000 ao invés de 1000 ?
como você faria ?

Meus agradecimentos ao utroz,enygmata e o kov do canal ##c-br da freenode
😉

 
4 Comentários

Publicado por em janeiro 13, 2012 em Linguagem C, math

 

Tags:

Migrando do excel para algum DB

Vou ser bem retórico, missão aqui é abrir vários arquivos
.xls“(extensão de arquivos do excel) que contenham a mesma
tabela,passar para XML e depois dar parser para dar “INSERT
em algum DB.

Justificativa da missão ,ano passado por 3 vezes eu
peguei freelancer de portar tabelas de “excel” para
algum SGBD, muita gente reclamando para mim que
gostaria de saber como o fazer e tudo mais foi outro
motivo, muitos clientes por falta de tempo e de estudo
preferem usar “excel” do que DB,pessoal de contabilidade
principalmente ,só olham para possibilidade de usar
banco de dados quando se tem milhares de tabelas do excel
para se alterar etc
, Isso é o que mantêm os estagiários em
algumas empresas,mas se perde muito tempo e dinheiro com
isso…
Read the rest of this entry »

 
Deixe um comentário

Publicado por em janeiro 6, 2012 em Banco de dados, Linguagem C, Perl

 

Uma humilde visão de Kernel,syscalls e módulos.

Não sou conhecedor de tudo que o sistema Linux tem , mesmo por que
uso a pouco tempo , mas vou tentar explanar alguns conceitos básicos,
dos quais me deparei no decorrer dos anos.

Kernel do Linux é um programa bem complexo escrito na linguagem “ansi C“,
com algumas partes específicas de cada arquitetura de computador utilizando
assembly“, sua missão é fazer o elo entre software e hardware. Quem já compilou
o kernel já teve o privilégio de ver uma tela com “ncurses” com uma das opções
“loadable Module”, se você ativar, poderá ativar e desativar drivers e funções,
maioria dos sistemas linux já vem com esta opção ativada , Estes módulos são
partes do “kernel” que possibilitam serem incorporados e removidos,sem a
reinicialização do sistema.

caso queira ver o código do kernel do linux
baixe o AQUI

Syscalls é um ponto de entrada para o kernel Linux, são chamadas indiretas
a maioria das chamadas de sistema têm correspondentes funções da biblioteca
C , um wrapper que executar os passos necessários (por exemplo, prendendo ao modo
kernel). Assim fazendo uma chamada de sistema é o mesmo que chamar uma função
de biblioteca normal.

tabkernel

antes de partir para o rock n roll, vamos entender o básico de inline ASM
__asm__("" : saida : entrada : modificador);

exemplo adição simples com “ADD”

#include <stdio.h>
#include <unistd.h>
 
int main()
{
  int data1 = 8,data2 = 3;
 
  __asm__("addl  %%ebx,%%eax":"=a"(data1):"a"(data1), "b"(data2));
  fprintf(stdout, "data1 + data2 = %d\n", data1);
 
  return 0;
}

Vamos analisar como um código em linguagem C ,interrupção para um syscall
no caso o write() , veja a tabela aqui

 int write(int fd,const char * buf,unsigned int count)
    {
        long __res;
        asm("int $0x80"
            : "=a" (__res)
            : "0" (__NR_write), "b" ((long)fd),
              "c" ((long)buf), "d" ((long)count));
        if ((unsigned long)__res >= (unsigned long)-129) {
            errno = -__res;
            __res = -1;
        }
        return (int) __res;
    }

de onde veio o “__NR_write” ?

$cat unistd_32.h | grep write
#define __NR_write 4

algo equivalente a

  write:
         pushl %ebx              ; adiciona ebx na pilha
         movl 8(%esp), %ebx      ; adiciona primeiro argumento em ebx
         movl 12(%esp), %ecx     ; adiciona segundo argumento ecx
         movl 16(%esp), %edx     ; adiciona terceiro argumento edx
         movl $4, %eax           ; adiciona _ _NR_write em eax
         int  $0x80              ; interrupção para syscall
         cmpl $-125, %eax        ; checa o retorno 
         jbe .PULA               ; se nenhum erro JUMP para PULA
         negl %eax               ; complementa valor em eax
         movl %eax, errno        ; adiciona resultado em errno
         movl $-1, %eax          ; seta eax para -1
  .PULA: popl %ebx               ; tira ebx da pilha
         ret                     ; returna chamando programa

Em caso de erro, a maioria das chamadas do sistema retornam um número
negativo erro (ou seja, o valor negado de uma das constantes descritas
na errno (3)). O wrapper da biblioteca C esconde esse detalhe do chamador,
quando uma chamada de sistema retorna um valor negativo, o wrapper
copia o valor absoluto na variável errno, e retorna -1 como o valor de
retorno do wrapper.

O valor retornado por uma chamada de sistema bem sucedida, varia da chamada,
mais detalhes estão descritos no manual de páginas individuais. GNU C Library (glibc)
fornece a interface de syscall que se conecta ao kernel e fornece o mecanismo
para transição entre o aplicativo de espaço de usuário e o kernel.

mais informações
$ man syscall
$ man libc

Voltando para módulos de kernel

Qual é a vantagem de trabalhar com módulos do kernel ?

Bom você não precisa reiniciar seu sistema operacional toda vez que quiser
testar um driver, fora a transparência em que o linux faz isso, ajuda na
otimização do mesmo.
Vamos na prática

Arquivo que contém o módulo é um “arquivo objeto”, bem como um programa
gerado com GCC para depois compilar,utilizando oa argumento “-c”(compile only),
eles contêm símbolos para ajudar o kernel no percurso de carregamento de registro,
em suma passam pelo filesystem onde esta como “arquivo objeto” para memória RAM na
parte destinada de programas sendo carregados por um syscall, no endereço correto
reservada ao kernel.

vamos fazer nosso primeiro módulo

Makefile:

KDIR := /lib/modules/$(shell uname -r)/build

# Objeto
obj-m = macacos.o

# Regra default do Makefile
default:
        $(MAKE) -C $(KDIR) M=$(PWD) modules
        @rm -rf *.mod* Module.symvers *.o *~ *.markers *.order

# Limpando objetos e afins
clean:
        @rm -rf *~ *.o *.ko

arquivo macacos.c

#include <linux/module.h>

int init_module(void)
{
 printk("macacos me mordam \n");
 return 0;
}

void cleanup_module(void)
{
 printk("saindo\n");
}

MODULE_AUTHOR("Cooler_ ");
MODULE_DESCRIPTION("Just another test");
MODULE_LICENSE("BSD");

Passamos alguns comandos para compilar e instalar nosso módulo
e um comando para conferir se o módulo foi inserido…

$ make; insmod macacos.ko; dmesg | grep macacos
[17205.255807] macacos me mordam

Para remover o módulo
$ rmmod macacos

Olhe que interessante analisando o arquivo “.ko” com comando “strings”
$ strings macacos.ko
macacos me mordam
saindo
srcversion=F9191437D66715B7ADCB1E5
depends=
vermagic=3.0.0-14-generic SMP mod_unload modversions 686
module_layout
Pprintk
mcount
macacos

Bom o “insmod” usamos para instalar módulos e o “rmmod” para remover
como foi mostrado no exemplo, além deles temos o “lsmod” para listar módulos
exemplo

$ lsmod | grep snd
snd_hda_codec_hdmi     31426  1 
snd_hda_codec_realtek   254125  1 
snd_hda_intel          24262  6 
   |                      |    \_referências de outros módulos...
   |_ Nome Modulo         |_memória usada pelo módulo

modinfo” para se obter informações do módulo
$ modinfo snd_pcm
filename: /lib/modules/3.0.0-14-generic/kernel/sound/core/snd-pcm.ko
license: GPL
description: Midlevel PCM code for ALSA.
author: Jaroslav Kysela , Abramo Bagnara
srcversion: B1C966040673ADEA6AD0FAA
depends: snd,snd-page-alloc,snd-timer
vermagic: 3.0.0-14-generic SMP mod_unload modversions 686
parm: preallocate_dma:Preallocate DMA memory when the PCM devices are initialized. (int)
parm: maximum_substreams:Maximum substreams with preallocated DMA memory. (int)

Isso foi uma breve introdução…

 
1 comentário

Publicado por em dezembro 27, 2011 em Linguagem C, Linux

 

Tags:

Detector de batimentos cardíacos

Iai meus Leitores prediletos do meu blog falido 😛

Bom neste Post, vou falar sobre detector de mentira
algo simples em conjunto com um “heartbeat” , ideia do detector
de mentira não é só pegar batidas do coração mais pegar dados
de suor,movimentos da perna entre outras coisas significantes,
como nosso post vai ser informal não espere aqui um guia
definitivo de polígrafo.

moe

Nossa missão aqui é fazer um HeartBeat com um outro sistema
para pegar dados e fazer o Plot bem simples algo bem tabajara,
Plot é para a pessoa que vai julgar se é verdade ou mentira poder
ter algo visual, poderia ter usado um LED RGB para
ter seu valor atribuído de a cordo com valor do heartbeat, eu gravei
um vídeo para mostrar um ponto empírico. Agradeço ajuda do “Eremitah
por dar a dica do buzzer fez eu economizar uns 4 dollares com sensores
de tremor, buzzer você acha em qualquer lugar custa de 15centavos a
2 reais no máximo.

Foi usado apenas um buzzer , seria interessante usar mais de um, talvez
usar uma rede neural para pegar as batidas certas de forma descartar os erros e a ajudar no julgamento
de resultados de 4 sensores ou mais ,bem como sensor de umidade e movimento etc, talvez aumentar o delay de
5 segundos. fica a seu critério…

vamos a diversão,código do arduino

/*
author:Antonio Costa (Cooler_)
e-mail:c00f3r[at]gmail[dot]com

 Simple HeartBeat Detector with Arduino

 needs:
  1 resistor 1M ohms
  1 Buzzer
  1 Led +1 resistor 1k
  y finger on buzzer and run...

*/

#include <Time.h>  

// cada X segundos pega Y batidas
#define SEG 5

 int count=0;
 int ledPin = 6;
 int piezoPin = 5;
 int sensorValue = 0; 

void setup() {
 Serial.begin(9600);
 pinMode(ledPin, OUTPUT);
 pinMode(piezoPin, INPUT);
}

void loop()
{
 sensorValue = analogRead(piezoPin);
 if(sensorValue)
 {
  count+=sensorValue;
// light LED by knock
  digitalWrite(ledPin, HIGH);
  delay(25);
  digitalWrite(ledPin, LOW);
 }

 if( (!(second()%SEG)) && (count>20) )
 {
//  Serial.print("second:");
//  Serial.println(second());
//  Serial.print("HeartBeats:");
  Serial.println(count);
  count=0;
  delay(50);
 }
}

Agora código que vai ficar no nosso PC

/*
contato: c00f3r@gmail.com
autor: Antonio Costa aka Cooler_
coolerlab.wordpress.com

Simple Heartbeat detector with arduino

 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>
#include <time.h>

// sempre concatene com 'B' a  taxa de transmissão ,"9600" padrão do AVR
#define BAUDRATE B9600

// macros debug
#define BUGVIEW 1

#define DEBUG(x, s...) do { \
 if (!BUGVIEW) { break; } \
 time_t t = time(NULL); \
 char *d = ctime(&t); \
 fprintf(stderr, "%.*s %s[%d] %s(): ", \
 (int)strlen(d) - 1, d, __FILE__, \
 __LINE__, __FUNCTION__); \
 fprintf(stderr, x, ## s); \
} while (0);

// vai pegar os dados a cada 5 segundos
#define SECOND 5

int serialboot(const char* serialport, int baud);
int serialread( int fd, char* buf, char until, int max );
int WriteFile(char *file,char *str);

void banner()
{
 printf("\nFollow patern: ./heartbeat <SerialPort> <times 2 get>\n"
  "Just Another geek thing to get HeartBeat and plot!!!\n"
  "Coded By Cooler_\n"
  "coolerlab.wordpress.com\n"
  "\n");
}

int main(int argc, char *argv[])
{
 int baudrate = BAUDRATE,fd=0,counter=0,times=0;
 char *buf=malloc(sizeof(char)*16);
 char *serialport=malloc(sizeof(char)*512);

// apagamos o último log
 unlink("logbeat.txt");

  if(argc<2)
  {
   banner();
   exit(EXIT_SUCCESS);
  }

  printf("Serial:%s\n",argv[1]);

  strncpy(serialport,argv[1],sizeof(char)*511);
  fd=serialboot(serialport, baudrate);

   if(fd<=0)
   {
    DEBUG("veja se o dispositivo esta conectado!!");
    DEBUG("%d\n",fd);
    exit(EXIT_SUCCESS);
   }

//número de dados que seram pegos a cada 5 segundos
  if(strnlen(argv[2],3)<2)
  {
   times=atoi(argv[2]);
  } else {
   puts("error at argument time");
   exit(EXIT_SUCCESS);
  }

  while(1)
  {
   serialread(fd, buf, '\n',15);

   if(strncmp(buf," ",15)>0)
   {
    fprintf(stdout,"%s",buf);
    sleep(SECOND);
    WriteFile("logbeat.txt",buf);
    times--;
   }
// se terminar número de vezes então pula
   if(!times)
    break;
  }

// nosso amigão gnuplot nos ajudando 🙂
 FILE *pipe = popen("gnuplot -persist","w");
  fprintf(pipe, "set grid'\n");
  fprintf(pipe, "set style data lines\n");
  fprintf(pipe, "set terminal png\n");
  fprintf(pipe, "set output 'heartbeat.png'\n");
  fprintf(pipe, "plot \"logbeat.txt\"\n");
 pclose(pipe);

// fechando a banca xD
 puts("end HeartBeat, look image heartbeat.png");
 close(fd);
 free(buf);
 free(serialport);

 exit(EXIT_SUCCESS);
} 

int serialread(int fd, char* buf, char until,int max)
{
char b[1];
int i = 0;
do {
int n = read( fd, b, 1 );
if( n==-1 )
return -1;
if( !n )
{
usleep(16000);
continue;
}
buf[i] = b[0];
i++;
} while ( b[0]!=until && max != i );
buf[i] = 0;
return 0;
}

int serialboot(const char* serialport, int baud)
{
 struct termios toptions;
 int fd;

    fd = open(serialport, O_RDWR | O_NOCTTY | O_NDELAY);

    if(fd == -1)
    {
     DEBUG("serialboot: não foi possivel abrir a porta ");
     return -1;
    }

    if(tcgetattr(fd, &toptions) < 0)
    {
     DEBUG("serialboot: nao foi possivel pegar atributos do terminal");
     return -1;
    }
    speed_t brate = baud;
    cfsetispeed(&toptions, brate);
    cfsetospeed(&toptions, brate);
   // para default recv com termios.h
    // 8N1
    toptions.c_cflag &= ~PARENB;
    toptions.c_cflag &= ~CSTOPB;
    toptions.c_cflag &= ~CSIZE;
    toptions.c_cflag |= CS8;
    // no flow control
    toptions.c_cflag &= ~CRTSCTS;
    toptions.c_cflag |= CREAD | CLOCAL;  // turn on READ & ignore ctrl lines
    toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl
    toptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw
    toptions.c_oflag &= ~OPOST; // make raw

    // olhe http://unixwiz.net/techtips/termios-vmin-vtime.html
    toptions.c_cc[VMIN]  = 0;
    toptions.c_cc[VTIME] = 20;

    if(tcsetattr(fd, TCSANOW, &toptions) < 0)
    {
     DEBUG("serialboot: nao foi possivel adicionar atributos no term erro 1");
     return -1;
    }

 return fd;
}

//escreve num txt
int WriteFile(char *file,char *str)
{
 FILE *arq;

 arq=fopen(file,"a");
  if(!arq)
  {
   DEBUG("error in WriteFile() %s",file);
   return 0;
  }
 fprintf(arq,"%s",str);
 fclose(arq);
 return 1;
}

$ gcc -o heartbeat heartbeat.c -Ofast -fstack-protector-all -Wl,-z,relro,-z,now -D_FORTIFY_SOURCE=fast
$ ./heartbeat /dev/ttyUSB1 10

deixe seu dedo indicador do braço direito no buzzer,
quando ver o LED piscar quer dizer que esta capitando…

*Dica caso queira testar em alguém
-faça um PCB , algo decente, o que mostrei foi só protótipo,use a imaginação
-use algum elástico de forma colar o buzzer no local onde quer capturar as batidas
-comece perguntando coisas que são obviamente verdade e analise o Plot
-preste atenção nos ticks nervosos
-olhe outros projetos hack a day ,por la tem vários polígrafos
-altere o delay e use mais buzzers se necessário

espero ter ajudado 😉

curtiu ? quer mais procura no google por “Knock sensor

 
1 comentário

Publicado por em dezembro 22, 2011 em arduino, hacking, Linguagem C

 

Tags:

Introdução a bibliotecas em C

Lendo post do meu amigo sigsegv sobre “ld preload”
fiquei motivado escrever algo sobre bibliotecas em C ,
algo bem informal bem como ajudar iniciantes.assim como fiz
no post de pkg-config.

master librarian

master librarian do game castlevania

Criando uma biblioteca estática (Static library)
———————————————————————
Quando a ligação é feita durante a criação de um executável ou
outro arquivo objeto, ele é conhecido como vinculação estática
ou early binding. Neste caso, a ligação é feita geralmente por
um linker, mas também pode ser feito pelo compilador. A biblioteca
estática, também conhecida como um archive, é que se destina a ser
ligada estaticamente.

vamos la

$ vim test.c

int sum(int a,int b)
{
 return a+b;
}

:wq!
para criar o arquivo com extensão “.o”
$ gcc -Wall -c test.c

passamos para “.a”
$ ar -cvq test.a test.o

pronto agora você pode usar sua bibliotéca estática
$ gcc -o a a.c test.a

também pode-se fazer
$ gcc -o a a.c -ltest

$ vim a.c

 #include <stdio.h>

 int main()
 {
  printf("%d \n",sum(2,2));
 }

:wq!

ao executar “a” devera resultar em “4” no stdout


Criando uma biblioteca dinâmica (Dynamic Library)

———————————————————-

Carregamento dinâmico é um mecanismo pelo qual um programa de computador pode, em
tempo de execução, carregar uma biblioteca (ou binário outros) para a memória,
recuperar os endereços de funções e variáveis contidas na biblioteca, executar
essas funções ou acessar essas variáveis, e descarregar o biblioteca da memória.

Ao contrário de vinculação estática e tempo de carregamento ligando, este mecanismo
permite que um programa de computador para a inicialização, na ausência destas
bibliotecas, para descobrir as bibliotecas disponíveis e potencialmente ganhar
funcionalidades adicionais.

No windows este tipo de biblioteca se chama DLL (dynamic-link library) em Unix Like
e afins chama-se DSOdynamic shared object

man ld.so” para mais informações

vamos la

$ gcc -Wall -fPIC -c test.c
$ gcc -shared -Wl,-soname,test.so.1 -o test.so.1.0 test.o
$ mv test.so.1.0 /lib
$ ln -sf /lib/test.so.1.0 /lib/test.so
$ ln -sf /lib/test.so.1.0 /lib/test.so.1

Entendendo os argv(argumentos)

-fPIC” seria uma diretiva para compilar de forma independente
Ideia é adicionar um nível adicional de indireção a todos os
dados globais e referências de função no código. utilizando algumas
partes da ligação e carregamento de processos, é possível fazer a
seção de texto da biblioteca compartilhada e independente
de posição, no sentido de que ele possa ser facilmente mapeado em diferentes
endereços da memória sem a necessidade de mudar um pouco.
-shared” Produzir um objeto compartilhado que pode ser relacionado com
outros objetos para formar um executável.
aqui explica melhor

um “man gcc” não faz mal para saúde 😉

na hora de compilar

$ gcc -Wall -I/path/to/include-files -L/path/to/libraries a.c -ltest -o a

ou também
$ gcc -Wall -L/lib a.c -ltest -o a

Por fim
————
bom aqui foi uma introdução bem superficial, sugiro estudar
autotools e cmake,bem como automatizar suas tarefas , não
conheço ninguém que goste deles, são muitas paradigmas a
seguir, muitos fins de semana a perder fazendo testes com
autoconf automake… Entretanto é um estudo que me parece
indispensável para quem quer ser um programador em C completo.

Para estudo do cmake(é bem mais fácil de usar) esse link
cmake

Caso queira estudar autotools(estou lendo este livro 😉 )
autotools

bom se este post não fui o suficiente para você sugiro que leia
o paper do meu amigo sigsegv sobre ELF para entender linkagem
das bibliotecas e algo mais… AQUI

 
Deixe um comentário

Publicado por em dezembro 17, 2011 em Linguagem C

 

the thief detector (detector de ladrão ) :-D

Post não vai ser sobre o carrinho de controle remoto com infravermelho
sim já terminei o protótipo dele já funciona, mas quero corroer a
placa fazer algo bem mais decente, invés de ficar usando breadboard.
como eu sou bem NOOB em tudo e em eletrônica este post vai demorar.

Olhe meu vídeo que você vai entender por que quero usar IR no carrinho

strikes back

Já algum tempo que comprei sensor de movimento para fazer um sistema
detector de “ladrão”, até pensei em usar um buzzer e tudo mais,
mas detector de ladrão com buzzer é muito manjado. Como eu gosto de trazer o que é
meio incomum para o blog então tive uma ideia…

Missão comunicação serial para quando for detectar o
movimento tirar uma foto da webcam e mandar e-mail com anexo a foto.
já tem soluções com o “motion” ou mesmo com opencv detectando movimentos
da webcam reconhecimento e tudo mais, mas a ideia do feito foi treinar
desenvolvimento com “arduino pro mini” em conjunto com “FTDI“…

material usado:
Arduino pro mini – $18.95 USD sparkfun (anda meio salgado o preço prefiro o diavolino )
Resistor 10k Ohm – $0.15 santa efigenia
Pir motion sensor – $9.95 USD sparkfun
Machine Pin headers – $2.00 santa efigenia (muito chato soldar isso no arduino)
FTDI Basic Breakout 5V – $12.00 USD sparkfun

vendo como fica
pronto1

seguindo a dica de
http://bildr.org/2011/06/pir_arduino/

código do arduino

int pirPin = 9; 

void setup(){
 Serial.begin(9600);
 pinMode(pirPin, INPUT);
}

void loop(){
  int pirVal = digitalRead(pirPin);


// achou movimento
  if(pirVal == LOW)
  { 
//pausa em milesegundos equivalente ao usleep do ansi C
     delay(500);
    Serial.println("1");
  }
  //sem movimento
  else
  {
    Serial.println("0");
  }

}

Lembra da nossa Missão ?
Se o arduino detectar valor com sensor de movimento
ira mandar um OUTPUT para a porta serial,nosso programa em C
irá ficar na esculta se ele julgar movimento do conjunto de
OUTPUT ele ira tirar uma SHOOT da WEBCAM e ira mandar e-mail
com anexo
a foto…

Vamos resolver o problema do E-mail,bom fazer um cliente de e-mail do zero
em C é trabalhoso e leva tempo, então vamos instalar cliente de e-mail
instalamos o “mutt

//use o gerenciador do seu OS,se for BSD use ports...
$ sudo apt-get install mutt
$ vi ~/.muttrc

set realname="seunome"
set from="exemplo@gmail.com;"
set my_user=exemplo@gmail.com
set my_pass='sua senha'
set smtp_url=smtps://$my_user:$my_pass@smtp.gmail.com
set ssl_force_tls = yes
:wq!

vamos testar

echo 'conteúdo do e-mail' | mutt -s 'assunto do e-mail' exemplo@gmail.com

e vá ver sua caixa de corrêio verificar…

como enviar nosso anexo ?

echo 'LogLog!!!' | mutt -s 'THief Get LOg' -a c/arduino/test.jpg -- exemplo@gmail.com

quer aprender mais sobre o mutt ? “man mutt

agora podemos partir para o código
não fique triste por eu ter usado o OpenCV para tirar foto da webcam

/*
contato: c00f3r@gmail.com
autor: Antonio Costa aka Cooler_
coolerlab.wordpress.com

Simples detector de ladrão usando Arduino+sensor de movimento

apt-get install libhighgui-dev  libcv
gcc -o thiefget thiefget.c  -lcv -lhighgui -lcxcore; ./thiefget

usei o OpenCV para tirar shoot da webcam pois não conheço outra API
que faça o mesmo...

só para enviar e-mail que usei programa de terceiro... parece gambi até xD

executando:
como argumento o seu dispositivo onde esta o arduino
./thiefget /dev/ttyUSB0


 */
#include <stdio.h>    
#include <stdlib.h> 
#include <string.h>   
#include <unistd.h>   
#include <termios.h>  
#include <fcntl.h> 
#include "opencv/cv.h"
#include "opencv/highgui.h"

// quantas vezes o sensor retornara 1 para mandar e-mail ?
#define MOVES 16

// numero que tolera erros
#define FAIL 16

// sempre concatene com 'B' a  taxa de transmissão ,"9600" padrão do AVR
#define BAUDRATE B9600

int serialboot(const char* serialport, int baud);
int serialread(int fd, char* buf, char until);
void webcam(const char* file);

void banner() 
{
 printf("\nFollow patern: ./PegaLadrao <SerialPort>\n"
  "Just Another geek Cool THing With ArduinO!!!\n"
  "Simple THief Get\n"
  "Coded By Cooler_\n"
  "coolerlab.wordpress.com\n"
  "\n");
}

int main(int argc, char *argv[]) 
{
 int baudrate = BAUDRATE,fd=0,counter=0,OFF=0; 
 char *buf=malloc(sizeof(char)*16);
 char *serialport=malloc(sizeof(char)*512);

  if(argc<2) 
  {
   banner();
   exit(EXIT_SUCCESS);
  }
    
  printf("Serial:%s\n",argv[1]);

//conection
  strncpy(serialport,argv[1],512);
  fd=serialboot(serialport, baudrate);

   if(fd<=0)
   {
    puts("veja se o dispositivo esta conectado!!");
    printf("%d\n",fd);
    exit(EXIT_SUCCESS);
   }
 
  while(1) 
  {
    
// tempo em milesegundos, altere como for necessário
   serialread(fd, buf, '\n');
   printf("====================\nread: %s\ncounter: %d\n===================\n",buf,counter);

// se ler "1" contador é atribuido
     if(strcmp(buf,"1")>0)
     {
      usleep(500000);
      puts("MOVEMENT ONLINE");
      puts(buf);
      counter++;
      OFF=0;
     } 
//numero de vezes que achou movimento
     if(counter==MOVES)
     {
      puts("cof cof thief in HOME");
      webcam("test.jpg");
      system("echo 'LogLog!!!' | mutt -s 'THief Get LOg' -a /home/nick/c/arduino/test.jpg -- exemplo@gmail.com");
      break;
      counter=0;
     } 
     if(!strlen(buf))
      OFF--;
     if(OFF==FAIL)
      break;
     
  }

 puts("Simple THief Get ,set to OFF");
 close(fd);
 free(buf);
 free(serialport);

 exit(EXIT_SUCCESS);    
} 

int serialread(int fd, char* buf, char until)
{
 char b[1];
 int i=0;
 do { 
  int n=read(fd, b, 1);  
  if(n==-1) 
    return -1;    
  if(!n) 
  {
   usleep(16000); 
   continue;
  }
  buf[i] = b[0]; 
  i++;
 } while(b[0]!=until);

 buf[i]=0;  

 return 0;
}

int serialboot(const char* serialport, int baud)
{
 struct termios toptions;
 int fd;

    fd = open(serialport, O_RDWR | O_NOCTTY | O_NDELAY);

    if(fd == -1)  
    {
     puts("serialboot: não foi possivel abrir a porta ");
     return -1;
    }
    
    if(tcgetattr(fd, &toptions) < 0) 
    {
     puts("serialboot: nao foi possivel pegar atributos do terminal");
     return -1;
    }
    speed_t brate = baud; 
    cfsetispeed(&toptions, brate);
    cfsetospeed(&toptions, brate);
   // para default recv com termios.h
    // 8N1
    toptions.c_cflag &= ~PARENB;
    toptions.c_cflag &= ~CSTOPB;
    toptions.c_cflag &= ~CSIZE;
    toptions.c_cflag |= CS8;
    // no flow control
    toptions.c_cflag &= ~CRTSCTS;
    toptions.c_cflag |= CREAD | CLOCAL;  // turn on READ & ignore ctrl lines
    toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl
    toptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw
    toptions.c_oflag &= ~OPOST; // make raw

    // olhe http://unixwiz.net/techtips/termios-vmin-vtime.html
    toptions.c_cc[VMIN]  = 0;
    toptions.c_cc[VTIME] = 20;
    
    if(tcsetattr(fd, TCSANOW, &toptions) < 0) 
    {
     puts("serialboot: nao foi possivel adicionar atributos no term erro 1");
     return -1;
    }

 return fd;
}

/*tira foto usando opencv
  não queria usar opencv, mas unica API que ja tinha
 usado com a webcam...
*/
void webcam(const char* file)
{
 CvCapture *capture = cvCreateCameraCapture(0);
   if(capture==NULL)
    puts( "nao he possivel pegar foto!\n");

  IplImage* frame = cvQueryFrame( capture );
   if(!frame)
    puts( "erro na foto!\n");

  int imageParams[3] = {CV_IMWRITE_JPEG_QUALITY, 100, 0};
  cvSaveImage(file , frame,imageParams);
  cvReleaseCapture( &capture );
}

veja o e-mail que chegou quando cheguei proximo do sensor
e-mailcooler

muito divertido…

bom é isso ai,
escrevi o código meio que na correria mas acho
que deu para explanar a ideia…
fique avontade para melhorar o código 😉

 
8 Comentários

Publicado por em dezembro 4, 2011 em arduino, hacking, Linguagem C, segurança de sistemas

 

A magia dos Bits

Antes de entender a magia dos bits vamos ver algo leve, claro em
linguagem C , bem como dar uma introdução ao entendimento de bits
e seu funcionamento em variáveis.

Captura de Tela 2014-07-14 às 21.14.21

Uma variável do tipo “int” tem 4bytes ou seja 32bits

se você faz:

 "int var = 3;"

Então temos:

4bytes = 32bits
cada octeto é um byte, meio octeto pode-se chamar de nibble.
“…00000000 00000000 00000011”

cada casa de número binário contamos como um bit
bit nada mais é que mnemônico para “Binary digiT”

Para saber número de bytes de uma variável usamos operador “sizeof(var)”
que nos retorna o valor em bytes da variável.

Se desejamos saber valor binário de um número fazemos divisão por 2
e enquanto o resto da divisão for diferente de “1” fazemos a divisão
no final pegamos os restos ao contrário para ser o resultado final

número 12 para binário logo:

12 | 2
12 +------                   1100 <-- resultado ao contrário
 0  6    | 2              -------------
         +-----
    0      3  | 2
              +-----
          1     1

Resultado 1100,repare que só temos um nibble ou seja um semiocteto
metade de 1 byte ou seja 4bits, lembra 1byte é 8 bits.

façamos então um programa para automatizar a tarefa de converter
decimal para binário

#include <stdio.h>

int main()
{
 int bin[8],num=0,counter=0;

 puts("Dec2Bin\n digite um numero");
 scanf("%d",&num);

//para somente quando a divisão der "1"
 while(num!=1)
 {
//pegamos o resto da divisão ou se tiver um resultado é 1 se não é 0
  bin[counter]=(num%2)?1:0;
//dividimos num por 2 e armazenamos em num para pegar o próximo resto
  num/=2;
  counter++;
 }
 bin[counter]=num;

//mostramos o array ao contrário
 printf("\nResultado: ");
 while(counter!=-1)
 {
  printf("%d",bin[counter]);
  counter--;
 }
 printf("\n");

 return 0;
}

continuando, tem outra forma melhor de se fazer isso, mas não
é hora de abordar isso agora.

Introdução Escovação de Bits “BitWise”
=======================================

Quando dizemos escovação de bits é uma mera referência ao trabalho
de manipular bits para se obter certos resultados. pessoal que trabalha
com microcontrolador seja AVR,PIC por muitas vezes tem que fazer tal
manipulação. Quando queremos desempenho escovação de bits pode nos
ajudar também embora o compilador já otimize muitas das tarefas.Outra
utilização é em tratamento de imagens e manipulação das mesmas,OpenCV
mesmo obriga você usar sempre que não existe uma solução pronta…

Bit Shifting “deslocamento de bit”
======================================

Deslocar um bit nada mais é que mudar o bit da sua posição original
para se chegar num certo resultado,chamamos esta técnica de bit shift
é um mnemônico do assembly “shl,shr”(shifiting left,shifiting right),
vamos a um exemplo de deslocamento para esquerda:

 int var = 3;
 var <<= 1;

 o nosso 3

  0011

 recebeu um deslocamento para esquerda

  0110

resultou em “6”, pode dar uma ilusão de aritmética de produto ou de
adição por ele mesmo, mas foi o resultado do deslocamento, forma
matemática correta segundo o livro do K&R para explanar nossa expressão
do exemplo seria “2*3¹”.

agora vamos ver deslocamento para direita:

 int var = 100;

 temos então 1100100

 var >>= 2; 

 removemos os dois últimos digitos 

  11001

nos resulta “25”,forma matemática para tal é a seguinte “(100/2)²”
você me diz 25mil, cadê os zeros ? como disse remove os dois últimos
dígitos.

Mascaramento de Bit
======================

OR

Vamos ao operador “|” tem o mnemonico “OR” em assembly, vamos entender seu impacto

 x=26|19;

   11010
 | 10011
 ---------
   11011   ==  27

AND

Agora o “&” mnemônico com “AND” em assembly

 x=26&19;

   11010
 & 10011
 ---------
   10010 == 18

NOT

O “~” é mnemônico com “NOT” ou seja ele é uma negação, fazendo um efeito inverso
do seu valor carregado, ou seja onde está 1 fica zero e vice e versa.

 x=~26; 

  11010
   flip
  00101

resultado seria -27, Como mas por que não 5 ? lembra que falei um “int” é
4 bytes equivale a 32bits, então

0000 0000 0001 1010

1111 1111 1110 0101

agora sim,eu fiz em nibble para não precisar escrever muito…

XOR

O “^” é mnemônico para o XOR

 x=26^19;

   11010
 ^ 10011
 ---------
   01001  == 9

veja se a tabela ne ajuda

,---,---,--------,
| a | b |  a ^ b |  pode-se fazer SWAP sem usar uma terceira variável
|---|---|--------|  exemplo:
| 0 | 0 |   0    |
| 0 | 1 |   1    |  int A=4,B=7;
| 1 | 0 |   1    |  A^=B; B^=A; A^=B;
| 1 | 1 |   0    |  // "A" agora vale 7
'---'---'--------'
 alguns usam XOR em criptografia também...

Escovando Bits
================

Vamos usar bitwise para obter “desempenho” vejamos
alguns códigos com bitwise


// programa para verificar se é impar ou par
main(int argc,char *argv[]){printf("%s\x0a",(!((atoi(argv[1]))&1))?"Par":"impar");}
// Isso = "x&1" usa mesma lógica disso "x%2"
// se retornar 0 é por que o último num binário é ZERO ou seja PAR...

// Sempre que precisar verificar se um número é multiplo
// fazer
resto = num & (divisor - 1);
x = 122 % 6;
//forma mais rápida
x = 122 & (6 - 1);

/*
se quiser fazer casting de float para Int
invés de fazer Casting de Float para Int assim "x = int(3.142)",
faça assim "x=3.142>>0;", melhora desempenho em 10%
*/
//operações ternárias são rapidas mas bit a bit são mais</b>
//invés
i = x < 0 ? -x : x;
//faça
i = (x ^ (x >> 31)) - (x >> 31);

//Comparando dois inteiros
x = a * b > 0;
//melhor forma
x = a ^ b >= 0;

//Comparar duas variáveis ver qual é a maior e menor
gamma = y ^ ((x ^ y) & -(x < y)); // gamma=menor(x, y)
gamma = x ^ ((x ^ y) & -(x < y)); // gamma=maior(x, y)

//Determinar se um inteiro é uma potência de 2
x = v && !(v & (v - 1));
//vai retornar verdadeiro ou falso 😉

//média para int
int a=6,b=8; printf("%d\n",((a&b)+(a^b)>>1));

//verificar se a posição "n" em bit é "1"
if( n & 1 << i ) 

lembra do nosso código simples de converter decimal para binário
vamos fazer um usando escovação de bits 🙂

// retirado da header beer.h https://github.com/CoolerVoid/C/edit/master/beer.h
char * dec2bin(int n, char * string)
{
 int i;
 static int size = 8 * sizeof(int);

  for(i = size - 1; i >= 0; i--, n >>= 1)
   string[i] = (01 & n) + '0';

 string[size] = '\0';
 return string;
}

calcular raiz quadrada escovando bit por que não…

// retirado da header beer.h https://github.com/CoolerVoid/C/edit/master/beer.h
int bit_sqrt(int num)
{
//so 32 is sizeof(int)<<3
 int num0=num,result=0,tbit=1<<((sizeof(int)<<3)-2);

 if(num<=0)
 {
  printf("error bit_sqrt(), num = %d ",num);
  return -1;
 }

 while(tbit>num0)
  tbit>>=2;
 while(tbit^0)
 {
  if(num0>=result+tbit)
  {
   num0-=result+tbit;
   result=(result>>1)+tbit;
  }else
   result>>=1;
  tbit>>=2;
 }
 return result;
}

não se compara esta função a de APIs como GMP,OpenSSL
mesmo por que é uma função simples muito menos a “math.h”,
foi mais para ilustrar.

posso usar bitwise em strings ?
se for um ponteiro por que não

// return reverse string
char *strrev(char *str)
{
 char *p1, *p2;

 if(! str || ! *str)
  return str;
 for(p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2)
 {
  *p1 ^= *p2;
  *p2 ^= *p1;
  *p1 ^= *p2;
 }
 return str;
}

esse assunto é gigante vou ficar por aqui, por final
sugiro que leiam caso queiram se aprofundar no assunto
de bitwise , o livro “hacker’s delight”

hackers delight

2d175-hackers_delight

 
9 Comentários

Publicado por em novembro 24, 2011 em hacking, Linguagem C, math